Browse Source

Cleaned up some APIs and added support for prepare constraints.

Robert Payne 11 years ago
parent
commit
b7eb62fba0
3 changed files with 104 additions and 92 deletions
  1. 73 59
      Snap/Constraint.swift
  2. 27 33
      Snap/ConstraintMaker.swift
  3. 4 0
      Snap/View+Snap.swift

+ 73 - 59
Snap/Constraint.swift

@@ -31,19 +31,24 @@ import AppKit
  * Constraint is a single item that defines all the properties for a single ConstraintMaker chain
  */
 public class Constraint {
-    public var left: Constraint { return addConstraint(ConstraintAttributes.Left) }
-    public var top: Constraint { return addConstraint(ConstraintAttributes.Top) }
-    public var right: Constraint { return addConstraint(ConstraintAttributes.Right) }
-    public var bottom: Constraint { return addConstraint(ConstraintAttributes.Bottom) }
-    public var leading: Constraint { return addConstraint(ConstraintAttributes.Leading) }
-    public var trailing: Constraint { return addConstraint(ConstraintAttributes.Trailing) }
-    public var width: Constraint { return addConstraint(ConstraintAttributes.Width) }
-    public var height: Constraint { return addConstraint(ConstraintAttributes.Height) }
-    public var centerX: Constraint { return addConstraint(ConstraintAttributes.CenterX) }
-    public var centerY: Constraint { return addConstraint(ConstraintAttributes.CenterY) }
-    public var baseline: Constraint { return addConstraint(ConstraintAttributes.Baseline) }
-    
-    public var and: Constraint { return self }
+    public var left: Constraint { return self.addConstraint(ConstraintAttributes.Left) }
+    public var top: Constraint { return self.addConstraint(ConstraintAttributes.Top) }
+    public var right: Constraint { return self.addConstraint(ConstraintAttributes.Right) }
+    public var bottom: Constraint { return self.addConstraint(ConstraintAttributes.Bottom) }
+    public var leading: Constraint { return self.addConstraint(ConstraintAttributes.Leading) }
+    public var trailing: Constraint { return self.addConstraint(ConstraintAttributes.Trailing) }
+    public var width: Constraint { return self.addConstraint(ConstraintAttributes.Width) }
+    public var height: Constraint { return self.addConstraint(ConstraintAttributes.Height) }
+    public var centerX: Constraint { return self.addConstraint(ConstraintAttributes.CenterX) }
+    public var centerY: Constraint { return self.addConstraint(ConstraintAttributes.CenterY) }
+    public var baseline: Constraint { return self.addConstraint(ConstraintAttributes.Baseline) }
+    
+    public var and: Constraint {
+        if self.relation != nil {
+            fatalError("And is semantic only and can only be used before a relation is set.")
+        }
+        return self
+    }
     public var with: Constraint { return self }
     
     // MARK: initializer
@@ -56,115 +61,115 @@ public class Constraint {
     // MARK: equalTo
     
     public func equalTo(other: ConstraintItem) -> Constraint {
-        return constrainTo(other, relation: .Equal)
+        return self.constrainTo(other, relation: .Equal)
     }
     public func equalTo(other: View) -> Constraint {
-        return constrainTo(other, relation: .Equal)
+        return self.constrainTo(other, relation: .Equal)
     }
     #if os(iOS)
     public func equalTo(other: UILayoutSupport) -> Constraint {
-        return constrainTo(other, relation: .Equal)
+        return self.constrainTo(other, relation: .Equal)
     }
     #endif
     public func equalTo(other: Float) -> Constraint {
-        return constrainTo(other, relation: .Equal)
+        return self.constrainTo(other, relation: .Equal)
     }
     public func equalTo(other: Double) -> Constraint {
-        return constrainTo(Float(other), relation: .Equal)
+        return self.constrainTo(Float(other), relation: .Equal)
     }
     public func equalTo(other: CGFloat) -> Constraint {
-        return constrainTo(Float(other), relation: .Equal)
+        return self.constrainTo(Float(other), relation: .Equal)
     }
     public func equalTo(other: Int) -> Constraint {
-        return constrainTo(Float(other), relation: .Equal)
+        return self.constrainTo(Float(other), relation: .Equal)
     }
     public func equalTo(other: UInt) -> Constraint {
-        return constrainTo(Float(other), relation: .Equal)
+        return self.constrainTo(Float(other), relation: .Equal)
     }
     public func equalTo(other: CGSize) -> Constraint {
-        return constrainTo(other, relation: .Equal)
+        return self.constrainTo(other, relation: .Equal)
     }
     public func equalTo(other: CGPoint) -> Constraint {
-        return constrainTo(other, relation: .Equal)
+        return self.constrainTo(other, relation: .Equal)
     }
     public func equalTo(other: EdgeInsets) -> Constraint {
-        return constrainTo(other, relation: .Equal)
+        return self.constrainTo(other, relation: .Equal)
     }
     
     // MARK: lessThanOrEqualTo
     
     public func lessThanOrEqualTo(other: ConstraintItem) -> Constraint {
-        return constrainTo(other, relation: .LessThanOrEqualTo)
+        return self.constrainTo(other, relation: .LessThanOrEqualTo)
     }
     public func lessThanOrEqualTo(other: View) -> Constraint {
-        return constrainTo(other, relation: .LessThanOrEqualTo)
+        return self.constrainTo(other, relation: .LessThanOrEqualTo)
     }
     #if os(iOS)
     public func lessThanOrEqualTo(other: UILayoutSupport) -> Constraint {
-        return constrainTo(other, relation: .LessThanOrEqualTo)
+        return self.constrainTo(other, relation: .LessThanOrEqualTo)
     }
     #endif
     public func lessThanOrEqualTo(other: Float) -> Constraint {
-        return constrainTo(other, relation: .LessThanOrEqualTo)
+        return self.constrainTo(other, relation: .LessThanOrEqualTo)
     }
     public func lessThanOrEqualTo(other: Double) -> Constraint {
-        return constrainTo(Float(other), relation: .LessThanOrEqualTo)
+        return self.constrainTo(Float(other), relation: .LessThanOrEqualTo)
     }
     public func lessThanOrEqualTo(other: CGFloat) -> Constraint {
-        return constrainTo(Float(other), relation: .LessThanOrEqualTo)
+        return self.constrainTo(Float(other), relation: .LessThanOrEqualTo)
     }
     public func lessThanOrEqualTo(other: Int) -> Constraint {
-        return constrainTo(Float(other), relation: .LessThanOrEqualTo)
+        return self.constrainTo(Float(other), relation: .LessThanOrEqualTo)
     }
     public func lessThanOrEqualTo(other: UInt) -> Constraint {
-        return constrainTo(Float(other), relation: .LessThanOrEqualTo)
+        return self.constrainTo(Float(other), relation: .LessThanOrEqualTo)
     }
     public func lessThanOrEqualTo(other: CGSize) -> Constraint {
-        return constrainTo(other, relation: .LessThanOrEqualTo)
+        return self.constrainTo(other, relation: .LessThanOrEqualTo)
     }
     public func lessThanOrEqualTo(other: CGPoint) -> Constraint {
-        return constrainTo(other, relation: .LessThanOrEqualTo)
+        return self.constrainTo(other, relation: .LessThanOrEqualTo)
     }
     public func lessThanOrEqualTo(other: EdgeInsets) -> Constraint {
-        return constrainTo(other, relation: .LessThanOrEqualTo)
+        return self.constrainTo(other, relation: .LessThanOrEqualTo)
     }
     
     // MARK: greaterThanOrEqualTo
     
     public func greaterThanOrEqualTo(other: ConstraintItem) -> Constraint {
-        return constrainTo(other, relation: .GreaterThanOrEqualTo)
+        return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
     }
     public func greaterThanOrEqualTo(other: View) -> Constraint {
-        return constrainTo(other, relation: .GreaterThanOrEqualTo)
+        return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
     }
     #if os(iOS)
     public func greaterThanOrEqualTo(other: UILayoutSupport) -> Constraint {
-        return constrainTo(other, relation: .GreaterThanOrEqualTo)
+        return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
     }
     #endif
     public func greaterThanOrEqualTo(other: Float) -> Constraint {
-        return constrainTo(other, relation: .GreaterThanOrEqualTo)
+        return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
     }
     public func greaterThanOrEqualTo(other: Double) -> Constraint {
-        return constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
+        return self.constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
     }
     public func greaterThanOrEqualTo(other: CGFloat) -> Constraint {
-        return constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
+        return self.constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
     }
     public func greaterThanOrEqualTo(other: Int) -> Constraint {
-        return constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
+        return self.constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
     }
     public func greaterThanOrEqualTo(other: UInt) -> Constraint {
-        return constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
+        return self.constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
     }
     public func greaterThanOrEqualTo(other: CGSize) -> Constraint {
-        return constrainTo(other, relation: .GreaterThanOrEqualTo)
+        return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
     }
     public func greaterThanOrEqualTo(other: CGPoint) -> Constraint {
-        return constrainTo(other, relation: .GreaterThanOrEqualTo)
+        return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
     }
     public func greaterThanOrEqualTo(other: EdgeInsets) -> Constraint {
-        return constrainTo(other, relation: .GreaterThanOrEqualTo)
+        return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
     }
     
     // MARK: multiplier
@@ -308,7 +313,7 @@ public class Constraint {
             }
         }
         
-        var layoutConstraints: Array<LayoutConstraint> = []
+        var newLayoutConstraints = Array<LayoutConstraint>()
         let layoutFromAttributes = self.fromItem.attributes.layoutAttributes
         let layoutToAttributes = self.toItem.attributes.layoutAttributes
         
@@ -348,7 +353,7 @@ public class Constraint {
             // set constraint
             layoutConstraint.constraint = self
             
-            layoutConstraints.append(layoutConstraint)
+            newLayoutConstraints.append(layoutConstraint)
         }
         
         // special logic for updating
@@ -356,11 +361,11 @@ public class Constraint {
             // get existing constraints for this view
             let existingLayoutConstraints = reverse(layoutFrom!.snp_installedLayoutConstraints)
             
-            // array that will contain only new layout constraints
-            var newLayoutConstraints = Array<LayoutConstraint>()
-            
+            // array that will contain only new layout constraints to keep
+            var newLayoutConstraintsToKeep = Array<LayoutConstraint>()
+
             // begin looping
-            for layoutConstraint in layoutConstraints {
+            for layoutConstraint in newLayoutConstraints {
                 // layout constraint that should be updated
                 var updateLayoutConstraint: LayoutConstraint? = nil
                 
@@ -376,26 +381,35 @@ public class Constraint {
                 if updateLayoutConstraint != nil {
                     updateLayoutConstraint!.constant = layoutConstraint.constant
                 }
-                // otherwise add this layout constraint to new list
+                // otherwise add this layout constraint to new keep list
                 else {
-                    newLayoutConstraints.append(layoutConstraint)
+                    newLayoutConstraintsToKeep.append(layoutConstraint)
                 }
             }
-            
+
             // set constraints to only new ones
-            layoutConstraints = newLayoutConstraints
+            newLayoutConstraints = newLayoutConstraintsToKeep
         }
         
         // add constraints
-        installOnView!.addConstraints(layoutConstraints)
+        installOnView!.addConstraints(newLayoutConstraints)
         
+        // store which view this constraint was installed on
         self.installedOnView = installOnView
+        
+        // store which layout constraints are installed for this constraint
         self.installedLayoutConstraints = NSHashTable.weakObjectsHashTable()
-        for layoutConstraint in layoutConstraints {
+        for layoutConstraint in newLayoutConstraints {
             self.installedLayoutConstraints!.addObject(layoutConstraint)
         }
         
-        return layoutConstraints
+        // store the layout constraints against the installed on view
+        var layoutConstraints = Array<LayoutConstraint>(layoutFrom!.snp_installedLayoutConstraints)
+        layoutConstraints += newLayoutConstraints
+        layoutFrom!.snp_installedLayoutConstraints = layoutConstraints
+        
+        // return the new constraints
+        return newLayoutConstraints
     }
     
     internal func uninstallFromView() {

+ 27 - 33
Snap/ConstraintMaker.swift

@@ -31,21 +31,21 @@ import AppKit
  * ConstraintMaker is the maker in snap that gets all constraints kickstarted
  */
 public class ConstraintMaker {
-    public var left: Constraint { return addConstraint(ConstraintAttributes.Left) }
-    public var top: Constraint { return addConstraint(ConstraintAttributes.Top) }
-    public var right: Constraint { return addConstraint(ConstraintAttributes.Right) }
-    public var bottom: Constraint { return addConstraint(ConstraintAttributes.Bottom) }
-    public var leading: Constraint { return addConstraint(ConstraintAttributes.Leading) }
-    public var trailing: Constraint { return addConstraint(ConstraintAttributes.Trailing) }
-    public var width: Constraint { return addConstraint(ConstraintAttributes.Width) }
-    public var height: Constraint { return addConstraint(ConstraintAttributes.Height) }
-    public var centerX: Constraint { return addConstraint(ConstraintAttributes.CenterX) }
-    public var centerY: Constraint { return addConstraint(ConstraintAttributes.CenterY) }
-    public var baseline: Constraint { return addConstraint(ConstraintAttributes.Baseline) }
+    public var left: Constraint { return self.addConstraint(ConstraintAttributes.Left) }
+    public var top: Constraint { return self.addConstraint(ConstraintAttributes.Top) }
+    public var right: Constraint { return self.addConstraint(ConstraintAttributes.Right) }
+    public var bottom: Constraint { return self.addConstraint(ConstraintAttributes.Bottom) }
+    public var leading: Constraint { return self.addConstraint(ConstraintAttributes.Leading) }
+    public var trailing: Constraint { return self.addConstraint(ConstraintAttributes.Trailing) }
+    public var width: Constraint { return self.addConstraint(ConstraintAttributes.Width) }
+    public var height: Constraint { return self.addConstraint(ConstraintAttributes.Height) }
+    public var centerX: Constraint { return self.addConstraint(ConstraintAttributes.CenterX) }
+    public var centerY: Constraint { return self.addConstraint(ConstraintAttributes.CenterY) }
+    public var baseline: Constraint { return self.addConstraint(ConstraintAttributes.Baseline) }
     
-    public var edges: Constraint { return addConstraint(ConstraintAttributes.Edges) }
-    public var size: Constraint { return addConstraint(ConstraintAttributes.Size) }
-    public var center: Constraint { return addConstraint(ConstraintAttributes.Center) }
+    public var edges: Constraint { return self.addConstraint(ConstraintAttributes.Edges) }
+    public var size: Constraint { return self.addConstraint(ConstraintAttributes.Size) }
+    public var center: Constraint { return self.addConstraint(ConstraintAttributes.Center) }
     
     init(view: View) {
         self.view = view
@@ -61,6 +61,12 @@ public class ConstraintMaker {
         return constraint
     }
     
+    internal class func prepareConstraints(view: View, block: (make: ConstraintMaker) -> Void) -> Array<Constraint> {
+        let maker = ConstraintMaker(view: view)
+        block(make: maker)
+        return maker.constraints
+    }
+    
     internal class func makeConstraints(view: View, block: (make: ConstraintMaker) -> Void) {
         #if os(iOS)
         view.setTranslatesAutoresizingMaskIntoConstraints(false)
@@ -69,13 +75,9 @@ public class ConstraintMaker {
         #endif
         let maker = ConstraintMaker(view: view)
         block(make: maker)
-        
-        var layoutConstraints = Array<LayoutConstraint>(view.snp_installedLayoutConstraints)
         for constraint in maker.constraints {
-            layoutConstraints += constraint.install()
+            constraint.installOnView(updateExisting: false)
         }
-        
-        view.snp_installedLayoutConstraints = layoutConstraints
     }
     
     internal class func remakeConstraints(view: View, block: (make: ConstraintMaker) -> Void) {
@@ -89,15 +91,12 @@ public class ConstraintMaker {
         
         var layoutConstraints = Array<LayoutConstraint>(view.snp_installedLayoutConstraints)
         for existingLayoutConstraint in layoutConstraints {
-            existingLayoutConstraint.constraint?.uninstall()
+            existingLayoutConstraint.constraint?.uninstallFromView()
         }
-        layoutConstraints = []
         
         for constraint in maker.constraints {
-            layoutConstraints += constraint.install()
+            constraint.installOnView(updateExisting: false)
         }
-        
-        view.snp_installedLayoutConstraints = layoutConstraints
     }
     
     internal class func updateConstraints(view: View, block: (make: ConstraintMaker) -> Void) {
@@ -109,20 +108,15 @@ public class ConstraintMaker {
         let maker = ConstraintMaker(view: view)
         block(make: maker)
         
-        var layoutConstraints = Array<LayoutConstraint>(view.snp_installedLayoutConstraints)
         for constraint in maker.constraints {
-            layoutConstraints += constraint.installOnView(updateExisting: true)
+            constraint.installOnView(updateExisting: true)
         }
-        
-        view.snp_installedLayoutConstraints = layoutConstraints
     }
     
     internal class func removeConstraints(view: View) {
-        let eixsitingLayoutConstraints = Array<LayoutConstraint>(view.snp_installedLayoutConstraints)
-        for existingLayoutConstraint in eixsitingLayoutConstraints {
-            existingLayoutConstraint.constraint?.uninstall()
+        let existingLayoutConstraints = Array<LayoutConstraint>(view.snp_installedLayoutConstraints)
+        for existingLayoutConstraint in existingLayoutConstraints {
+            existingLayoutConstraint.constraint?.uninstallFromView()
         }
-        
-        view.snp_installedLayoutConstraints = []
     }
 }

+ 4 - 0
Snap/View+Snap.swift

@@ -68,6 +68,10 @@ public extension View {
     public var snp_centerWithinMargins: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterWithinMargins) }
     #endif
     
+    public func snp_prepareConstraints(block: (make: ConstraintMaker) -> Void) -> Array<Constraint> {
+        return ConstraintMaker.prepareConstraints(self, block: block)
+    }
+    
     public func snp_makeConstraints(block: (make: ConstraintMaker) -> Void) {
         ConstraintMaker.makeConstraints(self, block: block)
     }