Refactor Constraint -> ConcreteConstraint & Add Updaters!

This commit is contained in:
Robert Payne 2015-04-12 23:32:03 +12:00
parent 73e038f3ab
commit 2b00e7b50c
3 changed files with 141 additions and 36 deletions

View File

@ -27,17 +27,114 @@ import UIKit
import AppKit
#endif
public class Constraint {
/**
Used to expose API's for a Constraint
*/
public protocol Constraint: class {
public func install() -> [LayoutConstraint] {
func install() -> [LayoutConstraint]
func uninstall()
func activate()
func deactivate()
func updateOffset(amount: Float) -> Void
func updateOffset(amount: Double) -> Void
func updateOffset(amount: CGFloat) -> Void
func updateOffset(amount: Int) -> Void
func updateOffset(amount: UInt) -> Void
func updateOffset(amount: CGPoint) -> Void
func updateOffset(amount: CGSize) -> Void
func updateOffset(amount: EdgeInsets) -> Void
func updateInsets(amount: EdgeInsets) -> Void
func updatePriority(priority: Float) -> Void
func updatePriority(priority: Double) -> Void
func updatePriority(priority: CGFloat) -> Void
func updatePriority(priority: UInt) -> Void
func updatePriority(priority: Int) -> Void
func updatePriorityRequired() -> Void
func updatePriorityHigh() -> Void
func updatePriorityMedium() -> Void
func updatePriorityLow() -> Void
}
/**
Used internally to implement a ConcreteConstraint
*/
internal class ConcreteConstraint: Constraint {
internal func updateOffset(amount: Float) -> Void {
self.constant = amount
}
internal func updateOffset(amount: Double) -> Void {
self.updateOffset(Float(amount))
}
internal func updateOffset(amount: CGFloat) -> Void {
self.updateOffset(Float(amount))
}
internal func updateOffset(amount: Int) -> Void {
self.updateOffset(Float(amount))
}
internal func updateOffset(amount: UInt) -> Void {
self.updateOffset(Float(amount))
}
internal func updateOffset(amount: CGPoint) -> Void {
self.constant = amount
}
internal func updateOffset(amount: CGSize) -> Void {
self.constant = amount
}
internal func updateOffset(amount: EdgeInsets) -> Void {
self.constant = amount
}
internal func updateInsets(amount: EdgeInsets) -> Void {
self.constant = EdgeInsets(top: amount.top, left: amount.left, bottom: -amount.bottom, right: -amount.right)
}
internal func updatePriority(priority: Float) -> Void {
self.priority = priority
}
internal func updatePriority(priority: Double) -> Void {
self.updatePriority(Float(priority))
}
internal func updatePriority(priority: CGFloat) -> Void {
self.updatePriority(Float(priority))
}
internal func updatePriority(priority: UInt) -> Void {
self.updatePriority(Float(priority))
}
internal func updatePriority(priority: Int) -> Void {
self.updatePriority(Float(priority))
}
internal func updatePriorityRequired() -> Void {
self.updatePriority(Float(1000.0))
}
internal func updatePriorityHigh() -> Void {
self.updatePriority(Float(750.0))
}
internal func updatePriorityMedium() -> Void {
#if os(iOS)
self.updatePriority(Float(500.0))
#else
self.updatePriority(Float(501.0))
#endif
}
internal func updatePriorityLow() -> Void {
self.updatePriority(Float(250.0))
}
internal func install() -> [LayoutConstraint] {
return self.installOnView(updateExisting: false)
}
public func uninstall() {
internal func uninstall() {
self.uninstallFromView()
}
public func activate() {
internal func activate() {
if NSLayoutConstraint.respondsToSelector("activateConstraints:") && self.installInfo != nil {
let layoutConstraints = self.installInfo!.layoutConstraints.allObjects as! [LayoutConstraint]
if layoutConstraints.count > 0 {
@ -48,7 +145,7 @@ public class Constraint {
}
}
public func deactivate() {
internal func deactivate() {
if NSLayoutConstraint.respondsToSelector("deactivateConstraints:") && self.installInfo != nil {
let layoutConstraints = self.installInfo!.layoutConstraints.allObjects as! [LayoutConstraint]
if layoutConstraints.count > 0 {
@ -62,11 +159,28 @@ public class Constraint {
private let fromItem: ConstraintItem
private let toItem: ConstraintItem
private let relation: ConstraintRelation
private var constant: Any
private var multiplier: Float
private var priority: Float
private let multiplier: Float
private var constant: Any {
didSet {
if let installInfo = self.installInfo {
for layoutConstraint in installInfo.layoutConstraints.allObjects as! [LayoutConstraint] {
let attribute = (layoutConstraint.secondAttribute == .NotAnAttribute) ? layoutConstraint.firstAttribute : layoutConstraint.secondAttribute
layoutConstraint.constant = attribute.snp_constantForValue(self.constant)
}
}
}
}
private var priority: Float {
didSet {
if let installInfo = self.installInfo {
for layoutConstraint in installInfo.layoutConstraints.allObjects as! [LayoutConstraint] {
layoutConstraint.priority = self.priority
}
}
}
}
private var installInfo: ConstraintInstallInfo? = nil
private var installInfo: ConcreteConstraintInstallInfo? = nil
internal init(fromItem: ConstraintItem, toItem: ConstraintItem, relation: ConstraintRelation, constant: Any, multiplier: Float, priority: Float) {
self.fromItem = fromItem
@ -188,7 +302,7 @@ public class Constraint {
installOnView!.addConstraints(newLayoutConstraints)
// set install info
self.installInfo = ConstraintInstallInfo(view: installOnView, layoutConstraints: NSHashTable.weakObjectsHashTable())
self.installInfo = ConcreteConstraintInstallInfo(view: installOnView, layoutConstraints: NSHashTable.weakObjectsHashTable())
// store which layout constraints are installed for this constraint
for layoutConstraint in newLayoutConstraints {
@ -227,7 +341,7 @@ public class Constraint {
}
private struct ConstraintInstallInfo {
private struct ConcreteConstraintInstallInfo {
weak var view: View? = nil
let layoutConstraints: NSHashTable
@ -342,19 +456,10 @@ private func closestCommonSuperviewBetween(fromView: View?, toView: View?) -> Vi
return nil
}
private func ==(left: Constraint, right: Constraint) -> Bool {
private func ==(left: ConcreteConstraint, right: ConcreteConstraint) -> Bool {
return (left.fromItem == right.fromItem &&
left.toItem == right.toItem &&
left.relation == right.relation &&
left.multiplier == right.multiplier &&
left.priority == right.priority)
}
//public protocol Constraint: class {
//
// func install() -> [LayoutConstraint]
// func uninstall() -> Void
// func activate() -> Void
// func deactivate() -> Void
//
//}

View File

@ -429,11 +429,11 @@ final internal class ConstraintDescription: ConstraintDescriptionExtendable, Con
// MARK: Constraint
internal var constraint: Constraint {
if self.createdConstraint == nil {
if self.concreteConstraint == nil {
if self.relation == nil {
fatalError("Attempting to create a constraint from a ConstraintDescription before it has been fully chained.")
}
self.createdConstraint = Constraint(
self.concreteConstraint = ConcreteConstraint(
fromItem: self.fromItem,
toItem: self.toItem,
relation: self.relation!,
@ -441,7 +441,7 @@ final internal class ConstraintDescription: ConstraintDescriptionExtendable, Con
multiplier: self.multiplier,
priority: self.priority)
}
return self.createdConstraint!
return self.concreteConstraint!
}
// MARK: Private
@ -449,40 +449,40 @@ final internal class ConstraintDescription: ConstraintDescriptionExtendable, Con
private let fromItem: ConstraintItem
private var toItem: ConstraintItem {
willSet {
if self.createdConstraint != nil {
if self.concreteConstraint != nil {
fatalError("Attempting to modify a ConstraintDescription after its constraint has been created.")
}
}
}
private var relation: ConstraintRelation? {
willSet {
if self.createdConstraint != nil {
if self.concreteConstraint != nil {
fatalError("Attempting to modify a ConstraintDescription after its constraint has been created.")
}
}
}
private var constant: Any = Float(0.0) {
willSet {
if self.createdConstraint != nil {
if self.concreteConstraint != nil {
fatalError("Attempting to modify a ConstraintDescription after its constraint has been created.")
}
}
}
private var multiplier: Float = 1.0 {
willSet {
if self.createdConstraint != nil {
if self.concreteConstraint != nil {
fatalError("Attempting to modify a ConstraintDescription after its constraint has been created.")
}
}
}
private var priority: Float = 1000.0 {
willSet {
if self.createdConstraint != nil {
if self.concreteConstraint != nil {
fatalError("Attempting to modify a ConstraintDescription after its constraint has been created.")
}
}
}
private var createdConstraint: Constraint? = nil
private var concreteConstraint: ConcreteConstraint? = nil
private func addConstraint(attributes: ConstraintAttributes) -> ConstraintDescription {
if self.relation == nil {

View File

@ -118,7 +118,7 @@ final public class ConstraintMaker {
self.view = view
}
internal weak var view: View?
internal let view: View
internal var constraintDescriptions = [ConstraintDescription]()
internal func makeConstraintDescription(attributes: ConstraintAttributes) -> ConstraintDescription {
@ -144,7 +144,7 @@ final public class ConstraintMaker {
let maker = ConstraintMaker(view: view)
closure(make: maker)
let constraints = maker.constraintDescriptions.map { $0.constraint }
let constraints = maker.constraintDescriptions.map { $0.constraint as! ConcreteConstraint }
for constraint in constraints {
constraint.installOnView(updateExisting: false)
}
@ -160,7 +160,7 @@ final public class ConstraintMaker {
closure(make: maker)
self.removeConstraints(view)
let constraints = maker.constraintDescriptions.map { $0.constraint }
let constraints = maker.constraintDescriptions.map { $0.constraint as! ConcreteConstraint }
for constraint in constraints {
constraint.installOnView(updateExisting: false)
}
@ -175,7 +175,7 @@ final public class ConstraintMaker {
let maker = ConstraintMaker(view: view)
closure(make: maker)
let constraints = maker.constraintDescriptions.map { $0.constraint }
let constraints = maker.constraintDescriptions.map { $0.constraint as! ConcreteConstraint}
for constraint in constraints {
constraint.installOnView(updateExisting: true)
}
@ -183,7 +183,7 @@ final public class ConstraintMaker {
internal class func removeConstraints(view: View) {
for existingLayoutConstraint in view.snp_installedLayoutConstraints {
existingLayoutConstraint.snp_constraint?.uninstallFromView()
existingLayoutConstraint.snp_constraint?.uninstall()
}
}
}