motion-kit 0.10.11 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +92 -2
  3. data/lib/motion-kit/calculator/calculate.rb +1 -1
  4. data/lib/motion-kit/calculator/view_calculator.rb +5 -5
  5. data/lib/motion-kit/layouts/base_layout.rb +21 -15
  6. data/lib/motion-kit/layouts/base_layout_class_methods.rb +2 -7
  7. data/lib/motion-kit/layouts/tree_layout.rb +141 -106
  8. data/lib/motion-kit/object.rb +0 -9
  9. data/lib/motion-kit/version.rb +1 -1
  10. data/lib/motion-kit-cocoa/constraints/constraint.rb +11 -12
  11. data/lib/motion-kit-cocoa/constraints/constraint_placeholder.rb +3 -3
  12. data/lib/motion-kit-cocoa/constraints/constraints_layout.rb +103 -58
  13. data/lib/motion-kit-ios/layouts/constraints_layout.rb +4 -2
  14. data/lib/motion-kit-ios/layouts/uiview_layout.rb +0 -17
  15. data/lib/motion-kit-ios/layouts/uiview_layout_constraints.rb +10 -10
  16. data/lib/motion-kit-ios/layouts/uiview_layout_frame.rb +1 -1
  17. data/lib/motion-kit-osx/layouts/constraints_layout.rb +18 -16
  18. data/lib/motion-kit-osx/layouts/nstableview_layout.rb +13 -0
  19. data/lib/motion-kit-osx/layouts/nsview_layout.rb +0 -19
  20. data/lib/motion-kit-osx/layouts/nsview_layout_constraints.rb +10 -10
  21. data/lib/motion-kit-osx/layouts/nsview_layout_frame.rb +1 -1
  22. data/lib/motion-kit-osx/layouts/nswindow_layout.rb +0 -49
  23. data/spec/ios/apply_styles_spec.rb +27 -12
  24. data/spec/ios/calayer_spec.rb +9 -0
  25. data/spec/ios/child_layouts_spec.rb +53 -0
  26. data/spec/ios/constraints_helpers/scale_constraints_spec.rb +62 -0
  27. data/spec/ios/create_layout_spec.rb +1 -1
  28. data/spec/ios/custom_root_layout_spec.rb +1 -1
  29. data/spec/ios/frame_helper_spec.rb +2 -2
  30. data/spec/ios/layout_spec.rb +3 -20
  31. data/spec/ios/layout_state_spec.rb +1 -1
  32. data/spec/ios/motionkit_util_spec.rb +0 -87
  33. data/spec/ios/reapply_frame.rb +0 -2
  34. data/spec/ios/relative_layout.spec.rb +2 -2
  35. data/spec/ios/remove_layout_spec.rb +2 -3
  36. data/spec/ios/view_attr_spec.rb +7 -0
  37. data/spec/osx/constraints_helpers/table_view_spec.rb +34 -0
  38. data/spec/osx/custom_root_layout_spec.rb +1 -1
  39. data/spec/osx/frame_helper_spec.rb +2 -2
  40. metadata +10 -3
  41. data/lib/motion-kit-cocoa/cocoa_util.rb +0 -59
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8a10411c98102a36da52805858f833ea4e6e3f04
4
- data.tar.gz: 56f823f65361bd4141c5f9e7a9c4f5bc57511347
3
+ metadata.gz: e90a4e2a89071ea4a7c57be68a26bcef7b868a84
4
+ data.tar.gz: 4ac95d41d19e21264920f090de6a5516c226d331
5
5
  SHA512:
6
- metadata.gz: 06e500e3f4a458becc6024937193bf36b4e99fce587138a9017f764cfa8340a562912a511265431b5f3970b018c569fc88abdc902a92e36935b6e832717213ce
7
- data.tar.gz: 3952471f3d7b3ab7181a8a8373b5954fbd8f73f5475c3eb99d42fc87155a4105202d7b2b19af5da6fb83b12ec02f43d80596e7f59b3d133ea4b7bee56e788cb6
6
+ metadata.gz: 884f0edc12798df07d0f82b0396d6cbdb48f5eb4fa2da67c2554259403e7402c8de6f7076a26d473bd1f5de385b8216efd3bf944e838ec5573fe4a15ec131c5d
7
+ data.tar.gz: bec3426f2ffe80d9f47a7d6f0423816b3595a5474753893a00d6e9caf022b781347beb944a6fea3a690924f24911f18a243dd966404cd819a78de2e9fd07689a
data/README.md CHANGED
@@ -20,7 +20,7 @@
20
20
  7. Styles and layouts are "just code" (not hash-based like in Teacup)
21
21
  8. Written by [the authors][authors] of [ProMotion][] and [Teacup][]
22
22
 
23
- [authors]: CONTRIBUTORS.md
23
+ [authors]: CONTRIBUTORS.yaml
24
24
  [Colin]: https://github.com/colinta
25
25
  [Jamon]: https://github.com/jamonholmgren
26
26
  [ProMotion]: https://github.com/clearsightstudio/ProMotion
@@ -115,6 +115,8 @@ class SimpleLayout < MotionKit::Layout
115
115
  def button_style
116
116
  # this will call 'setTitle(forState:)' via a UIButton helper
117
117
  title 'Press it!'
118
+ size_to_fit
119
+
118
120
  # this shorthand is much better! More about frame helpers below.
119
121
  center ['50%', '50% + 50']
120
122
  end
@@ -267,6 +269,32 @@ end
267
269
  ```
268
270
 
269
271
 
272
+ ### Using child-layouts
273
+
274
+ If you have a very complicated layout that you want to break up into child
275
+ layouts, that is supported as well:
276
+
277
+ ```ruby
278
+ class ParentLayout < MK::Layout
279
+
280
+ def layout
281
+ add ChildLayout, :child_id
282
+ end
283
+
284
+ end
285
+ ```
286
+
287
+ The id is (as always) optional, but allows you to fetch the layout using
288
+ `get(id)`.
289
+
290
+ ```ruby
291
+ layout.get(:child_id) # => ChildLayout
292
+ ```
293
+
294
+ Calling `get(:child_id).view` will return the *view* associated with that
295
+ layout.
296
+
297
+
270
298
  ### Setting a custom root view
271
299
 
272
300
  If you need to use a custom root view, you can use the `root` method from within
@@ -593,6 +621,8 @@ constraints do
593
621
  # setting the priority:
594
622
  (x.is >= 10).priority(:required)
595
623
  (x.is == 15).priority(:low)
624
+ # setting the identifier
625
+ x.equals(15).identifier('foo')
596
626
  end
597
627
  ```
598
628
 
@@ -601,12 +631,20 @@ the element-id as a placeholder for a view works especially well here.
601
631
 
602
632
  ```ruby
603
633
  constraints do
604
- top_left.equals x: 5, y:5
634
+ top_left.equals x: 5, y: 5 # this sets the origin relative to the superview
635
+ top_left.equals(:superview).plus([5, 5]) # this will do the same thing!
636
+
605
637
  width.equals(:foo).minus(10) # searches for a view named :foo
606
638
  height.equals(:foo).minus(10)
607
639
  # that's repetitive, so just set 'size'
608
640
  size.equals(:foo).minus(10)
609
641
  size.equals(:foo).minus([10, 15]) # 10pt thinner, 15pt shorter
642
+
643
+ # if you are using a view that has a sensible intrinsic size, like an image,
644
+ # you can use :scale to have the width or height adjusted according to the
645
+ # other size
646
+ width.equals(:superview)
647
+ height(:scale) # scale the height according to the width
610
648
  end
611
649
  ```
612
650
 
@@ -700,6 +738,58 @@ class MainController < UIViewController
700
738
  end
701
739
  ```
702
740
 
741
+ #### Animating and Changing constraints
742
+
743
+ It might feel natural to treat constraints as "frame setters", but they are
744
+ persistent objects that are attached to your views. This means if you create
745
+ new constraints, like during a screen rotation, your old constraints don't “go
746
+ away”. For example:
747
+
748
+ ```ruby
749
+ def label_style
750
+ portrait do
751
+ left 10
752
+ end
753
+
754
+ landscape do
755
+ left 15 # adds *another* constraint on the left attribute - in addition to the `left 10` constraint!
756
+ end
757
+ end
758
+ ```
759
+
760
+ Instead, you should retain the constraint and make changes to it directly:
761
+
762
+ ```ruby
763
+ initial do
764
+ constraints do
765
+ @label_left_constraint = left 10
766
+ end
767
+ end
768
+
769
+ reapply do
770
+ portrait do
771
+ @label_left_constraint.equals 10
772
+ end
773
+
774
+ landscape do
775
+ @label_left_constraint.equals 15
776
+ end
777
+ end
778
+ ```
779
+
780
+ If you want to animate a constraint change, you can use `layoutIfNeeded` from
781
+ within a UIView animation block. The sample app "Chatty" does this to move a
782
+ text field when the keyboard is displayed. `kbd_height` is the height of the
783
+ keyboard.
784
+
785
+ ```ruby
786
+ @container_bottom.minus kbd_height # set @container_bottom.constant = 0 when the keyboard disappears
787
+
788
+ UIView.animateWithDuration(duration, delay: 0, options: curve, animations: -> do
789
+ self.view.layoutIfNeeded # applies the constraint change
790
+ end, completion: nil)
791
+ ```
792
+
703
793
  ### MotionKit::Events
704
794
 
705
795
  gem install motion-kit-events
@@ -3,7 +3,7 @@ module MotionKit
3
3
  module_function
4
4
 
5
5
  def calculate(view, dimension, amount, full_view=nil)
6
- ViewCalculator.new.calculate(view, dimension, amount, full_view)
6
+ ViewCalculator.calculate(view, dimension, amount, full_view)
7
7
  end
8
8
 
9
9
  end
@@ -5,11 +5,11 @@
5
5
  # @provides MotionKit::ViewCalculator
6
6
  module MotionKit
7
7
  class ViewCalculator
8
- include MotionKit::OriginCalculator
9
- include MotionKit::SizeCalculator
10
- include MotionKit::FrameCalculator
8
+ extend MotionKit::OriginCalculator
9
+ extend MotionKit::SizeCalculator
10
+ extend MotionKit::FrameCalculator
11
11
 
12
- def calculate(view, dimension, amount, full_view=nil)
12
+ def self.calculate(view, dimension, amount, full_view=nil)
13
13
  if amount.is_a? Proc
14
14
  return view.instance_exec(&amount)
15
15
  elsif dimension == :origin || dimension == :center
@@ -35,7 +35,7 @@ module MotionKit
35
35
  end
36
36
  end
37
37
 
38
- def intrinsic_size(view)
38
+ def self.intrinsic_size(view)
39
39
  size_that_fits = view.intrinsicContentSize
40
40
  if size_that_fits.width == MotionKit.no_intrinsic_metric
41
41
  size_that_fits.width = 0
@@ -30,7 +30,7 @@ module MotionKit
30
30
  @preset_root = args[:root]
31
31
  end
32
32
 
33
- def set_layout(layout)
33
+ def set_parent_layout(layout)
34
34
  @layout = WeakRef.new(layout)
35
35
  end
36
36
 
@@ -88,14 +88,14 @@ module MotionKit
88
88
  # corner_radius 5
89
89
  # end
90
90
  # end
91
- def context(target, &block)
92
- return target unless block
91
+ def context(new_target, &block)
92
+ return new_target unless block
93
93
  # this little line is incredibly important; the context is only set on
94
94
  # the top-level Layout object.
95
- return parent_layout.context(target, &block) unless is_parent_layout?
95
+ return parent_layout.context(new_target, &block) unless is_parent_layout?
96
96
 
97
- if target.is_a?(Symbol)
98
- target = self.get(target)
97
+ if new_target.is_a?(Symbol)
98
+ new_target = self.get_view(new_target)
99
99
  end
100
100
 
101
101
  context_was, parent_was, delegate_was = @context, @parent, @layout_delegate
@@ -107,17 +107,20 @@ module MotionKit
107
107
  @should_run_deferred = false
108
108
  end
109
109
  @parent = MK::Parent.new(context_was)
110
- @context = target
111
- @context.motion_kit_meta[:delegate] ||= Layout.layout_for(parent_layout, @context.class)
110
+ @context = new_target
111
+ @context.motion_kit_meta[:delegate] ||= Layout.layout_for(@context.class)
112
112
  @layout_delegate = @context.motion_kit_meta[:delegate]
113
+ if @layout_delegate
114
+ @layout_delegate.set_parent_layout(parent_layout)
115
+ end
113
116
  yield
114
117
  @layout_delegate, @context, @parent = delegate_was, context_was, parent_was
115
118
  if @should_run_deferred
116
- run_deferred(target)
119
+ run_deferred(new_target)
117
120
  end
118
121
  @should_run_deferred = prev_should_run
119
122
 
120
- target
123
+ new_target
121
124
  end
122
125
 
123
126
  # Blocks passed to `deferred` are run at the end of a "session", usually
@@ -217,11 +220,14 @@ module MotionKit
217
220
  objc_method_name, objc_method_args = objc_version(method_name, args)
218
221
  ruby_method_name = ruby_version(method_name)
219
222
 
220
- @layout_delegate ||= Layout.layout_for(parent_layout, target.class)
221
- if objc_method_name && @layout_delegate.respond_to?(objc_method_name)
222
- return @layout_delegate.send(objc_method_name, *objc_method_args, &block)
223
- elsif @layout_delegate.respond_to?(ruby_method_name)
224
- return @layout_delegate.send(ruby_method_name, *args, &block)
223
+ @layout_delegate ||= Layout.layout_for(target.class)
224
+ if @layout_delegate
225
+ @layout_delegate.set_parent_layout(parent_layout)
226
+ if objc_method_name && @layout_delegate.respond_to?(objc_method_name)
227
+ return @layout_delegate.send(objc_method_name, *objc_method_args, &block)
228
+ elsif @layout_delegate.respond_to?(ruby_method_name)
229
+ return @layout_delegate.send(ruby_method_name, *args, &block)
230
+ end
225
231
  end
226
232
 
227
233
  if block
@@ -22,9 +22,9 @@ module MotionKit
22
22
  end
23
23
 
24
24
  # Instantiates a new Layout instance using `layout` as the root-level layout
25
- def layout_for(layout, klass)
25
+ def layout_for(klass)
26
26
  memoized_klass = memoize(klass)
27
- memoized_klass.new_child(layout) if memoized_klass
27
+ memoized_klass && memoized_klass.new
28
28
  end
29
29
 
30
30
  # Cache registered classes
@@ -40,10 +40,5 @@ module MotionKit
40
40
  @memoize[klass]
41
41
  end
42
42
 
43
- def new_child(layout=nil)
44
- child = self.new
45
- child.set_layout(layout)
46
- child
47
- end
48
43
  end
49
44
  end
@@ -28,26 +28,41 @@ module MotionKit
28
28
  # end
29
29
  #
30
30
  # end
31
- def view(name)
32
- ivar_name = "@#{name}"
33
- define_method(name) do
34
- unless instance_variable_get(ivar_name)
35
- view = self.get(name)
36
- unless view
37
- build_view unless @view
38
- view = instance_variable_get(ivar_name) || self.get(name)
31
+ #
32
+ # You can also set multiple views in a single line.
33
+ #
34
+ # @example
35
+ # class MyLayout < MK::Layout
36
+ # view :label, :login_button
37
+ # end
38
+ def view(*names)
39
+ names.each do |name|
40
+ ivar_name = "@#{name}"
41
+ define_method(name) do
42
+ unless instance_variable_get(ivar_name)
43
+ view = self.get_view(name)
44
+ unless view
45
+ build_view unless @view
46
+ view = instance_variable_get(ivar_name) || self.get_view(name)
47
+ end
48
+ self.send("#{name}=", view)
49
+ return view
39
50
  end
40
- self.send("#{name}=", view)
41
- return view
51
+ return instance_variable_get(ivar_name)
42
52
  end
43
- return instance_variable_get(ivar_name)
53
+ # KVO compliance
54
+ attr_writer name
44
55
  end
45
- # KVO compliance
46
- attr_writer name
47
56
  end
48
57
 
49
58
  end
50
59
 
60
+ def initialize(args={})
61
+ super
62
+ @child_layouts = []
63
+ @elements = {}
64
+ end
65
+
51
66
  # The main view. This method builds the layout and returns the root view.
52
67
  def view
53
68
  unless is_parent_layout?
@@ -56,14 +71,6 @@ module MotionKit
56
71
  @view ||= build_view
57
72
  end
58
73
 
59
- # For private use. The "root" is context sensitive, whereas the "view" is
60
- # constant. In most cases they are the same object, but when you are
61
- # building a hierarchy that is *outside* the view created from the "layout"
62
- # method, the top-most view in that hierarchy will be "root".
63
- def _root
64
- @root || view
65
- end
66
-
67
74
  # Builds the layout and then returns self for chaining.
68
75
  def build
69
76
  view
@@ -104,59 +111,44 @@ module MotionKit
104
111
  raise ContextConflictError.new("Already created the root view")
105
112
  end
106
113
 
107
- @view = initialize_element(element)
114
+ @view = initialize_element(element, element_id)
115
+
108
116
  if block
109
117
  if @context
110
118
  raise ContextConflictError.new("Already in a context")
111
119
  end
112
-
113
- context(@view) do
114
- # We're just using the `create` method for its side effects: calling the
115
- # style method and calling the block.
116
- create(@view, element_id, &block)
117
- end
118
- elsif element_id
119
- create(@view, element_id)
120
120
  end
121
121
 
122
+ style_and_context(@view, element_id, &block)
123
+
122
124
  return @view
123
125
  end
124
126
 
125
127
  # instantiates a view, possibly running a 'layout block' to add child views.
126
128
  def create(element, element_id=nil, &block)
127
- element = initialize_element(element)
128
-
129
- if element_id
130
- # We set the optional id and call the '_style' method, if it's been
131
- # defined.
132
- element.motion_kit_id = element_id
133
- self.call_style_method(element, element_id)
134
- end
135
-
136
- if block
137
- context(element, &block)
138
- end
129
+ element = initialize_element(element, element_id)
130
+ style_and_context(element, element_id, &block)
139
131
 
140
132
  element
141
133
  end
142
134
 
143
- def call_style_method(element, element_id)
144
- style_method = "#{element_id}_style"
145
- if parent_layout.respond_to?(style_method)
146
- parent_layout.context(element) do
147
- parent_layout.send(style_method)
135
+ # Calls the style method of all objects in the view hierarchy that are
136
+ # part of this layout. The views in a child layout are not styled, but
137
+ # those layouts will receive a `reapply!` message if no root is specified.
138
+ def reapply!
139
+ root ||= self.view
140
+ @layout_state = :reapply
141
+
142
+ @elements.each do |element_id, elements|
143
+ elements.each do |element|
144
+ style_and_context(element, element_id)
148
145
  end
149
146
  end
150
- return element
151
- end
152
147
 
153
- # Calls the style method of all objects in the view hierarchy
154
- def reapply!(root=nil)
155
- root ||= self.view
156
- @layout_state = :reapply
157
- MotionKit.find_all_views(root) do |view|
158
- call_style_method(view, view.motion_kit_id) if view.motion_kit_id
148
+ @child_layouts.each do |child_layout|
149
+ child_layout.reapply!
159
150
  end
151
+
160
152
  @layout_state = :initial
161
153
 
162
154
  return self
@@ -189,70 +181,93 @@ module MotionKit
189
181
  return self
190
182
  end
191
183
 
184
+ def name_element(element, element_id)
185
+ @elements[element_id] ||= []
186
+ @elements[element_id] << element
187
+ end
188
+
192
189
  # Instantiates a view via `create` and adds the view to the current target.
193
- # If no view exists on the stack, a default root view can be created if that
194
- # has been enabled. The block is run in the context of the new view.
190
+ # If there is no context, a default root view can be created if that has
191
+ # been enabled (e.g. within the `layout` method). The block is run in the
192
+ # context of the new view.
195
193
  def add(element, element_id=nil, &block)
196
194
  # make sure we have a target - raises NoContextError if none exists
197
195
  self.target
198
196
 
199
- element = initialize_element(element)
200
197
  unless @context
201
198
  create_default_root_context
202
199
  end
203
- self.apply(:add_child, element)
204
- create(element, element_id)
205
200
 
206
- if block
207
- context(element, &block)
208
- end
201
+ # We want to be sure that the element has a supeview or superlayer before
202
+ # the style method is called.
203
+ element = initialize_element(element, element_id)
204
+ self.apply(:add_child, element)
205
+ style_and_context(element, element_id, &block)
209
206
 
210
207
  element
211
208
  end
212
209
 
210
+ def child_layouts
211
+ @child_layouts
212
+ end
213
+
213
214
  # Retrieves a view by its element id. This will return the *first* view
214
- # with this element_id in the tree, where *first* means the view closest to
215
- # the root view. Aliased to `first` to distinguish it from `last`.
215
+ # with this element_id in the tree, where *first* means the first object
216
+ # that was added with assigned that name.
216
217
  def get(element_id)
217
218
  unless is_parent_layout?
218
219
  return parent_layout.get(element_id)
219
220
  end
220
- self.get(element_id, in: self._root)
221
+ @elements[element_id] && @elements[element_id].first
221
222
  end
222
223
  def first(element_id) ; get(element_id) ; end
223
224
 
224
- # Same as `get`, but with the root view specified.
225
- def get(element_id, in: root)
226
- MotionKit.find_first_view(root) { |view| view.motion_kit_id == element_id }
225
+ # Just like `get`, but if `get` returns a Layout, this method returns the
226
+ # layout's view.
227
+ def get_view(element_id)
228
+ element = get(element_id)
229
+ if element.is_a?(Layout)
230
+ element = element.view
231
+ end
232
+ element
227
233
  end
228
- def first(element_id, in: root) ; get(element_id, in: root) ; end
229
234
 
230
- # Retrieves a view by its element id. This will return the *last* view
231
- # with this element_id, where last means the view deepest and furthest from
232
- # the root view.
235
+ # Retrieves a view by its element id. This will return the *last* view with
236
+ # this element_id in the tree, where *last* means the last object that was
237
+ # added with assigned that name.
233
238
  def last(element_id)
234
239
  unless is_parent_layout?
235
240
  return parent_layout.last(element_id)
236
241
  end
237
- self.last(element_id, in: self._root)
242
+ @elements[element_id] && @elements[element_id].last
238
243
  end
239
244
 
240
- # Same as `last`, but with the root view specified.
241
- def last(element_id, in: root)
242
- MotionKit.find_last_view(root) { |view| view.motion_kit_id == element_id }
245
+ # Just like `last`, but if `last` returns a Layout, this method returns the
246
+ # layout's view.
247
+ def last_view(element_id)
248
+ element = last(element_id)
249
+ if element.is_a?(Layout)
250
+ element = element.view
251
+ end
252
+ element
243
253
  end
244
254
 
245
- # Returns all the elements with a given element_id in the view tree.
255
+ # Returns all the elements with a given element_id
246
256
  def all(element_id)
247
257
  unless is_parent_layout?
248
258
  return parent_layout.all(element_id)
249
259
  end
250
- self.all(element_id, in: self._root)
260
+ @elements[element_id] || []
251
261
  end
252
262
 
253
- # Same as `all`, but with the root view specified.
254
- def all(element_id, in: root)
255
- MotionKit.find_all_views(root) { |view| view.motion_kit_id == element_id }
263
+ # Just like `all`, but if `all` returns a Layout, this method returns the
264
+ # layout's view.
265
+ def all_views(element_id)
266
+ element = all(element_id)
267
+ if element.is_a?(Layout)
268
+ element = element.view
269
+ end
270
+ element
256
271
  end
257
272
 
258
273
  # Returns all the elements with a given element_id
@@ -260,9 +275,14 @@ module MotionKit
260
275
  self.all(element_id)[index]
261
276
  end
262
277
 
263
- # Same as `nth`, but with the root view specified.
264
- def nth(element_id, at: index, in: root)
265
- self.all(element_id, in: root)[index]
278
+ # Just like `nth`, but if `nth` returns a Layout, this method returns the
279
+ # layout's view.
280
+ def nth_view(element_id, index)
281
+ element = nth(element_id)
282
+ if element.is_a?(Layout)
283
+ element = element.view
284
+ end
285
+ element
266
286
  end
267
287
 
268
288
  # Removes a view (or several with the same name) from the hierarchy
@@ -271,15 +291,11 @@ module MotionKit
271
291
  unless is_parent_layout?
272
292
  return parent_layout.remove(element_id)
273
293
  end
274
- self.remove(element_id, from: self._root)
275
- end
276
-
277
- # Same as `remove`, but with the root view specified.
278
- def remove(element_id, from: root)
279
- context(root) do
280
- all(element_id).each do |subview|
281
- self.apply(:remove_child, subview)
294
+ context(self.view) do
295
+ all(element_id).each do |element|
296
+ self.apply(:remove_child, element)
282
297
  end
298
+ @elements[element_id] = nil
283
299
  end
284
300
  end
285
301
 
@@ -329,17 +345,6 @@ module MotionKit
329
345
  @view
330
346
  end
331
347
 
332
- # This method needs to set the @root so that calls to `get(:id)` defer to
333
- # the "current root", not the layout root view.
334
- def run_deferred(top_level_context)
335
- root_was = @root
336
- @root = top_level_context
337
- retval = super
338
- @root = root_was
339
-
340
- return retval
341
- end
342
-
343
348
  def layout
344
349
  end
345
350
 
@@ -348,18 +353,48 @@ module MotionKit
348
353
  #
349
354
  # Accepts a view instance, a class (which is instantiated with 'new') or a
350
355
  # `ViewLayout`, which returns the root view.
351
- def initialize_element(elem)
356
+ def initialize_element(elem, element_id)
352
357
  if elem.is_a?(Class) && elem < TreeLayout
353
- elem = elem.new_child(parent_layout).view
358
+ layout = elem.new
359
+ elem = layout.view
354
360
  elsif elem.is_a?(Class)
355
361
  elem = elem.new
356
362
  elsif elem.is_a?(TreeLayout)
363
+ layout = elem
357
364
  elem = elem.view
358
365
  end
359
366
 
367
+ if layout
368
+ if element_id
369
+ name_element(layout, element_id)
370
+ end
371
+ @child_layouts << layout
372
+ elsif element_id
373
+ name_element(elem, element_id)
374
+ end
375
+
360
376
  return elem
361
377
  end
362
378
 
379
+ # Calls the `_style` method with the element as the context, and runs the
380
+ # optional block in that context. This is usually done immediately after
381
+ # `initialize_element`, except in the case of `add`, which adds the item to
382
+ # the tree before styling it.
383
+ def style_and_context(element, element_id, &block)
384
+ style_method = "#{element_id}_style"
385
+ if parent_layout.respond_to?(style_method) || block_given?
386
+ parent_layout.context(element) do
387
+ if parent_layout.respond_to?(style_method)
388
+ parent_layout.send(style_method)
389
+ end
390
+
391
+ if block_given?
392
+ yield
393
+ end
394
+ end
395
+ end
396
+ end
397
+
363
398
  end
364
399
 
365
400
  end
@@ -1,13 +1,4 @@
1
1
  class Object
2
- attr_accessor :motion_kit_meta
3
-
4
- def motion_kit_id=(element_id)
5
- motion_kit_meta[:id] = element_id
6
- end
7
-
8
- def motion_kit_id
9
- motion_kit_meta[:id]
10
- end
11
2
 
12
3
  def motion_kit_meta
13
4
  @motion_kit_meta ||= {}
@@ -1,3 +1,3 @@
1
1
  module MotionKit
2
- VERSION = '0.10.11'
2
+ VERSION = '0.11.0'
3
3
  end