Class: MotionKit::Constraint

Inherits:
Object
  • Object
show all
Defined in:
lib/motion-kit-cocoa/constraints/constraint.rb

Direct Known Subclasses

CompoundConstraint

Constant Summary collapse

Priorities =
{
  required: 1000,  # NSLayoutPriorityRequired
  high: 750,  # NSLayoutPriorityDefaultHigh
  medium: 500,
  low: 250,  # NSLayoutPriorityDefaultLow
}
Relationships =

NSLayoutPriorityDefaultLow

{
  equal: NSLayoutRelationEqual,
  lte: NSLayoutRelationLessThanOrEqual,
  gte: NSLayoutRelationGreaterThanOrEqual,
}
Attributes =
{
  none: NSLayoutAttributeNotAnAttribute,
  left: NSLayoutAttributeLeft,
  right: NSLayoutAttributeRight,
  top: NSLayoutAttributeTop,
  bottom: NSLayoutAttributeBottom,
  leading: NSLayoutAttributeLeading,
  trailing: NSLayoutAttributeTrailing,
  width: NSLayoutAttributeWidth,
  height: NSLayoutAttributeHeight,
  center_x: NSLayoutAttributeCenterX,
  center_y: NSLayoutAttributeCenterY,
  baseline: NSLayoutAttributeBaseline,
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(target, attribute = nil, relationship) ⇒ Constraint

Returns a new instance of Constraint.



48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 48

def initialize(target, attribute=nil, relationship)
  @target = target
  @attribute = attribute
  @attribute2 = attribute
  @relative_to = nil
  @relationship = relationship
  @multiplier = 1
  @constant = 0
  @priority = nil
  @compare_flag = false
  @active = true
end

Instance Attribute Details

#attributeObject

Returns the value of attribute attribute.



13
14
15
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 13

def attribute
  @attribute
end

#attribute2Object

Returns the value of attribute attribute2.



16
17
18
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 16

def attribute2
  @attribute2
end

#constantObject

Returns the value of attribute constant.



18
19
20
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 18

def constant
  @constant
end

#identifier(identifier = nil) ⇒ Object Also known as: identified_by



229
230
231
232
233
234
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 229

def identifier(identifier=nil)
  return @identifier if identifier.nil?

  @identifier = identifier
  self
end

#multiplierObject

Returns the value of attribute multiplier.



17
18
19
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 17

def multiplier
  @multiplier
end

#priority(priority = nil) ⇒ Object



222
223
224
225
226
227
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 222

def priority(priority=nil)
  return @priority if priority.nil?

  @priority = priority
  self
end

#relationshipObject

Returns the value of attribute relationship.



14
15
16
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 14

def relationship
  @relationship
end

#relative_toObject

Returns the value of attribute relative_to.



15
16
17
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 15

def relative_to
  @relative_to
end

#targetObject

Returns the value of attribute target.



12
13
14
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 12

def target
  @target
end

Class Method Details

.attribute_lookup(attribute) ⇒ Object



376
377
378
379
380
381
382
383
384
385
386
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 376

def attribute_lookup(attribute)
  if attribute.is_a? Fixnum
    return attribute
  end

  unless Attributes.key? attribute
    raise InvalidAttributeError.new("Unsupported attribute #{attribute.inspect}")
  end

  Attributes[attribute]
end

.attribute_reverse(attribute) ⇒ Object



412
413
414
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 412

def attribute_reverse(attribute)
  Attributes.key(attribute) || :none
end

.axis_lookup(axis) ⇒ Object



342
343
344
345
346
347
348
349
350
351
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 342

def axis_lookup(axis)
  case axis
  when :horizontal
    UILayoutConstraintAxisHorizontal
  when :vertical
    UILayoutConstraintAxisVertical
  else
    axis
  end
end

.calculate?(value) ⇒ Boolean

Returns:

  • (Boolean)


420
421
422
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 420

def calculate?(value)
  value.is_a?(String)
end

.constant?(value) ⇒ Boolean

Returns:

  • (Boolean)


424
425
426
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 424

def constant?(value)
  value.is_a?(Numeric) || value.is_a?(Hash) || value.is_a?(Array)
end

.orientation_lookup(orientation) ⇒ Object



353
354
355
356
357
358
359
360
361
362
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 353

def orientation_lookup(orientation)
  case orientation
  when :horizontal
    NSLayoutConstraintOrientationHorizontal
  when :vertical
    NSLayoutConstraintOrientationVertical
  else
    orientation
  end
end

.priority_lookup(priority) ⇒ Object



388
389
390
391
392
393
394
395
396
397
398
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 388

def priority_lookup(priority)
  if priority.is_a? Fixnum
    return priority
  end

  unless Priorities.key? priority
    raise InvalidPriorityError.new("Unsupported priority #{priority.inspect}")
  end

  Priorities[priority]
end

.relationship_lookup(relationship) ⇒ Object



400
401
402
403
404
405
406
407
408
409
410
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 400

def relationship_lookup(relationship)
  if relationship.is_a? Fixnum
    return relationship
  end

  unless Relationships.key? relationship
    raise InvalidRelationshipError.new("Unsupported relationship #{relationship.inspect}")
  end

  Relationships[relationship]
end

.relationship_reverse(relationship) ⇒ Object



416
417
418
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 416

def relationship_reverse(relationship)
  Relationships.key(relationship)
end

.view_lookup(layout, view, target) ⇒ Object



364
365
366
367
368
369
370
371
372
373
374
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 364

def view_lookup(layout, view, target)
  if ! target || target.is_a?(MotionKit.base_view_class)
    target
  elsif target == :self
    view
  elsif target == :superview
    view.superview
  else
    layout.get_view(target)
  end
end

Instance Method Details

#<=(compare) ⇒ Object



99
100
101
102
103
104
105
106
107
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 99

def <=(compare)
  if @compare_flag
    lte(compare)

    self
  else
    super
  end
end

#==(compare) ⇒ Object



79
80
81
82
83
84
85
86
87
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 79

def ==(compare)
  if @compare_flag
    equals(compare)

    self
  else
    super
  end
end

#>=(compare) ⇒ Object



89
90
91
92
93
94
95
96
97
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 89

def >=(compare)
  if @compare_flag
    gte(compare)

    self
  else
    super
  end
end

#activateObject



294
295
296
297
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 294

def activate
  self.active = true
  self
end

#activeObject



274
275
276
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 274

def active
  @active
end

#active=(active) ⇒ Object



278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 278

def active=(active)
  if @resolved
    if active
      @resolved.each do |constraint|
        common_ancestor.addConstraint(constraint)
      end
    else
      @resolved.each do |constraint|
        common_ancestor.removeConstraint(constraint)
      end
    end
  else
    @active = active
  end
end

#common_ancestorObject



304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 304

def common_ancestor
  if @resolved
    @common_ancestor ||= begin
      constraint = @resolved[0]
      base_view_class = MotionKit.base_view_class

      if constraint.firstItem.is_a?(base_view_class) && constraint.secondItem.is_a?(base_view_class)
        common_ancestor = nil

        ancestors = [constraint.firstItem]
        parent_view = constraint.firstItem
        while parent_view = parent_view.superview
          ancestors << parent_view
        end

        current_view = constraint.secondItem
        while current_view
          if ancestors.include? current_view
            common_ancestor = current_view
            break
          end
          current_view = current_view.superview
        end

        unless common_ancestor
          raise NoCommonAncestorError.new("No common ancestors between #{constraint.firstItem} and #{constraint.secondItem}")
        end
      else
        common_ancestor = constraint.firstItem
      end

      common_ancestor
    end
  end
end

#deactivateObject



299
300
301
302
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 299

def deactivate
  self.active = false
  self
end

#divided_by(multiplier) ⇒ Object



199
200
201
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 199

def divided_by(multiplier)
  times 1.0/multiplier
end

#equals(target, attribute2 = nil) ⇒ Object Also known as: is_equal_to, equal_to



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 109

def equals(target, attribute2=nil)
  self.relationship ||= :equal
  if Constraint.constant?(target)
    self.constant = target
  elsif Constraint.calculate?(target)
    calc = Calculator.scan(target)
    self.multiplier = calc.factor
    self.constant = calc.constant || 0
  else
    self.relative_to = target
    if attribute2
      self.attribute2 = attribute2
    end
  end
  @compare_flag = false
  self
end

#gte(target, attribute2 = nil) ⇒ Object Also known as: is_at_least, at_least



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 149

def gte(target, attribute2=nil)
  self.relationship = :gte
  if Constraint.constant?(target)
    self.constant = target
  elsif Constraint.calculate?(target)
    calc = Calculator.scan(target)
    self.multiplier = calc.factor
    self.constant = calc.constant || 0
  else
    self.relative_to = target
    if attribute2
      self.attribute2 = attribute2
    end
  end
  @compare_flag = false
  self
end

#is(value = nil) ⇒ Object

like ‘equals`, but also sets `compare_flag` to true, so you can use ==, <=, and >=

Examples:

x.is(10)
x.is(10).priority(:required)
x.is == 10
(x.is == 10).priority :required
width.is >= 100
height.is <= 200


71
72
73
74
75
76
77
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 71

def is(value=nil)
  if value
    self.equals(value)
  end
  @compare_flag = true
  self
end

#lte(target, attribute2 = nil) ⇒ Object Also known as: is_at_most, at_most



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 129

def lte(target, attribute2=nil)
  self.relationship = :lte
  if Constraint.constant?(target)
    self.constant = target
  elsif Constraint.calculate?(target)
    calc = Calculator.scan(target)
    self.multiplier = calc.factor
    self.constant = calc.constant || 0
  else
    self.relative_to = target
    if attribute2
      self.attribute2 = attribute2
    end
  end
  @compare_flag = false
  self
end

#minus(constant) ⇒ Object



218
219
220
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 218

def minus(constant)
  plus -constant
end

#of(target, attribute2 = nil) ⇒ Object

width.is(‘100%’).of(:view, :width)



170
171
172
173
174
175
176
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 170

def of(target, attribute2=nil)
  self.relative_to = target
  if attribute2
    self.attribute2 = attribute2
  end
  self
end

#plus(constant) ⇒ Object

If no relationship has been set, the “use case” here is:

c.plus(10).equals(:view, :x)

Which is the same as

c.equals(:view, :x).minus(10)


210
211
212
213
214
215
216
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 210

def plus(constant)
  unless self.relationship
    constant = -constant
  end
  self.constant += constant
  self
end

#resolve_all(layout, view) ⇒ Object



245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 245

def resolve_all(layout, view)
  @resolved ||= begin
    item = Constraint.view_lookup(layout, view, self.target)
    rel_item = Constraint.view_lookup(layout, view, self.relative_to)
    relationship = Constraint.relationship_lookup(self.relationship)
    attribute1 = Constraint.attribute_lookup(self.attribute)
    attribute2 = Constraint.attribute_lookup(self.attribute2)

    nsconstraint = NSLayoutConstraint.constraintWithItem(item,
      attribute: attribute1,
      relatedBy: relationship,
      toItem: rel_item,
      attribute: attribute2,
      multiplier: self.multiplier,
      constant: self.constant
      )

    if self.priority
      nsconstraint.priority = Constraint.priority_lookup(self.priority)
    end

    if self.identifier
      nsconstraint.setIdentifier(self.identifier)
    end

    [nsconstraint]
  end
end

#times(multiplier) ⇒ Object



194
195
196
197
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 194

def times(multiplier)
  self.multiplier *= multiplier
  self
end

#update_constraintObject



237
238
239
240
241
242
243
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 237

def update_constraint
  if @resolved
    constraint = @resolved[0]

    constraint.constant = self.constant
  end
end