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.



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

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
end

Instance Attribute Details

#attributeObject

Returns the value of attribute attribute.



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

def attribute
  @attribute
end

#attribute2Object

Returns the value of attribute attribute2.



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

def attribute2
  @attribute2
end

#constantObject

Returns the value of attribute constant.



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

def constant
  @constant
end

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



235
236
237
238
239
240
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 235

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

  @identifier = identifier
  self
end

#multiplierObject

Returns the value of attribute multiplier.



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

def multiplier
  @multiplier
end

#priority(priority = nil) ⇒ Object



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

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

  @priority = priority
  self
end

#relationshipObject

Returns the value of attribute relationship.



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

def relationship
  @relationship
end

#relative_toObject

Returns the value of attribute relative_to.



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

def relative_to
  @relative_to
end

#targetObject

Returns the value of attribute target.



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

def target
  @target
end

Class Method Details

.attribute_lookup(attribute) ⇒ Object



313
314
315
316
317
318
319
320
321
322
323
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 313

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



349
350
351
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 349

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

.axis_lookup(axis) ⇒ Object



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

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

  return axis
end

.calculate?(value) ⇒ Boolean

Returns:

  • (Boolean)


357
358
359
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 357

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

.constant?(value) ⇒ Boolean

Returns:

  • (Boolean)


361
362
363
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 361

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

.orientation_lookup(orientation) ⇒ Object



290
291
292
293
294
295
296
297
298
299
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 290

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

  return orientation
end

.priority_lookup(priority) ⇒ Object



325
326
327
328
329
330
331
332
333
334
335
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 325

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



337
338
339
340
341
342
343
344
345
346
347
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 337

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



353
354
355
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 353

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

.view_lookup(layout, view, target) ⇒ Object



301
302
303
304
305
306
307
308
309
310
311
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 301

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

Instance Method Details

#<=(compare) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 100

def <=(compare)
  if @compare_flag
    if @relationship && Constraint.relationship_lookup(@relationship) != NSLayoutRelationEqual
      raise InvalidRelationshipError.new("You cannot use `.is <=` on a constraint that is already defined as #{@relationship}")
    end

    lte(compare)
    @compare_flag = false

    self
  else
    super
  end
end

#==(compare) ⇒ Object



74
75
76
77
78
79
80
81
82
83
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 74

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

    self
  else
    super
  end
end

#>=(compare) ⇒ Object



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

def >=(compare)
  if @compare_flag
    if @relationship && Constraint.relationship_lookup(@relationship) != NSLayoutRelationEqual
      raise InvalidRelationshipError.new("You cannot use `.is >=` on a constraint that is already defined as #{@relationship}")
    end

    gte(compare)
    @compare_flag = false

    self
  else
    super
  end
end

#divided_by(multiplier) ⇒ Object



205
206
207
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 205

def divided_by(multiplier)
  times 1.0/multiplier
end

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



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 115

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



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 155

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
width.is >= 100
height.is <= 200


66
67
68
69
70
71
72
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 66

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



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 135

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



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

def minus(constant)
  plus -constant
end

#of(target, attribute2 = nil) ⇒ Object

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



176
177
178
179
180
181
182
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 176

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)


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

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

#resolve_all(layout, view) ⇒ Object



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

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)

    nsconstraint = NSLayoutConstraint.constraintWithItem(item,
      attribute: Constraint.attribute_lookup(self.attribute),
      relatedBy: Constraint.relationship_lookup(self.relationship),
      toItem: rel_item,
      attribute: Constraint.attribute_lookup(self.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



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

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

#update_constraintObject



243
244
245
246
247
248
249
# File 'lib/motion-kit-cocoa/constraints/constraint.rb', line 243

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

    constraint.constant = self.constant
  end
end