diff --git a/Snappy/Constraint.swift b/Snappy/Constraint.swift index b1dfde1..f51d18c 100644 --- a/Snappy/Constraint.swift +++ b/Snappy/Constraint.swift @@ -27,6 +27,38 @@ import UIKit import AppKit #endif +public protocol FloatConstantConstraint { + func update(float: Float) +} + +public protocol DoubleConstantConstraint { + func update(float: Float) +} + +public protocol CGFloatConstantConstraint { + func update(float: Float) +} + +public protocol IntConstantConstraint { + func update(float: Float) +} + +public protocol UIntConstantConstraint { + func update(float: Float) +} + +public protocol CGPointConstantConstraint { + func update(float: Float) +} + +public protocol CGSizeConstantConstraint { + func update(size: CGSize) +} + +public protocol EdgeInsetsConstantConstraint { + func update(insets: EdgeInsets) +} + /** * Constraint is a single item that defines all the properties for a single ConstraintMaker chain */ @@ -269,9 +301,14 @@ public class Constraint { return self } - // MARK: install + // MARK: internal - public func install() -> Array { + internal func install() -> Array { + if self.installedOnView != nil { + NSException(name: "Cannot Install Constraint", reason: "Already installed", userInfo: nil).raise() + return [] + } + var installOnView: View? = nil if self.toItem.view != nil { installOnView = Constraint.closestCommonSuperviewFromView(self.fromItem.view, toView: self.toItem.view) @@ -330,15 +367,13 @@ public class Constraint { layoutConstraints.append(layoutConstraint) } - installOnView?.addConstraints(layoutConstraints) + installOnView!.addConstraints(layoutConstraints) self.installedOnView = installOnView return layoutConstraints } - // MARK: uninstall - - public func uninstall() { + internal func uninstall() { if let view = self.installedOnView { #if os(iOS) var installedConstraints = view.constraints() @@ -556,4 +591,12 @@ private extension NSLayoutAttribute { return CGFloat(0); } +} + +internal func ==(left: Constraint, right: Constraint) -> Bool { + return (left.fromItem == right.fromItem && + left.toItem == right.toItem && + left.relation == right.relation && + left.multiplier == right.multiplier && + left.priority == right.priority) } \ No newline at end of file diff --git a/Snappy/ConstraintAttributes.swift b/Snappy/ConstraintAttributes.swift index ec451d0..3497b58 100644 --- a/Snappy/ConstraintAttributes.swift +++ b/Snappy/ConstraintAttributes.swift @@ -156,12 +156,12 @@ internal struct ConstraintAttributes: RawOptionSetType, BooleanType { return attrs } } -internal func += (inout left: ConstraintAttributes, right: ConstraintAttributes) { +internal func +=(inout left: ConstraintAttributes, right: ConstraintAttributes) { left = (left | right) } -internal func -= (inout left: ConstraintAttributes, right: ConstraintAttributes) { +internal func -=(inout left: ConstraintAttributes, right: ConstraintAttributes) { left = left & ~right } -internal func == (left: ConstraintAttributes, right: ConstraintAttributes) -> Bool { +internal func ==(left: ConstraintAttributes, right: ConstraintAttributes) -> Bool { return left.rawValue == right.rawValue } diff --git a/Snappy/ConstraintItem.swift b/Snappy/ConstraintItem.swift index e0d392c..1de3704 100644 --- a/Snappy/ConstraintItem.swift +++ b/Snappy/ConstraintItem.swift @@ -59,4 +59,21 @@ public class ConstraintItem { } } #endif +} + + +internal func ==(left: ConstraintItem, right: ConstraintItem) -> Bool { + if left.object == nil { + return false + } + if right.object == nil { + return false + } + if left.object !== right.object { + return false + } + if left.attributes != right.attributes { + return false + } + return true } \ No newline at end of file diff --git a/Snappy/ConstraintMaker.swift b/Snappy/ConstraintMaker.swift index 640db23..c5ca843 100644 --- a/Snappy/ConstraintMaker.swift +++ b/Snappy/ConstraintMaker.swift @@ -70,11 +70,12 @@ public class ConstraintMaker { let maker = ConstraintMaker(view: view) block(make: maker) - var layoutConstraints = LayoutConstraint.layoutConstraintsInstalledOnView(view) + var layoutConstraints = view.snp_installedLayoutConstraints for constraint in maker.constraints { layoutConstraints += constraint.install() } - LayoutConstraint.setLayoutConstraints(layoutConstraints, installedOnView: view) + + view.snp_installedLayoutConstraints = layoutConstraints } internal class func remakeConstraints(view: View, block: (make: ConstraintMaker) -> ()) { @@ -86,7 +87,7 @@ public class ConstraintMaker { let maker = ConstraintMaker(view: view) block(make: maker) - var layoutConstraints: Array = LayoutConstraint.layoutConstraintsInstalledOnView(view) + var layoutConstraints: Array = view.snp_installedLayoutConstraints for existingLayoutConstraint in layoutConstraints { existingLayoutConstraint.constraint?.uninstall() } @@ -95,13 +96,15 @@ public class ConstraintMaker { for constraint in maker.constraints { layoutConstraints += constraint.install() } - LayoutConstraint.setLayoutConstraints(layoutConstraints, installedOnView: view) + + view.snp_installedLayoutConstraints = layoutConstraints } internal class func removeConstraints(view: View) { - for existingLayoutConstraint in LayoutConstraint.layoutConstraintsInstalledOnView(view) { + for existingLayoutConstraint in view.snp_installedLayoutConstraints { existingLayoutConstraint.constraint?.uninstall() } - LayoutConstraint.setLayoutConstraints([], installedOnView: view) + + view.snp_installedLayoutConstraints = [] } } \ No newline at end of file diff --git a/Snappy/LayoutConstraint.swift b/Snappy/LayoutConstraint.swift index 815f7e3..c61068f 100644 --- a/Snappy/LayoutConstraint.swift +++ b/Snappy/LayoutConstraint.swift @@ -31,21 +31,5 @@ import AppKit * LayoutConstraint is a subclass of NSLayoutConstraint to assist Snappy and also provide better debugging */ public class LayoutConstraint: NSLayoutConstraint { - - // internal - internal var constraint: Constraint? - - internal class func layoutConstraintsInstalledOnView(view: View) -> Array { - var constraints = objc_getAssociatedObject(view, &layoutConstraintsInstalledOnViewKey) as? Array - if constraints != nil { - return constraints! - } - return [] - } - internal class func setLayoutConstraints(layoutConstraints: Array, installedOnView view: View) { - objc_setAssociatedObject(view, &layoutConstraintsInstalledOnViewKey, layoutConstraints, UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC)) - } -} - -private var layoutConstraintsInstalledOnViewKey = "" \ No newline at end of file +} \ No newline at end of file diff --git a/Snappy/View+Snappy.swift b/Snappy/View+Snappy.swift index ff174c2..0051707 100644 --- a/Snappy/View+Snappy.swift +++ b/Snappy/View+Snappy.swift @@ -30,6 +30,9 @@ public typealias View = NSView #endif public extension View { + + // normal + public var snp_left: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Left) } public var snp_top: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Top) } public var snp_right: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Right) } @@ -42,8 +45,8 @@ public extension View { public var snp_centerY: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterY) } public var snp_baseline: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Baseline) } + #if os(iOS) public var snp_firstBaseline: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.FirstBaseline) } - public var snp_leftMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.LeftMargin) } public var snp_rightMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.RightMargin) } public var snp_topMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.TopMargin) } @@ -52,18 +55,27 @@ public extension View { public var snp_trailingMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.TrailingMargin) } public var snp_centerXWithinMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterXWithinMargins) } public var snp_centerYWithinMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterYWithinMargins) } + #endif + + // aggregates public var snp_edges: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Edges) } public var snp_size: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Size) } public var snp_center: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Center) } + #if os(iOS) public var snp_margins: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Margins) } public var snp_centerWithinMargins: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterWithinMargins) } + #endif public func snp_makeConstraints(block: (maker: ConstraintMaker) -> ()) { ConstraintMaker.makeConstraints(self, block: block) } + public func snp_updateConstraints(block: (maker: ConstraintMaker) -> ()) { + ConstraintMaker.updateConstraints(self, block: block) + } + public func snp_remakeConstraints(block: (maker: ConstraintMaker) -> ()) { ConstraintMaker.remakeConstraints(self, block: block) } @@ -71,4 +83,21 @@ public extension View { public func snp_removeConstraints() { ConstraintMaker.removeConstraints(self) } -} \ No newline at end of file + + // internal + + internal var snp_installedLayoutConstraints: Array { + get { + var constraints = objc_getAssociatedObject(self, &installedLayoutConstraintsKey) as? Array + if constraints != nil { + return constraints! + } + return [] + } + set { + objc_setAssociatedObject(self, &installedLayoutConstraintsKey, newValue, UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC)) + } + } +} + +private var installedLayoutConstraintsKey = "" \ No newline at end of file