mirror of
https://github.com/zhigang1992/rmq.git
synced 2026-01-12 22:51:53 +08:00
Finished v0.5, new view_controller system. Beta testing now.
This commit is contained in:
49
README.md
49
README.md
@@ -83,6 +83,12 @@ for **bleeding edge**, add this to your `Gemfile`:
|
||||
|
||||
- `gem 'ruby_motion_query', :git => 'git@github.com:infinitered/rmq.git'`
|
||||
|
||||
|
||||
## Deprecation
|
||||
|
||||
- **UIView#rmq_did_create(self_in_rmq)** - *Use rmq_build instead*
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
### Example App
|
||||
@@ -418,8 +424,8 @@ end
|
||||
|
||||
# Your cell
|
||||
class StoreCell < UITableViewCell
|
||||
def rmq_did_create(self_in_rmq)
|
||||
self_in_rmq.append(UILabel, :title_label) # <- this works even though this object isn't in a controller
|
||||
def rmq_build
|
||||
rmq(self).append(UILabel, :title_label) # <- this works even though this object isn't in a controller
|
||||
end
|
||||
end
|
||||
```
|
||||
@@ -615,11 +621,12 @@ The following are the only pollution in RMQ
|
||||
- UIViewController
|
||||
- rmq
|
||||
- rmq_data
|
||||
- TopLevel *(Only in development, used for console)*
|
||||
- Object
|
||||
- rmq
|
||||
|
||||
### Console Fun
|
||||
|
||||
rmq.log :tree
|
||||
rmq.all.log
|
||||
rmq.all.log :wide
|
||||
rmq(UIView).show
|
||||
@@ -1083,20 +1090,34 @@ You can also include all of your custom stylers in one file, which works well if
|
||||
|
||||
### Creating your own views
|
||||
|
||||
If you use RMQ's stylesheets and you create your own views, you should add your subviews and such in this method:
|
||||
RMQ calls 3 methods when you create, append, or build a view using rmq. rmq_build is the one you most want to use
|
||||
```ruby
|
||||
def rmq_created_or_appended
|
||||
def rmq_build
|
||||
end
|
||||
|
||||
def rmq_created
|
||||
end
|
||||
|
||||
def rmq_appended
|
||||
end
|
||||
```
|
||||
If you append a view like so:
|
||||
```ruby
|
||||
rmq.append(UILabel)
|
||||
```
|
||||
The 3 methods will be called in this order:
|
||||
- rmq_created
|
||||
- rmq_appended
|
||||
- rmq_build
|
||||
|
||||
In the following example an instance of YourView is created, :your_style is applied
|
||||
then rmq_did_create is called on the instance that was just created. In that
|
||||
then rmq_build is called on the instance that was just created. In that
|
||||
order.
|
||||
|
||||
```ruby
|
||||
# Your view
|
||||
class YourView < UIView
|
||||
def rmq_created_or_appended
|
||||
def rmq_build
|
||||
rmq(self).tap do |q|
|
||||
q.append(UILabel, :section_title)
|
||||
q.append(UIButton, :buy_button).on(:tap) do |sender|
|
||||
@@ -1112,7 +1133,19 @@ rmq.append(YourView, :your_style)
|
||||
|
||||
### Future features
|
||||
|
||||
Future features that I plan on adding
|
||||
Current roadmap:
|
||||
|
||||
- v0.5 new view_controller system: which solves the #1 problem in rmq: having to pass rmq around in things like cells. rmq command will work everywhere
|
||||
- v0.6 new frame system: I’ve already designed this, I just have to implement it and use it in the real world and tweak. This is going to be very cool. It adds to the existing frame system. It doesn’t replace constraints, but rather gives you almost all the features you need without the complexity of constraints.
|
||||
- v0.6.5 templates and stylers all finished
|
||||
- v0.6.7 performance improvements
|
||||
- v0.7 first rmq plugin and any base features needed to support plugins (I don’t think there will be any base features needed)
|
||||
- v0.8 binding system
|
||||
- ?
|
||||
- ?
|
||||
- v1.0
|
||||
|
||||
Random future features that I plan on adding
|
||||
|
||||
- rmq.push_sub_controller(my_controller) and rmq.pop_sub_controller and rmq.pop_this_controller
|
||||
- add borders to UIView styler: st.borders = {l: {w: 2, color: color.black}, r: {w: 2, color: color.black}}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
class AppDelegate
|
||||
attr_reader :window
|
||||
|
||||
def application(application, didFinishLaunchingWithOptions:launchOptions)
|
||||
@window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
|
||||
|
||||
main_controller = MainController.alloc.initWithNibName(nil, bundle: nil)
|
||||
@window.rootViewController = main_controller
|
||||
@window.rootViewController = UINavigationController.alloc.initWithRootViewController(main_controller)
|
||||
|
||||
@window.makeKeyAndVisible
|
||||
true
|
||||
|
||||
58
app/controllers/collection_controller.rb
Normal file
58
app/controllers/collection_controller.rb
Normal file
@@ -0,0 +1,58 @@
|
||||
class CollectionController < UICollectionViewController
|
||||
COLLECTION_CELL_ID = "CollectionCell"
|
||||
|
||||
def self.new(args = {})
|
||||
# Set layout
|
||||
layout = UICollectionViewFlowLayout.alloc.init
|
||||
self.alloc.initWithCollectionViewLayout(layout)
|
||||
end
|
||||
|
||||
def viewDidLoad
|
||||
super
|
||||
|
||||
self.title = 'Collection View'
|
||||
|
||||
rmq.stylesheet = CollectionControllerStylesheet
|
||||
|
||||
collectionView.tap do |cv|
|
||||
cv.registerClass(CollectionCell, forCellWithReuseIdentifier: COLLECTION_CELL_ID)
|
||||
cv.delegate = self
|
||||
cv.dataSource = self
|
||||
cv.allowsSelection = true
|
||||
cv.allowsMultipleSelection = false
|
||||
rmq(cv).apply_style :collection_view
|
||||
end
|
||||
end
|
||||
|
||||
# Remove if you are only supporting portrait
|
||||
def supportedInterfaceOrientations
|
||||
UIInterfaceOrientationMaskAll
|
||||
end
|
||||
|
||||
# Remove if you are only supporting portrait
|
||||
def willAnimateRotationToInterfaceOrientation(orientation, duration: duration)
|
||||
rmq(:reapply_style).reapply_styles
|
||||
end
|
||||
|
||||
def numberOfSectionsInCollectionView(view)
|
||||
1
|
||||
end
|
||||
|
||||
def collectionView(view, numberOfItemsInSection: section)
|
||||
200
|
||||
end
|
||||
|
||||
def collectionView(view, cellForItemAtIndexPath: index_path)
|
||||
view.dequeueReusableCellWithReuseIdentifier(COLLECTION_CELL_ID, forIndexPath: index_path).tap do |cell|
|
||||
rmq.build(cell) unless cell.reused
|
||||
|
||||
# Update cell's data here
|
||||
end
|
||||
end
|
||||
|
||||
def collectionView(view, didSelectItemAtIndexPath: index_path)
|
||||
cell = view.cellForItemAtIndexPath(index_path)
|
||||
puts "Selected at section: #{index_path.section}, row: #{index_path.row}"
|
||||
end
|
||||
|
||||
end
|
||||
@@ -6,33 +6,43 @@ class MainController < UIViewController
|
||||
rmq.stylesheet = MainStylesheet
|
||||
rmq(self.view).apply_style :root_view
|
||||
|
||||
@title_label = rmq.append(UILabel, :title_label).get
|
||||
init_nav
|
||||
|
||||
rmq.append UIImageView, :logo
|
||||
rmq.append Section
|
||||
|
||||
rmq.append(UIButton, :make_labels_blink).on(:tap) do |sender|
|
||||
rmq(UILabel).animations.blink
|
||||
end
|
||||
|
||||
rmq.append(UIButton.buttonWithType(UIButtonTypeRoundedRect), :make_buttons_throb).on(:tap) do |sender|
|
||||
rmq(UIButton).not(sender).animations.throb
|
||||
end
|
||||
|
||||
rmq.append(Section, :section)
|
||||
|
||||
init_animation_button
|
||||
init_buttons
|
||||
init_benchmark_section
|
||||
end
|
||||
|
||||
# This is if you are supporting multiple orientations
|
||||
def init_nav
|
||||
self.title = 'Title Here'
|
||||
|
||||
self.navigationItem.tap do |nav|
|
||||
nav.leftBarButtonItem = UIBarButtonItem.alloc.initWithBarButtonSystemItem(UIBarButtonSystemItemAction,
|
||||
target: self, action: :nav_left_button)
|
||||
nav.rightBarButtonItem = UIBarButtonItem.alloc.initWithBarButtonSystemItem(UIBarButtonSystemItemRefresh,
|
||||
target: self, action: :nav_right_button)
|
||||
end
|
||||
end
|
||||
|
||||
def nav_left_button
|
||||
puts 'Left button'
|
||||
end
|
||||
|
||||
def nav_right_button
|
||||
puts 'Right button'
|
||||
end
|
||||
|
||||
# Remove if you are only supporting portrait
|
||||
def supportedInterfaceOrientations
|
||||
UIInterfaceOrientationMaskAll
|
||||
end
|
||||
|
||||
# This is if you are supporting multiple orientations
|
||||
# Remove if you are only supporting portrait
|
||||
def willAnimateRotationToInterfaceOrientation(orientation, duration: duration)
|
||||
rmq.all.reapply_styles
|
||||
|
||||
end
|
||||
# You don't have to reapply styles to all UIViews, if you want to optimize,
|
||||
# another way to do it is tag the views you need to restyle in your stylesheet,
|
||||
# then only reapply the tagged views, like so:
|
||||
@@ -46,9 +56,15 @@ class MainController < UIViewController
|
||||
#
|
||||
# Then here in willAnimateRotationToInterfaceOrientation
|
||||
# rmq(:reapply_style).reapply_styles
|
||||
|
||||
def init_buttons
|
||||
rmq.append(UIButton, :make_labels_blink).on(:tap) do |sender|
|
||||
rmq(UILabel).animations.blink
|
||||
end
|
||||
|
||||
def init_animation_button
|
||||
rmq.append(UIButton.buttonWithType(UIButtonTypeRoundedRect), :make_buttons_throb).on(:tap) do |sender|
|
||||
rmq(UIButton).not(sender).animations.throb
|
||||
end
|
||||
|
||||
rmq.append(UIButton, :animate_move).on(:tap) do |sender|
|
||||
rmq(sender).animate( duration: 0.5, animations: -> (rmq) {
|
||||
@@ -63,18 +79,25 @@ class MainController < UIViewController
|
||||
rmq.animate( duration: 0.2, animations: -> (rmq) {
|
||||
rmq.style do |sv|
|
||||
sv.scale = 1.0
|
||||
sv.top = 180
|
||||
sv.top = 230
|
||||
end
|
||||
})
|
||||
})
|
||||
end
|
||||
|
||||
rmq.append(UIButton, :collection).on(:touch_up) do |sender|
|
||||
controller = CollectionController.new
|
||||
self.navigationController.pushViewController(controller, animated: true)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def init_benchmark_section
|
||||
|
||||
rmq.append(UIButton, :run_benchmarks).on(:touch_down) do |sender|
|
||||
rmq.append(UIView, :benchmark_section).tap do |q|
|
||||
|
||||
@title_label = q.append(UILabel, :title_label).get
|
||||
q.append(UIButton, :run_benchmarks).on(:touch_down) do |sender|
|
||||
|
||||
rmq(sender).apply_style(:run_benchmarks_disabled)
|
||||
rmq.animations.start_spinner
|
||||
@@ -94,6 +117,7 @@ class MainController < UIViewController
|
||||
rmq.animations.stop_spinner
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -151,4 +175,3 @@ class MainController < UIViewController
|
||||
out
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ class ApplicationStylesheet < RubyMotionQuery::Stylesheet
|
||||
font_family = 'Helvetica Neue'
|
||||
font.add_named :large, font_family, 36
|
||||
font.add_named :medium, font_family, 24
|
||||
font.add_named :small, font_family, 18
|
||||
font.add_named :small, font_family, 11
|
||||
|
||||
color.add_named :translucent_black, color.from_rgba(0, 0, 0, 0.4)
|
||||
color.add_named :battleship_gray, '#7F7F7F'
|
||||
|
||||
19
app/stylesheets/collection_cell_stylesheet.rb
Normal file
19
app/stylesheets/collection_cell_stylesheet.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
module CollectionCellStylesheet
|
||||
def cell_size
|
||||
{w: 96, h: 96}
|
||||
end
|
||||
|
||||
def collection_cell(st)
|
||||
st.frame = cell_size
|
||||
st.background_color = color.random
|
||||
|
||||
# Style overall view here
|
||||
end
|
||||
|
||||
def title(st)
|
||||
st.frame = :full
|
||||
st.color = color.white
|
||||
st.text_alignment = :center
|
||||
end
|
||||
|
||||
end
|
||||
25
app/stylesheets/collection_controller_stylesheet.rb
Normal file
25
app/stylesheets/collection_controller_stylesheet.rb
Normal file
@@ -0,0 +1,25 @@
|
||||
class CollectionControllerStylesheet < ApplicationStylesheet
|
||||
|
||||
include CollectionCellStylesheet
|
||||
|
||||
def setup
|
||||
# Add sytlesheet specific setup stuff here.
|
||||
# Add application specific setup stuff in application_stylesheet.rb
|
||||
|
||||
@margin = ipad? ? 12 : 8
|
||||
end
|
||||
|
||||
def collection_view(st)
|
||||
st.view.contentInset = [@margin, @margin, @margin, @margin]
|
||||
st.background_color = color.white
|
||||
|
||||
st.view.collectionViewLayout.tap do |cl|
|
||||
cl.itemSize = [cell_size[:w], cell_size[:h]]
|
||||
#cl.scrollDirection = UICollectionViewScrollDirectionHorizontal
|
||||
#cl.headerReferenceSize = [cell_size[:w], cell_size[:h]]
|
||||
cl.minimumInteritemSpacing = @margin
|
||||
cl.minimumLineSpacing = @margin
|
||||
#cl.sectionInsert = [0,0,0,0]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -9,21 +9,14 @@ class MainStylesheet < ApplicationStylesheet
|
||||
end
|
||||
|
||||
def logo(st)
|
||||
st.frame = {t: 20, w: 200, h: 95.5}
|
||||
st.frame = {t: 77, w: 200, h: 95.5}
|
||||
st.centered = :horizontal
|
||||
st.image = image.resource('logo')
|
||||
end
|
||||
|
||||
def title_label(st)
|
||||
label st # stack styles
|
||||
st.frame = {l: PADDING, t: 120, w: 200, h: 20}
|
||||
st.text = 'Test label'
|
||||
st.color = color.from_rgba(34, 132, 198, 1.0)
|
||||
st.font = font.medium
|
||||
end
|
||||
|
||||
def make_labels_blink(st)
|
||||
st.frame = {t: 120, w: 150, h: 20}
|
||||
st.frame = {t: 180, w: 150, h: 20}
|
||||
st.from_right = PADDING
|
||||
|
||||
# ipad? (and landscape?, etc) is just a convenience methods for
|
||||
@@ -57,12 +50,33 @@ class MainStylesheet < ApplicationStylesheet
|
||||
end
|
||||
|
||||
def make_buttons_throb(st)
|
||||
st.frame = {t: 150, w: 150, h: 20}
|
||||
st.frame = {t: 205, w: 150, h: 20}
|
||||
st.from_right = PADDING
|
||||
st.text = 'Throb buttons'
|
||||
st.color = color.black
|
||||
end
|
||||
|
||||
def animate_move(st)
|
||||
st.scale = 1.0
|
||||
st.frame = {t: 230, w: 150, h: 20}
|
||||
st.from_right = PADDING
|
||||
st.text = 'Animate move and scale'
|
||||
st.font = font.system(10)
|
||||
st.color = color.white
|
||||
st.background_color = color.from_hex('ed1160')
|
||||
st.z_position = 99
|
||||
st.color = color.white
|
||||
end
|
||||
|
||||
def collection(st)
|
||||
st.frame = {t: 260, w: 150, h: 20}
|
||||
st.from_right = PADDING
|
||||
st.background_color = color.black
|
||||
st.font = font.small
|
||||
st.text = 'Collection View'
|
||||
end
|
||||
|
||||
|
||||
def section(st)
|
||||
st.frame = {w: 270, h: 110}
|
||||
|
||||
@@ -128,16 +142,33 @@ class MainStylesheet < ApplicationStylesheet
|
||||
st.color = color.white
|
||||
end
|
||||
|
||||
def animate_move(st)
|
||||
st.scale = 1.0
|
||||
st.frame = {t: 180, w: 150, h: 20}
|
||||
st.from_right = PADDING
|
||||
st.text = 'Animate move and scale'
|
||||
st.font = font.system(10)
|
||||
st.color = color.white
|
||||
st.background_color = color.from_hex('ed1160')
|
||||
st.z_position = 99
|
||||
st.color = color.white
|
||||
def benchmark_section(st)
|
||||
t = (landscape? && iphone?) ? 100 : 180
|
||||
st.frame = {l: PADDING, t: t, w: 100 + (PADDING * 2), h: 60}
|
||||
st.background_color = color.from_hex('faa619')
|
||||
end
|
||||
|
||||
def run_benchmarks(st)
|
||||
st.frame = {l: PADDING, t: 30, w: 100, h: 20}
|
||||
st.text = 'Run benchmarks'
|
||||
st.font = font.system(11)
|
||||
st.color = color.from_hex('faa619')
|
||||
st.enabled = true
|
||||
st.background_color = color.white
|
||||
end
|
||||
|
||||
def run_benchmarks_disabled(st)
|
||||
st.enabled = false
|
||||
st.color = color.from_hex('de8714')
|
||||
end
|
||||
|
||||
def title_label(st)
|
||||
label st # stack styles
|
||||
st.frame = {l: PADDING, t: PADDING, w: 100, h: 15}
|
||||
|
||||
st.text = 'Test label'
|
||||
st.color = color.from_rgba(34, 132, 198, 1.0)
|
||||
st.font = font.small
|
||||
end
|
||||
|
||||
def overlay(st)
|
||||
@@ -168,20 +199,6 @@ class MainStylesheet < ApplicationStylesheet
|
||||
st.view.lineBreakMode = NSLineBreakByWordWrapping
|
||||
end
|
||||
|
||||
def run_benchmarks(st)
|
||||
st.frame = {l: PADDING, t: 150, w: 130, h: 20}
|
||||
st.text = 'Run benchmarks'
|
||||
st.font = font.system(11)
|
||||
st.color = color.white
|
||||
st.enabled = true
|
||||
st.background_color = color.from_hex('faa619')
|
||||
end
|
||||
|
||||
def run_benchmarks_disabled(st)
|
||||
st.enabled = false
|
||||
st.color = color.from_hex('de8714')
|
||||
end
|
||||
|
||||
def benchmark(st)
|
||||
st.hidden = false
|
||||
st.text = 'foo'
|
||||
|
||||
15
app/views/collection_cell.rb
Normal file
15
app/views/collection_cell.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
class CollectionCell < UICollectionViewCell
|
||||
attr_reader :reused
|
||||
|
||||
def rmq_build
|
||||
rmq(self).apply_style :collection_cell
|
||||
|
||||
rmq(self.contentView).tap do |q|
|
||||
q.append(UILabel, :title).get.text = rand(100).to_s
|
||||
end
|
||||
end
|
||||
|
||||
def prepareForReuse
|
||||
@reused = true
|
||||
end
|
||||
end
|
||||
@@ -1,22 +1,26 @@
|
||||
class Section < UIView
|
||||
|
||||
def rmq_created_or_appended
|
||||
rmq.append(UILabel, :section_title)
|
||||
def rmq_build
|
||||
rmq(self).tap do |q|
|
||||
q.apply_style :section
|
||||
|
||||
rmq.append(UILabel, :section_enabled_title)
|
||||
q.append(UILabel, :section_title)
|
||||
|
||||
rmq.append(UISwitch, :section_enabled).on(:change) do |sender|
|
||||
q.append(UILabel, :section_enabled_title)
|
||||
|
||||
q.append(UISwitch, :section_enabled).on(:change) do |sender|
|
||||
style = sender.isOn ? :section_button_enabled : :section_button_disabled
|
||||
buttons = rmq(sender).parent.find(UIButton).apply_style(style)
|
||||
end
|
||||
|
||||
rmq.append(UIButton, :start_spinner).on(:tap) do |sender|
|
||||
q.append(UIButton, :start_spinner).on(:tap) do |sender|
|
||||
rmq.animations.start_spinner
|
||||
end
|
||||
|
||||
rmq.append(UIButton, :stop_spinner).on(:tap) do |sender|
|
||||
q.append(UIButton, :stop_spinner).on(:tap) do |sender|
|
||||
rmq.animations.stop_spinner
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -11,14 +11,17 @@ class UIView
|
||||
@_rmq_data ||= RubyMotionQuery::ViewData.new
|
||||
end
|
||||
|
||||
# @deprecated No longer needed, use rmq_created_or_appended
|
||||
# @deprecated No longer needed, use rmq_build
|
||||
def rmq_did_create(self_in_rmq)
|
||||
end
|
||||
def rmq_created
|
||||
end
|
||||
def rmq_appended
|
||||
|
||||
# Override this to build your view and view's subviews
|
||||
def rmq_build
|
||||
end
|
||||
def rmq_created_or_appended
|
||||
|
||||
def rmq_appended
|
||||
end
|
||||
|
||||
# I intend for this to be protected
|
||||
@@ -39,10 +42,10 @@ end
|
||||
|
||||
class UIViewController
|
||||
def rmq(*selectors)
|
||||
if RubyMotionQuery::RMQ.cache_controller_rmqs && selectors.length == 0
|
||||
rmq_data.rmq ||= RubyMotionQuery::RMQ.create_with_selectors(selectors, self)
|
||||
if selectors.length == 0
|
||||
rmq_data.cached_rmq ||= RubyMotionQuery::RMQ.create_with_selectors(selectors, self)
|
||||
else
|
||||
RubyMotionQuery::RMQ.create_with_selectors(selectors, self, rmq_data.rmq)
|
||||
RubyMotionQuery::RMQ.create_with_selectors(selectors, self, rmq_data.cached_rmq)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -292,9 +292,6 @@ module RubyMotionQuery
|
||||
end
|
||||
|
||||
class << self
|
||||
attr_accessor :cache_controller_rmqs
|
||||
@cache_controller_rmqs = true
|
||||
|
||||
def debugging?
|
||||
@debugging ||= ENV['rmq_debug'] == 'true'
|
||||
end
|
||||
|
||||
@@ -54,6 +54,6 @@ module RubyMotionQuery
|
||||
end
|
||||
|
||||
class ControllerData
|
||||
attr_accessor :stylesheet, :rmq
|
||||
attr_accessor :stylesheet, :cached_rmq
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
module RubyMotionQuery
|
||||
class RMQ
|
||||
|
||||
# TODO
|
||||
def create_factory(klass)
|
||||
# TODO
|
||||
end
|
||||
|
||||
# This is used internally, to get a new rmq instance, just call "rmq" in your view or controller or
|
||||
# just create a new one like so: RubyMotionQuery::RMQ.new
|
||||
#
|
||||
@@ -51,4 +45,5 @@ module RubyMotionQuery
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -49,8 +49,8 @@ module RubyMotionQuery
|
||||
new_view.rmq_did_create(self.wrap(new_view))
|
||||
new_view.rmq_created
|
||||
end
|
||||
new_view.rmq_build
|
||||
new_view.rmq_appended if appended
|
||||
new_view.rmq_created_or_appended
|
||||
end
|
||||
|
||||
RMQ.create_with_array_and_selectors(subviews_added, selectors, @context, self)
|
||||
@@ -97,6 +97,24 @@ module RubyMotionQuery
|
||||
add_subview view_or_constant, opts
|
||||
end
|
||||
|
||||
# Build a view, similar to create and append, but only inits an existing view. Usefull
|
||||
# in collectionview cells for example
|
||||
#
|
||||
# @example
|
||||
# # In your collectionview
|
||||
# rmq.build(cell) unless cell.reused
|
||||
#
|
||||
# # Then in your cell
|
||||
#
|
||||
# def rmq_build
|
||||
# rmq.append(UIView, :foo)
|
||||
# end
|
||||
def build(view, style = nil, opts = {})
|
||||
opts[:do_not_add] = true
|
||||
opts[:style] = style
|
||||
add_subview view, opts
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def create_view(klass, opts)
|
||||
|
||||
@@ -275,7 +275,9 @@ module RubyMotionQuery
|
||||
if self.parent_rmq && vc = self.parent_rmq.view_controller
|
||||
vc
|
||||
else
|
||||
RMQ.app.current_view_controller
|
||||
vc = RMQ.app.current_view_controller
|
||||
@context.rmq_data.view_controller = vc if @context
|
||||
vc
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -61,7 +61,7 @@ describe 'app' do
|
||||
|
||||
describe 'app - current_view_controller' do
|
||||
it 'should return current_view_controller from current window' do
|
||||
rmq.app.current_view_controller.should == rmq.app.window.rootViewController
|
||||
rmq.app.current_view_controller.should == rmq.app.window.rootViewController.visibleViewController
|
||||
end
|
||||
|
||||
it 'should return current_view_controller when presenting a new controller' do
|
||||
|
||||
9
spec/controllers/collection_controller.rb
Normal file
9
spec/controllers/collection_controller.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
describe 'CollectionController' do
|
||||
|
||||
before do
|
||||
end
|
||||
|
||||
after do
|
||||
end
|
||||
|
||||
end
|
||||
@@ -14,8 +14,8 @@ describe 'rmq_data' do
|
||||
vc.rmq_data.stylesheet.should == :foo
|
||||
|
||||
q = vc.rmq
|
||||
vc.rmq_data.rmq = q
|
||||
vc.rmq_data.rmq.should == q
|
||||
vc.rmq_data.cached_rmq = q
|
||||
vc.rmq_data.cached_rmq.should == q
|
||||
|
||||
vc.view.rmq_data.tap do |q_data|
|
||||
q_data.style_name = :style_name
|
||||
|
||||
25
spec/ext.rb
25
spec/ext.rb
@@ -54,36 +54,43 @@ describe 'ext' do
|
||||
view.controller.should == vc
|
||||
view.created.should == true
|
||||
view.appended.nil?.should == true
|
||||
view.created_or_appended.should == true
|
||||
view.built.should == true
|
||||
end
|
||||
|
||||
it 'should call rmq_created_or_appended and rmq_appended after appending a view' do
|
||||
it 'should call rmq_build and rmq_appended after appending a view' do
|
||||
vc = UIViewController.alloc.init
|
||||
view = vc.rmq.append(ExtTestView).get
|
||||
view.controller.should == vc
|
||||
view.created.should == true
|
||||
view.appended.should == true
|
||||
view.created_or_appended.should == true
|
||||
view.built.should == true
|
||||
end
|
||||
|
||||
it 'should call rmq_created_or_appended and rmq_appended after appending a existing view' do
|
||||
it 'should call rmq_build and rmq_appended after appending a existing view' do
|
||||
vc = UIViewController.alloc.init
|
||||
v = ExtTestView.alloc.initWithFrame(CGRectZero)
|
||||
v.created.nil?.should == true
|
||||
v.appended.nil?.should == true
|
||||
v.created_or_appended.nil?.should == true
|
||||
v.built.nil?.should == true
|
||||
v.controller.nil?.should == true
|
||||
|
||||
view = vc.rmq.append(v).get
|
||||
view.controller.should == vc
|
||||
view.created.nil?.should == true
|
||||
view.appended.should == true
|
||||
view.created_or_appended.should == true
|
||||
view.built.should == true
|
||||
end
|
||||
|
||||
it 'should call rmq_build after calling build on a view' do
|
||||
v = ExtTestView.alloc.initWithFrame(CGRectZero)
|
||||
v.built.should == nil
|
||||
rmq.build(v)
|
||||
v.built.should == true
|
||||
end
|
||||
end
|
||||
|
||||
class ExtTestView < UIView
|
||||
attr_accessor :controller, :created, :appended, :created_or_appended
|
||||
attr_accessor :controller, :created, :appended, :built
|
||||
def rmq_did_create(rmq)
|
||||
@controller = rmq.view_controller
|
||||
end
|
||||
@@ -98,9 +105,9 @@ class ExtTestView < UIView
|
||||
@appended = true
|
||||
end
|
||||
|
||||
def rmq_created_or_appended
|
||||
def rmq_build
|
||||
@controller = rmq.view_controller
|
||||
@created_or_appended = true
|
||||
@built = true
|
||||
end
|
||||
|
||||
def get_context
|
||||
|
||||
@@ -156,6 +156,44 @@ describe 'subviews' do
|
||||
test_view.subview.backgroundColor.should == RubyMotionQuery::Color.orange
|
||||
end
|
||||
end
|
||||
|
||||
describe 'build' do
|
||||
it 'should allow you to build a existing view without creating or appending it to the view tree' do
|
||||
my_view = SubviewTestView.alloc.initWithFrame(CGRectZero)
|
||||
test_view_wrapped = @vc.rmq.build(my_view)
|
||||
test_view = test_view_wrapped.get
|
||||
|
||||
test_view.superview.nil?.should == true
|
||||
test_view.nextResponder.nil?.should == true
|
||||
test_view.get_context.should == test_view
|
||||
end
|
||||
|
||||
it 'should allow you to build an existing view with a style, and it to use the stylesheet of view_controller that created it' do
|
||||
my_view = UILabel.alloc.initWithFrame(CGRectZero)
|
||||
@vc.rmq.stylesheet = SyleSheetForSubviewsTests
|
||||
test_view = @vc.rmq.build(my_view, :create_view_style).get
|
||||
test_view.backgroundColor.should == RubyMotionQuery::Color.blue
|
||||
end
|
||||
|
||||
it 'should allow you to build a view outside any view tree, then append subviews and those should use the stylesheet from the rmq that created the parent view' do
|
||||
q = @vc.rmq
|
||||
q.stylesheet = SyleSheetForSubviewsTests
|
||||
my_view = SubviewTestView.alloc.initWithFrame(CGRectZero)
|
||||
test_view_wrapped = q.build(my_view)
|
||||
test_view = test_view_wrapped.get
|
||||
|
||||
test_view_wrapped.parent_rmq.should == q
|
||||
|
||||
test_view_wrapped.wrap(test_view).parent_rmq.parent_rmq.should == q
|
||||
|
||||
sv = test_view.build_subview
|
||||
test_view_wrapped.children.first.get.should == sv
|
||||
test_view.subviews.first.should == sv
|
||||
|
||||
test_view.build_subview.rmq_data.style_name.should == :create_sub_view_style
|
||||
test_view.build_subview.backgroundColor.should == RubyMotionQuery::Color.orange
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class SyleSheetForSubviewsTests < RubyMotionQuery::Stylesheet
|
||||
@@ -172,7 +210,11 @@ class SyleSheetForSubviewsTests < RubyMotionQuery::Stylesheet
|
||||
end
|
||||
|
||||
class SubviewTestView < UIView
|
||||
attr_accessor :subview
|
||||
attr_accessor :subview, :build_subview
|
||||
|
||||
def rmq_build
|
||||
@build_subview = rmq.append(UIView, :create_sub_view_style).get
|
||||
end
|
||||
|
||||
def rmq_created
|
||||
@subview = rmq.append(UIView, :create_sub_view_style).get
|
||||
|
||||
@@ -309,7 +309,7 @@ describe 'transversing' do
|
||||
view_4 = UIView.alloc.initWithFrame(CGRectZero)
|
||||
|
||||
q = RubyMotionQuery::RMQ.new
|
||||
q.wrap(view_4).view_controller.should == q.app.window.rootViewController
|
||||
q.wrap(view_4).view_controller.should == q.app.window.rootViewController.visibleViewController
|
||||
end
|
||||
|
||||
it 'should be located from any view if the view is in subview tree of a controller' do
|
||||
@@ -343,6 +343,13 @@ describe 'transversing' do
|
||||
view_2.rmq_data.view_controller = @vc2
|
||||
RubyMotionQuery::RMQ.new.wrap(view_2).view_controller.should == @vc2
|
||||
end
|
||||
|
||||
it 'should assign a found controller to a view that didn\'t have one' do
|
||||
orphan_view = UIView.alloc.initWithFrame(CGRectZero)
|
||||
orphan_view.rmq_data.view_controller.should == nil
|
||||
vc = orphan_view.rmq.view_controller
|
||||
orphan_view.rmq_data.view_controller.should == vc
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
9
spec/views/collection_cell.rb
Normal file
9
spec/views/collection_cell.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
describe 'CollectionCell' do
|
||||
|
||||
before do
|
||||
end
|
||||
|
||||
after do
|
||||
end
|
||||
|
||||
end
|
||||
@@ -49,7 +49,7 @@ class <%= @name_camel_case %>Controller < UICollectionViewController
|
||||
|
||||
def collectionView(view, cellForItemAtIndexPath: index_path)
|
||||
view.dequeueReusableCellWithReuseIdentifier(<%= @name.upcase %>_CELL_ID, forIndexPath: index_path).tap do |cell|
|
||||
cell.setup_with(rmq)
|
||||
rmq.build(cell) unless cell.reused
|
||||
|
||||
# Update cell's data here
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module <%= @name_camel_case %>CellStylesheet
|
||||
def cell_size
|
||||
[96, 96]
|
||||
{w: 96, h: 96}
|
||||
end
|
||||
|
||||
def <%= @name %>_cell(st)
|
||||
|
||||
@@ -14,9 +14,9 @@ class <%= @name_camel_case %>ControllerStylesheet < ApplicationStylesheet
|
||||
st.background_color = color.white
|
||||
|
||||
st.view.collectionViewLayout.tap do |cl|
|
||||
cl.itemSize = cell_size
|
||||
cl.itemSize = [cell_size[:w], cell_size[:h]]
|
||||
#cl.scrollDirection = UICollectionViewScrollDirectionHorizontal
|
||||
#cl.headerReferenceSize = cell_size
|
||||
#cl.headerReferenceSize = [cell_size[:w], cell_size[:h]]
|
||||
cl.minimumInteritemSpacing = @margin
|
||||
cl.minimumLineSpacing = @margin
|
||||
#cl.sectionInsert = [0,0,0,0]
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
class <%= @name_camel_case %>Cell < UICollectionViewCell
|
||||
def setup_with(controller_rmq)
|
||||
unless @initialized
|
||||
@initialized = true
|
||||
attr_reader :reused
|
||||
|
||||
controller_rmq.wrap(self).tap do |q|
|
||||
q.apply_style :<%= @name %>_cell
|
||||
def rmq_build
|
||||
rmq(self).apply_style :<%= @name %>_cell
|
||||
|
||||
rmq(self.contentView).tap do |q|
|
||||
# Add your subviews, init stuff here
|
||||
# @foo = q.append(UILabel, :foo).get
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def prepareForReuse
|
||||
@reused = true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
class <%= @name_camel_case %>ControllerStylesheet < ApplicationStylesheet
|
||||
# Add your view stylesheets here. You can then override styles if needed, example:
|
||||
# include FooStylesheet
|
||||
|
||||
def setup
|
||||
# Add sytlesheet specific setup stuff here.
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
class <%= @name_camel_case %> < UIView
|
||||
|
||||
def rmq_did_create(self_in_rmq)
|
||||
def rmq_build
|
||||
|
||||
self_in_rmq.tap do |q|
|
||||
q.apply_style :<%= @name %>
|
||||
rmq.apply_style :<%= @name %>
|
||||
|
||||
# Add subviews here, like so:
|
||||
#q.append(UILabel, :some_label)
|
||||
end
|
||||
#rmq.append(UILabel, :some_label)
|
||||
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user