motion-kit 0.0.1 → 0.9.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 (94) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +839 -0
  3. data/lib/motion-kit-cocoa/cocoa_util.rb +59 -0
  4. data/lib/motion-kit-cocoa/constraints/constraint.rb +765 -0
  5. data/lib/motion-kit-cocoa/constraints/constraint_placeholder.rb +22 -0
  6. data/lib/motion-kit-cocoa/constraints/constraints_layout.rb +536 -0
  7. data/lib/motion-kit-cocoa/constraints/constraints_target.rb +52 -0
  8. data/lib/motion-kit-cocoa/layouts/cagradientlayer_layout.rb +13 -0
  9. data/lib/motion-kit-cocoa/layouts/calayer_layout.rb +27 -0
  10. data/lib/motion-kit-cocoa/layouts/sugarcube_compat.rb +38 -0
  11. data/lib/motion-kit-ios/dummy.rb +93 -0
  12. data/lib/motion-kit-ios/ios_util.rb +20 -0
  13. data/lib/motion-kit-ios/layouts/constraints_layout.rb +22 -0
  14. data/lib/motion-kit-ios/layouts/layout_device.rb +32 -0
  15. data/lib/motion-kit-ios/layouts/layout_orientation.rb +47 -0
  16. data/lib/motion-kit-ios/layouts/uibutton_layout.rb +52 -0
  17. data/lib/motion-kit-ios/layouts/uiview_layout.rb +45 -0
  18. data/lib/motion-kit-ios/layouts/uiview_layout_autoresizing.rb +75 -0
  19. data/lib/motion-kit-ios/layouts/uiview_layout_constraints.rb +36 -0
  20. data/lib/motion-kit-ios/layouts/uiview_layout_frame.rb +307 -0
  21. data/lib/motion-kit-ios/layouts/uiview_layout_gradient.rb +20 -0
  22. data/lib/motion-kit-osx/dummy.rb +89 -0
  23. data/lib/motion-kit-osx/layouts/constraints_layout.rb +42 -0
  24. data/lib/motion-kit-osx/layouts/nsmenu_extensions.rb +186 -0
  25. data/lib/motion-kit-osx/layouts/nsmenu_layout.rb +109 -0
  26. data/lib/motion-kit-osx/layouts/nsmenuitem_extensions.rb +45 -0
  27. data/lib/motion-kit-osx/layouts/nstablecolumn_layout.rb +12 -0
  28. data/lib/motion-kit-osx/layouts/nstableview_layout.rb +20 -0
  29. data/lib/motion-kit-osx/layouts/nsview_layout.rb +47 -0
  30. data/lib/motion-kit-osx/layouts/nsview_layout_autoresizing.rb +75 -0
  31. data/lib/motion-kit-osx/layouts/nsview_layout_constraints.rb +34 -0
  32. data/lib/motion-kit-osx/layouts/nsview_layout_frame.rb +375 -0
  33. data/lib/motion-kit-osx/layouts/nswindow_frame.rb +14 -0
  34. data/lib/motion-kit-osx/layouts/nswindow_layout.rb +77 -0
  35. data/lib/motion-kit-osx/osx_util.rb +16 -0
  36. data/lib/motion-kit.rb +33 -0
  37. data/lib/motion-kit/calculate.rb +263 -0
  38. data/lib/motion-kit/layouts/base_layout.rb +299 -0
  39. data/lib/motion-kit/layouts/base_layout_class_methods.rb +43 -0
  40. data/lib/motion-kit/layouts/parent.rb +68 -0
  41. data/lib/motion-kit/layouts/view_layout.rb +327 -0
  42. data/lib/motion-kit/motion-kit.rb +18 -0
  43. data/lib/motion-kit/object.rb +16 -0
  44. data/lib/motion-kit/util.rb +20 -0
  45. data/lib/motion-kit/version.rb +1 -1
  46. data/spec/ios/apply_styles_spec.rb +21 -0
  47. data/spec/ios/autoresizing_helper_spec.rb +224 -0
  48. data/spec/ios/calculate_spec.rb +322 -0
  49. data/spec/ios/calculator_spec.rb +31 -0
  50. data/spec/ios/constraints_helpers/attribute_lookup_spec.rb +27 -0
  51. data/spec/ios/constraints_helpers/axis_lookup_spec.rb +13 -0
  52. data/spec/ios/constraints_helpers/center_constraints_spec.rb +419 -0
  53. data/spec/ios/constraints_helpers/constraint_placeholder_spec.rb +72 -0
  54. data/spec/ios/constraints_helpers/priority_lookup_spec.rb +19 -0
  55. data/spec/ios/constraints_helpers/relationship_lookup_spec.rb +27 -0
  56. data/spec/ios/constraints_helpers/relative_corners_spec.rb +274 -0
  57. data/spec/ios/constraints_helpers/relative_location_spec.rb +111 -0
  58. data/spec/ios/constraints_helpers/simple_constraints_spec.rb +2763 -0
  59. data/spec/ios/constraints_helpers/size_constraints_spec.rb +422 -0
  60. data/spec/ios/constraints_helpers/view_lookup_constraints_spec.rb +93 -0
  61. data/spec/ios/create_layout_spec.rb +40 -0
  62. data/spec/ios/custom_layout_spec.rb +13 -0
  63. data/spec/ios/deferred_spec.rb +89 -0
  64. data/spec/ios/device_helpers_spec.rb +51 -0
  65. data/spec/ios/frame_helper_spec.rb +1150 -0
  66. data/spec/ios/layer_layout_spec.rb +36 -0
  67. data/spec/ios/layout_extensions_spec.rb +70 -0
  68. data/spec/ios/layout_spec.rb +74 -0
  69. data/spec/ios/layout_state_spec.rb +27 -0
  70. data/spec/ios/motionkit_util_spec.rb +102 -0
  71. data/spec/ios/objc_selectors_spec.rb +10 -0
  72. data/spec/ios/orientation_helper_specs.rb +67 -0
  73. data/spec/ios/parent_layout_spec.rb +19 -0
  74. data/spec/ios/parent_spec.rb +45 -0
  75. data/spec/ios/remove_layout_spec.rb +25 -0
  76. data/spec/ios/root_layout_spec.rb +53 -0
  77. data/spec/ios/setters_spec.rb +63 -0
  78. data/spec/ios/uibutton_layout_spec.rb +24 -0
  79. data/spec/ios/uitextfield_spec.rb +14 -0
  80. data/spec/ios/view_attr_spec.rb +25 -0
  81. data/spec/osx/autoresizing_helper_spec.rb +224 -0
  82. data/spec/osx/constraints_helper_spec.rb +0 -0
  83. data/spec/osx/constraints_helpers/orientation_lookup_spec.rb +13 -0
  84. data/spec/osx/constraints_helpers/simple_constraints_spec.rb +2095 -0
  85. data/spec/osx/constraints_helpers/size_constraints_spec.rb +362 -0
  86. data/spec/osx/create_menu_spec.rb +14 -0
  87. data/spec/osx/create_via_extensions_spec.rb +63 -0
  88. data/spec/osx/deferred_spec.rb +85 -0
  89. data/spec/osx/frame_helper_spec.rb +1881 -0
  90. data/spec/osx/menu_extensions_spec.rb +376 -0
  91. data/spec/osx/menu_layout_spec.rb +157 -0
  92. data/spec/osx/menu_spec.rb +70 -0
  93. data/spec/osx/root_menu_spec.rb +15 -0
  94. metadata +166 -14
@@ -0,0 +1,59 @@
1
+ module MotionKit
2
+ module_function
3
+
4
+ # performs a breadth-first search
5
+ def find_first_view(root, &condition)
6
+ if condition.call(root)
7
+ root
8
+ else
9
+ found = nil
10
+ root.subviews.find do |subview|
11
+ found = find_first_view(subview, &condition)
12
+ end
13
+ return found
14
+ end
15
+ end
16
+
17
+ # performs a depth-first and reversed search
18
+ def find_last_view(root, &condition)
19
+ found = nil
20
+ root.subviews.reverse.find do |subview|
21
+ found = find_last_view(subview, &condition)
22
+ end
23
+
24
+ if ! found && condition.call(root)
25
+ found = root
26
+ end
27
+
28
+ return found
29
+ end
30
+
31
+ # performs a breadth-first search, but returns all matches
32
+ def find_all_views(root, &condition)
33
+ found = []
34
+ if condition.call(root)
35
+ found << root
36
+ end
37
+
38
+ (root.subviews || []).each do |subview|
39
+ found.concat(find_all_views(subview, &condition))
40
+ end
41
+
42
+ return found
43
+ end
44
+
45
+ # similar to find_all_views, but for CALayer
46
+ def find_all_layers(root, &condition)
47
+ found = []
48
+ if condition.call(root)
49
+ found << root
50
+ end
51
+
52
+ (root.sublayers || []).each do |sublayer|
53
+ found.concat(find_all_layers(sublayer, &condition))
54
+ end
55
+
56
+ return found
57
+ end
58
+
59
+ end
@@ -0,0 +1,765 @@
1
+ module MotionKit
2
+ class InvalidRelationshipError < Exception
3
+ end
4
+ class InvalidAttributeError < Exception
5
+ end
6
+ class InvalidPriorityError < Exception
7
+ end
8
+
9
+ class Constraint
10
+ attr_accessor :target
11
+ attr_accessor :attribute
12
+ attr_accessor :relationship
13
+ attr_accessor :relative_to
14
+ attr_accessor :attribute2
15
+ attr_accessor :multiplier
16
+ attr_accessor :constant
17
+ attr_accessor :priority
18
+ attr_accessor :identifier
19
+
20
+ Priorities = {
21
+ required: 1000, # NSLayoutPriorityRequired
22
+ high: 750, # NSLayoutPriorityDefaultHigh
23
+ medium: 500,
24
+ low: 250, # NSLayoutPriorityDefaultLow
25
+ }
26
+ Relationships = {
27
+ equal: NSLayoutRelationEqual,
28
+ lte: NSLayoutRelationLessThanOrEqual,
29
+ gte: NSLayoutRelationGreaterThanOrEqual,
30
+ }
31
+ Attributes = {
32
+ none: NSLayoutAttributeNotAnAttribute,
33
+ left: NSLayoutAttributeLeft,
34
+ right: NSLayoutAttributeRight,
35
+ top: NSLayoutAttributeTop,
36
+ bottom: NSLayoutAttributeBottom,
37
+ leading: NSLayoutAttributeLeading,
38
+ trailing: NSLayoutAttributeTrailing,
39
+ width: NSLayoutAttributeWidth,
40
+ height: NSLayoutAttributeHeight,
41
+ center_x: NSLayoutAttributeCenterX,
42
+ center_y: NSLayoutAttributeCenterY,
43
+ baseline: NSLayoutAttributeBaseline,
44
+ }
45
+
46
+ def initialize(target, attribute=nil, relationship)
47
+ @target = target
48
+ @attribute = attribute
49
+ @attribute2 = attribute
50
+ @relative_to = nil
51
+ @relationship = relationship
52
+ @multiplier = 1
53
+ @constant = 0
54
+ @priority = nil
55
+ @compare_flag = false
56
+ end
57
+
58
+ # like `equals`, but also sets `compare_flag` to true, so you can use ==,
59
+ # <=, and >=
60
+ #
61
+ # @example
62
+ # x.is == 10
63
+ # (x.is == 10).priority :required
64
+ # width.is >= 100
65
+ # height.is <= 200
66
+ def is(value=nil)
67
+ if value
68
+ self.equals(value)
69
+ end
70
+ @compare_flag = true
71
+ self
72
+ end
73
+
74
+ def ==(compare)
75
+ if @compare_flag
76
+ equals(compare)
77
+ @compare_flag = false
78
+
79
+ self
80
+ else
81
+ super
82
+ end
83
+ end
84
+
85
+ def >=(compare)
86
+ if @compare_flag
87
+ if @relationship && Constraint.relationship_lookup(@relationship) != NSLayoutRelationEqual
88
+ raise InvalidRelationshipError.new("You cannot use `.is >=` on a constraint that is already defined as #{@relationship}")
89
+ end
90
+
91
+ gte(compare)
92
+ @compare_flag = false
93
+
94
+ self
95
+ else
96
+ super
97
+ end
98
+ end
99
+
100
+ def <=(compare)
101
+ if @compare_flag
102
+ if @relationship && Constraint.relationship_lookup(@relationship) != NSLayoutRelationEqual
103
+ raise InvalidRelationshipError.new("You cannot use `.is <=` on a constraint that is already defined as #{@relationship}")
104
+ end
105
+
106
+ lte(compare)
107
+ @compare_flag = false
108
+
109
+ self
110
+ else
111
+ super
112
+ end
113
+ end
114
+
115
+ def equals(target, attribute2=nil)
116
+ self.relationship ||= :equal
117
+ if Constraint.constant?(target)
118
+ self.constant = target
119
+ elsif Constraint.calculate?(target)
120
+ calc = Calculator.scan(target)
121
+ self.multiplier = calc.factor
122
+ self.constant = calc.constant || 0
123
+ else
124
+ self.relative_to = target
125
+ if attribute2
126
+ self.attribute2 = attribute2
127
+ end
128
+ end
129
+ @compare_flag = false
130
+ self
131
+ end
132
+ alias is_equal_to equals
133
+ alias equal_to equals
134
+
135
+ def lte(target, attribute2=nil)
136
+ self.relationship = :lte
137
+ if Constraint.constant?(target)
138
+ self.constant = target
139
+ elsif Constraint.calculate?(target)
140
+ calc = Calculator.scan(target)
141
+ self.multiplier = calc.factor
142
+ self.constant = calc.constant || 0
143
+ else
144
+ self.relative_to = target
145
+ if attribute2
146
+ self.attribute2 = attribute2
147
+ end
148
+ end
149
+ @compare_flag = false
150
+ self
151
+ end
152
+ alias is_at_most lte
153
+ alias at_most lte
154
+
155
+ def gte(target, attribute2=nil)
156
+ self.relationship = :gte
157
+ if Constraint.constant?(target)
158
+ self.constant = target
159
+ elsif Constraint.calculate?(target)
160
+ calc = Calculator.scan(target)
161
+ self.multiplier = calc.factor
162
+ self.constant = calc.constant || 0
163
+ else
164
+ self.relative_to = target
165
+ if attribute2
166
+ self.attribute2 = attribute2
167
+ end
168
+ end
169
+ @compare_flag = false
170
+ self
171
+ end
172
+ alias is_at_least gte
173
+ alias at_least gte
174
+
175
+ # width.is('100%').of(:view, :width)
176
+ def of(target, attribute2=nil)
177
+ self.relative_to = target
178
+ if attribute2
179
+ self.attribute2 = attribute2
180
+ end
181
+ self
182
+ end
183
+
184
+ def constant=(constant)
185
+ @constant = constant
186
+
187
+ case Constraint.attribute_lookup(self.attribute)
188
+ when NSLayoutAttributeLeft, NSLayoutAttributeRight, NSLayoutAttributeTop, NSLayoutAttributeBottom, NSLayoutAttributeLeading, NSLayoutAttributeTrailing, NSLayoutAttributeCenterX, NSLayoutAttributeCenterY, NSLayoutAttributeBaseline
189
+ self.relative_to ||= :superview
190
+ end
191
+
192
+ self.update_constraint
193
+ end
194
+
195
+ def multiplier=(multiplier)
196
+ @multiplier = multiplier
197
+ self.update_constraint
198
+ end
199
+
200
+ def times(multiplier)
201
+ self.multiplier *= multiplier
202
+ self
203
+ end
204
+
205
+ def divided_by(multiplier)
206
+ times 1.0/multiplier
207
+ end
208
+
209
+ # If no relationship has been set, the "use case" here is:
210
+ #
211
+ # c.plus(10).equals(:view, :x)
212
+ #
213
+ # Which is the same as
214
+ #
215
+ # c.equals(:view, :x).minus(10)
216
+ def plus(constant)
217
+ unless self.relationship
218
+ constant = -constant
219
+ end
220
+ self.constant += constant
221
+ self
222
+ end
223
+
224
+ def minus(constant)
225
+ plus -constant
226
+ end
227
+
228
+ def priority(priority=nil)
229
+ return @priority if priority.nil?
230
+
231
+ @priority = priority
232
+ self
233
+ end
234
+
235
+ def identifier(identifier=nil)
236
+ return @identifier if identifier.nil?
237
+
238
+ @identifier = identifier
239
+ self
240
+ end
241
+ alias identified_by identifier
242
+ alias id identifier
243
+
244
+ def update_constraint
245
+ if @resolved
246
+ constraint = @resolved[0]
247
+
248
+ constraint.constant = self.constant
249
+ end
250
+ end
251
+
252
+ def resolve_all(layout, view)
253
+ @resolved ||= begin
254
+ item = Constraint.view_lookup(layout, view, self.target)
255
+ rel_item = Constraint.view_lookup(layout, view, self.relative_to)
256
+
257
+ nsconstraint = NSLayoutConstraint.constraintWithItem(item,
258
+ attribute: Constraint.attribute_lookup(self.attribute),
259
+ relatedBy: Constraint.relationship_lookup(self.relationship),
260
+ toItem: rel_item,
261
+ attribute: Constraint.attribute_lookup(self.attribute2),
262
+ multiplier: self.multiplier,
263
+ constant: self.constant
264
+ )
265
+
266
+ if self.priority
267
+ nsconstraint.priority = Constraint.priority_lookup(self.priority)
268
+ end
269
+
270
+ if self.identifier
271
+ nsconstraint.setIdentifier(self.identifier)
272
+ end
273
+
274
+ [nsconstraint]
275
+ end
276
+ end
277
+
278
+ class << self
279
+
280
+ def axis_lookup(axis)
281
+ case axis
282
+ when :horizontal
283
+ axis = UILayoutConstraintAxisHorizontal
284
+ when :vertical
285
+ axis = UILayoutConstraintAxisVertical
286
+ end
287
+
288
+ return axis
289
+ end
290
+
291
+ def orientation_lookup(orientation)
292
+ case orientation
293
+ when :horizontal
294
+ orientation = NSLayoutConstraintOrientationHorizontal
295
+ when :vertical
296
+ orientation = NSLayoutConstraintOrientationVertical
297
+ end
298
+
299
+ return orientation
300
+ end
301
+
302
+ def view_lookup(layout, view, target)
303
+ if ! target || target.is_a?(MotionKit.base_view_class)
304
+ target
305
+ elsif target.is_a?(ConstraintPlaceholder)
306
+ target.resolve(layout)
307
+ elsif target == :superview
308
+ view.superview
309
+ else
310
+ layout.get(target)
311
+ end
312
+ end
313
+
314
+ def attribute_lookup(attribute)
315
+ if attribute.is_a? Fixnum
316
+ return attribute
317
+ end
318
+
319
+ unless Attributes.key? attribute
320
+ raise InvalidAttributeError.new("Unsupported attribute #{attribute.inspect}")
321
+ end
322
+
323
+ Attributes[attribute]
324
+ end
325
+
326
+ def priority_lookup(priority)
327
+ if priority.is_a? Fixnum
328
+ return priority
329
+ end
330
+
331
+ unless Priorities.key? priority
332
+ raise InvalidPriorityError.new("Unsupported priority #{priority.inspect}")
333
+ end
334
+
335
+ Priorities[priority]
336
+ end
337
+
338
+ def relationship_lookup(relationship)
339
+ if relationship.is_a? Fixnum
340
+ return relationship
341
+ end
342
+
343
+ unless Relationships.key? relationship
344
+ raise InvalidRelationshipError.new("Unsupported relationship #{relationship.inspect}")
345
+ end
346
+
347
+ Relationships[relationship]
348
+ end
349
+
350
+ def attribute_reverse(attribute)
351
+ Attributes.key(attribute) || :none
352
+ end
353
+
354
+ def relationship_reverse(relationship)
355
+ Relationships.key(relationship)
356
+ end
357
+
358
+ def calculate?(value)
359
+ value.is_a?(String)
360
+ end
361
+
362
+ def constant?(value)
363
+ value.is_a?(Numeric) || value.is_a?(Hash) || value.is_a?(Array)
364
+ end
365
+
366
+ end
367
+
368
+ end
369
+
370
+ class CompoundConstraint < Constraint
371
+
372
+ def initialize(target, attribute=nil, relationship=:equal)
373
+ super
374
+ @constant = [0, 0]
375
+ @multiplier = [1, 1]
376
+ end
377
+
378
+ def update_constraint
379
+ if @resolved
380
+ [0, 1].each do |index|
381
+ constraint = @resolved[index]
382
+ constraint.constant = self.constant[index]
383
+ end
384
+ end
385
+ end
386
+
387
+ end
388
+
389
+ class SizeConstraint < CompoundConstraint
390
+
391
+ def initialize(target, attribute=nil, relationship=:equal)
392
+ super
393
+ @attribute = [:width, :height]
394
+ @attribute2 = [:width, :height]
395
+ end
396
+
397
+ def attribute=(value)
398
+ raise NoMethodError.new('attribute=')
399
+ end
400
+
401
+ def attribute2=(value)
402
+ raise NoMethodError.new('attribute2=')
403
+ end
404
+
405
+ def constant=(constant)
406
+ if constant.is_a?(Array)
407
+ @constant = constant[0..1]
408
+ elsif constant.is_a?(Hash)
409
+ @constant = [0, 0]
410
+
411
+ if constant.key?(:w)
412
+ @constant[0] = constant[:w]
413
+ elsif constant.key?(:width)
414
+ @constant[0] = constant[:width]
415
+ end
416
+
417
+ if constant.key?(:h)
418
+ @constant[1] = constant[:h]
419
+ elsif constant.key?(:height)
420
+ @constant[1] = constant[:height]
421
+ end
422
+ else
423
+ @constant = [constant, constant]
424
+ end
425
+
426
+ self.update_constraint
427
+ end
428
+
429
+ def multiplier=(multiplier)
430
+ if multiplier.is_a?(Array)
431
+ @multiplier = multiplier[0..1]
432
+ elsif multiplier.is_a?(Hash)
433
+ @multiplier = [0, 0]
434
+
435
+ if multiplier.key?(:w)
436
+ @multiplier[0] = multiplier[:w]
437
+ elsif multiplier.key?(:width)
438
+ @multiplier[0] = multiplier[:width]
439
+ end
440
+
441
+ if multiplier.key?(:h)
442
+ @multiplier[1] = multiplier[:h]
443
+ elsif multiplier.key?(:height)
444
+ @multiplier[1] = multiplier[:height]
445
+ end
446
+ else
447
+ @multiplier = [multiplier, multiplier]
448
+ end
449
+
450
+ self.update_constraint
451
+ end
452
+
453
+ def plus(constant)
454
+ if constant.is_a?(Array)
455
+ self.constant[0] += constant[0]
456
+ self.constant[1] += constant[1]
457
+ elsif constant.is_a?(Hash)
458
+ if constant.key?(:w)
459
+ self.constant[0] += constant[:w]
460
+ elsif constant.key?(:width)
461
+ self.constant[0] += constant[:width]
462
+ end
463
+
464
+ if constant.key?(:h)
465
+ self.constant[1] += constant[:h]
466
+ elsif constant.key?(:height)
467
+ self.constant[1] += constant[:height]
468
+ end
469
+ else
470
+ self.constant[0] += constant
471
+ self.constant[1] += constant
472
+ end
473
+
474
+ self.update_constraint
475
+ self
476
+ end
477
+
478
+ def minus(constant)
479
+ if constant.is_a?(Array)
480
+ self.constant[0] -= constant[0]
481
+ self.constant[1] -= constant[1]
482
+ elsif constant.is_a?(Hash)
483
+ if constant.key?(:w)
484
+ self.constant[0] -= constant[:w]
485
+ elsif constant.key?(:width)
486
+ self.constant[0] -= constant[:width]
487
+ end
488
+
489
+ if constant.key?(:h)
490
+ self.constant[1] -= constant[:h]
491
+ elsif constant.key?(:height)
492
+ self.constant[1] -= constant[:height]
493
+ end
494
+ else
495
+ self.constant[0] -= constant
496
+ self.constant[1] -= constant
497
+ end
498
+
499
+ self.update_constraint
500
+ self
501
+ end
502
+
503
+ def times(multiplier)
504
+ if multiplier.is_a?(Array)
505
+ self.multiplier[0] *= multiplier[0]
506
+ self.multiplier[1] *= multiplier[1]
507
+ elsif multiplier.is_a?(Hash)
508
+ if multiplier.key?(:w)
509
+ self.multiplier[0] *= multiplier[:w]
510
+ elsif multiplier.key?(:width)
511
+ self.multiplier[0] *= multiplier[:width]
512
+ end
513
+
514
+ if multiplier.key?(:h)
515
+ self.multiplier[1] *= multiplier[:h]
516
+ elsif multiplier.key?(:height)
517
+ self.multiplier[1] *= multiplier[:height]
518
+ end
519
+ else
520
+ self.multiplier[0] *= multiplier
521
+ self.multiplier[1] *= multiplier
522
+ end
523
+
524
+ self.update_constraint
525
+ self
526
+ end
527
+
528
+ def divided_by(multiplier)
529
+ if multiplier.is_a?(Array)
530
+ self.multiplier[0] /= multiplier[0].to_f
531
+ self.multiplier[1] /= multiplier[1].to_f
532
+ elsif multiplier.is_a?(Hash)
533
+ if multiplier.key?(:w)
534
+ self.multiplier[0] /= multiplier[:w].to_f
535
+ elsif multiplier.key?(:width)
536
+ self.multiplier[0] /= multiplier[:width].to_f
537
+ end
538
+
539
+ if multiplier.key?(:h)
540
+ self.multiplier[1] /= multiplier[:h].to_f
541
+ elsif multiplier.key?(:height)
542
+ self.multiplier[1] /= multiplier[:height].to_f
543
+ end
544
+ else
545
+ self.multiplier[0] /= multiplier.to_f
546
+ self.multiplier[1] /= multiplier.to_f
547
+ end
548
+
549
+ self.update_constraint
550
+ self
551
+ end
552
+
553
+ def resolve_all(layout, view)
554
+ @resolved ||= begin
555
+ item = Constraint.view_lookup(layout, view, self.target)
556
+ rel_item = Constraint.view_lookup(layout, view, self.relative_to)
557
+
558
+ [[:width, 0], [:height, 1]].map do |attribute, index|
559
+ nsconstraint = NSLayoutConstraint.constraintWithItem(item,
560
+ attribute: Constraint.attribute_lookup(attribute),
561
+ relatedBy: Constraint.relationship_lookup(self.relationship),
562
+ toItem: rel_item,
563
+ attribute: Constraint.attribute_lookup(attribute),
564
+ multiplier: self.multiplier[index],
565
+ constant: self.constant[index]
566
+ )
567
+
568
+ if self.priority
569
+ nsconstraint.priority = Constraint.priority_lookup(self.priority)
570
+ end
571
+
572
+ if self.identifier
573
+ nsconstraint.setIdentifier(self.identifier)
574
+ end
575
+
576
+ nsconstraint
577
+ end
578
+ end
579
+ end
580
+
581
+ end
582
+
583
+ class PointConstraint < CompoundConstraint
584
+
585
+ def constant=(constant)
586
+ if constant.is_a?(Array)
587
+ @constant = constant[0..1]
588
+ elsif constant.is_a?(Hash)
589
+ @constant = [0, 0]
590
+
591
+ if constant.key?(:x)
592
+ @constant[0] = constant[:x]
593
+ end
594
+
595
+ if constant.key?(:y)
596
+ @constant[1] = constant[:y]
597
+ end
598
+ else
599
+ @constant = [constant, constant]
600
+ end
601
+
602
+ self.relative_to ||= :superview
603
+ self.update_constraint
604
+ end
605
+
606
+ def multiplier=(multiplier)
607
+ if multiplier.is_a?(Array)
608
+ @multiplier = multiplier[0..1]
609
+ elsif multiplier.is_a?(Hash)
610
+ @multiplier = [0, 0]
611
+
612
+ if multiplier.key?(:x)
613
+ @multiplier[0] = multiplier[:x]
614
+ end
615
+
616
+ if multiplier.key?(:y)
617
+ @multiplier[1] = multiplier[:y]
618
+ end
619
+ else
620
+ @multiplier = [multiplier, multiplier]
621
+ end
622
+
623
+ self.update_constraint
624
+ end
625
+
626
+ def plus(constant)
627
+ if constant.is_a?(Array)
628
+ self.constant[0] += constant[0]
629
+ self.constant[1] += constant[1]
630
+ elsif constant.is_a?(Hash)
631
+ if constant.key?(:x)
632
+ self.constant[0] += constant[:x]
633
+ elsif constant.key?(:right)
634
+ self.constant[0] += constant[:right]
635
+ elsif constant.key?(:left)
636
+ self.constant[0] -= constant[:left]
637
+ end
638
+
639
+ if constant.key?(:y)
640
+ self.constant[1] += constant[:y]
641
+ elsif constant.key?(:up)
642
+ self.constant[1] += constant[:up]
643
+ elsif constant.key?(:down)
644
+ self.constant[1] -= constant[:down]
645
+ end
646
+ else
647
+ self.constant[0] += constant
648
+ self.constant[1] += constant
649
+ end
650
+
651
+ self.update_constraint
652
+ self
653
+ end
654
+
655
+ def minus(constant)
656
+ if constant.is_a?(Array)
657
+ self.constant[0] -= constant[0]
658
+ self.constant[1] -= constant[1]
659
+ elsif constant.is_a?(Hash)
660
+ if constant.key?(:x)
661
+ self.constant[0] -= constant[:x]
662
+ elsif constant.key?(:right)
663
+ self.constant[0] -= constant[:right]
664
+ elsif constant.key?(:left)
665
+ self.constant[0] += constant[:left]
666
+ end
667
+
668
+ if constant.key?(:y)
669
+ self.constant[1] -= constant[:y]
670
+ elsif constant.key?(:up)
671
+ self.constant[1] -= constant[:up]
672
+ elsif constant.key?(:down)
673
+ self.constant[1] += constant[:down]
674
+ end
675
+ else
676
+ self.constant[0] -= constant
677
+ self.constant[1] -= constant
678
+ end
679
+
680
+ self.update_constraint
681
+ self
682
+ end
683
+
684
+ def times(multiplier)
685
+ if multiplier.is_a?(Array)
686
+ self.multiplier[0] *= multiplier[0]
687
+ self.multiplier[1] *= multiplier[1]
688
+ elsif multiplier.is_a?(Hash)
689
+ if multiplier.key?(:x)
690
+ self.multiplier[0] *= multiplier[:x]
691
+ end
692
+
693
+ if multiplier.key?(:y)
694
+ self.multiplier[1] *= multiplier[:y]
695
+ end
696
+ else
697
+ self.multiplier[0] *= multiplier
698
+ self.multiplier[1] *= multiplier
699
+ end
700
+
701
+ self.update_constraint
702
+ self
703
+ end
704
+
705
+ def divided_by(multiplier)
706
+ if multiplier.is_a?(Array)
707
+ self.multiplier[0] /= multiplier[0].to_f
708
+ self.multiplier[1] /= multiplier[1].to_f
709
+ elsif multiplier.is_a?(Hash)
710
+ if multiplier.key?(:x)
711
+ self.multiplier[0] /= multiplier[:x].to_f
712
+ end
713
+
714
+ if multiplier.key?(:y)
715
+ self.multiplier[1] /= multiplier[:y].to_f
716
+ end
717
+ else
718
+ self.multiplier[0] /= multiplier.to_f
719
+ self.multiplier[1] /= multiplier.to_f
720
+ end
721
+
722
+ self.update_constraint
723
+ self
724
+ end
725
+
726
+ def update_constraint
727
+ if @resolved
728
+ @resolved.each do
729
+ end
730
+ end
731
+ end
732
+
733
+ def resolve_all(layout, view)
734
+ @resolved ||= begin
735
+ item = Constraint.view_lookup(layout, view, self.target)
736
+ rel_item = Constraint.view_lookup(layout, view, self.relative_to)
737
+
738
+ [0, 1].map do |index|
739
+ attribute = Constraint.attribute_lookup(self.attribute[index])
740
+
741
+ nsconstraint = NSLayoutConstraint.constraintWithItem(item,
742
+ attribute: attribute,
743
+ relatedBy: Constraint.relationship_lookup(self.relationship),
744
+ toItem: rel_item,
745
+ attribute: attribute,
746
+ multiplier: self.multiplier[index],
747
+ constant: self.constant[index]
748
+ )
749
+
750
+ if self.priority
751
+ nsconstraint.priority = Constraint.priority_lookup(self.priority)
752
+ end
753
+
754
+ if self.identifier
755
+ nsconstraint.setIdentifier(self.identifier)
756
+ end
757
+
758
+ nsconstraint
759
+ end
760
+ end
761
+ end
762
+
763
+ end
764
+
765
+ end