motion-kit 0.10.11 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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