mirror of
https://github.com/robb/Cartography.git
synced 2024-10-06 21:47:18 +03:00
Merge branch 'master' into xcode6-3
This commit is contained in:
commit
4b41a72f48
@ -1,7 +1,7 @@
|
||||
Pod::Spec.new do |s|
|
||||
|
||||
s.name = "Cartography"
|
||||
s.version = "0.2.1"
|
||||
s.version = "0.3.0-beta1"
|
||||
s.summary = "Declarative Auto Layout in Swift"
|
||||
|
||||
s.description = <<-DESC
|
||||
|
@ -14,42 +14,107 @@ import AppKit
|
||||
|
||||
private func makeEqual<P: RelativeEquality>(attribute: LayoutProxy -> P, first: LayoutProxy, rest: [LayoutProxy]) -> [NSLayoutConstraint] {
|
||||
return reduce(rest, []) { acc, current in
|
||||
current.view.car_translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
return acc + [ attribute(first) == attribute(current) ]
|
||||
}
|
||||
}
|
||||
|
||||
/// Aligns multiple views by their top edge.
|
||||
///
|
||||
/// All views passed to this function will have
|
||||
/// their `translatesAutoresizingMaskIntoConstraints` properties set to `false`.
|
||||
///
|
||||
/// :returns: An array of `NSLayoutConstraint` instances.
|
||||
///
|
||||
public func align(top first: LayoutProxy, rest: LayoutProxy...) -> [NSLayoutConstraint] {
|
||||
return makeEqual({ $0.top }, first, rest)
|
||||
}
|
||||
|
||||
/// Aligns multiple views by their right edge.
|
||||
///
|
||||
/// All views passed to this function will have
|
||||
/// their `translatesAutoresizingMaskIntoConstraints` properties set to `false`.
|
||||
///
|
||||
/// :returns: An array of `NSLayoutConstraint` instances.
|
||||
///
|
||||
public func align(right first: LayoutProxy, rest: LayoutProxy...) -> [NSLayoutConstraint] {
|
||||
return makeEqual({ $0.right }, first, rest)
|
||||
}
|
||||
|
||||
/// Aligns multiple views by their bottom edge.
|
||||
///
|
||||
/// All views passed to this function will have
|
||||
/// their `translatesAutoresizingMaskIntoConstraints` properties set to `false`.
|
||||
///
|
||||
/// :returns: An array of `NSLayoutConstraint` instances.
|
||||
///
|
||||
public func align(bottom first: LayoutProxy, rest: LayoutProxy...) -> [NSLayoutConstraint] {
|
||||
return makeEqual({ $0.bottom }, first, rest)
|
||||
}
|
||||
|
||||
/// Aligns multiple views by their left edge.
|
||||
///
|
||||
/// All views passed to this function will have
|
||||
/// their `translatesAutoresizingMaskIntoConstraints` properties set to `false`.
|
||||
///
|
||||
/// :returns: An array of `NSLayoutConstraint` instances.
|
||||
///
|
||||
public func align(left first: LayoutProxy, rest: LayoutProxy...) -> [NSLayoutConstraint] {
|
||||
return makeEqual({ $0.left }, first, rest)
|
||||
}
|
||||
|
||||
/// Aligns multiple views by their leading edge.
|
||||
///
|
||||
/// All views passed to this function will have
|
||||
/// their `translatesAutoresizingMaskIntoConstraints` properties set to `false`.
|
||||
///
|
||||
/// :returns: An array of `NSLayoutConstraint` instances.
|
||||
///
|
||||
public func align(leading first: LayoutProxy, rest: LayoutProxy...) -> [NSLayoutConstraint] {
|
||||
return makeEqual({ $0.leading }, first, rest)
|
||||
}
|
||||
|
||||
/// Aligns multiple vies by their trailing edge.
|
||||
///
|
||||
/// All views passed to this function will have
|
||||
/// their `translatesAutoresizingMaskIntoConstraints` properties set to `false`.
|
||||
///
|
||||
/// :returns: An array of `NSLayoutConstraint` instances.
|
||||
///
|
||||
public func align(trailing first: LayoutProxy, rest: LayoutProxy...) -> [NSLayoutConstraint] {
|
||||
return makeEqual({ $0.trailing }, first, rest)
|
||||
}
|
||||
|
||||
/// Aligns multiple views by their horizontal center.
|
||||
///
|
||||
/// All views passed to this function will have
|
||||
/// their `translatesAutoresizingMaskIntoConstraints` properties set to `false`.
|
||||
///
|
||||
/// :returns: An array of `NSLayoutConstraint` instances.
|
||||
///
|
||||
public func align(centerX first: LayoutProxy, rest: LayoutProxy...) -> [NSLayoutConstraint] {
|
||||
return makeEqual({ $0.centerX }, first, rest)
|
||||
}
|
||||
|
||||
/// Aligns multiple views by their vertical center.
|
||||
///
|
||||
/// All views passed to this function will have
|
||||
/// their `translatesAutoresizingMaskIntoConstraints` properties set to `false`.
|
||||
///
|
||||
/// :returns: An array of `NSLayoutConstraint` instances.
|
||||
///
|
||||
public func align(centerY first: LayoutProxy, rest: LayoutProxy...) -> [NSLayoutConstraint] {
|
||||
return makeEqual({ $0.centerY }, first, rest)
|
||||
}
|
||||
|
||||
/// Aligns multiple views by their baseline.
|
||||
///
|
||||
/// All views passed to this function will have
|
||||
/// their `translatesAutoresizingMaskIntoConstraints` properties set to `false`.
|
||||
///
|
||||
/// :returns: An array of `NSLayoutConstraint` instances.
|
||||
///
|
||||
public func align(baseline first: LayoutProxy, rest: LayoutProxy...) -> [NSLayoutConstraint] {
|
||||
return makeEqual({ $0.baseline }, first, rest)
|
||||
}
|
||||
|
@ -16,37 +16,25 @@ public class Context {
|
||||
internal var constraints: [Constraint] = []
|
||||
|
||||
internal func addConstraint(from: Property, to: Property? = nil, coefficients: Coefficients = Coefficients(), relation: NSLayoutRelation = .Equal) -> NSLayoutConstraint {
|
||||
from.view.car_disableTranslatesAutoresizingMaskIntoConstraintsIfPossible()
|
||||
to?.view.car_disableTranslatesAutoresizingMaskIntoConstraintsIfPossible()
|
||||
|
||||
var toAttribute: NSLayoutAttribute! = NSLayoutAttribute.NotAnAttribute
|
||||
|
||||
if to == nil {
|
||||
toAttribute = NSLayoutAttribute.NotAnAttribute
|
||||
} else {
|
||||
toAttribute = to!.attribute
|
||||
}
|
||||
|
||||
var targetView: View
|
||||
|
||||
if let toView = to?.view {
|
||||
let target = closestCommonAncestor(from.view, toView)
|
||||
assert(target != .None, "No common superview found between \(from.view) and \(toView)")
|
||||
|
||||
targetView = target!
|
||||
} else {
|
||||
targetView = from.view
|
||||
}
|
||||
from.view.car_translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
let layoutConstraint = NSLayoutConstraint(item: from.view,
|
||||
attribute: from.attribute,
|
||||
relatedBy: relation,
|
||||
toItem: to?.view,
|
||||
attribute: toAttribute,
|
||||
attribute: to?.attribute ?? .NotAnAttribute,
|
||||
multiplier: CGFloat(coefficients.multiplier),
|
||||
constant: CGFloat(coefficients.constant))
|
||||
|
||||
constraints += [ Constraint(view: targetView, layoutConstraint: layoutConstraint) ]
|
||||
let targetView: View = to.map { to in
|
||||
let commonSuperivew = closestCommonAncestor(from.view, to.view)
|
||||
|
||||
assert(commonSuperivew != .None, "No common superview found between \(from.view) and \(to.view)")
|
||||
|
||||
return commonSuperivew!
|
||||
} ?? from.view
|
||||
|
||||
constraints.append(Constraint(view: targetView, layoutConstraint: layoutConstraint))
|
||||
|
||||
return layoutConstraint
|
||||
}
|
||||
|
@ -11,6 +11,8 @@ import Foundation
|
||||
typealias Accumulator = ([NSLayoutConstraint], LayoutProxy)
|
||||
|
||||
private func reduce(first: LayoutProxy, rest: [LayoutProxy], combine: (LayoutProxy, LayoutProxy) -> NSLayoutConstraint) -> [NSLayoutConstraint] {
|
||||
rest.last?.view.car_translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
return reduce(rest, ([], first)) { (acc, current) -> Accumulator in
|
||||
var (constraints, previous) = acc
|
||||
|
||||
@ -18,14 +20,44 @@ private func reduce(first: LayoutProxy, rest: [LayoutProxy], combine: (LayoutPro
|
||||
}.0
|
||||
}
|
||||
|
||||
/// Distributes multiple views horizontally.
|
||||
///
|
||||
/// All views passed to this function will have
|
||||
/// their `translatesAutoresizingMaskIntoConstraints` properties set to `false`.
|
||||
///
|
||||
/// :param: amount The distance between the views.
|
||||
/// :param: views The views to distribute.
|
||||
///
|
||||
/// :returns: An array of `NSLayoutConstraint` instances.
|
||||
///
|
||||
public func distribute(by amount: Double, horizontally first: LayoutProxy, rest: LayoutProxy...) -> [NSLayoutConstraint] {
|
||||
return reduce(first, rest) { $0.trailing + amount == $1.leading }
|
||||
return reduce(first, rest) { $0.trailing == $1.leading - amount }
|
||||
}
|
||||
|
||||
/// Distributes multiple views horizontally from left to right.
|
||||
///
|
||||
/// All views passed to this function will have
|
||||
/// their `translatesAutoresizingMaskIntoConstraints` properties set to `false`.
|
||||
///
|
||||
/// :param: amount The distance between the views.
|
||||
/// :param: views The views to distribute.
|
||||
///
|
||||
/// :returns: An array of `NSLayoutConstraint` instances.
|
||||
///
|
||||
public func distribute(by amount: Double, leftToRight first: LayoutProxy, rest: LayoutProxy...) -> [NSLayoutConstraint] {
|
||||
return reduce(first, rest) { $0.right + amount == $1.left }
|
||||
return reduce(first, rest) { $0.right == $1.left - amount }
|
||||
}
|
||||
|
||||
/// Distributes multiple views vertically.
|
||||
///
|
||||
/// All views passed to this function will have
|
||||
/// their `translatesAutoresizingMaskIntoConstraints` properties set to `false`.
|
||||
///
|
||||
/// :param: amount The distance between the views.
|
||||
/// :param: views The views to distribute.
|
||||
///
|
||||
/// :returns: An array of `NSLayoutConstraint` instances.
|
||||
///
|
||||
public func distribute(by amount: Double, vertically first: LayoutProxy, rest: LayoutProxy...) -> [NSLayoutConstraint] {
|
||||
return reduce(first, rest) { $0.bottom + amount == $1.top }
|
||||
return reduce(first, rest) { $0.bottom == $1.top - amount }
|
||||
}
|
||||
|
@ -35,14 +35,41 @@ public enum Edges : Compound {
|
||||
}
|
||||
}
|
||||
|
||||
/// Insets all edges.
|
||||
///
|
||||
/// :param: edges The edges to inset.
|
||||
/// :param: all The amount by which to inset all edges, in points.
|
||||
///
|
||||
/// :returns: A new expression with the inset edges.
|
||||
///
|
||||
public func inset(edges: Edges, all: Number) -> Expression<Edges> {
|
||||
return inset(edges, all, all, all, all)
|
||||
}
|
||||
|
||||
/// Insets the horizontal and vertical edges.
|
||||
///
|
||||
/// :param: edges The edges to inset.
|
||||
/// :param: horizontal The amount by which to inset the horizontal edges, in
|
||||
/// points.
|
||||
/// :param: vertical The amount by which to inset the vertical edges, in
|
||||
/// points.
|
||||
///
|
||||
/// :returns: A new expression with the inset edges.
|
||||
///
|
||||
public func inset(edges: Edges, horizontal: Number, vertical: Number) -> Expression<Edges> {
|
||||
return inset(edges, vertical, horizontal, vertical, horizontal)
|
||||
}
|
||||
|
||||
/// Insets edges individually.
|
||||
///
|
||||
/// :param: edges The edges to inset.
|
||||
/// :param: top The amount by which to inset the top edge, in points.
|
||||
/// :param: leading The amount by which to inset the leading edge, in points.
|
||||
/// :param: bottom The amount by which to inset the bottom edge, in points.
|
||||
/// :param: trailing The amount by which to inset the trailing edge, in points.
|
||||
///
|
||||
/// :returns: A new expression with the inset edges.
|
||||
///
|
||||
public func inset(edges: Edges, top: Number, leading: Number, bottom: Number, trailing: Number) -> Expression<Edges> {
|
||||
return Expression(edges, [
|
||||
Coefficients(1, top.doubleValue),
|
||||
@ -54,40 +81,76 @@ public func inset(edges: Edges, top: Number, leading: Number, bottom: Number, tr
|
||||
|
||||
// MARK: Equality
|
||||
|
||||
/// Declares a property equal to the result of an expression.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The expression.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func == (lhs: Edges, rhs: Expression<Edges>) -> [NSLayoutConstraint] {
|
||||
return lhs.context.addConstraint(lhs, coefficients: rhs.coefficients, to: rhs.value)
|
||||
}
|
||||
|
||||
public func == (lhs: Expression<Edges>, rhs: Edges) -> [NSLayoutConstraint] {
|
||||
return rhs == lhs
|
||||
}
|
||||
|
||||
/// Declares a property equal to another property.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The other property.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func == (lhs: Edges, rhs: Edges) -> [NSLayoutConstraint] {
|
||||
return lhs.context.addConstraint(lhs, to: rhs)
|
||||
}
|
||||
|
||||
// MARK: Inequality
|
||||
|
||||
/// Declares a property less than or equal to another property.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The other property.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func <= (lhs: Edges, rhs: Edges) -> [NSLayoutConstraint] {
|
||||
return lhs.context.addConstraint(lhs, to: rhs, relation: NSLayoutRelation.LessThanOrEqual)
|
||||
}
|
||||
|
||||
/// Declares a property greater than or equal to another property.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The other property.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func >= (lhs: Edges, rhs: Edges) -> [NSLayoutConstraint] {
|
||||
return lhs.context.addConstraint(lhs, to: rhs, relation: NSLayoutRelation.GreaterThanOrEqual)
|
||||
}
|
||||
|
||||
/// Declares a property less than or equal to the result of an expression.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The expression.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func <= (lhs: Edges, rhs: Expression<Edges>) -> [NSLayoutConstraint] {
|
||||
return lhs.context.addConstraint(lhs, coefficients: rhs.coefficients, to: rhs.value, relation: NSLayoutRelation.LessThanOrEqual)
|
||||
}
|
||||
|
||||
public func <= (lhs: Expression<Edges>, rhs: Edges) -> [NSLayoutConstraint] {
|
||||
return rhs >= lhs
|
||||
}
|
||||
|
||||
/// Declares a property greater than or equal to the result of an expression.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The expression.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func >= (lhs: Edges, rhs: Expression<Edges>) -> [NSLayoutConstraint] {
|
||||
return lhs.context.addConstraint(lhs, coefficients: rhs.coefficients, to: rhs.value, relation: NSLayoutRelation.GreaterThanOrEqual)
|
||||
}
|
||||
|
||||
public func >= (lhs: Expression<Edges>, rhs: Edges) -> [NSLayoutConstraint] {
|
||||
return rhs <= lhs
|
||||
}
|
||||
|
@ -8,6 +8,14 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Layouts a single view.
|
||||
///
|
||||
/// The views will have its layout updated after this call.
|
||||
///
|
||||
/// :param: view The view to layout.
|
||||
/// :param: replace The `ConstraintGroup` whose constraints should be replaced.
|
||||
/// :param: block A block that declares the layout for `view`.
|
||||
///
|
||||
public func layout(view: View, replace group: ConstraintGroup = ConstraintGroup(), block: LayoutProxy -> ()) -> ConstraintGroup {
|
||||
let context = Context()
|
||||
block(LayoutProxy(context, view))
|
||||
@ -16,22 +24,49 @@ public func layout(view: View, replace group: ConstraintGroup = ConstraintGroup(
|
||||
return group
|
||||
}
|
||||
|
||||
public func layout(v1: View, v2: View, replace group: ConstraintGroup = ConstraintGroup(), block: (LayoutProxy, LayoutProxy) -> ()) -> ConstraintGroup {
|
||||
/// Layouts two views.
|
||||
///
|
||||
/// The views will have their layout updated after this call.
|
||||
///
|
||||
/// :param: view1 A view to layout.
|
||||
/// :param: view2 A view to layout.
|
||||
/// :param: replace The `ConstraintGroup` whose constraints should be replaced.
|
||||
/// :param: block A block that declares the layout for the views.
|
||||
///
|
||||
public func layout(view1: View, view2: View, replace group: ConstraintGroup = ConstraintGroup(), block: (LayoutProxy, LayoutProxy) -> ()) -> ConstraintGroup {
|
||||
let context = Context()
|
||||
block(LayoutProxy(context, v1), LayoutProxy(context, v2))
|
||||
block(LayoutProxy(context, view1), LayoutProxy(context, view2))
|
||||
group.replaceConstraints(context.constraints, performLayout: true)
|
||||
|
||||
return group
|
||||
}
|
||||
|
||||
public func layout(v1: View, v2: View, v3: View, replace group: ConstraintGroup = ConstraintGroup(), block: (LayoutProxy, LayoutProxy, LayoutProxy) -> ()) -> ConstraintGroup {
|
||||
/// Layouts three views.
|
||||
///
|
||||
/// The views will have their layout updated after this call.
|
||||
///
|
||||
/// :param: view1 A view to layout.
|
||||
/// :param: view2 A view to layout.
|
||||
/// :param: view3 A view to layout.
|
||||
/// :param: replace The `ConstraintGroup` whose constraints should be replaced.
|
||||
/// :param: block A block that declares the layout for the views.
|
||||
///
|
||||
public func layout(view1: View, view2: View, view3: View, replace group: ConstraintGroup = ConstraintGroup(), block: (LayoutProxy, LayoutProxy, LayoutProxy) -> ()) -> ConstraintGroup {
|
||||
let context = Context()
|
||||
block(LayoutProxy(context, v1), LayoutProxy(context, v2), LayoutProxy(context, v3))
|
||||
block(LayoutProxy(context, view1), LayoutProxy(context, view2), LayoutProxy(context, view3))
|
||||
group.replaceConstraints(context.constraints, performLayout: true)
|
||||
|
||||
return group
|
||||
}
|
||||
|
||||
/// Layouts an array of views.
|
||||
///
|
||||
/// The views will have their layout updated after this call.
|
||||
///
|
||||
/// :param: views The views to layout.
|
||||
/// :param: replace The `ConstraintGroup` whose constraints should be replaced.
|
||||
/// :param: block A block that declares the layout for `views`.
|
||||
///
|
||||
public func layout(views: [View], replace group: ConstraintGroup = ConstraintGroup(), block: ([LayoutProxy]) -> ()) -> ConstraintGroup {
|
||||
let context = Context()
|
||||
block(views.map({ LayoutProxy(context, $0) }))
|
||||
@ -40,6 +75,14 @@ public func layout(views: [View], replace group: ConstraintGroup = ConstraintGro
|
||||
return group
|
||||
}
|
||||
|
||||
/// Layouts a dictioary of views.
|
||||
///
|
||||
/// The views will have their layout updated after this call.
|
||||
///
|
||||
/// :param: views The views to layout.
|
||||
/// :param: replace The `ConstraintGroup` whose constraints should be replaced.
|
||||
/// :param: block A block that declares the layout for `views`.
|
||||
///
|
||||
public func layout<T: Hashable>(views: [T: View], replace group: ConstraintGroup = ConstraintGroup(), block: ([T : LayoutProxy] -> ())) -> ConstraintGroup {
|
||||
let context = Context()
|
||||
let proxies = map(views) { ($0, LayoutProxy(context, $1)) }
|
||||
@ -49,10 +92,22 @@ public func layout<T: Hashable>(views: [T: View], replace group: ConstraintGroup
|
||||
return group
|
||||
}
|
||||
|
||||
/// Removes all constraints for a group.
|
||||
///
|
||||
/// The affected views will have their layout updated after this call.
|
||||
///
|
||||
/// :param: clear The `ConstraintGroup` whose constraints should be removed.
|
||||
///
|
||||
public func layout(clear group: ConstraintGroup) {
|
||||
group.replaceConstraints([], performLayout: true)
|
||||
}
|
||||
|
||||
/// Updates the constraints of a single view.
|
||||
///
|
||||
/// :param: view The view to layout.
|
||||
/// :param: replace The `ConstraintGroup` whose constraints should be replaced.
|
||||
/// :param: block A block that declares the layout for `view`.
|
||||
///
|
||||
public func constrain(view: View, replace group: ConstraintGroup = ConstraintGroup(), block: LayoutProxy -> ()) -> ConstraintGroup {
|
||||
let context = Context()
|
||||
block(LayoutProxy(context, view))
|
||||
@ -61,6 +116,13 @@ public func constrain(view: View, replace group: ConstraintGroup = ConstraintGro
|
||||
return group
|
||||
}
|
||||
|
||||
/// Updates the constraints of two views.
|
||||
///
|
||||
/// :param: view1 A view to layout.
|
||||
/// :param: view2 A view to layout.
|
||||
/// :param: replace The `ConstraintGroup` whose constraints should be replaced.
|
||||
/// :param: block A block that declares the layout for the views.
|
||||
///
|
||||
public func constrain(v1: View, v2: View, replace group: ConstraintGroup = ConstraintGroup(), block: (LayoutProxy, LayoutProxy) -> ()) -> ConstraintGroup {
|
||||
let context = Context()
|
||||
block(LayoutProxy(context, v1), LayoutProxy(context, v2))
|
||||
@ -69,6 +131,14 @@ public func constrain(v1: View, v2: View, replace group: ConstraintGroup = Const
|
||||
return group
|
||||
}
|
||||
|
||||
/// Updates the constraints of three views.
|
||||
///
|
||||
/// :param: view1 A view to layout.
|
||||
/// :param: view2 A view to layout.
|
||||
/// :param: view3 A view to layout.
|
||||
/// :param: replace The `ConstraintGroup` whose constraints should be replaced.
|
||||
/// :param: block A block that declares the layout for the views.
|
||||
///
|
||||
public func constrain(v1: View, v2: View, v3: View, replace group: ConstraintGroup = ConstraintGroup(), block: (LayoutProxy, LayoutProxy, LayoutProxy) -> ()) -> ConstraintGroup {
|
||||
let context = Context()
|
||||
block(LayoutProxy(context, v1), LayoutProxy(context, v2), LayoutProxy(context, v3))
|
||||
@ -77,6 +147,12 @@ public func constrain(v1: View, v2: View, v3: View, replace group: ConstraintGro
|
||||
return group
|
||||
}
|
||||
|
||||
/// Updates the constraints of an array of views.
|
||||
///
|
||||
/// :param: views The views to layout.
|
||||
/// :param: replace The `ConstraintGroup` whose constraints should be replaced.
|
||||
/// :param: block A block that declares the layout for `views`.
|
||||
///
|
||||
public func constrain(views: [View], replace group: ConstraintGroup = ConstraintGroup(), block: ([LayoutProxy]) -> ()) -> ConstraintGroup {
|
||||
let context = Context()
|
||||
block(views.map({ LayoutProxy(context, $0) }))
|
||||
@ -85,6 +161,12 @@ public func constrain(views: [View], replace group: ConstraintGroup = Constraint
|
||||
return group
|
||||
}
|
||||
|
||||
/// Updates the constraints of a dictionary of views.
|
||||
///
|
||||
/// :param: views The views to layout.
|
||||
/// :param: replace The `ConstraintGroup` whose constraints should be replaced.
|
||||
/// :param: block A block that declares the layout for `views`.
|
||||
///
|
||||
public func constrain<T: Hashable>(views: [T: View], replace group: ConstraintGroup = ConstraintGroup(), block: ([T : LayoutProxy] -> ())) -> ConstraintGroup {
|
||||
let context = Context()
|
||||
let proxies = map(views) { ($0, LayoutProxy(context, $1)) }
|
||||
@ -94,6 +176,10 @@ public func constrain<T: Hashable>(views: [T: View], replace group: ConstraintGr
|
||||
return group
|
||||
}
|
||||
|
||||
/// Removes all constraints for a group.
|
||||
///
|
||||
/// :param: clear The `ConstraintGroup` whose constraints should be removed.
|
||||
///
|
||||
public func constrain(clear group: ConstraintGroup) {
|
||||
group.replaceConstraints([], performLayout: false)
|
||||
}
|
||||
|
@ -9,30 +9,54 @@
|
||||
import Foundation
|
||||
|
||||
public class LayoutProxy {
|
||||
/// The width of the view.
|
||||
public let width: Dimension
|
||||
|
||||
/// The height of the view.
|
||||
public let height: Dimension
|
||||
|
||||
/// The size of the view. This property affects both `width` and `height`.
|
||||
public let size: Size
|
||||
|
||||
/// The top edge of the view.
|
||||
public let top: Edge
|
||||
|
||||
/// The right edge of the view.
|
||||
public let right: Edge
|
||||
|
||||
/// The bottom edge of the view.
|
||||
public let bottom: Edge
|
||||
|
||||
/// The left edge of the view.
|
||||
public let left: Edge
|
||||
|
||||
/// All edges of the view. This property affects `top`, `bottom`, `leading`
|
||||
/// and `trailing`.
|
||||
public let edges: Edges
|
||||
|
||||
/// The leading edge of the view.
|
||||
public let leading: Edge
|
||||
|
||||
/// The trailing edge of the view.
|
||||
public let trailing: Edge
|
||||
|
||||
/// The horizontal center of the view.
|
||||
public let centerX: Edge
|
||||
|
||||
/// The vertical center of the view.
|
||||
public let centerY: Edge
|
||||
|
||||
/// The center point of the view. This property affects `centerX` and
|
||||
/// `centerY`.
|
||||
public let center: Point
|
||||
|
||||
/// The baseline of the view.
|
||||
public let baseline: Edge
|
||||
|
||||
internal let context: Context
|
||||
internal let view: View
|
||||
|
||||
/// The superview of the view, if it exists.
|
||||
public var superview: LayoutProxy? {
|
||||
if let superview = view.superview {
|
||||
return LayoutProxy(context, superview)
|
||||
|
@ -32,40 +32,76 @@ public enum Point: Compound {
|
||||
|
||||
// MARK: Equality
|
||||
|
||||
/// Declares a property equal to the result of an expression.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The expression.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func == (lhs: Point, rhs: Expression<Point>) -> [NSLayoutConstraint] {
|
||||
return lhs.context.addConstraint(lhs, coefficients: rhs.coefficients, to: rhs.value)
|
||||
}
|
||||
|
||||
public func == (lhs: Expression<Point>, rhs: Point) -> [NSLayoutConstraint] {
|
||||
return rhs == lhs
|
||||
}
|
||||
|
||||
/// Declares a property equal to another property.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The other property.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func == (lhs: Point, rhs: Point) -> [NSLayoutConstraint] {
|
||||
return lhs.context.addConstraint(lhs, to: rhs)
|
||||
}
|
||||
|
||||
// MARK: Inequality
|
||||
|
||||
/// Declares a property less than or equal to another property.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The other property.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func <= (lhs: Point, rhs: Point) -> [NSLayoutConstraint] {
|
||||
return lhs.context.addConstraint(lhs, to: rhs, relation: NSLayoutRelation.LessThanOrEqual)
|
||||
}
|
||||
|
||||
/// Declares a property greater than or equal to another property.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The other property.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func >= (lhs: Point, rhs: Point) -> [NSLayoutConstraint] {
|
||||
return lhs.context.addConstraint(lhs, to: rhs, relation: NSLayoutRelation.GreaterThanOrEqual)
|
||||
}
|
||||
|
||||
/// Declares a property less than or equal to the result of an expression.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The expression.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func <= (lhs: Point, rhs: Expression<Point>) -> [NSLayoutConstraint] {
|
||||
return lhs.context.addConstraint(lhs, coefficients: rhs.coefficients, to: rhs.value, relation: NSLayoutRelation.LessThanOrEqual)
|
||||
}
|
||||
|
||||
public func <= (lhs: Expression<Point>, rhs: Point) -> [NSLayoutConstraint] {
|
||||
return rhs >= lhs
|
||||
}
|
||||
|
||||
/// Declares a property greater than or equal to the result of an expression.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The expression.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func >= (lhs: Point, rhs: Expression<Point>) -> [NSLayoutConstraint] {
|
||||
return lhs.context.addConstraint(lhs, coefficients: rhs.coefficients, to: rhs.value, relation: NSLayoutRelation.GreaterThanOrEqual)
|
||||
}
|
||||
|
||||
public func >= (lhs: Expression<Point>, rhs: Point) -> [NSLayoutConstraint] {
|
||||
return rhs <= lhs
|
||||
}
|
||||
|
@ -8,19 +8,37 @@
|
||||
|
||||
#if os(iOS)
|
||||
import UIKit
|
||||
|
||||
public typealias LayoutPriority = UILayoutPriority
|
||||
#else
|
||||
import AppKit
|
||||
|
||||
public typealias LayoutPriority = NSLayoutPriority
|
||||
#endif
|
||||
|
||||
infix operator ~ { }
|
||||
|
||||
public func ~ (lhs: NSLayoutConstraint, rhs: Float) -> NSLayoutConstraint {
|
||||
/// Sets the priority for a constraint.
|
||||
///
|
||||
/// :param: lhs The constraint to update.
|
||||
/// :param: rhs The new priority.
|
||||
///
|
||||
/// :returns: The same constraint with its priority updated.
|
||||
///
|
||||
public func ~ (lhs: NSLayoutConstraint, rhs: LayoutPriority) -> NSLayoutConstraint {
|
||||
lhs.priority = rhs
|
||||
|
||||
return lhs
|
||||
}
|
||||
|
||||
public func ~ (lhs: [NSLayoutConstraint], rhs: Float) -> [NSLayoutConstraint] {
|
||||
/// Sets the priority for multiple constraints.
|
||||
///
|
||||
/// :param: lhs An array of `NSLayoutConstraint` instances.
|
||||
/// :param: rhs The new priority.
|
||||
///
|
||||
/// :returns: The same constraints with their priorities updated.
|
||||
///
|
||||
public func ~ (lhs: [NSLayoutConstraint], rhs: LayoutPriority) -> [NSLayoutConstraint] {
|
||||
return lhs.map {
|
||||
$0 ~ rhs
|
||||
}
|
||||
|
@ -24,26 +24,40 @@ public protocol Property {
|
||||
/// numerical constants.
|
||||
public protocol NumericalEquality : Property { }
|
||||
|
||||
/// Declares a property equal to a numerical constant.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The numerical constant.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func == (lhs: NumericalEquality, rhs: Number) -> NSLayoutConstraint {
|
||||
return lhs.context.addConstraint(lhs, coefficients: Coefficients(1, rhs))
|
||||
}
|
||||
|
||||
public func == (lhs: Number, rhs: NumericalEquality) -> NSLayoutConstraint {
|
||||
return rhs == lhs
|
||||
}
|
||||
|
||||
/// Properties conforming to this protocol can use the `==` operator with other
|
||||
/// properties of the same type.
|
||||
public protocol RelativeEquality : Property { }
|
||||
|
||||
/// Declares a property equal to a the result of an expression.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The expression.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func == <P: RelativeEquality>(lhs: P, rhs: Expression<P>) -> NSLayoutConstraint {
|
||||
return lhs.context.addConstraint(lhs, coefficients: rhs.coefficients[0], to: rhs.value)
|
||||
}
|
||||
|
||||
public func == <P: RelativeEquality>(lhs: Expression<P>, rhs: P) -> NSLayoutConstraint {
|
||||
return rhs == lhs
|
||||
}
|
||||
|
||||
/// Declares a property equal to another property.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The other property.
|
||||
///
|
||||
public func == <P: RelativeEquality>(lhs: P, rhs: P) -> NSLayoutConstraint {
|
||||
return lhs.context.addConstraint(lhs, to: rhs)
|
||||
}
|
||||
@ -54,50 +68,82 @@ public func == <P: RelativeEquality>(lhs: P, rhs: P) -> NSLayoutConstraint {
|
||||
/// with numerical constants.
|
||||
public protocol NumericalInequality : Property { }
|
||||
|
||||
/// Declares a property less than or equal to a numerical constant.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The numerical constant.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func <= (lhs: NumericalInequality, rhs: Number) -> NSLayoutConstraint {
|
||||
return lhs.context.addConstraint(lhs, coefficients: Coefficients(1, rhs), relation: NSLayoutRelation.LessThanOrEqual)
|
||||
}
|
||||
|
||||
public func <= (lhs: Number, rhs: NumericalInequality) -> NSLayoutConstraint {
|
||||
return rhs >= lhs
|
||||
}
|
||||
|
||||
/// Declares a property greater than or equal to a numerical constant.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The numerical constant.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func >= (lhs: NumericalInequality, rhs: Number) -> NSLayoutConstraint {
|
||||
return lhs.context.addConstraint(lhs, coefficients: Coefficients(1, rhs), relation: NSLayoutRelation.GreaterThanOrEqual)
|
||||
}
|
||||
|
||||
public func >= (lhs: Number, rhs: NumericalInequality) -> NSLayoutConstraint {
|
||||
return rhs <= lhs
|
||||
}
|
||||
|
||||
/// Properties conforming to this protocol can use the `<=` and `>=` operators
|
||||
/// with other properties of the same type.
|
||||
public protocol RelativeInequality : Property { }
|
||||
|
||||
/// Declares a property less than or equal to another property.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The other property.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func <= <P: RelativeInequality>(lhs: P, rhs: P) -> NSLayoutConstraint {
|
||||
return lhs.context.addConstraint(lhs, to: rhs, relation: NSLayoutRelation.LessThanOrEqual)
|
||||
}
|
||||
|
||||
/// Declares a property greater than or equal to another property.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The other property.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func >= <P: RelativeInequality>(lhs: P, rhs: P) -> NSLayoutConstraint {
|
||||
return lhs.context.addConstraint(lhs, to: rhs, relation: NSLayoutRelation.GreaterThanOrEqual)
|
||||
}
|
||||
|
||||
/// Declares a property less than or equal to the result of an expression.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The other property.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func <= <P: RelativeInequality>(lhs: P, rhs: Expression<P>) -> NSLayoutConstraint {
|
||||
return lhs.context.addConstraint(lhs, coefficients: rhs.coefficients[0], to: rhs.value, relation: NSLayoutRelation.LessThanOrEqual)
|
||||
}
|
||||
|
||||
public func <= <P: RelativeInequality>(lhs: Expression<P>, rhs: P) -> NSLayoutConstraint {
|
||||
return rhs >= lhs
|
||||
}
|
||||
|
||||
/// Declares a property greater than or equal to the result of an expression.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The other property.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func >= <P: RelativeInequality>(lhs: P, rhs: Expression<P>) -> NSLayoutConstraint {
|
||||
return lhs.context.addConstraint(lhs, coefficients: rhs.coefficients[0], to: rhs.value, relation: NSLayoutRelation.GreaterThanOrEqual)
|
||||
}
|
||||
|
||||
public func >= <P: RelativeInequality>(lhs: Expression<P>, rhs: P) -> NSLayoutConstraint {
|
||||
return rhs <= lhs
|
||||
}
|
||||
|
||||
// Mark: Addition
|
||||
|
||||
public protocol Addition : Property { }
|
||||
@ -154,18 +200,10 @@ public func * <P: Multiplication>(lhs: P, rhs: Number) -> Expression<P> {
|
||||
return rhs * lhs
|
||||
}
|
||||
|
||||
public func / <P: Multiplication>(m: Number, rhs: Expression<P>) -> Expression<P> {
|
||||
return Expression(rhs.value, rhs.coefficients.map { $0 / m })
|
||||
}
|
||||
|
||||
public func / <P: Multiplication>(lhs: Expression<P>, rhs: Number) -> Expression<P> {
|
||||
return rhs / lhs
|
||||
}
|
||||
|
||||
public func / <P: Multiplication>(m: Number, rhs: P) -> Expression<P> {
|
||||
return Expression(rhs, [ Coefficients(1 / m.doubleValue, 0) ])
|
||||
return lhs * (1 / rhs.doubleValue)
|
||||
}
|
||||
|
||||
public func / <P: Multiplication>(lhs: P, rhs: Number) -> Expression<P> {
|
||||
return rhs / lhs
|
||||
return lhs * (1 / rhs.doubleValue)
|
||||
}
|
||||
|
@ -32,44 +32,80 @@ public enum Size : Compound {
|
||||
|
||||
// MARK: Equality
|
||||
|
||||
/// Declares a property equal to the result of an expression.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The expression.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func == (lhs: Size, rhs: Expression<Size>) -> [NSLayoutConstraint] {
|
||||
return lhs.context.addConstraint(lhs, coefficients: rhs.coefficients, to: rhs.value)
|
||||
}
|
||||
|
||||
public func == (lhs: Expression<Size>, rhs: Size) -> [NSLayoutConstraint] {
|
||||
return rhs == lhs
|
||||
}
|
||||
|
||||
/// Declares a property equal to another property.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The other property.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func == (lhs: Size, rhs: Size) -> [NSLayoutConstraint] {
|
||||
return lhs.context.addConstraint(lhs, to: rhs)
|
||||
}
|
||||
|
||||
// MARK: Inequality
|
||||
|
||||
/// Declares a property less than or equal to another property.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The other property.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func <= (lhs: Size, rhs: Size) -> [NSLayoutConstraint] {
|
||||
return lhs.context.addConstraint(lhs, to: rhs, relation: NSLayoutRelation.LessThanOrEqual)
|
||||
}
|
||||
|
||||
/// Declares a property greater than or equal to another property.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The other property.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func >= (lhs: Size, rhs: Size) -> [NSLayoutConstraint] {
|
||||
return lhs.context.addConstraint(lhs, to: rhs, relation: NSLayoutRelation.GreaterThanOrEqual)
|
||||
}
|
||||
|
||||
/// Declares a property less than or equal to the result of an expression.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The expression.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func <= (lhs: Size, rhs: Expression<Size>) -> [NSLayoutConstraint] {
|
||||
return lhs.context.addConstraint(lhs, coefficients: rhs.coefficients, to: rhs.value, relation: NSLayoutRelation.LessThanOrEqual)
|
||||
}
|
||||
|
||||
public func <= (lhs: Expression<Size>, rhs: Size) -> [NSLayoutConstraint] {
|
||||
return rhs >= lhs
|
||||
}
|
||||
|
||||
/// Declares a property greater than or equal to the result of an expression.
|
||||
///
|
||||
/// :param: lhs The affected property. The associated view will have
|
||||
/// `translatesAutoresizingMaskIntoConstraints` set to `false`.
|
||||
/// :param: rhs The expression.
|
||||
///
|
||||
/// :returns: An `NSLayoutConstraint`.
|
||||
///
|
||||
public func >= (lhs: Size, rhs: Expression<Size>) -> [NSLayoutConstraint] {
|
||||
return lhs.context.addConstraint(lhs, coefficients: rhs.coefficients, to: rhs.value, relation: NSLayoutRelation.GreaterThanOrEqual)
|
||||
}
|
||||
|
||||
public func >= (lhs: Expression<Size>, rhs: Size) -> [NSLayoutConstraint] {
|
||||
return rhs <= lhs
|
||||
}
|
||||
|
||||
// MARK: Multiplication
|
||||
|
||||
public func * (m: Number, rhs: Expression<Size>) -> Expression<Size> {
|
||||
@ -90,18 +126,10 @@ public func * (lhs: Size, rhs: Number) -> Expression<Size> {
|
||||
|
||||
// MARK: Division
|
||||
|
||||
public func / (m: Number, rhs: Expression<Size>) -> Expression<Size> {
|
||||
return Expression(rhs.value, rhs.coefficients.map { $0 / m.doubleValue })
|
||||
}
|
||||
|
||||
public func / (lhs: Expression<Size>, rhs: Number) -> Expression<Size> {
|
||||
return rhs / lhs
|
||||
}
|
||||
|
||||
public func / (m: Number, rhs: Size) -> Expression<Size> {
|
||||
return Expression(rhs, [ Coefficients(1 / m.doubleValue, 0), Coefficients(1 / m.doubleValue, 0) ])
|
||||
return lhs * (1 / rhs.doubleValue)
|
||||
}
|
||||
|
||||
public func / (lhs: Size, rhs: Number) -> Expression<Size> {
|
||||
return rhs / lhs
|
||||
return lhs * (1 / rhs.doubleValue)
|
||||
}
|
||||
|
@ -17,28 +17,9 @@ import Foundation
|
||||
layoutIfNeeded()
|
||||
}
|
||||
|
||||
func car_disableTranslatesAutoresizingMaskIntoConstraintsIfPossible() {
|
||||
if !car_isOwnedByViewController {
|
||||
setTranslatesAutoresizingMaskIntoConstraints(false)
|
||||
}
|
||||
}
|
||||
|
||||
private var car_isOwnedByViewController: Bool {
|
||||
return self === car_closestViewController?.view
|
||||
}
|
||||
|
||||
private var car_closestViewController: UIViewController? {
|
||||
var responder: UIResponder = self
|
||||
|
||||
while let nextResponder = nextResponder() {
|
||||
if nextResponder === responder { break }
|
||||
|
||||
responder = nextResponder
|
||||
|
||||
if nextResponder.isKindOfClass(UIViewController.Type) { break }
|
||||
}
|
||||
|
||||
return responder as? UIViewController
|
||||
public var car_translatesAutoresizingMaskIntoConstraints: Bool {
|
||||
get { return translatesAutoresizingMaskIntoConstraints() }
|
||||
set { setTranslatesAutoresizingMaskIntoConstraints(newValue) }
|
||||
}
|
||||
}
|
||||
#else
|
||||
@ -50,8 +31,9 @@ import Foundation
|
||||
(superview ?? self).layoutSubtreeIfNeeded()
|
||||
}
|
||||
|
||||
func car_disableTranslatesAutoresizingMaskIntoConstraintsIfPossible() {
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
public var car_translatesAutoresizingMaskIntoConstraints: Bool {
|
||||
get { return translatesAutoresizingMaskIntoConstraints }
|
||||
set { translatesAutoresizingMaskIntoConstraints = newValue }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -67,4 +49,4 @@ extension View {
|
||||
objc_setAssociatedObject(self, &InstalledLayoutConstraintsKey, newValue, objc_AssociationPolicy(OBJC_ASSOCIATION_COPY_NONATOMIC))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,14 +6,12 @@
|
||||
// Copyright (c) 2014 Robert Böhnke. All rights reserved.
|
||||
//
|
||||
|
||||
#if os(iOS) && TEST
|
||||
#if TEST
|
||||
import Cartography
|
||||
#elseif os(iOS)
|
||||
import UIKit
|
||||
typealias View = UIView
|
||||
#elseif TEST
|
||||
import AppKit
|
||||
typealias View = NSView
|
||||
#else
|
||||
import Foundation
|
||||
import AppKit
|
||||
#endif
|
||||
|
||||
func closestCommonAncestor(a: View, b: View) -> View? {
|
||||
|
@ -46,6 +46,10 @@ class AlignTests: XCTestCase {
|
||||
|
||||
XCTAssertEqual(viewA.frame, viewB.frame, "It should align the edges")
|
||||
XCTAssertEqual(viewA.frame, viewC.frame, "It should align the edges")
|
||||
|
||||
XCTAssertFalse(viewA.car_translatesAutoresizingMaskIntoConstraints)
|
||||
XCTAssertFalse(viewB.car_translatesAutoresizingMaskIntoConstraints)
|
||||
XCTAssertFalse(viewC.car_translatesAutoresizingMaskIntoConstraints)
|
||||
}
|
||||
|
||||
func testAlignCenter() {
|
||||
@ -59,5 +63,9 @@ class AlignTests: XCTestCase {
|
||||
|
||||
XCTAssertEqual(viewA.frame, viewB.frame, "It should align the edges")
|
||||
XCTAssertEqual(viewA.frame, viewC.frame, "It should align the edges")
|
||||
|
||||
XCTAssertFalse(viewA.car_translatesAutoresizingMaskIntoConstraints)
|
||||
XCTAssertFalse(viewB.car_translatesAutoresizingMaskIntoConstraints)
|
||||
XCTAssertFalse(viewC.car_translatesAutoresizingMaskIntoConstraints)
|
||||
}
|
||||
}
|
||||
|
@ -34,8 +34,8 @@ class DistributeTests: XCTestCase {
|
||||
viewA.top == viewA.superview!.top
|
||||
viewA.left == viewA.superview!.left
|
||||
|
||||
viewB.size == viewA.size
|
||||
viewC.size == viewA.size
|
||||
viewA.size == viewB.size
|
||||
viewA.size == viewC.size
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,6 +48,10 @@ class DistributeTests: XCTestCase {
|
||||
XCTAssertEqual(viewA.frame, CGRect(x: 0, y: 0, width: 100, height: 100), "It should distribute the views")
|
||||
XCTAssertEqual(viewB.frame, CGRect(x: 110, y: 0, width: 100, height: 100), "It should distribute the views")
|
||||
XCTAssertEqual(viewC.frame, CGRect(x: 220, y: 0, width: 100, height: 100), "It should distribute the views")
|
||||
|
||||
XCTAssertFalse(viewA.car_translatesAutoresizingMaskIntoConstraints)
|
||||
XCTAssertFalse(viewB.car_translatesAutoresizingMaskIntoConstraints)
|
||||
XCTAssertFalse(viewC.car_translatesAutoresizingMaskIntoConstraints)
|
||||
}
|
||||
|
||||
func testDistributeLeftToRight() {
|
||||
@ -59,6 +63,10 @@ class DistributeTests: XCTestCase {
|
||||
XCTAssertEqual(viewA.frame, CGRect(x: 0, y: 0, width: 100, height: 100), "It should distribute the views")
|
||||
XCTAssertEqual(viewB.frame, CGRect(x: 110, y: 0, width: 100, height: 100), "It should distribute the views")
|
||||
XCTAssertEqual(viewC.frame, CGRect(x: 220, y: 0, width: 100, height: 100), "It should distribute the views")
|
||||
|
||||
XCTAssertFalse(viewA.car_translatesAutoresizingMaskIntoConstraints)
|
||||
XCTAssertFalse(viewB.car_translatesAutoresizingMaskIntoConstraints)
|
||||
XCTAssertFalse(viewC.car_translatesAutoresizingMaskIntoConstraints)
|
||||
}
|
||||
|
||||
func testDistributeVertically() {
|
||||
@ -70,6 +78,9 @@ class DistributeTests: XCTestCase {
|
||||
XCTAssertEqual(viewA.frame, CGRect(x: 0, y: 0, width: 100, height: 100), "It should distribute the views")
|
||||
XCTAssertEqual(viewB.frame, CGRect(x: 0, y: 110, width: 100, height: 100), "It should distribute the views")
|
||||
XCTAssertEqual(viewC.frame, CGRect(x: 0, y: 220, width: 100, height: 100), "It should distribute the views")
|
||||
|
||||
XCTAssertFalse(viewA.car_translatesAutoresizingMaskIntoConstraints)
|
||||
XCTAssertFalse(viewB.car_translatesAutoresizingMaskIntoConstraints)
|
||||
XCTAssertFalse(viewC.car_translatesAutoresizingMaskIntoConstraints)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ class ViewHierarchyTests: XCTestCase {
|
||||
XCTAssert(testBothWays(viewA, viewAGrandparent) == viewAGrandparent, "It should handle a view and its grandparent")
|
||||
}
|
||||
|
||||
func testSharedSuperTestView() {
|
||||
func testSharedSuperview() {
|
||||
viewB.removeFromSuperview()
|
||||
viewAParent.addSubview(viewB)
|
||||
XCTAssert(testBothWays(viewA, viewB) == viewAParent, "It should handle two views with the same superview")
|
||||
|
@ -33,6 +33,13 @@ layout(view1, view2) { view1, view2 in
|
||||
}
|
||||
```
|
||||
|
||||
For every view on the left hand side of an equality or inequality operator,
|
||||
Cartography will automatically set its
|
||||
`translatesAutoresizingMaskIntoConstraints` property to `false`. If the view is
|
||||
not controlled by you–for example if it belongs to a Apple-provided
|
||||
`UIViewController` class–you should take appropriate care when declaring its
|
||||
constraints.
|
||||
|
||||
Note that `layout` will automatically relayout the views as necessary. If you
|
||||
instead want to trigger the layouting step yourself, you can instead use the
|
||||
`constrain` function:
|
||||
|
Loading…
Reference in New Issue
Block a user