Finished v0.5, new view_controller system. Beta testing now.

This commit is contained in:
Todd Werth
2013-12-06 22:18:35 -08:00
parent 68ecf0245a
commit 8e2e714b71
29 changed files with 449 additions and 164 deletions

View File

@@ -83,6 +83,12 @@ for **bleeding edge**, add this to your `Gemfile`:
- `gem 'ruby_motion_query', :git => 'git@github.com:infinitered/rmq.git'` - `gem 'ruby_motion_query', :git => 'git@github.com:infinitered/rmq.git'`
## Deprecation
- **UIView#rmq_did_create(self_in_rmq)** - *Use rmq_build instead*
## Usage ## Usage
### Example App ### Example App
@@ -418,8 +424,8 @@ end
# Your cell # Your cell
class StoreCell < UITableViewCell class StoreCell < UITableViewCell
def rmq_did_create(self_in_rmq) def rmq_build
self_in_rmq.append(UILabel, :title_label) # <- this works even though this object isn't in a controller rmq(self).append(UILabel, :title_label) # <- this works even though this object isn't in a controller
end end
end end
``` ```
@@ -610,16 +616,17 @@ RubyMotionQuery::RMQ.view_to_s(view)
The following are the only pollution in RMQ The following are the only pollution in RMQ
- UIView - UIView
- rmq - rmq
- rmq_data - rmq_data
- UIViewController - UIViewController
- rmq - rmq
- rmq_data - rmq_data
- TopLevel *(Only in development, used for console)* - Object
- rmq - rmq
### Console Fun ### Console Fun
rmq.log :tree
rmq.all.log rmq.all.log
rmq.all.log :wide rmq.all.log :wide
rmq(UIView).show 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 ### 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 ```ruby
def rmq_created_or_appended def rmq_build
end
def rmq_created
end
def rmq_appended
end 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 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. order.
```ruby ```ruby
# Your view # Your view
class YourView < UIView class YourView < UIView
def rmq_created_or_appended def rmq_build
rmq(self).tap do |q| rmq(self).tap do |q|
q.append(UILabel, :section_title) q.append(UILabel, :section_title)
q.append(UIButton, :buy_button).on(:tap) do |sender| q.append(UIButton, :buy_button).on(:tap) do |sender|
@@ -1112,7 +1133,19 @@ rmq.append(YourView, :your_style)
### Future features ### 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: Ive 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 doesnt 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 dont 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 - 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}} - add borders to UIView styler: st.borders = {l: {w: 2, color: color.black}, r: {w: 2, color: color.black}}

View File

@@ -1,9 +1,11 @@
class AppDelegate class AppDelegate
attr_reader :window
def application(application, didFinishLaunchingWithOptions:launchOptions) def application(application, didFinishLaunchingWithOptions:launchOptions)
@window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds) @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
main_controller = MainController.alloc.initWithNibName(nil, bundle: nil) main_controller = MainController.alloc.initWithNibName(nil, bundle: nil)
@window.rootViewController = main_controller @window.rootViewController = UINavigationController.alloc.initWithRootViewController(main_controller)
@window.makeKeyAndVisible @window.makeKeyAndVisible
true true

View 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

View File

@@ -1,4 +1,4 @@
class MainController < UIViewController class MainController < UIViewController
def viewDidLoad def viewDidLoad
super super
@@ -6,10 +6,58 @@ class MainController < UIViewController
rmq.stylesheet = MainStylesheet rmq.stylesheet = MainStylesheet
rmq(self.view).apply_style :root_view rmq(self.view).apply_style :root_view
@title_label = rmq.append(UILabel, :title_label).get init_nav
rmq.append UIImageView, :logo rmq.append UIImageView, :logo
rmq.append Section
init_buttons
init_benchmark_section
end
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
# 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:
#
# def logo(st)
# st.frame = {t: 10, w: 200, h: 96}
# st.centered = :horizontal
# st.image = image.resource('logo')
# st.tag(:reapply_style)
# end
#
# Then here in willAnimateRotationToInterfaceOrientation
# rmq(:reapply_style).reapply_styles
def init_buttons
rmq.append(UIButton, :make_labels_blink).on(:tap) do |sender| rmq.append(UIButton, :make_labels_blink).on(:tap) do |sender|
rmq(UILabel).animations.blink rmq(UILabel).animations.blink
end end
@@ -18,38 +66,6 @@ class MainController < UIViewController
rmq(UIButton).not(sender).animations.throb rmq(UIButton).not(sender).animations.throb
end end
rmq.append(Section, :section)
init_animation_button
init_benchmark_section
end
# This is if you are supporting multiple orientations
def supportedInterfaceOrientations
UIInterfaceOrientationMaskAll
end
# This is if you are supporting multiple orientations
def willAnimateRotationToInterfaceOrientation(orientation, duration: duration)
rmq.all.reapply_styles
# 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:
#
# def logo(st)
# st.frame = {t: 10, w: 200, h: 96}
# st.centered = :horizontal
# st.image = image.resource('logo')
# st.tag(:reapply_style)
# end
#
# Then here in willAnimateRotationToInterfaceOrientation
# rmq(:reapply_style).reapply_styles
end
def init_animation_button
rmq.append(UIButton, :animate_move).on(:tap) do |sender| rmq.append(UIButton, :animate_move).on(:tap) do |sender|
rmq(sender).animate( duration: 0.5, animations: -> (rmq) { rmq(sender).animate( duration: 0.5, animations: -> (rmq) {
# You really should create a new style in the stylesheet, # You really should create a new style in the stylesheet,
@@ -63,36 +79,44 @@ class MainController < UIViewController
rmq.animate( duration: 0.2, animations: -> (rmq) { rmq.animate( duration: 0.2, animations: -> (rmq) {
rmq.style do |sv| rmq.style do |sv|
sv.scale = 1.0 sv.scale = 1.0
sv.top = 180 sv.top = 230
end end
}) })
}) })
end end
rmq.append(UIButton, :collection).on(:touch_up) do |sender|
controller = CollectionController.new
self.navigationController.pushViewController(controller, animated: true)
end
end end
def init_benchmark_section def init_benchmark_section
rmq.append(UIView, :benchmark_section).tap do |q|
rmq.append(UIButton, :run_benchmarks).on(:touch_down) do |sender| @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(sender).apply_style(:run_benchmarks_disabled)
rmq.animations.start_spinner rmq.animations.start_spinner
rmq.append(UIView, :overlay).animations.fade_in.on(:tap) do |sender|
rmq.find(:benchmarks_results_label, :benchmarks_results_wrapper, sender).hide.remove
end
end.on(:touch_up) do |sender|
rmq.append(UILabel, :benchmarks_results_wrapper).tap do |o|
o.animations.fade_in
o.append(UILabel, :benchmarks_results_label).get.text = self.benchmark
end
rmq(sender).apply_style(:run_benchmarks)
rmq.animations.stop_spinner
rmq.append(UIView, :overlay).animations.fade_in.on(:tap) do |sender|
rmq.find(:benchmarks_results_label, :benchmarks_results_wrapper, sender).hide.remove
end end
end.on(:touch_up) do |sender|
rmq.append(UILabel, :benchmarks_results_wrapper).tap do |o|
o.animations.fade_in
o.append(UILabel, :benchmarks_results_label).get.text = self.benchmark
end
rmq(sender).apply_style(:run_benchmarks)
rmq.animations.stop_spinner
end end
end end
@@ -151,4 +175,3 @@ class MainController < UIViewController
out out
end end
end end

View File

@@ -5,7 +5,7 @@ class ApplicationStylesheet < RubyMotionQuery::Stylesheet
font_family = 'Helvetica Neue' font_family = 'Helvetica Neue'
font.add_named :large, font_family, 36 font.add_named :large, font_family, 36
font.add_named :medium, font_family, 24 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 :translucent_black, color.from_rgba(0, 0, 0, 0.4)
color.add_named :battleship_gray, '#7F7F7F' color.add_named :battleship_gray, '#7F7F7F'

View 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

View 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

View File

@@ -9,21 +9,14 @@ class MainStylesheet < ApplicationStylesheet
end end
def logo(st) 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.centered = :horizontal
st.image = image.resource('logo') st.image = image.resource('logo')
end 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) 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 st.from_right = PADDING
# ipad? (and landscape?, etc) is just a convenience methods for # ipad? (and landscape?, etc) is just a convenience methods for
@@ -57,12 +50,33 @@ class MainStylesheet < ApplicationStylesheet
end end
def make_buttons_throb(st) 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.from_right = PADDING
st.text = 'Throb buttons' st.text = 'Throb buttons'
st.color = color.black st.color = color.black
end 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) def section(st)
st.frame = {w: 270, h: 110} st.frame = {w: 270, h: 110}
@@ -128,16 +142,33 @@ class MainStylesheet < ApplicationStylesheet
st.color = color.white st.color = color.white
end end
def animate_move(st) def benchmark_section(st)
st.scale = 1.0 t = (landscape? && iphone?) ? 100 : 180
st.frame = {t: 180, w: 150, h: 20} st.frame = {l: PADDING, t: t, w: 100 + (PADDING * 2), h: 60}
st.from_right = PADDING st.background_color = color.from_hex('faa619')
st.text = 'Animate move and scale' end
st.font = font.system(10)
st.color = color.white def run_benchmarks(st)
st.background_color = color.from_hex('ed1160') st.frame = {l: PADDING, t: 30, w: 100, h: 20}
st.z_position = 99 st.text = 'Run benchmarks'
st.color = color.white 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 end
def overlay(st) def overlay(st)
@@ -168,20 +199,6 @@ class MainStylesheet < ApplicationStylesheet
st.view.lineBreakMode = NSLineBreakByWordWrapping st.view.lineBreakMode = NSLineBreakByWordWrapping
end 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) def benchmark(st)
st.hidden = false st.hidden = false
st.text = 'foo' st.text = 'foo'

View 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

View File

@@ -1,21 +1,25 @@
class Section < UIView class Section < UIView
def rmq_created_or_appended def rmq_build
rmq.append(UILabel, :section_title) 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)
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(UISwitch, :section_enabled).on(:change) do |sender|
rmq.animations.start_spinner style = sender.isOn ? :section_button_enabled : :section_button_disabled
end buttons = rmq(sender).parent.find(UIButton).apply_style(style)
end
rmq.append(UIButton, :stop_spinner).on(:tap) do |sender| q.append(UIButton, :start_spinner).on(:tap) do |sender|
rmq.animations.stop_spinner rmq.animations.start_spinner
end
q.append(UIButton, :stop_spinner).on(:tap) do |sender|
rmq.animations.stop_spinner
end
end end
end end

View File

@@ -11,14 +11,17 @@ class UIView
@_rmq_data ||= RubyMotionQuery::ViewData.new @_rmq_data ||= RubyMotionQuery::ViewData.new
end end
# @deprecated No longer needed, use rmq_created_or_appended # @deprecated No longer needed, use rmq_build
def rmq_did_create(self_in_rmq) def rmq_did_create(self_in_rmq)
end end
def rmq_created def rmq_created
end end
def rmq_appended
# Override this to build your view and view's subviews
def rmq_build
end end
def rmq_created_or_appended
def rmq_appended
end end
# I intend for this to be protected # I intend for this to be protected
@@ -39,10 +42,10 @@ end
class UIViewController class UIViewController
def rmq(*selectors) def rmq(*selectors)
if RubyMotionQuery::RMQ.cache_controller_rmqs && selectors.length == 0 if selectors.length == 0
rmq_data.rmq ||= RubyMotionQuery::RMQ.create_with_selectors(selectors, self) rmq_data.cached_rmq ||= RubyMotionQuery::RMQ.create_with_selectors(selectors, self)
else else
RubyMotionQuery::RMQ.create_with_selectors(selectors, self, rmq_data.rmq) RubyMotionQuery::RMQ.create_with_selectors(selectors, self, rmq_data.cached_rmq)
end end
end end

View File

@@ -292,9 +292,6 @@ module RubyMotionQuery
end end
class << self class << self
attr_accessor :cache_controller_rmqs
@cache_controller_rmqs = true
def debugging? def debugging?
@debugging ||= ENV['rmq_debug'] == 'true' @debugging ||= ENV['rmq_debug'] == 'true'
end end

View File

@@ -54,6 +54,6 @@ module RubyMotionQuery
end end
class ControllerData class ControllerData
attr_accessor :stylesheet, :rmq attr_accessor :stylesheet, :cached_rmq
end end
end end

View File

@@ -1,11 +1,5 @@
module RubyMotionQuery module RubyMotionQuery
class RMQ 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 # 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 # just create a new one like so: RubyMotionQuery::RMQ.new
# #
@@ -51,4 +45,5 @@ module RubyMotionQuery
end end
end end
end end

View File

@@ -49,8 +49,8 @@ module RubyMotionQuery
new_view.rmq_did_create(self.wrap(new_view)) new_view.rmq_did_create(self.wrap(new_view))
new_view.rmq_created new_view.rmq_created
end end
new_view.rmq_build
new_view.rmq_appended if appended new_view.rmq_appended if appended
new_view.rmq_created_or_appended
end end
RMQ.create_with_array_and_selectors(subviews_added, selectors, @context, self) RMQ.create_with_array_and_selectors(subviews_added, selectors, @context, self)
@@ -97,6 +97,24 @@ module RubyMotionQuery
add_subview view_or_constant, opts add_subview view_or_constant, opts
end 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 protected
def create_view(klass, opts) def create_view(klass, opts)

View File

@@ -275,7 +275,9 @@ module RubyMotionQuery
if self.parent_rmq && vc = self.parent_rmq.view_controller if self.parent_rmq && vc = self.parent_rmq.view_controller
vc vc
else else
RMQ.app.current_view_controller vc = RMQ.app.current_view_controller
@context.rmq_data.view_controller = vc if @context
vc
end end
end end
end end

View File

@@ -61,7 +61,7 @@ describe 'app' do
describe 'app - current_view_controller' do describe 'app - current_view_controller' do
it 'should return current_view_controller from current window' 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 end
it 'should return current_view_controller when presenting a new controller' do it 'should return current_view_controller when presenting a new controller' do

View File

@@ -0,0 +1,9 @@
describe 'CollectionController' do
before do
end
after do
end
end

View File

@@ -14,8 +14,8 @@ describe 'rmq_data' do
vc.rmq_data.stylesheet.should == :foo vc.rmq_data.stylesheet.should == :foo
q = vc.rmq q = vc.rmq
vc.rmq_data.rmq = q vc.rmq_data.cached_rmq = q
vc.rmq_data.rmq.should == q vc.rmq_data.cached_rmq.should == q
vc.view.rmq_data.tap do |q_data| vc.view.rmq_data.tap do |q_data|
q_data.style_name = :style_name q_data.style_name = :style_name

View File

@@ -54,36 +54,43 @@ describe 'ext' do
view.controller.should == vc view.controller.should == vc
view.created.should == true view.created.should == true
view.appended.nil?.should == true view.appended.nil?.should == true
view.created_or_appended.should == true view.built.should == true
end 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 vc = UIViewController.alloc.init
view = vc.rmq.append(ExtTestView).get view = vc.rmq.append(ExtTestView).get
view.controller.should == vc view.controller.should == vc
view.created.should == true view.created.should == true
view.appended.should == true view.appended.should == true
view.created_or_appended.should == true view.built.should == true
end 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 vc = UIViewController.alloc.init
v = ExtTestView.alloc.initWithFrame(CGRectZero) v = ExtTestView.alloc.initWithFrame(CGRectZero)
v.created.nil?.should == true v.created.nil?.should == true
v.appended.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 v.controller.nil?.should == true
view = vc.rmq.append(v).get view = vc.rmq.append(v).get
view.controller.should == vc view.controller.should == vc
view.created.nil?.should == true view.created.nil?.should == true
view.appended.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
end end
class ExtTestView < UIView class ExtTestView < UIView
attr_accessor :controller, :created, :appended, :created_or_appended attr_accessor :controller, :created, :appended, :built
def rmq_did_create(rmq) def rmq_did_create(rmq)
@controller = rmq.view_controller @controller = rmq.view_controller
end end
@@ -98,9 +105,9 @@ class ExtTestView < UIView
@appended = true @appended = true
end end
def rmq_created_or_appended def rmq_build
@controller = rmq.view_controller @controller = rmq.view_controller
@created_or_appended = true @built = true
end end
def get_context def get_context

View File

@@ -156,6 +156,44 @@ describe 'subviews' do
test_view.subview.backgroundColor.should == RubyMotionQuery::Color.orange test_view.subview.backgroundColor.should == RubyMotionQuery::Color.orange
end end
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 end
class SyleSheetForSubviewsTests < RubyMotionQuery::Stylesheet class SyleSheetForSubviewsTests < RubyMotionQuery::Stylesheet
@@ -172,7 +210,11 @@ class SyleSheetForSubviewsTests < RubyMotionQuery::Stylesheet
end end
class SubviewTestView < UIView 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 def rmq_created
@subview = rmq.append(UIView, :create_sub_view_style).get @subview = rmq.append(UIView, :create_sub_view_style).get

View File

@@ -309,7 +309,7 @@ describe 'transversing' do
view_4 = UIView.alloc.initWithFrame(CGRectZero) view_4 = UIView.alloc.initWithFrame(CGRectZero)
q = RubyMotionQuery::RMQ.new 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 end
it 'should be located from any view if the view is in subview tree of a controller' do 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 view_2.rmq_data.view_controller = @vc2
RubyMotionQuery::RMQ.new.wrap(view_2).view_controller.should == @vc2 RubyMotionQuery::RMQ.new.wrap(view_2).view_controller.should == @vc2
end 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
end end

View File

@@ -0,0 +1,9 @@
describe 'CollectionCell' do
before do
end
after do
end
end

View File

@@ -49,7 +49,7 @@ class <%= @name_camel_case %>Controller < UICollectionViewController
def collectionView(view, cellForItemAtIndexPath: index_path) def collectionView(view, cellForItemAtIndexPath: index_path)
view.dequeueReusableCellWithReuseIdentifier(<%= @name.upcase %>_CELL_ID, forIndexPath: index_path).tap do |cell| 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 # Update cell's data here
end end

View File

@@ -1,6 +1,6 @@
module <%= @name_camel_case %>CellStylesheet module <%= @name_camel_case %>CellStylesheet
def cell_size def cell_size
[96, 96] {w: 96, h: 96}
end end
def <%= @name %>_cell(st) def <%= @name %>_cell(st)

View File

@@ -14,9 +14,9 @@ class <%= @name_camel_case %>ControllerStylesheet < ApplicationStylesheet
st.background_color = color.white st.background_color = color.white
st.view.collectionViewLayout.tap do |cl| st.view.collectionViewLayout.tap do |cl|
cl.itemSize = cell_size cl.itemSize = [cell_size[:w], cell_size[:h]]
#cl.scrollDirection = UICollectionViewScrollDirectionHorizontal #cl.scrollDirection = UICollectionViewScrollDirectionHorizontal
#cl.headerReferenceSize = cell_size #cl.headerReferenceSize = [cell_size[:w], cell_size[:h]]
cl.minimumInteritemSpacing = @margin cl.minimumInteritemSpacing = @margin
cl.minimumLineSpacing = @margin cl.minimumLineSpacing = @margin
#cl.sectionInsert = [0,0,0,0] #cl.sectionInsert = [0,0,0,0]

View File

@@ -1,17 +1,17 @@
class <%= @name_camel_case %>Cell < UICollectionViewCell class <%= @name_camel_case %>Cell < UICollectionViewCell
def setup_with(controller_rmq) attr_reader :reused
unless @initialized
@initialized = true
controller_rmq.wrap(self).tap do |q| def rmq_build
q.apply_style :<%= @name %>_cell rmq(self).apply_style :<%= @name %>_cell
# Add your subviews, init stuff here rmq(self.contentView).tap do |q|
# @foo = q.append(UILabel, :foo).get # Add your subviews, init stuff here
end # @foo = q.append(UILabel, :foo).get
end end
end end
def prepareForReuse def prepareForReuse
@reused = true
end end
end end

View File

@@ -1,4 +1,6 @@
class <%= @name_camel_case %>ControllerStylesheet < ApplicationStylesheet class <%= @name_camel_case %>ControllerStylesheet < ApplicationStylesheet
# Add your view stylesheets here. You can then override styles if needed, example:
# include FooStylesheet
def setup def setup
# Add sytlesheet specific setup stuff here. # Add sytlesheet specific setup stuff here.

View File

@@ -1,13 +1,11 @@
class <%= @name_camel_case %> < UIView class <%= @name_camel_case %> < UIView
def rmq_did_create(self_in_rmq) def rmq_build
self_in_rmq.tap do |q| rmq.apply_style :<%= @name %>
q.apply_style :<%= @name %>
# Add subviews here, like so: # Add subviews here, like so:
#q.append(UILabel, :some_label) #rmq.append(UILabel, :some_label)
end
end end