motion-kit 0.0.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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