diff --git a/README.md b/README.md index e2f3331..748892e 100755 --- a/README.md +++ b/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 ``` @@ -610,16 +616,17 @@ RubyMotionQuery::RMQ.view_to_s(view) The following are the only pollution in RMQ - UIView - - rmq - - rmq_data + - rmq + - rmq_data - UIViewController - - rmq - - rmq_data - - TopLevel *(Only in development, used for console)* - - rmq + - rmq + - rmq_data + - 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}} diff --git a/app/app_delegate.rb b/app/app_delegate.rb index 5719fbf..ae3011b 100644 --- a/app/app_delegate.rb +++ b/app/app_delegate.rb @@ -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 diff --git a/app/controllers/collection_controller.rb b/app/controllers/collection_controller.rb new file mode 100644 index 0000000..898e826 --- /dev/null +++ b/app/controllers/collection_controller.rb @@ -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 diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb index 6f8317c..868c140 100644 --- a/app/controllers/main_controller.rb +++ b/app/controllers/main_controller.rb @@ -1,4 +1,4 @@ -class MainController < UIViewController +class MainController < UIViewController def viewDidLoad super @@ -6,10 +6,58 @@ 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 + 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(UILabel).animations.blink end @@ -18,38 +66,6 @@ class MainController < UIViewController rmq(UIButton).not(sender).animations.throb 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(sender).animate( duration: 0.5, animations: -> (rmq) { # 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.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(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.animations.start_spinner + rmq(sender).apply_style(:run_benchmarks_disabled) + 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.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 @@ -151,4 +175,3 @@ class MainController < UIViewController out end end - diff --git a/app/stylesheets/application_stylesheet.rb b/app/stylesheets/application_stylesheet.rb index 242f613..5ca2b46 100644 --- a/app/stylesheets/application_stylesheet.rb +++ b/app/stylesheets/application_stylesheet.rb @@ -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' diff --git a/app/stylesheets/collection_cell_stylesheet.rb b/app/stylesheets/collection_cell_stylesheet.rb new file mode 100644 index 0000000..ae0e82b --- /dev/null +++ b/app/stylesheets/collection_cell_stylesheet.rb @@ -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 diff --git a/app/stylesheets/collection_controller_stylesheet.rb b/app/stylesheets/collection_controller_stylesheet.rb new file mode 100644 index 0000000..4587f72 --- /dev/null +++ b/app/stylesheets/collection_controller_stylesheet.rb @@ -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 diff --git a/app/stylesheets/main_stylesheet.rb b/app/stylesheets/main_stylesheet.rb index abaafdf..6231136 100644 --- a/app/stylesheets/main_stylesheet.rb +++ b/app/stylesheets/main_stylesheet.rb @@ -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' diff --git a/app/views/collection_cell.rb b/app/views/collection_cell.rb new file mode 100644 index 0000000..4cabcf2 --- /dev/null +++ b/app/views/collection_cell.rb @@ -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 diff --git a/app/views/section.rb b/app/views/section.rb index 318e021..4b98a24 100644 --- a/app/views/section.rb +++ b/app/views/section.rb @@ -1,21 +1,25 @@ 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| - style = sender.isOn ? :section_button_enabled : :section_button_disabled - buttons = rmq(sender).parent.find(UIButton).apply_style(style) - end + q.append(UILabel, :section_enabled_title) - rmq.append(UIButton, :start_spinner).on(:tap) do |sender| - rmq.animations.start_spinner - end + 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, :stop_spinner).on(:tap) do |sender| - rmq.animations.stop_spinner + q.append(UIButton, :start_spinner).on(:tap) do |sender| + rmq.animations.start_spinner + end + + q.append(UIButton, :stop_spinner).on(:tap) do |sender| + rmq.animations.stop_spinner + end end end diff --git a/motion/ext.rb b/motion/ext.rb index 45179c8..24478ce 100644 --- a/motion/ext.rb +++ b/motion/ext.rb @@ -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 diff --git a/motion/ruby_motion_query/base.rb b/motion/ruby_motion_query/base.rb index d3c4b4b..37bcdb1 100644 --- a/motion/ruby_motion_query/base.rb +++ b/motion/ruby_motion_query/base.rb @@ -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 diff --git a/motion/ruby_motion_query/data.rb b/motion/ruby_motion_query/data.rb index ff7cc71..ff4b672 100644 --- a/motion/ruby_motion_query/data.rb +++ b/motion/ruby_motion_query/data.rb @@ -54,6 +54,6 @@ module RubyMotionQuery end class ControllerData - attr_accessor :stylesheet, :rmq + attr_accessor :stylesheet, :cached_rmq end end diff --git a/motion/ruby_motion_query/factory.rb b/motion/ruby_motion_query/factory.rb index 53ee640..0cfff67 100644 --- a/motion/ruby_motion_query/factory.rb +++ b/motion/ruby_motion_query/factory.rb @@ -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 diff --git a/motion/ruby_motion_query/subviews.rb b/motion/ruby_motion_query/subviews.rb index a6194c1..15a2cc4 100644 --- a/motion/ruby_motion_query/subviews.rb +++ b/motion/ruby_motion_query/subviews.rb @@ -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) diff --git a/motion/ruby_motion_query/traverse.rb b/motion/ruby_motion_query/traverse.rb index be8d10c..37d2e4e 100644 --- a/motion/ruby_motion_query/traverse.rb +++ b/motion/ruby_motion_query/traverse.rb @@ -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 diff --git a/spec/app.rb b/spec/app.rb index 6c634a1..1b3614b 100644 --- a/spec/app.rb +++ b/spec/app.rb @@ -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 diff --git a/spec/controllers/collection_controller.rb b/spec/controllers/collection_controller.rb new file mode 100644 index 0000000..4d9b25d --- /dev/null +++ b/spec/controllers/collection_controller.rb @@ -0,0 +1,9 @@ +describe 'CollectionController' do + + before do + end + + after do + end + +end diff --git a/spec/data.rb b/spec/data.rb index e120364..9499507 100644 --- a/spec/data.rb +++ b/spec/data.rb @@ -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 diff --git a/spec/ext.rb b/spec/ext.rb index 70b091c..44cfcbb 100644 --- a/spec/ext.rb +++ b/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 diff --git a/spec/subviews.rb b/spec/subviews.rb index 640ce0d..02faa59 100644 --- a/spec/subviews.rb +++ b/spec/subviews.rb @@ -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 diff --git a/spec/traversing.rb b/spec/traversing.rb index c4c86c4..fc85bcb 100644 --- a/spec/traversing.rb +++ b/spec/traversing.rb @@ -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 diff --git a/spec/views/collection_cell.rb b/spec/views/collection_cell.rb new file mode 100644 index 0000000..bea4666 --- /dev/null +++ b/spec/views/collection_cell.rb @@ -0,0 +1,9 @@ +describe 'CollectionCell' do + + before do + end + + after do + end + +end diff --git a/templates/collection_view_controller/app/controllers/name_controller.rb b/templates/collection_view_controller/app/controllers/name_controller.rb index c327e15..131e3cd 100644 --- a/templates/collection_view_controller/app/controllers/name_controller.rb +++ b/templates/collection_view_controller/app/controllers/name_controller.rb @@ -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 diff --git a/templates/collection_view_controller/app/stylesheets/name_cell_stylesheet.rb b/templates/collection_view_controller/app/stylesheets/name_cell_stylesheet.rb index fe30a48..444c181 100644 --- a/templates/collection_view_controller/app/stylesheets/name_cell_stylesheet.rb +++ b/templates/collection_view_controller/app/stylesheets/name_cell_stylesheet.rb @@ -1,6 +1,6 @@ module <%= @name_camel_case %>CellStylesheet def cell_size - [96, 96] + {w: 96, h: 96} end def <%= @name %>_cell(st) diff --git a/templates/collection_view_controller/app/stylesheets/name_controller_stylesheet.rb b/templates/collection_view_controller/app/stylesheets/name_controller_stylesheet.rb index ce9deda..ce50241 100644 --- a/templates/collection_view_controller/app/stylesheets/name_controller_stylesheet.rb +++ b/templates/collection_view_controller/app/stylesheets/name_controller_stylesheet.rb @@ -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] diff --git a/templates/collection_view_controller/app/views/name_cell.rb b/templates/collection_view_controller/app/views/name_cell.rb index 30879a8..8366706 100644 --- a/templates/collection_view_controller/app/views/name_cell.rb +++ b/templates/collection_view_controller/app/views/name_cell.rb @@ -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 - # Add your subviews, init stuff here - # @foo = q.append(UILabel, :foo).get - end + rmq(self.contentView).tap do |q| + # Add your subviews, init stuff here + # @foo = q.append(UILabel, :foo).get end end def prepareForReuse + @reused = true end + end diff --git a/templates/controller/app/stylesheets/name_controller_stylesheet.rb b/templates/controller/app/stylesheets/name_controller_stylesheet.rb index ccf09aa..7e84fbd 100644 --- a/templates/controller/app/stylesheets/name_controller_stylesheet.rb +++ b/templates/controller/app/stylesheets/name_controller_stylesheet.rb @@ -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. diff --git a/templates/view/app/views/name.rb b/templates/view/app/views/name.rb index 770029d..f424404 100644 --- a/templates/view/app/views/name.rb +++ b/templates/view/app/views/name.rb @@ -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 + # Add subviews here, like so: + #rmq.append(UILabel, :some_label) end