Merge branch 'feature/0.40.0' of github.com:SnapKit/SnapKit into develop

# Conflicts:
#	.travis.yml
#	CHANGELOG.md
#	README.md
#	SnapKit.podspec
#	SnapKit.xcodeproj/project.pbxproj
#	SnapKit.xcodeproj/xcshareddata/xcschemes/SnapKit OSX.xcscheme
#	SnapKit.xcodeproj/xcshareddata/xcschemes/SnapKit iOS.xcscheme
#	Source/Constraint.swift
#	Source/ConstraintAttributes.swift
#	Source/ConstraintDescription.swift
#	Source/ConstraintMaker.swift
#	Source/ConstraintView.swift
#	Source/Debugging.swift
#	Source/LayoutConstraint.swift
#	Source/View+SnapKit.swift
#	Tests/Tests.swift
This commit is contained in:
Robert Payne 2016-09-14 20:55:25 +12:00
commit f03dd0e85f
42 changed files with 2821 additions and 2769 deletions

View File

@ -1,15 +1,10 @@
language: objective-c
osx_image: xcode7.3
branches:
only:
- master
- develop
osx_image: xcode8
env:
- LC_CTYPE=en_US.UTF-8 LANG=en_US.UTF-8
before_install:
- gem install xcpretty -N
- ACTION=test PLATFORM=Mac DESTINATION='platform=OS X'
- ACTION=test PLATFORM=iOS DESTINATION='platform=iOS Simulator,name=iPhone 6S'
- ACTION=test PLATFORM=tvOS DESTINATION='platform=tvOS Simulator,name=Apple TV 1080p'
script:
- set -o pipefail
- xcodebuild -project SnapKit.xcodeproj -scheme "SnapKit iOS" -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPhone 6" ONLY_ACTIVE_ARCH=NO test | xcpretty -c
- xcodebuild -project SnapKit.xcodeproj -scheme "SnapKit OSX" ONLY_ACTIVE_ARCH=YES test | xcpretty -c
- pod lib lint --quick
- set -o pipefail && xcodebuild -scheme SnapKit -destination "$DESTINATION" $ACTION | xcpretty

View File

@ -1,6 +1,32 @@
CHANGELOG
=======
# 0.40.0.beta - WIP
**SnapKit 0.40.0** is a complete re-write to take advantage of modern Swift 3.0 as well as
clean up the API. As such please use with caution and check your apps thoroughly
### Breaking
* iOS 7.0 support has been removed
* `install` and `uninstall` have been removed, use `activate` and `deactivate` instead
* DSL is now accessed through `.snp.*` rather than `.snp_*`. For example `view.snp.makeConstraints { }`
* Constraints are now updated through `update(offset:)`, `update(inset:)` and `update(priority:)`
* `.inset()` will no longer take `CGPoint` or `CGSize` as input
* `.offset()` will no longer take `CGPoint`, `CGSize`, `EdgeInsets` as input
* `updateConstraints` will no longer allow creating new constraints unless there are no existing constraints for the view. If it does generate new constraints it will throw a fatal error.
* `UIEdgeInsets` are now have their right and bottom value inverted for more natural results such as `make.edges.equalTo(UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)).inset()`
### Enhancements
* Debugging output has been improved to show exact file/line number from which the broken constraint was created
* Exceptions thrown during constraint creation have been replaced with `fatalError` with better output
* Constraints are now installed through `NSLayoutConstraint.activate` and what view they are added to is now deferred to UIKit
* Added `var contentHugging<Axis>Priority: CGFloat` to `make`
* Added `var contentCompressionResistance<Axis>Priority: CGFloat` to `make`
* Added support for `UILayoutGuide` via `make.left.equalTo(guide.snp.top)`
* Added support for constraining edges to margins or vice versa via `make.edges.equalTo(other.snp.margins)`
# 0.22.0 - August 8 2016
* Added `layoutConstraint` getter to `Constraint` to get the underlying NSLayoutConstraints created by a constraint

View File

@ -17,7 +17,7 @@ class MyViewController: UIViewController {
super.viewDidLoad()
self.view.addSubview(box)
box.snp_makeConstraints { make in
box.snp.makeConstraints { (make) -> Void in
make.width.height.equalTo(50)
make.center.equalTo(self.view)
}
@ -30,7 +30,6 @@ class MyViewController: UIViewController {
* [Documentation](http://snapkit.io/docs/)
* [F.A.Q.](http://snapkit.io/faq/)
* [Legacy Platforms (iOS 7.0, OS X 10.9)](http://snapkit.io/legacy-platforms/)
## License

View File

@ -1,12 +1,12 @@
Pod::Spec.new do |s|
s.name = 'SnapKit'
s.version = '0.22.0'
s.version = '0.40.0.beta4'
s.license = 'MIT'
s.summary = 'Harness the power of auto layout with a simplified, chainable, and compile time safe syntax.'
s.homepage = 'https://github.com/SnapKit/SnapKit'
s.authors = { 'Robert Payne' => 'robertpayne@me.com' }
s.social_media_url = 'http://twitter.com/robertjpayne'
s.source = { :git => 'https://github.com/SnapKit/SnapKit.git', :tag => '0.22.0' }
s.source = { :git => 'https://github.com/SnapKit/SnapKit.git', :tag => '0.40.0.beta4' }
s.ios.deployment_target = '8.0'
s.osx.deployment_target = '10.10'

File diff suppressed because it is too large Load Diff

View File

@ -1,113 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "EECDB3791AC0C9D4006BBC11"
BuildableName = "SnapKit.framework"
BlueprintName = "SnapKit OSX"
ReferencedContainer = "container:SnapKit.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "NO"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "EECDB3831AC0C9D4006BBC11"
BuildableName = "SnapKit OSX Tests.xctest"
BlueprintName = "SnapKit OSX Tests"
ReferencedContainer = "container:SnapKit.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "EECDB3831AC0C9D4006BBC11"
BuildableName = "SnapKit OSX Tests.xctest"
BlueprintName = "SnapKit OSX Tests"
ReferencedContainer = "container:SnapKit.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "EECDB3791AC0C9D4006BBC11"
BuildableName = "SnapKit.framework"
BlueprintName = "SnapKit OSX"
ReferencedContainer = "container:SnapKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "EECDB3791AC0C9D4006BBC11"
BuildableName = "SnapKit.framework"
BlueprintName = "SnapKit OSX"
ReferencedContainer = "container:SnapKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "EECDB3791AC0C9D4006BBC11"
BuildableName = "SnapKit.framework"
BlueprintName = "SnapKit OSX"
ReferencedContainer = "container:SnapKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "EEBCC9E119CC627D0083B827"
BuildableName = "SnapKit Tests.xctest"
BlueprintName = "SnapKit Tests"
ReferencedContainer = "container:SnapKit.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -1,113 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "537DCE911C35CC8800B5B899"
BuildableName = "SnapKit.framework"
BlueprintName = "SnapKit tvOS"
ReferencedContainer = "container:SnapKit.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "NO"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "537DCEAE1C35D90A00B5B899"
BuildableName = "SnapKit tvOS Tests.xctest"
BlueprintName = "SnapKit tvOS Tests"
ReferencedContainer = "container:SnapKit.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "537DCEAE1C35D90A00B5B899"
BuildableName = "SnapKit tvOS Tests.xctest"
BlueprintName = "SnapKit tvOS Tests"
ReferencedContainer = "container:SnapKit.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "537DCE911C35CC8800B5B899"
BuildableName = "SnapKit.framework"
BlueprintName = "SnapKit tvOS"
ReferencedContainer = "container:SnapKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "537DCE911C35CC8800B5B899"
BuildableName = "SnapKit.framework"
BlueprintName = "SnapKit tvOS"
ReferencedContainer = "container:SnapKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "537DCE911C35CC8800B5B899"
BuildableName = "SnapKit.framework"
BlueprintName = "SnapKit tvOS"
ReferencedContainer = "container:SnapKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -16,7 +16,7 @@
BuildableIdentifier = "primary"
BlueprintIdentifier = "EEBCC9D719CC627D0083B827"
BuildableName = "SnapKit.framework"
BlueprintName = "SnapKit iOS"
BlueprintName = "SnapKit"
ReferencedContainer = "container:SnapKit.xcodeproj">
</BuildableReference>
</BuildActionEntry>
@ -28,9 +28,9 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "EEBCC9E119CC627D0083B827"
BuildableName = "SnapKit iOS Tests.xctest"
BlueprintName = "SnapKit iOS Tests"
BlueprintIdentifier = "537DCEAE1C35D90A00B5B899"
BuildableName = "SnapKit tvOS Tests.xctest"
BlueprintName = "SnapKit tvOS Tests"
ReferencedContainer = "container:SnapKit.xcodeproj">
</BuildableReference>
</BuildActionEntry>
@ -47,8 +47,8 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "EEBCC9E119CC627D0083B827"
BuildableName = "SnapKit iOS Tests.xctest"
BlueprintName = "SnapKit iOS Tests"
BuildableName = "SnapKit Tests.xctest"
BlueprintName = "SnapKit Tests"
ReferencedContainer = "container:SnapKit.xcodeproj">
</BuildableReference>
</TestableReference>
@ -58,7 +58,7 @@
BuildableIdentifier = "primary"
BlueprintIdentifier = "EEBCC9D719CC627D0083B827"
BuildableName = "SnapKit.framework"
BlueprintName = "SnapKit iOS"
BlueprintName = "SnapKit"
ReferencedContainer = "container:SnapKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
@ -80,7 +80,7 @@
BuildableIdentifier = "primary"
BlueprintIdentifier = "EEBCC9D719CC627D0083B827"
BuildableName = "SnapKit.framework"
BlueprintName = "SnapKit iOS"
BlueprintName = "SnapKit"
ReferencedContainer = "container:SnapKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
@ -98,7 +98,7 @@
BuildableIdentifier = "primary"
BlueprintIdentifier = "EEBCC9D719CC627D0083B827"
BuildableName = "SnapKit.framework"
BlueprintName = "SnapKit iOS"
BlueprintName = "SnapKit"
ReferencedContainer = "container:SnapKit.xcodeproj">
</BuildableReference>
</MacroExpansion>

View File

@ -22,496 +22,229 @@
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
import UIKit
#else
import AppKit
import AppKit
#endif
/**
Used to expose API's for a Constraint
*/
public class Constraint {
public func install() -> [LayoutConstraint] { fatalError("Must be implemented by Concrete subclass.") }
public func uninstall() -> Void { fatalError("Must be implemented by Concrete subclass.") }
public func activate() -> Void { fatalError("Must be implemented by Concrete subclass.") }
public func deactivate() -> Void { fatalError("Must be implemented by Concrete subclass.") }
internal let sourceLocation: (String, UInt)
internal let label: String?
public func updateOffset(amount: Float) -> Void { fatalError("Must be implemented by Concrete subclass.") }
public func updateOffset(amount: Double) -> Void { fatalError("Must be implemented by Concrete subclass.") }
public func updateOffset(amount: CGFloat) -> Void { fatalError("Must be implemented by Concrete subclass.") }
public func updateOffset(amount: Int) -> Void { fatalError("Must be implemented by Concrete subclass.") }
public func updateOffset(amount: UInt) -> Void { fatalError("Must be implemented by Concrete subclass.") }
public func updateOffset(amount: CGPoint) -> Void { fatalError("Must be implemented by Concrete subclass.") }
public func updateOffset(amount: CGSize) -> Void { fatalError("Must be implemented by Concrete subclass.") }
public func updateOffset(amount: EdgeInsets) -> Void { fatalError("Must be implemented by Concrete subclass.") }
public func updateInsets(amount: EdgeInsets) -> Void { fatalError("Must be implemented by Concrete subclass.") }
public func updatePriority(priority: Float) -> Void { fatalError("Must be implemented by Concrete subclass.") }
public func updatePriority(priority: Double) -> Void { fatalError("Must be implemented by Concrete subclass.") }
public func updatePriority(priority: CGFloat) -> Void { fatalError("Must be implemented by Concrete subclass.") }
public func updatePriority(priority: UInt) -> Void { fatalError("Must be implemented by Concrete subclass.") }
public func updatePriority(priority: Int) -> Void { fatalError("Must be implemented by Concrete subclass.") }
public func updatePriorityRequired() -> Void { fatalError("Must be implemented by Concrete subclass.") }
public func updatePriorityHigh() -> Void { fatalError("Must be implemented by Concrete subclass.") }
public func updatePriorityMedium() -> Void { fatalError("Must be implemented by Concrete subclass.") }
public func updatePriorityLow() -> Void { fatalError("Must be implemented by Concrete subclass.") }
public var layoutConstraints: [LayoutConstraint] { fatalError("Must be implemented by Concrete subclass.") }
internal var makerFile: String = "Unknown"
internal var makerLine: UInt = 0
}
/**
Used internally to implement a ConcreteConstraint
*/
internal class ConcreteConstraint: Constraint {
internal override func updateOffset(amount: Float) -> Void {
self.constant = amount
}
internal override func updateOffset(amount: Double) -> Void {
self.updateOffset(Float(amount))
}
internal override func updateOffset(amount: CGFloat) -> Void {
self.updateOffset(Float(amount))
}
internal override func updateOffset(amount: Int) -> Void {
self.updateOffset(Float(amount))
}
internal override func updateOffset(amount: UInt) -> Void {
self.updateOffset(Float(amount))
}
internal override func updateOffset(amount: CGPoint) -> Void {
self.constant = amount
}
internal override func updateOffset(amount: CGSize) -> Void {
self.constant = amount
}
internal override func updateOffset(amount: EdgeInsets) -> Void {
self.constant = amount
}
internal override func updateInsets(amount: EdgeInsets) -> Void {
self.constant = EdgeInsets(top: amount.top, left: amount.left, bottom: -amount.bottom, right: -amount.right)
}
internal override func updatePriority(priority: Float) -> Void {
self.priority = priority
}
internal override func updatePriority(priority: Double) -> Void {
self.updatePriority(Float(priority))
}
internal override func updatePriority(priority: CGFloat) -> Void {
self.updatePriority(Float(priority))
}
internal override func updatePriority(priority: UInt) -> Void {
self.updatePriority(Float(priority))
}
internal override func updatePriority(priority: Int) -> Void {
self.updatePriority(Float(priority))
}
internal override func updatePriorityRequired() -> Void {
self.updatePriority(Float(1000.0))
}
internal override func updatePriorityHigh() -> Void {
self.updatePriority(Float(750.0))
}
internal override func updatePriorityMedium() -> Void {
#if os(iOS) || os(tvOS)
self.updatePriority(Float(500.0))
#else
self.updatePriority(Float(501.0))
#endif
}
internal override func updatePriorityLow() -> Void {
self.updatePriority(Float(250.0))
}
internal override func install() -> [LayoutConstraint] {
return self.installOnView(updateExisting: false, file: self.makerFile, line: self.makerLine)
}
internal override func uninstall() -> Void {
self.uninstallFromView()
}
internal override func activate() -> Void {
guard self.installInfo != nil else {
self.install()
return
}
#if SNAPKIT_DEPLOYMENT_LEGACY
guard #available(iOS 8.0, OSX 10.10, *) else {
self.install()
return
}
#endif
let layoutConstraints = self.installInfo!.layoutConstraints.allObjects as! [LayoutConstraint]
if layoutConstraints.count > 0 {
NSLayoutConstraint.activateConstraints(layoutConstraints)
}
}
internal override func deactivate() -> Void {
guard self.installInfo != nil else {
return
}
#if SNAPKIT_DEPLOYMENT_LEGACY
guard #available(iOS 8.0, OSX 10.10, *) else {
return
}
#endif
let layoutConstraints = self.installInfo!.layoutConstraints.allObjects as! [LayoutConstraint]
if layoutConstraints.count > 0 {
NSLayoutConstraint.deactivateConstraints(layoutConstraints)
}
}
private let fromItem: ConstraintItem
private let toItem: ConstraintItem
private let from: ConstraintItem
private let to: ConstraintItem
private let relation: ConstraintRelation
private let multiplier: Float
private var constant: Any {
private let multiplier: ConstraintMultiplierTarget
private var constant: ConstraintConstantTarget {
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)
}
}
self.updateConstantAndPriorityIfNeeded()
}
}
private var priority: Float {
private var priority: ConstraintPriorityTarget {
didSet {
if let installInfo = self.installInfo {
for layoutConstraint in installInfo.layoutConstraints.allObjects as! [LayoutConstraint] {
layoutConstraint.priority = self.priority
}
}
self.updateConstantAndPriorityIfNeeded()
}
}
private var layoutConstraints: [LayoutConstraint]
private let label: String?
// MARK: Initialization
private var installInfo: ConcreteConstraintInstallInfo? = nil
override var layoutConstraints: [LayoutConstraint] {
if installInfo == nil {
install()
}
guard let installInfo = installInfo else {
return []
}
return installInfo.layoutConstraints.allObjects as! [LayoutConstraint]
}
internal init(fromItem: ConstraintItem, toItem: ConstraintItem, relation: ConstraintRelation, constant: Any, multiplier: Float, priority: Float, label: String? = nil) {
self.fromItem = fromItem
self.toItem = toItem
internal init(from: ConstraintItem,
to: ConstraintItem,
relation: ConstraintRelation,
sourceLocation: (String, UInt),
label: String?,
multiplier: ConstraintMultiplierTarget,
constant: ConstraintConstantTarget,
priority: ConstraintPriorityTarget) {
self.from = from
self.to = to
self.relation = relation
self.constant = constant
self.multiplier = multiplier
self.priority = priority
self.sourceLocation = sourceLocation
self.label = label
}
self.multiplier = multiplier
self.constant = constant
self.priority = priority
self.layoutConstraints = []
internal func installOnView(updateExisting updateExisting: Bool = false, file: String? = nil, line: UInt? = nil) -> [LayoutConstraint] {
var installOnView: View? = nil
if self.toItem.view != nil {
installOnView = closestCommonSuperviewFromView(self.fromItem.view, toView: self.toItem.view)
if installOnView == nil {
NSException(name: "Cannot Install Constraint", reason: "No common superview between views (@\(self.makerFile)#\(self.makerLine))", userInfo: nil).raise()
return []
}
} else {
if self.fromItem.attributes.isSubsetOf(ConstraintAttributes.Width.union(.Height)) {
installOnView = self.fromItem.view
} else {
installOnView = self.fromItem.view?.superview
if installOnView == nil {
NSException(name: "Cannot Install Constraint", reason: "Missing superview (@\(self.makerFile)#\(self.makerLine))", userInfo: nil).raise()
return []
}
}
}
if let installedOnView = self.installInfo?.view {
if installedOnView != installOnView {
NSException(name: "Cannot Install Constraint", reason: "Already installed on different view. (@\(self.makerFile)#\(self.makerLine))", userInfo: nil).raise()
return []
}
return self.installInfo?.layoutConstraints.allObjects as? [LayoutConstraint] ?? []
}
var newLayoutConstraints = [LayoutConstraint]()
let layoutFromAttributes = self.fromItem.attributes.layoutAttributes
let layoutToAttributes = self.toItem.attributes.layoutAttributes
// get attributes
let layoutFromAttributes = self.from.attributes.layoutAttributes
let layoutToAttributes = self.to.attributes.layoutAttributes
// get layout from
let layoutFrom: View? = self.fromItem.view
let layoutFrom: ConstraintView = self.from.view!
// get layout relation
let layoutRelation: NSLayoutRelation = self.relation.layoutRelation
// get relation
let layoutRelation = self.relation.layoutRelation
for layoutFromAttribute in layoutFromAttributes {
// get layout to attribute
let layoutToAttribute = (layoutToAttributes.count > 0) ? layoutToAttributes[0] : layoutFromAttribute
let layoutToAttribute: NSLayoutAttribute
#if os(iOS) || os(tvOS)
if layoutToAttributes.count > 0 {
if self.from.attributes == .edges && self.to.attributes == .margins {
switch layoutFromAttribute {
case .left:
layoutToAttribute = .leftMargin
case .right:
layoutToAttribute = .rightMargin
case .top:
layoutToAttribute = .topMargin
case .bottom:
layoutToAttribute = .bottomMargin
default:
fatalError()
}
} else if self.from.attributes == .margins && self.to.attributes == .edges {
switch layoutFromAttribute {
case .leftMargin:
layoutToAttribute = .left
case .rightMargin:
layoutToAttribute = .right
case .topMargin:
layoutToAttribute = .top
case .bottomMargin:
layoutToAttribute = .bottom
default:
fatalError()
}
} else if self.from.attributes == self.to.attributes {
layoutToAttribute = layoutFromAttribute
} else {
layoutToAttribute = layoutToAttributes[0]
}
} else {
layoutToAttribute = layoutFromAttribute
}
#else
if layoutToAttributes.count > 0 {
layoutToAttribute = layoutToAttributes[0]
} else {
layoutToAttribute = layoutFromAttribute
}
#endif
// get layout constant
let layoutConstant: CGFloat = layoutToAttribute.snp_constantForValue(self.constant)
let layoutConstant: CGFloat = self.constant.constraintConstantTargetValueFor(layoutAttribute: layoutToAttribute)
// get layout to
#if os(iOS) || os(tvOS)
var layoutTo: AnyObject? = self.toItem.view ?? self.toItem.layoutSupport
#else
var layoutTo: AnyObject? = self.toItem.view
#endif
if layoutTo == nil && layoutToAttribute != .Width && layoutToAttribute != .Height {
layoutTo = installOnView
var layoutTo: AnyObject? = self.to.target
// use superview if possible
if layoutTo == nil && layoutToAttribute != .width && layoutToAttribute != .height {
layoutTo = layoutFrom.superview
}
// create layout constraint
let layoutConstraint = LayoutConstraint(
item: layoutFrom!,
item: layoutFrom,
attribute: layoutFromAttribute,
relatedBy: layoutRelation,
toItem: layoutTo,
attribute: layoutToAttribute,
multiplier: CGFloat(self.multiplier),
constant: layoutConstant)
layoutConstraint.identifier = self.label
multiplier: self.multiplier.constraintMultiplierTargetValue,
constant: layoutConstant
)
// set label
layoutConstraint.label = self.label
// set priority
layoutConstraint.priority = self.priority
layoutConstraint.priority = self.priority.constraintPriorityTargetValue
// set constraint
layoutConstraint.snp_constraint = self
layoutConstraint.constraint = self
newLayoutConstraints.append(layoutConstraint)
// append
self.layoutConstraints.append(layoutConstraint)
}
}
// special logic for updating
if updateExisting {
// get existing constraints for this view
let existingLayoutConstraints = layoutFrom!.snp_installedLayoutConstraints.reverse()
// MARK: Public
// array that will contain only new layout constraints to keep
var newLayoutConstraintsToKeep = [LayoutConstraint]()
public func activate() {
self.activateIfNeeded()
}
// begin looping
for layoutConstraint in newLayoutConstraints {
// layout constraint that should be updated
var updateLayoutConstraint: LayoutConstraint? = nil
public func deactivate() {
self.deactivateIfNeeded()
}
// loop through existing and check for match
for existingLayoutConstraint in existingLayoutConstraints {
if existingLayoutConstraint == layoutConstraint {
updateLayoutConstraint = existingLayoutConstraint
break
}
@discardableResult
public func update(offset: ConstraintOffsetTarget) -> Constraint {
self.constant = offset.constraintOffsetTargetValue
return self
}
@discardableResult
public func update(inset: ConstraintInsetTarget) -> Constraint {
self.constant = inset.constraintInsetTargetValue
return self
}
@discardableResult
public func update(priority: ConstraintPriorityTarget) -> Constraint {
self.priority = priority.constraintPriorityTargetValue
return self
}
@available(*, deprecated:0.40.0, message:"Use update(offset: ConstraintOffsetTarget) instead.")
public func updateOffset(amount: ConstraintOffsetTarget) -> Void { self.update(offset: amount) }
@available(*, deprecated:0.40.0, message:"Use update(inset: ConstraintInsetTarget) instead.")
public func updateInsets(amount: ConstraintInsetTarget) -> Void { self.update(inset: amount) }
@available(*, deprecated:0.40.0, message:"Use update(priority: ConstraintPriorityTarget) instead.")
public func updatePriority(amount: ConstraintPriorityTarget) -> Void { self.update(priority: amount) }
@available(*, obsoleted:0.40.0, message:"Use update(priority: ConstraintPriorityTarget) instead.")
public func updatePriorityRequired() -> Void {}
@available(*, obsoleted:0.40.0, message:"Use update(priority: ConstraintPriorityTarget) instead.")
public func updatePriorityHigh() -> Void { fatalError("Must be implemented by Concrete subclass.") }
@available(*, obsoleted:0.40.0, message:"Use update(priority: ConstraintPriorityTarget) instead.")
public func updatePriorityMedium() -> Void { fatalError("Must be implemented by Concrete subclass.") }
@available(*, obsoleted:0.40.0, message:"Use update(priority: ConstraintPriorityTarget) instead.")
public func updatePriorityLow() -> Void { fatalError("Must be implemented by Concrete subclass.") }
// MARK: Internal
internal func updateConstantAndPriorityIfNeeded() {
for layoutConstraint in self.layoutConstraints {
let attribute = (layoutConstraint.secondAttribute == .notAnAttribute) ? layoutConstraint.firstAttribute : layoutConstraint.secondAttribute
layoutConstraint.constant = self.constant.constraintConstantTargetValueFor(layoutAttribute: attribute)
layoutConstraint.priority = self.priority.constraintPriorityTargetValue
}
}
internal func activateIfNeeded(updatingExisting: Bool = false) {
let view = self.from.view!
let layoutConstraints = self.layoutConstraints
let existingLayoutConstraints = view.snp.layoutConstraints
if updatingExisting {
for layoutConstraint in layoutConstraints {
let existingLayoutConstraint = existingLayoutConstraints.first { $0 == layoutConstraint }
guard let updateLayoutConstraint = existingLayoutConstraint else {
fatalError("Updated constraint could not find existing matching constraint to update: \(layoutConstraint)")
}
// if we have existing one lets just update the constant
if updateLayoutConstraint != nil {
updateLayoutConstraint!.constant = layoutConstraint.constant
}
// otherwise add this layout constraint to new keep list
else {
newLayoutConstraintsToKeep.append(layoutConstraint)
}
let updateLayoutAttribute = (updateLayoutConstraint.secondAttribute == .notAnAttribute) ? updateLayoutConstraint.firstAttribute : updateLayoutConstraint.secondAttribute
updateLayoutConstraint.constant = self.constant.constraintConstantTargetValueFor(layoutAttribute: updateLayoutAttribute)
}
// set constraints to only new ones
newLayoutConstraints = newLayoutConstraintsToKeep
}
// add constraints
#if SNAPKIT_DEPLOYMENT_LEGACY && !os(OSX)
if #available(iOS 8.0, *) {
NSLayoutConstraint.activateConstraints(newLayoutConstraints)
} else {
installOnView!.addConstraints(newLayoutConstraints)
NSLayoutConstraint.activate(layoutConstraints)
view.snp.add(layoutConstraints: layoutConstraints)
}
#else
NSLayoutConstraint.activateConstraints(newLayoutConstraints)
#endif
// set install info
self.installInfo = ConcreteConstraintInstallInfo(view: installOnView, layoutConstraints: NSHashTable.weakObjectsHashTable())
// store which layout constraints are installed for this constraint
for layoutConstraint in newLayoutConstraints {
self.installInfo!.layoutConstraints.addObject(layoutConstraint)
}
// store the layout constraints against the layout from view
layoutFrom!.snp_installedLayoutConstraints += newLayoutConstraints
// return the new constraints
return newLayoutConstraints
}
internal func uninstallFromView() {
if let installInfo = self.installInfo,
let installedLayoutConstraints = installInfo.layoutConstraints.allObjects as? [LayoutConstraint] {
if installedLayoutConstraints.count > 0 {
// remove the constraints from the UIView's storage
#if SNAPKIT_DEPLOYMENT_LEGACY && !os(OSX)
if #available(iOS 8.0, *) {
NSLayoutConstraint.deactivateConstraints(installedLayoutConstraints)
} else if let installedOnView = installInfo.view {
installedOnView.removeConstraints(installedLayoutConstraints)
}
#else
NSLayoutConstraint.deactivateConstraints(installedLayoutConstraints)
#endif
// remove the constraints from the from item view
if let fromView = self.fromItem.view {
fromView.snp_installedLayoutConstraints = fromView.snp_installedLayoutConstraints.filter {
return !installedLayoutConstraints.contains($0)
}
}
}
}
self.installInfo = nil
}
}
private struct ConcreteConstraintInstallInfo {
weak var view: View? = nil
let layoutConstraints: NSHashTable
}
private extension NSLayoutAttribute {
private func snp_constantForValue(value: Any?) -> CGFloat {
// Float
if let float = value as? Float {
return CGFloat(float)
}
// Double
else if let double = value as? Double {
return CGFloat(double)
}
// UInt
else if let int = value as? Int {
return CGFloat(int)
}
// Int
else if let uint = value as? UInt {
return CGFloat(uint)
}
// CGFloat
else if let float = value as? CGFloat {
return float
}
// CGSize
else if let size = value as? CGSize {
if self == .Width {
return size.width
} else if self == .Height {
return size.height
}
}
// CGPoint
else if let point = value as? CGPoint {
#if os(iOS) || os(tvOS)
switch self {
case .Left, .CenterX, .LeftMargin, .CenterXWithinMargins: return point.x
case .Top, .CenterY, .TopMargin, .CenterYWithinMargins, .LastBaseline, .FirstBaseline: return point.y
case .Right, .RightMargin: return point.x
case .Bottom, .BottomMargin: return point.y
case .Leading, .LeadingMargin: return point.x
case .Trailing, .TrailingMargin: return point.x
case .Width, .Height, .NotAnAttribute: return CGFloat(0)
}
#else
switch self {
case .Left, .CenterX: return point.x
case .Top, .CenterY, .LastBaseline: return point.y
case .Right: return point.x
case .Bottom: return point.y
case .Leading: return point.x
case .Trailing: return point.x
case .Width, .Height, .NotAnAttribute: return CGFloat(0)
case .FirstBaseline: return point.y
}
#endif
}
// EdgeInsets
else if let insets = value as? EdgeInsets {
#if os(iOS) || os(tvOS)
switch self {
case .Left, .CenterX, .LeftMargin, .CenterXWithinMargins: return insets.left
case .Top, .CenterY, .TopMargin, .CenterYWithinMargins, .LastBaseline, .FirstBaseline: return insets.top
case .Right, .RightMargin: return insets.right
case .Bottom, .BottomMargin: return insets.bottom
case .Leading, .LeadingMargin: return (Config.interfaceLayoutDirection == .LeftToRight) ? insets.left : -insets.right
case .Trailing, .TrailingMargin: return (Config.interfaceLayoutDirection == .LeftToRight) ? insets.right : -insets.left
case .Width: return -insets.left + insets.right
case .Height: return -insets.top + insets.bottom
case .NotAnAttribute: return CGFloat(0)
}
#else
switch self {
case .Left, .CenterX: return insets.left
case .Top, .CenterY, .LastBaseline: return insets.top
case .Right: return insets.right
case .Bottom: return insets.bottom
case .Leading: return (Config.interfaceLayoutDirection == .LeftToRight) ? insets.left : -insets.right
case .Trailing: return (Config.interfaceLayoutDirection == .LeftToRight) ? insets.right : -insets.left
case .Width: return -insets.left + insets.right
case .Height: return -insets.top + insets.bottom
case .NotAnAttribute: return CGFloat(0)
case .FirstBaseline: return insets.bottom
}
#endif
}
return CGFloat(0);
internal func deactivateIfNeeded() {
let view = self.from.view!
let layoutConstraints = self.layoutConstraints
NSLayoutConstraint.deactivate(layoutConstraints)
view.snp.remove(layoutConstraints: layoutConstraints)
}
}
private func closestCommonSuperviewFromView(fromView: View?, toView: View?) -> View? {
var views = Set<View>()
var fromView = fromView
var toView = toView
repeat {
if let view = toView {
if views.contains(view) {
return view
}
views.insert(view)
toView = view.superview
}
if let view = fromView {
if views.contains(view) {
return view
}
views.insert(view)
fromView = view.superview
}
} while (fromView != nil || toView != nil)
return nil
}
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)
}

View File

@ -1,7 +1,7 @@
//
// SnapKit
//
// Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -22,15 +22,13 @@
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
import UIKit
#else
import AppKit
import AppKit
#endif
/**
Used to define `NSLayoutAttributes` in a more concise and composite manner
*/
internal struct ConstraintAttributes: OptionSetType, BooleanType {
internal struct ConstraintAttributes: OptionSet {
internal init(rawValue: UInt) {
self.rawValue = rawValue
@ -48,139 +46,145 @@ internal struct ConstraintAttributes: OptionSetType, BooleanType {
internal var boolValue: Bool { return self.rawValue != 0 }
internal func toRaw() -> UInt { return self.rawValue }
internal static func fromRaw(raw: UInt) -> ConstraintAttributes? { return self.init(raw) }
internal static func fromMask(raw: UInt) -> ConstraintAttributes { return self.init(raw) }
internal static func fromRaw(_ raw: UInt) -> ConstraintAttributes? { return self.init(raw) }
internal static func fromMask(_ raw: UInt) -> ConstraintAttributes { return self.init(raw) }
// normal
internal static var None: ConstraintAttributes { return self.init(0) }
internal static var Left: ConstraintAttributes { return self.init(1) }
internal static var Top: ConstraintAttributes { return self.init(2) }
internal static var Right: ConstraintAttributes { return self.init(4) }
internal static var Bottom: ConstraintAttributes { return self.init(8) }
internal static var Leading: ConstraintAttributes { return self.init(16) }
internal static var Trailing: ConstraintAttributes { return self.init(32) }
internal static var Width: ConstraintAttributes { return self.init(64) }
internal static var Height: ConstraintAttributes { return self.init(128) }
internal static var CenterX: ConstraintAttributes { return self.init(256) }
internal static var CenterY: ConstraintAttributes { return self.init(512) }
internal static var Baseline: ConstraintAttributes { return self.init(1024) }
internal static var none: ConstraintAttributes { return self.init(0) }
internal static var left: ConstraintAttributes { return self.init(1) }
internal static var top: ConstraintAttributes { return self.init(2) }
internal static var right: ConstraintAttributes { return self.init(4) }
internal static var bottom: ConstraintAttributes { return self.init(8) }
internal static var leading: ConstraintAttributes { return self.init(16) }
internal static var trailing: ConstraintAttributes { return self.init(32) }
internal static var width: ConstraintAttributes { return self.init(64) }
internal static var height: ConstraintAttributes { return self.init(128) }
internal static var centerX: ConstraintAttributes { return self.init(256) }
internal static var centerY: ConstraintAttributes { return self.init(512) }
internal static var lastBaseline: ConstraintAttributes { return self.init(1024) }
@available(iOS 8.0, OSX 10.11, *)
internal static var firstBaseline: ConstraintAttributes { return self.init(2048) }
@available(iOS 8.0, *)
internal static var FirstBaseline: ConstraintAttributes { return self.init(2048) }
internal static var leftMargin: ConstraintAttributes { return self.init(4096) }
@available(iOS 8.0, *)
internal static var LeftMargin: ConstraintAttributes { return self.init(4096) }
internal static var rightMargin: ConstraintAttributes { return self.init(8192) }
@available(iOS 8.0, *)
internal static var RightMargin: ConstraintAttributes { return self.init(8192) }
internal static var topMargin: ConstraintAttributes { return self.init(16384) }
@available(iOS 8.0, *)
internal static var TopMargin: ConstraintAttributes { return self.init(16384) }
internal static var bottomMargin: ConstraintAttributes { return self.init(32768) }
@available(iOS 8.0, *)
internal static var BottomMargin: ConstraintAttributes { return self.init(32768) }
internal static var leadingMargin: ConstraintAttributes { return self.init(65536) }
@available(iOS 8.0, *)
internal static var LeadingMargin: ConstraintAttributes { return self.init(65536) }
internal static var trailingMargin: ConstraintAttributes { return self.init(131072) }
@available(iOS 8.0, *)
internal static var TrailingMargin: ConstraintAttributes { return self.init(131072) }
internal static var centerXWithinMargins: ConstraintAttributes { return self.init(262144) }
@available(iOS 8.0, *)
internal static var CenterXWithinMargins: ConstraintAttributes { return self.init(262144) }
@available(iOS 8.0, *)
internal static var CenterYWithinMargins: ConstraintAttributes { return self.init(524288) }
internal static var centerYWithinMargins: ConstraintAttributes { return self.init(524288) }
// aggregates
internal static var Edges: ConstraintAttributes { return self.init(15) }
internal static var Size: ConstraintAttributes { return self.init(192) }
internal static var Center: ConstraintAttributes { return self.init(768) }
internal static var edges: ConstraintAttributes { return self.init(15) }
internal static var size: ConstraintAttributes { return self.init(192) }
internal static var center: ConstraintAttributes { return self.init(768) }
@available(iOS 8.0, *)
internal static var Margins: ConstraintAttributes { return self.init(61440) }
internal static var margins: ConstraintAttributes { return self.init(61440) }
@available(iOS 8.0, *)
internal static var CenterWithinMargins: ConstraintAttributes { return self.init(786432) }
internal static var centerWithinMargins: ConstraintAttributes { return self.init(786432) }
internal var layoutAttributes:[NSLayoutAttribute] {
var attrs = [NSLayoutAttribute]()
if (self.contains(ConstraintAttributes.Left)) {
attrs.append(.Left)
if (self.contains(ConstraintAttributes.left)) {
attrs.append(.left)
}
if (self.contains(ConstraintAttributes.Top)) {
attrs.append(.Top)
if (self.contains(ConstraintAttributes.top)) {
attrs.append(.top)
}
if (self.contains(ConstraintAttributes.Right)) {
attrs.append(.Right)
if (self.contains(ConstraintAttributes.right)) {
attrs.append(.right)
}
if (self.contains(ConstraintAttributes.Bottom)) {
attrs.append(.Bottom)
if (self.contains(ConstraintAttributes.bottom)) {
attrs.append(.bottom)
}
if (self.contains(ConstraintAttributes.Leading)) {
attrs.append(.Leading)
if (self.contains(ConstraintAttributes.leading)) {
attrs.append(.leading)
}
if (self.contains(ConstraintAttributes.Trailing)) {
attrs.append(.Trailing)
if (self.contains(ConstraintAttributes.trailing)) {
attrs.append(.trailing)
}
if (self.contains(ConstraintAttributes.Width)) {
attrs.append(.Width)
if (self.contains(ConstraintAttributes.width)) {
attrs.append(.width)
}
if (self.contains(ConstraintAttributes.Height)) {
attrs.append(.Height)
if (self.contains(ConstraintAttributes.height)) {
attrs.append(.height)
}
if (self.contains(ConstraintAttributes.CenterX)) {
attrs.append(.CenterX)
if (self.contains(ConstraintAttributes.centerX)) {
attrs.append(.centerX)
}
if (self.contains(ConstraintAttributes.CenterY)) {
attrs.append(.CenterY)
if (self.contains(ConstraintAttributes.centerY)) {
attrs.append(.centerY)
}
if (self.contains(ConstraintAttributes.Baseline)) {
#if swift(>=2.3)
attrs.append(.LastBaseline)
#else
attrs.append(.Baseline)
#endif
if (self.contains(ConstraintAttributes.lastBaseline)) {
attrs.append(.lastBaseline)
}
#if os(iOS) || os(tvOS)
#if SNAPKIT_DEPLOYMENT_LEGACY
guard #available(iOS 8.0, *) else {
return attrs
}
#endif
if (self.contains(ConstraintAttributes.FirstBaseline)) {
attrs.append(.FirstBaseline)
}
if (self.contains(ConstraintAttributes.LeftMargin)) {
attrs.append(.LeftMargin)
}
if (self.contains(ConstraintAttributes.RightMargin)) {
attrs.append(.RightMargin)
}
if (self.contains(ConstraintAttributes.TopMargin)) {
attrs.append(.TopMargin)
}
if (self.contains(ConstraintAttributes.BottomMargin)) {
attrs.append(.BottomMargin)
}
if (self.contains(ConstraintAttributes.LeadingMargin)) {
attrs.append(.LeadingMargin)
}
if (self.contains(ConstraintAttributes.TrailingMargin)) {
attrs.append(.TrailingMargin)
}
if (self.contains(ConstraintAttributes.CenterXWithinMargins)) {
attrs.append(.CenterXWithinMargins)
}
if (self.contains(ConstraintAttributes.CenterYWithinMargins)) {
attrs.append(.CenterYWithinMargins)
}
if (self.contains(ConstraintAttributes.firstBaseline)) {
attrs.append(.firstBaseline)
}
if (self.contains(ConstraintAttributes.leftMargin)) {
attrs.append(.leftMargin)
}
if (self.contains(ConstraintAttributes.rightMargin)) {
attrs.append(.rightMargin)
}
if (self.contains(ConstraintAttributes.topMargin)) {
attrs.append(.topMargin)
}
if (self.contains(ConstraintAttributes.bottomMargin)) {
attrs.append(.bottomMargin)
}
if (self.contains(ConstraintAttributes.leadingMargin)) {
attrs.append(.leadingMargin)
}
if (self.contains(ConstraintAttributes.trailingMargin)) {
attrs.append(.trailingMargin)
}
if (self.contains(ConstraintAttributes.centerXWithinMargins)) {
attrs.append(.centerXWithinMargins)
}
if (self.contains(ConstraintAttributes.centerYWithinMargins)) {
attrs.append(.centerYWithinMargins)
}
#endif
return attrs
}
}
internal func +=(inout left: ConstraintAttributes, right: ConstraintAttributes) {
left.unionInPlace(right)
internal func + (left: ConstraintAttributes, right: ConstraintAttributes) -> ConstraintAttributes {
return left.union(right)
}
internal func -=(inout left: ConstraintAttributes, right: ConstraintAttributes) {
left.subtractInPlace(right)
internal func +=(left: inout ConstraintAttributes, right: ConstraintAttributes) {
left.formUnion(right)
}
internal func -=(left: inout ConstraintAttributes, right: ConstraintAttributes) {
left.subtract(right)
}
internal func ==(left: ConstraintAttributes, right: ConstraintAttributes) -> Bool {
return left.rawValue == right.rawValue
}

View File

@ -1,7 +1,7 @@
//
// SnapKit
//
// Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -22,21 +22,16 @@
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
public typealias InterfaceLayoutDirection = UIUserInterfaceLayoutDirection
public typealias LayoutSupport = UILayoutSupport
import UIKit
public typealias ConstraintInterfaceLayoutDirection = UIUserInterfaceLayoutDirection
#else
import AppKit
public typealias InterfaceLayoutDirection = NSUserInterfaceLayoutDirection
public class LayoutSupport {}
import AppKit
public typealias ConstraintInterfaceLayoutDirection = NSUserInterfaceLayoutDirection
#endif
/**
Used to configure different parts of SnapKit
*/
public struct Config {
/// The interface layout direction
public static var interfaceLayoutDirection = InterfaceLayoutDirection.LeftToRight
public struct ConstraintConfig {
public static var interfaceLayoutDirection: ConstraintInterfaceLayoutDirection = .leftToRight
}

View File

@ -0,0 +1,147 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
public protocol ConstraintConstantTarget {
}
extension CGPoint: ConstraintConstantTarget {
}
extension CGSize: ConstraintConstantTarget {
}
extension ConstraintInsets: ConstraintConstantTarget {
}
extension ConstraintConstantTarget {
internal func constraintConstantTargetValueFor(layoutAttribute: NSLayoutAttribute) -> CGFloat {
if let value = self as? CGFloat {
return value
}
if let value = self as? Float {
return CGFloat(value)
}
if let value = self as? Double {
return CGFloat(value)
}
if let value = self as? Int {
return CGFloat(value)
}
if let value = self as? UInt {
return CGFloat(value)
}
if let value = self as? CGSize {
if layoutAttribute == .width {
return value.width
} else if layoutAttribute == .height {
return value.height
} else {
return 0.0
}
}
if let value = self as? CGPoint {
#if os(iOS) || os(tvOS)
switch layoutAttribute {
case .left, .right, .leading, .trailing, .centerX, .leftMargin, .rightMargin, .leadingMargin, .trailingMargin, .centerXWithinMargins:
return value.x
case .top, .bottom, .centerY, .topMargin, .bottomMargin, .centerYWithinMargins, .lastBaseline, .firstBaseline:
return value.y
case .width, .height, .notAnAttribute:
return 0.0
}
#else
switch layoutAttribute {
case .left, .right, .leading, .trailing, .centerX:
return value.x
case .top, .bottom, .centerY, .lastBaseline, .firstBaseline:
return value.y
case .width, .height, .notAnAttribute:
return 0.0
}
#endif
}
if let value = self as? ConstraintInsets {
#if os(iOS) || os(tvOS)
switch layoutAttribute {
case .left, .leftMargin, .centerX, .centerXWithinMargins:
return value.left
case .top, .topMargin, .centerY, .centerYWithinMargins, .lastBaseline, .firstBaseline:
return value.top
case .right, .rightMargin:
return -value.right
case .bottom, .bottomMargin:
return -value.bottom
case .leading, .leadingMargin:
return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? value.left : -value.right
case .trailing, .trailingMargin:
return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? value.right : -value.left
case .width:
return -(value.left + value.right)
case .height:
return -(value.top + value.bottom)
case .notAnAttribute:
return 0.0
}
#else
switch layoutAttribute {
case .left, .centerX:
return value.left
case .top, .centerY, .lastBaseline, .firstBaseline:
return value.top
case .right:
return -value.right
case .bottom:
return -value.bottom
case .leading:
return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? value.left : -value.right
case .trailing:
return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? value.right : -value.left
case .width:
return -(value.left + value.right)
case .height:
return -(value.top + value.bottom)
case .notAnAttribute:
return 0.0
}
#endif
}
return 0.0
}
}

179
Source/ConstraintDSL.swift Normal file
View File

@ -0,0 +1,179 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
public protocol ConstraintDSL {
var label: String? { get set }
var target: AnyObject? { get }
}
extension ConstraintDSL {
public var label: String? {
get {
return objc_getAssociatedObject(self.target, &labelKey) as? String
}
set {
objc_setAssociatedObject(self.target, &labelKey, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
}
}
}
private var labelKey: UInt8 = 0
public protocol ConstraintAttributesDSL: ConstraintDSL {
}
extension ConstraintAttributesDSL {
// MARK: Basics
public var left: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.left)
}
public var top: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.top)
}
public var right: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.right)
}
public var bottom: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottom)
}
public var leading: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leading)
}
public var trailing: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.trailing)
}
public var width: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.width)
}
public var height: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.height)
}
public var centerX: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerX)
}
public var centerY: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerY)
}
public var edges: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.edges)
}
public var size: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.size)
}
public var center: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.center)
}
// MARK: Baselines
@available(*, deprecated:0.40.0, message:"Use .lastBaseline instead")
public var baseline: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.lastBaseline)
}
@available(iOS 8.0, OSX 10.11, *)
public var lastBaseline: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.lastBaseline)
}
@available(iOS 8.0, OSX 10.11, *)
public var firstBaseline: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.firstBaseline)
}
// MARK: Margins
@available(iOS 8.0, *)
public var leftMargin: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leftMargin)
}
@available(iOS 8.0, *)
public var topMargin: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.topMargin)
}
@available(iOS 8.0, *)
public var rightMargin: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.rightMargin)
}
@available(iOS 8.0, *)
public var bottomMargin: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottomMargin)
}
@available(iOS 8.0, *)
public var leadingMargin: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leadingMargin)
}
@available(iOS 8.0, *)
public var trailingMargin: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.trailingMargin)
}
@available(iOS 8.0, *)
public var centerXWithinMargins: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerXWithinMargins)
}
@available(iOS 8.0, *)
public var centerYWithinMargins: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerYWithinMargins)
}
@available(iOS 8.0, *)
public var margins: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.margins)
}
@available(iOS 8.0, *)
public var centerWithinMargins: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerWithinMargins)
}
}

View File

@ -1,7 +1,7 @@
//
// SnapKit
//
// Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -22,609 +22,48 @@
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
import UIKit
#else
import AppKit
import AppKit
#endif
/**
Used to expose the final API of a `ConstraintDescription` which allows getting a constraint from it
*/
public protocol ConstraintDescriptionFinalizable: class {
var constraint: Constraint { get }
public class ConstraintDescription {
func labeled(label: String) -> ConstraintDescriptionFinalizable
internal let view: ConstraintView
internal var attributes: ConstraintAttributes
internal var relation: ConstraintRelation? = nil
internal var sourceLocation: (String, UInt)? = nil
internal var label: String? = nil
internal var related: ConstraintItem? = nil
internal var multiplier: ConstraintMultiplierTarget = 1.0
internal var constant: ConstraintConstantTarget = 0.0
internal var priority: ConstraintPriorityTarget = 1000.0
internal lazy var constraint: Constraint? = {
guard let relation = self.relation,
let related = self.related,
let sourceLocation = self.sourceLocation else {
return nil
}
let from = ConstraintItem(target: self.view, attributes: self.attributes)
return Constraint(
from: from,
to: related,
relation: relation,
sourceLocation: sourceLocation,
label: self.label,
multiplier: self.multiplier,
constant: self.constant,
priority: self.priority
)
}()
// MARK: Initialization
internal init(view: ConstraintView, attributes: ConstraintAttributes) {
self.view = view
self.attributes = attributes
}
}
/**
Used to expose priority APIs
*/
public protocol ConstraintDescriptionPriortizable: ConstraintDescriptionFinalizable {
func priority(priority: Float) -> ConstraintDescriptionFinalizable
func priority(priority: Double) -> ConstraintDescriptionFinalizable
func priority(priority: CGFloat) -> ConstraintDescriptionFinalizable
func priority(priority: UInt) -> ConstraintDescriptionFinalizable
func priority(priority: Int) -> ConstraintDescriptionFinalizable
func priorityRequired() -> ConstraintDescriptionFinalizable
func priorityHigh() -> ConstraintDescriptionFinalizable
func priorityMedium() -> ConstraintDescriptionFinalizable
func priorityLow() -> ConstraintDescriptionFinalizable
}
/**
Used to expose multiplier & constant APIs
*/
public protocol ConstraintDescriptionEditable: ConstraintDescriptionPriortizable {
func multipliedBy(amount: Float) -> ConstraintDescriptionEditable
func multipliedBy(amount: Double) -> ConstraintDescriptionEditable
func multipliedBy(amount: CGFloat) -> ConstraintDescriptionEditable
func multipliedBy(amount: Int) -> ConstraintDescriptionEditable
func multipliedBy(amount: UInt) -> ConstraintDescriptionEditable
func dividedBy(amount: Float) -> ConstraintDescriptionEditable
func dividedBy(amount: Double) -> ConstraintDescriptionEditable
func dividedBy(amount: CGFloat) -> ConstraintDescriptionEditable
func dividedBy(amount: Int) -> ConstraintDescriptionEditable
func dividedBy(amount: UInt) -> ConstraintDescriptionEditable
func offset(amount: Float) -> ConstraintDescriptionEditable
func offset(amount: Double) -> ConstraintDescriptionEditable
func offset(amount: CGFloat) -> ConstraintDescriptionEditable
func offset(amount: Int) -> ConstraintDescriptionEditable
func offset(amount: UInt) -> ConstraintDescriptionEditable
func offset(amount: CGPoint) -> ConstraintDescriptionEditable
func offset(amount: CGSize) -> ConstraintDescriptionEditable
func offset(amount: EdgeInsets) -> ConstraintDescriptionEditable
func inset(amount: Float) -> ConstraintDescriptionEditable
func inset(amount: Double) -> ConstraintDescriptionEditable
func inset(amount: CGFloat) -> ConstraintDescriptionEditable
func inset(amount: Int) -> ConstraintDescriptionEditable
func inset(amount: UInt) -> ConstraintDescriptionEditable
func inset(amount: EdgeInsets) -> ConstraintDescriptionEditable
}
/**
Used to expose relation APIs
*/
public protocol ConstraintDescriptionRelatable: class {
func equalTo(other: ConstraintItem) -> ConstraintDescriptionEditable
func equalTo(other: View) -> ConstraintDescriptionEditable
func equalToSuperview() -> ConstraintDescriptionEditable
@available(iOS 7.0, *)
func equalTo(other: LayoutSupport) -> ConstraintDescriptionEditable
@available(iOS 9.0, OSX 10.11, *)
func equalTo(other: NSLayoutAnchor) -> ConstraintDescriptionEditable
func equalTo(other: Float) -> ConstraintDescriptionEditable
func equalTo(other: Double) -> ConstraintDescriptionEditable
func equalTo(other: CGFloat) -> ConstraintDescriptionEditable
func equalTo(other: Int) -> ConstraintDescriptionEditable
func equalTo(other: UInt) -> ConstraintDescriptionEditable
func equalTo(other: CGSize) -> ConstraintDescriptionEditable
func equalTo(other: CGPoint) -> ConstraintDescriptionEditable
func equalTo(other: EdgeInsets) -> ConstraintDescriptionEditable
func lessThanOrEqualTo(other: ConstraintItem) -> ConstraintDescriptionEditable
func lessThanOrEqualTo(other: View) -> ConstraintDescriptionEditable
func lessThanOrEqualToSuperview() -> ConstraintDescriptionEditable
@available(iOS 7.0, *)
func lessThanOrEqualTo(other: LayoutSupport) -> ConstraintDescriptionEditable
@available(iOS 9.0, OSX 10.11, *)
func lessThanOrEqualTo(other: NSLayoutAnchor) -> ConstraintDescriptionEditable
func lessThanOrEqualTo(other: Float) -> ConstraintDescriptionEditable
func lessThanOrEqualTo(other: Double) -> ConstraintDescriptionEditable
func lessThanOrEqualTo(other: CGFloat) -> ConstraintDescriptionEditable
func lessThanOrEqualTo(other: Int) -> ConstraintDescriptionEditable
func lessThanOrEqualTo(other: UInt) -> ConstraintDescriptionEditable
func lessThanOrEqualTo(other: CGSize) -> ConstraintDescriptionEditable
func lessThanOrEqualTo(other: CGPoint) -> ConstraintDescriptionEditable
func lessThanOrEqualTo(other: EdgeInsets) -> ConstraintDescriptionEditable
func greaterThanOrEqualTo(other: ConstraintItem) -> ConstraintDescriptionEditable
func greaterThanOrEqualTo(other: View) -> ConstraintDescriptionEditable
func greaterThanOrEqualToSuperview() -> ConstraintDescriptionEditable
@available(iOS 7.0, *)
func greaterThanOrEqualTo(other: LayoutSupport) -> ConstraintDescriptionEditable
@available(iOS 9.0, OSX 10.11, *)
func greaterThanOrEqualTo(other: NSLayoutAnchor) -> ConstraintDescriptionEditable
func greaterThanOrEqualTo(other: Float) -> ConstraintDescriptionEditable
func greaterThanOrEqualTo(other: Double) -> ConstraintDescriptionEditable
func greaterThanOrEqualTo(other: CGFloat) -> ConstraintDescriptionEditable
func greaterThanOrEqualTo(other: Int) -> ConstraintDescriptionEditable
func greaterThanOrEqualTo(other: UInt) -> ConstraintDescriptionEditable
func greaterThanOrEqualTo(other: CGSize) -> ConstraintDescriptionEditable
func greaterThanOrEqualTo(other: CGPoint) -> ConstraintDescriptionEditable
func greaterThanOrEqualTo(other: EdgeInsets) -> ConstraintDescriptionEditable
}
/**
Used to expose chaining APIs
*/
public protocol ConstraintDescriptionExtendable: ConstraintDescriptionRelatable {
var left: ConstraintDescriptionExtendable { get }
var top: ConstraintDescriptionExtendable { get }
var bottom: ConstraintDescriptionExtendable { get }
var right: ConstraintDescriptionExtendable { get }
var leading: ConstraintDescriptionExtendable { get }
var trailing: ConstraintDescriptionExtendable { get }
var width: ConstraintDescriptionExtendable { get }
var height: ConstraintDescriptionExtendable { get }
var centerX: ConstraintDescriptionExtendable { get }
var centerY: ConstraintDescriptionExtendable { get }
var baseline: ConstraintDescriptionExtendable { get }
@available(iOS 8.0, *)
var firstBaseline: ConstraintDescriptionExtendable { get }
@available(iOS 8.0, *)
var leftMargin: ConstraintDescriptionExtendable { get }
@available(iOS 8.0, *)
var rightMargin: ConstraintDescriptionExtendable { get }
@available(iOS 8.0, *)
var topMargin: ConstraintDescriptionExtendable { get }
@available(iOS 8.0, *)
var bottomMargin: ConstraintDescriptionExtendable { get }
@available(iOS 8.0, *)
var leadingMargin: ConstraintDescriptionExtendable { get }
@available(iOS 8.0, *)
var trailingMargin: ConstraintDescriptionExtendable { get }
@available(iOS 8.0, *)
var centerXWithinMargins: ConstraintDescriptionExtendable { get }
@available(iOS 8.0, *)
var centerYWithinMargins: ConstraintDescriptionExtendable { get }
}
/**
Used to internally manage building constraint
*/
internal class ConstraintDescription: ConstraintDescriptionExtendable, ConstraintDescriptionEditable, ConstraintDescriptionFinalizable {
internal var left: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.Left) }
internal var top: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.Top) }
internal var right: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.Right) }
internal var bottom: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.Bottom) }
internal var leading: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.Leading) }
internal var trailing: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.Trailing) }
internal var width: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.Width) }
internal var height: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.Height) }
internal var centerX: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.CenterX) }
internal var centerY: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.CenterY) }
internal var baseline: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.Baseline) }
internal var label: String?
@available(iOS 8.0, *)
internal var firstBaseline: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.FirstBaseline) }
@available(iOS 8.0, *)
internal var leftMargin: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.LeftMargin) }
@available(iOS 8.0, *)
internal var rightMargin: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.RightMargin) }
@available(iOS 8.0, *)
internal var topMargin: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.TopMargin) }
@available(iOS 8.0, *)
internal var bottomMargin: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.BottomMargin) }
@available(iOS 8.0, *)
internal var leadingMargin: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.LeadingMargin) }
@available(iOS 8.0, *)
internal var trailingMargin: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.TrailingMargin) }
@available(iOS 8.0, *)
internal var centerXWithinMargins: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.CenterXWithinMargins) }
@available(iOS 8.0, *)
internal var centerYWithinMargins: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.CenterYWithinMargins) }
// MARK: initializer
init(fromItem: ConstraintItem) {
self.fromItem = fromItem
self.toItem = ConstraintItem(object: nil, attributes: ConstraintAttributes.None)
}
// MARK: equalTo
internal func equalTo(other: ConstraintItem) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .Equal)
}
internal func equalTo(other: View) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .Equal)
}
internal func equalToSuperview() -> ConstraintDescriptionEditable {
guard let superview = fromItem.view?.superview else {
fatalError("equalToSuperview() requires the view have a superview before being set.")
}
return self.equalTo(superview)
}
@available(iOS 7.0, *)
internal func equalTo(other: LayoutSupport) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .Equal)
}
@available(iOS 9.0, OSX 10.11, *)
internal func equalTo(other: NSLayoutAnchor) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .Equal)
}
internal func equalTo(other: Float) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .Equal)
}
internal func equalTo(other: Double) -> ConstraintDescriptionEditable {
return self.constrainTo(Float(other), relation: .Equal)
}
internal func equalTo(other: CGFloat) -> ConstraintDescriptionEditable {
return self.constrainTo(Float(other), relation: .Equal)
}
internal func equalTo(other: Int) -> ConstraintDescriptionEditable {
return self.constrainTo(Float(other), relation: .Equal)
}
internal func equalTo(other: UInt) -> ConstraintDescriptionEditable {
return self.constrainTo(Float(other), relation: .Equal)
}
internal func equalTo(other: CGSize) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .Equal)
}
internal func equalTo(other: CGPoint) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .Equal)
}
internal func equalTo(other: EdgeInsets) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .Equal)
}
// MARK: lessThanOrEqualTo
internal func lessThanOrEqualTo(other: ConstraintItem) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .LessThanOrEqualTo)
}
internal func lessThanOrEqualTo(other: View) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .LessThanOrEqualTo)
}
internal func lessThanOrEqualToSuperview() -> ConstraintDescriptionEditable {
guard let superview = fromItem.view?.superview else {
fatalError("lessThanOrEqualToSuperview() requires the view have a superview before being set.")
}
return self.lessThanOrEqualTo(superview)
}
@available(iOS 7.0, *)
internal func lessThanOrEqualTo(other: LayoutSupport) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .LessThanOrEqualTo)
}
@available(iOS 9.0, OSX 10.11, *)
internal func lessThanOrEqualTo(other: NSLayoutAnchor) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .LessThanOrEqualTo)
}
internal func lessThanOrEqualTo(other: Float) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .LessThanOrEqualTo)
}
internal func lessThanOrEqualTo(other: Double) -> ConstraintDescriptionEditable {
return self.constrainTo(Float(other), relation: .LessThanOrEqualTo)
}
internal func lessThanOrEqualTo(other: CGFloat) -> ConstraintDescriptionEditable {
return self.constrainTo(Float(other), relation: .LessThanOrEqualTo)
}
internal func lessThanOrEqualTo(other: Int) -> ConstraintDescriptionEditable {
return self.constrainTo(Float(other), relation: .LessThanOrEqualTo)
}
internal func lessThanOrEqualTo(other: UInt) -> ConstraintDescriptionEditable {
return self.constrainTo(Float(other), relation: .LessThanOrEqualTo)
}
internal func lessThanOrEqualTo(other: CGSize) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .LessThanOrEqualTo)
}
internal func lessThanOrEqualTo(other: CGPoint) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .LessThanOrEqualTo)
}
internal func lessThanOrEqualTo(other: EdgeInsets) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .LessThanOrEqualTo)
}
// MARK: greaterThanOrEqualTo
internal func greaterThanOrEqualTo(other: ConstraintItem) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
}
internal func greaterThanOrEqualTo(other: View) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
}
internal func greaterThanOrEqualToSuperview() -> ConstraintDescriptionEditable {
guard let superview = fromItem.view?.superview else {
fatalError("greaterThanOrEqualToSuperview() requires the view have a superview before being set.")
}
return self.greaterThanOrEqualTo(superview)
}
@available(iOS 7.0, *)
internal func greaterThanOrEqualTo(other: LayoutSupport) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
}
@available(iOS 9.0, OSX 10.11, *)
internal func greaterThanOrEqualTo(other: NSLayoutAnchor) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .LessThanOrEqualTo)
}
internal func greaterThanOrEqualTo(other: Float) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
}
internal func greaterThanOrEqualTo(other: Double) -> ConstraintDescriptionEditable {
return self.constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
}
internal func greaterThanOrEqualTo(other: CGFloat) -> ConstraintDescriptionEditable {
return self.constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
}
internal func greaterThanOrEqualTo(other: Int) -> ConstraintDescriptionEditable {
return self.constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
}
internal func greaterThanOrEqualTo(other: UInt) -> ConstraintDescriptionEditable {
return self.constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
}
internal func greaterThanOrEqualTo(other: CGSize) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
}
internal func greaterThanOrEqualTo(other: CGPoint) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
}
internal func greaterThanOrEqualTo(other: EdgeInsets) -> ConstraintDescriptionEditable {
return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
}
// MARK: multiplier
internal func multipliedBy(amount: Float) -> ConstraintDescriptionEditable {
self.multiplier = amount
return self
}
internal func multipliedBy(amount: Double) -> ConstraintDescriptionEditable {
return self.multipliedBy(Float(amount))
}
internal func multipliedBy(amount: CGFloat) -> ConstraintDescriptionEditable {
return self.multipliedBy(Float(amount))
}
internal func multipliedBy(amount: Int) -> ConstraintDescriptionEditable {
return self.multipliedBy(Float(amount))
}
internal func multipliedBy(amount: UInt) -> ConstraintDescriptionEditable {
return self.multipliedBy(Float(amount))
}
internal func dividedBy(amount: Float) -> ConstraintDescriptionEditable {
self.multiplier = 1.0 / amount;
return self
}
internal func dividedBy(amount: Double) -> ConstraintDescriptionEditable {
return self.dividedBy(Float(amount))
}
internal func dividedBy(amount: CGFloat) -> ConstraintDescriptionEditable {
return self.dividedBy(Float(amount))
}
internal func dividedBy(amount: Int) -> ConstraintDescriptionEditable {
return self.dividedBy(Float(amount))
}
internal func dividedBy(amount: UInt) -> ConstraintDescriptionEditable {
return self.dividedBy(Float(amount))
}
// MARK: offset
internal func offset(amount: Float) -> ConstraintDescriptionEditable {
self.constant = amount
return self
}
internal func offset(amount: Double) -> ConstraintDescriptionEditable {
return self.offset(Float(amount))
}
internal func offset(amount: CGFloat) -> ConstraintDescriptionEditable {
return self.offset(Float(amount))
}
internal func offset(amount: Int) -> ConstraintDescriptionEditable {
return self.offset(Float(amount))
}
internal func offset(amount: UInt) -> ConstraintDescriptionEditable {
return self.offset(Float(amount))
}
internal func offset(amount: CGPoint) -> ConstraintDescriptionEditable {
self.constant = amount
return self
}
internal func offset(amount: CGSize) -> ConstraintDescriptionEditable {
self.constant = amount
return self
}
internal func offset(amount: EdgeInsets) -> ConstraintDescriptionEditable {
self.constant = amount
return self
}
// MARK: inset
internal func inset(amount: Float) -> ConstraintDescriptionEditable {
let value = CGFloat(amount)
self.constant = EdgeInsets(top: value, left: value, bottom: -value, right: -value)
return self
}
internal func inset(amount: Double) -> ConstraintDescriptionEditable {
let value = CGFloat(amount)
self.constant = EdgeInsets(top: value, left: value, bottom: -value, right: -value)
return self
}
internal func inset(amount: CGFloat) -> ConstraintDescriptionEditable {
self.constant = EdgeInsets(top: amount, left: amount, bottom: -amount, right: -amount)
return self
}
internal func inset(amount: Int) -> ConstraintDescriptionEditable {
let value = CGFloat(amount)
self.constant = EdgeInsets(top: value, left: value, bottom: -value, right: -value)
return self
}
internal func inset(amount: UInt) -> ConstraintDescriptionEditable {
let value = CGFloat(amount)
self.constant = EdgeInsets(top: value, left: value, bottom: -value, right: -value)
return self
}
internal func inset(amount: EdgeInsets) -> ConstraintDescriptionEditable {
self.constant = EdgeInsets(top: amount.top, left: amount.left, bottom: -amount.bottom, right: -amount.right)
return self
}
// MARK: priority
internal func priority(priority: Float) -> ConstraintDescriptionFinalizable {
self.priority = priority
return self
}
internal func priority(priority: Double) -> ConstraintDescriptionFinalizable {
return self.priority(Float(priority))
}
internal func priority(priority: CGFloat) -> ConstraintDescriptionFinalizable {
return self.priority(Float(priority))
}
func priority(priority: UInt) -> ConstraintDescriptionFinalizable {
return self.priority(Float(priority))
}
internal func priority(priority: Int) -> ConstraintDescriptionFinalizable {
return self.priority(Float(priority))
}
internal func priorityRequired() -> ConstraintDescriptionFinalizable {
return self.priority(1000.0)
}
internal func priorityHigh() -> ConstraintDescriptionFinalizable {
return self.priority(750.0)
}
internal func priorityMedium() -> ConstraintDescriptionFinalizable {
#if os(iOS) || os(tvOS)
return self.priority(500.0)
#else
return self.priority(501.0)
#endif
}
internal func priorityLow() -> ConstraintDescriptionFinalizable {
return self.priority(250.0)
}
// MARK: Constraint
internal var constraint: Constraint {
if self.concreteConstraint == nil {
if self.relation == nil {
fatalError("Attempting to create a constraint from a ConstraintDescription before it has been fully chained.")
}
self.concreteConstraint = ConcreteConstraint(
fromItem: self.fromItem,
toItem: self.toItem,
relation: self.relation!,
constant: self.constant,
multiplier: self.multiplier,
priority: self.priority,
label: self.label)
}
return self.concreteConstraint!
}
func labeled(label: String) -> ConstraintDescriptionFinalizable {
self.label = label
return self
}
// MARK: Private
private let fromItem: ConstraintItem
private var toItem: ConstraintItem {
willSet {
if self.concreteConstraint != nil {
fatalError("Attempting to modify a ConstraintDescription after its constraint has been created.")
}
}
}
private var relation: ConstraintRelation? {
willSet {
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.concreteConstraint != nil {
fatalError("Attempting to modify a ConstraintDescription after its constraint has been created.")
}
}
}
private var multiplier: Float = 1.0 {
willSet {
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.concreteConstraint != nil {
fatalError("Attempting to modify a ConstraintDescription after its constraint has been created.")
}
}
}
private var concreteConstraint: ConcreteConstraint? = nil
private func addConstraint(attributes: ConstraintAttributes) -> ConstraintDescription {
if self.relation == nil {
self.fromItem.attributes += attributes
}
return self
}
private func constrainTo(other: ConstraintItem, relation: ConstraintRelation) -> ConstraintDescription {
if other.attributes != ConstraintAttributes.None {
let toLayoutAttributes = other.attributes.layoutAttributes
if toLayoutAttributes.count > 1 {
let fromLayoutAttributes = self.fromItem.attributes.layoutAttributes
if toLayoutAttributes != fromLayoutAttributes {
NSException(name: "Invalid Constraint", reason: "Cannot constrain to multiple non identical attributes", userInfo: nil).raise()
return self
}
other.attributes = ConstraintAttributes.None
}
}
self.toItem = other
self.relation = relation
return self
}
private func constrainTo(other: View, relation: ConstraintRelation) -> ConstraintDescription {
return constrainTo(ConstraintItem(object: other, attributes: ConstraintAttributes.None), relation: relation)
}
@available(iOS 7.0, *)
private func constrainTo(other: LayoutSupport, relation: ConstraintRelation) -> ConstraintDescription {
return constrainTo(ConstraintItem(object: other, attributes: ConstraintAttributes.None), relation: relation)
}
@available(iOS 9.0, OSX 10.11, *)
private func constrainTo(other: NSLayoutAnchor, relation: ConstraintRelation) -> ConstraintDescription {
return constrainTo(ConstraintItem(object: other, attributes: ConstraintAttributes.None), relation: relation)
}
private func constrainTo(other: Float, relation: ConstraintRelation) -> ConstraintDescription {
self.constant = other
return constrainTo(ConstraintItem(object: nil, attributes: ConstraintAttributes.None), relation: relation)
}
private func constrainTo(other: Double, relation: ConstraintRelation) -> ConstraintDescription {
self.constant = other
return constrainTo(ConstraintItem(object: nil, attributes: ConstraintAttributes.None), relation: relation)
}
private func constrainTo(other: CGSize, relation: ConstraintRelation) -> ConstraintDescription {
self.constant = other
return constrainTo(ConstraintItem(object: nil, attributes: ConstraintAttributes.None), relation: relation)
}
private func constrainTo(other: CGPoint, relation: ConstraintRelation) -> ConstraintDescription {
self.constant = other
return constrainTo(ConstraintItem(object: nil, attributes: ConstraintAttributes.None), relation: relation)
}
private func constrainTo(other: EdgeInsets, relation: ConstraintRelation) -> ConstraintDescription {
self.constant = other
return constrainTo(ConstraintItem(object: nil, attributes: ConstraintAttributes.None), relation: relation)
}
}

View File

@ -0,0 +1,72 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
public protocol ConstraintInsetTarget: ConstraintConstantTarget {
}
extension Int: ConstraintInsetTarget {
}
extension UInt: ConstraintInsetTarget {
}
extension Float: ConstraintInsetTarget {
}
extension Double: ConstraintInsetTarget {
}
extension CGFloat: ConstraintInsetTarget {
}
extension ConstraintInsets: ConstraintInsetTarget {
}
extension ConstraintInsetTarget {
internal var constraintInsetTargetValue: ConstraintInsets {
if let amount = self as? ConstraintInsets {
return amount
} else if let amount = self as? Float {
return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
} else if let amount = self as? Double {
return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
} else if let amount = self as? CGFloat {
return ConstraintInsets(top: amount, left: amount, bottom: amount, right: amount)
} else if let amount = self as? Int {
return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
} else if let amount = self as? UInt {
return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
} else {
return ConstraintInsets(top: 0, left: 0, bottom: 0, right: 0)
}
}
}

View File

@ -0,0 +1,35 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
#if os(iOS) || os(tvOS)
public typealias ConstraintInsets = UIEdgeInsets
#else
public typealias ConstraintInsets = EdgeInsets
#endif

View File

@ -1,7 +1,7 @@
//
// SnapKit
//
// Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -22,47 +22,40 @@
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
import UIKit
#else
import AppKit
import AppKit
#endif
/**
Used to assist in building a constraint
*/
public class ConstraintItem {
internal init(object: AnyObject?, attributes: ConstraintAttributes) {
self.object = object
public class ConstraintItem: Equatable {
internal weak var target: AnyObject?
internal let attributes: ConstraintAttributes
internal init(target: AnyObject?, attributes: ConstraintAttributes) {
self.target = target
self.attributes = attributes
}
internal weak var object: AnyObject?
internal var attributes: ConstraintAttributes
internal var view: View? {
return self.object as? View
internal var view: ConstraintView? {
return self.target as? ConstraintView
}
@available(iOS 7.0, *)
internal var layoutSupport: LayoutSupport? {
return self.object as? LayoutSupport
}
}
public func ==(lhs: ConstraintItem, rhs: ConstraintItem) -> Bool {
// pointer equality
guard lhs !== rhs else {
return true
}
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
// must both have valid targets and identical attributes
guard let target1 = lhs.target,
let target2 = rhs.target,
target1 === target2 && lhs.attributes == rhs.attributes else {
return false
}
return true
}

View File

@ -0,0 +1,36 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
#if os(iOS) || os(tvOS)
@available(iOS 9.0, *)
public typealias ConstraintLayoutGuide = UILayoutGuide
#else
public class ConstraintLayoutGuide {}
#endif

View File

@ -0,0 +1,45 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
@available(iOS 9.0, *)
public struct ConstraintLayoutGuideDSL: ConstraintAttributesDSL {
public var target: AnyObject? {
return self.guide
}
internal let guide: ConstraintLayoutGuide
internal init(guide: ConstraintLayoutGuide) {
self.guide = guide
}
}

View File

@ -0,0 +1,36 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
#if os(iOS) || os(tvOS)
@available(iOS 8.0, *)
public typealias ConstraintLayoutSupport = UILayoutSupport
#else
public class ConstraintLayoutSupport {}
#endif

View File

@ -1,7 +1,7 @@
//
// SnapKit
//
// Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -22,24 +22,35 @@
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
/**
Used to expose public API on view controllers
*/
public extension UIViewController {
/// top layout guide top
public var snp_topLayoutGuideTop: ConstraintItem { return ConstraintItem(object: self.topLayoutGuide, attributes: ConstraintAttributes.Top) }
/// top layout guide bottom
public var snp_topLayoutGuideBottom: ConstraintItem { return ConstraintItem(object: self.topLayoutGuide, attributes: ConstraintAttributes.Bottom) }
/// bottom layout guide top
public var snp_bottomLayoutGuideTop: ConstraintItem { return ConstraintItem(object: self.bottomLayoutGuide, attributes: ConstraintAttributes.Top) }
/// bottom layout guide bottom
public var snp_bottomLayoutGuideBottom: ConstraintItem { return ConstraintItem(object: self.bottomLayoutGuide, attributes: ConstraintAttributes.Bottom) }
}
import UIKit
#else
import AppKit
#endif
@available(iOS 8.0, *)
public struct ConstraintLayoutSupportDSL: ConstraintDSL {
public var target: AnyObject? {
return self.support
}
internal let support: ConstraintLayoutSupport
internal init(support: ConstraintLayoutSupport) {
self.support = support
}
public var top: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.top)
}
public var bottom: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottom)
}
public var height: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.height)
}
}

View File

@ -1,7 +1,7 @@
//
// SnapKit
//
// Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -22,175 +22,185 @@
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
import UIKit
#else
import AppKit
import AppKit
#endif
/**
Used to make constraints
*/
public class ConstraintMaker {
/// left edge
public var left: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Left) }
public var left: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.left)
}
/// top edge
public var top: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Top) }
public var top: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.top)
}
/// right edge
public var right: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Right) }
public var bottom: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.bottom)
}
/// bottom edge
public var bottom: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Bottom) }
public var right: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.right)
}
/// leading edge
public var leading: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Leading) }
public var leading: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.leading)
}
/// trailing edge
public var trailing: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Trailing) }
public var trailing: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.trailing)
}
/// width dimension
public var width: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Width) }
public var width: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.width)
}
/// height dimension
public var height: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Height) }
public var height: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.height)
}
/// centerX dimension
public var centerX: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.CenterX) }
public var centerX: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.centerX)
}
/// centerY dimension
public var centerY: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.CenterY) }
public var centerY: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.centerY)
}
/// baseline position
public var baseline: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Baseline) }
@available(*, deprecated:0.40.0, message:"Use lastBaseline instead")
public var baseline: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.lastBaseline)
}
public var lastBaseline: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.lastBaseline)
}
@available(iOS 8.0, OSX 10.11, *)
public var firstBaseline: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.firstBaseline)
}
/// firse baseline position
@available(iOS 8.0, *)
public var firstBaseline: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.FirstBaseline) }
public var leftMargin: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.leftMargin)
}
/// left margin
@available(iOS 8.0, *)
public var leftMargin: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.LeftMargin) }
public var rightMargin: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.rightMargin)
}
/// right margin
@available(iOS 8.0, *)
public var rightMargin: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.RightMargin) }
public var bottomMargin: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.bottomMargin)
}
/// top margin
@available(iOS 8.0, *)
public var topMargin: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.TopMargin) }
public var leadingMargin: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.leadingMargin)
}
/// bottom margin
@available(iOS 8.0, *)
public var bottomMargin: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.BottomMargin) }
public var trailingMargin: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.trailingMargin)
}
/// leading margin
@available(iOS 8.0, *)
public var leadingMargin: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.LeadingMargin) }
public var centerXWithinMargins: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.centerXWithinMargins)
}
/// trailing margin
@available(iOS 8.0, *)
public var trailingMargin: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.TrailingMargin) }
public var centerYWithinMargins: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.centerYWithinMargins)
}
public var edges: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.edges)
}
public var size: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.size)
}
public var center: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.center)
}
/// centerX within margins
@available(iOS 8.0, *)
public var centerXWithinMargins: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.CenterXWithinMargins) }
public var margins: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.margins)
}
/// centerY within margins
@available(iOS 8.0, *)
public var centerYWithinMargins: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.CenterYWithinMargins) }
public var centerWithinMargins: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.centerWithinMargins)
}
/// top + left + bottom + right edges
public var edges: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Edges) }
private let view: ConstraintView
private var descriptions = [ConstraintDescription]()
/// width + height dimensions
public var size: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Size) }
// centerX + centerY positions
public var center: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Center) }
// top + left + bottom + right margins
@available(iOS 8.0, *)
public var margins: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Margins) }
// centerX + centerY within margins
@available(iOS 8.0, *)
public var centerWithinMargins: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.CenterWithinMargins) }
internal init(view: View, file: String, line: UInt) {
internal init(view: ConstraintView) {
self.view = view
self.file = file
self.line = line
self.view.translatesAutoresizingMaskIntoConstraints = false
}
internal let file: String
internal let line: UInt
internal let view: View
internal var constraintDescriptions = [ConstraintDescription]()
internal func makeConstraintDescription(attributes: ConstraintAttributes) -> ConstraintDescription {
let item = ConstraintItem(object: self.view, attributes: attributes)
let constraintDescription = ConstraintDescription(fromItem: item)
self.constraintDescriptions.append(constraintDescription)
return constraintDescription
internal func makeExtendableWithAttributes(_ attributes: ConstraintAttributes) -> ConstraintMakerExtendable {
let description = ConstraintDescription(view: self.view, attributes: attributes)
self.descriptions.append(description)
return ConstraintMakerExtendable(description)
}
internal class func prepareConstraints(view view: View, file: String = "Unknown", line: UInt = 0, @noescape closure: (make: ConstraintMaker) -> Void) -> [Constraint] {
let maker = ConstraintMaker(view: view, file: file, line: line)
closure(make: maker)
let constraints = maker.constraintDescriptions.map { $0.constraint }
for constraint in constraints {
constraint.makerFile = maker.file
constraint.makerLine = maker.line
}
internal static func prepareConstraints(view: ConstraintView, closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] {
let maker = ConstraintMaker(view: view)
closure(maker)
let constraints = maker.descriptions
.map { $0.constraint }
.filter { $0 != nil }
.map { $0! }
return constraints
}
internal class func makeConstraints(view view: View, file: String = "Unknown", line: UInt = 0, @noescape closure: (make: ConstraintMaker) -> Void) {
view.translatesAutoresizingMaskIntoConstraints = false
let maker = ConstraintMaker(view: view, file: file, line: line)
closure(make: maker)
let constraints = maker.constraintDescriptions.map { $0.constraint as! ConcreteConstraint }
internal static func makeConstraints(view: ConstraintView, closure: (_ make: ConstraintMaker) -> Void) {
let maker = ConstraintMaker(view: view)
closure(maker)
let constraints = maker.descriptions
.map { $0.constraint }
.filter { $0 != nil }
.map { $0! }
for constraint in constraints {
constraint.makerFile = maker.file
constraint.makerLine = maker.line
constraint.installOnView(updateExisting: false)
constraint.activateIfNeeded(updatingExisting: false)
}
}
internal class func remakeConstraints(view view: View, file: String = "Unknown", line: UInt = 0, @noescape closure: (make: ConstraintMaker) -> Void) {
view.translatesAutoresizingMaskIntoConstraints = false
let maker = ConstraintMaker(view: view, file: file, line: line)
closure(make: maker)
internal static func remakeConstraints(view: ConstraintView, closure: (_ make: ConstraintMaker) -> Void) {
self.removeConstraints(view: view)
let constraints = maker.constraintDescriptions.map { $0.constraint as! ConcreteConstraint }
self.makeConstraints(view: view, closure: closure)
}
internal static func updateConstraints(view: ConstraintView, closure: (_ make: ConstraintMaker) -> Void) {
guard view.snp.layoutConstraints.count > 0 else {
self.makeConstraints(view: view, closure: closure)
return
}
let maker = ConstraintMaker(view: view)
closure(maker)
let constraints = maker.descriptions
.map { $0.constraint }
.filter { $0 != nil }
.map { $0! }
for constraint in constraints {
constraint.makerFile = maker.file
constraint.makerLine = maker.line
constraint.installOnView(updateExisting: false)
constraint.activateIfNeeded(updatingExisting: true)
}
}
internal class func updateConstraints(view view: View, file: String = "Unknown", line: UInt = 0, @noescape closure: (make: ConstraintMaker) -> Void) {
view.translatesAutoresizingMaskIntoConstraints = false
let maker = ConstraintMaker(view: view, file: file, line: line)
closure(make: maker)
let constraints = maker.constraintDescriptions.map { $0.constraint as! ConcreteConstraint}
internal static func removeConstraints(view: ConstraintView) {
let constraints = view.snp.layoutConstraints.map { $0.constraint! }
for constraint in constraints {
constraint.makerFile = maker.file
constraint.makerLine = maker.line
constraint.installOnView(updateExisting: true)
constraint.deactivateIfNeeded()
}
}
internal class func removeConstraints(view view: View) {
for existingLayoutConstraint in view.snp_installedLayoutConstraints {
existingLayoutConstraint.snp_constraint?.uninstall()
}
}
}

View File

@ -0,0 +1,56 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
public class ConstraintMakerEditable: ConstraintMakerPriortizable {
@discardableResult
public func multipliedBy(_ amount: ConstraintMultiplierTarget) -> ConstraintMakerEditable {
self.description.multiplier = amount
return self
}
@discardableResult
public func dividedBy(_ amount: ConstraintMultiplierTarget) -> ConstraintMakerEditable {
return self.multipliedBy(1.0 / amount.constraintMultiplierTargetValue)
}
@discardableResult
public func offset(_ amount: ConstraintOffsetTarget) -> ConstraintMakerEditable {
self.description.constant = amount.constraintOffsetTargetValue
return self
}
@discardableResult
public func inset(_ amount: ConstraintInsetTarget) -> ConstraintMakerEditable {
self.description.constant = amount.constraintInsetTargetValue
return self
}
}

View File

@ -0,0 +1,163 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
public class ConstraintMakerExtendable: ConstraintMakerRelatable {
public var left: ConstraintMakerExtendable {
self.description.attributes += .left
return self
}
public var top: ConstraintMakerExtendable {
self.description.attributes += .top
return self
}
public var bottom: ConstraintMakerExtendable {
self.description.attributes += .bottom
return self
}
public var right: ConstraintMakerExtendable {
self.description.attributes += .right
return self
}
public var leading: ConstraintMakerExtendable {
self.description.attributes += .leading
return self
}
public var trailing: ConstraintMakerExtendable {
self.description.attributes += .trailing
return self
}
public var width: ConstraintMakerExtendable {
self.description.attributes += .width
return self
}
public var height: ConstraintMakerExtendable {
self.description.attributes += .height
return self
}
public var centerX: ConstraintMakerExtendable {
self.description.attributes += .centerX
return self
}
public var centerY: ConstraintMakerExtendable {
self.description.attributes += .centerY
return self
}
@available(*, deprecated:0.40.0, message:"Use lastBaseline instead")
public var baseline: ConstraintMakerExtendable {
self.description.attributes += .lastBaseline
return self
}
public var lastBaseline: ConstraintMakerExtendable {
self.description.attributes += .lastBaseline
return self
}
@available(iOS 8.0, OSX 10.11, *)
public var firstBaseline: ConstraintMakerExtendable {
self.description.attributes += .firstBaseline
return self
}
@available(iOS 8.0, *)
public var leftMargin: ConstraintMakerExtendable {
self.description.attributes += .leftMargin
return self
}
@available(iOS 8.0, *)
public var rightMargin: ConstraintMakerExtendable {
self.description.attributes += .rightMargin
return self
}
@available(iOS 8.0, *)
public var bottomMargin: ConstraintMakerExtendable {
self.description.attributes += .bottomMargin
return self
}
@available(iOS 8.0, *)
public var leadingMargin: ConstraintMakerExtendable {
self.description.attributes += .leadingMargin
return self
}
@available(iOS 8.0, *)
public var trailingMargin: ConstraintMakerExtendable {
self.description.attributes += .trailingMargin
return self
}
@available(iOS 8.0, *)
public var centerXWithinMargins: ConstraintMakerExtendable {
self.description.attributes += .centerXWithinMargins
return self
}
@available(iOS 8.0, *)
public var centerYWithinMargins: ConstraintMakerExtendable {
self.description.attributes += .centerYWithinMargins
return self
}
public var edges: ConstraintMakerExtendable {
self.description.attributes += .edges
return self
}
public var size: ConstraintMakerExtendable {
self.description.attributes += .size
return self
}
@available(iOS 8.0, *)
public var margins: ConstraintMakerExtendable {
self.description.attributes += .margins
return self
}
@available(iOS 8.0, *)
public var centerWithinMargins: ConstraintMakerExtendable {
self.description.attributes += .centerWithinMargins
return self
}
}

View File

@ -0,0 +1,49 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
public class ConstraintMakerFinalizable {
internal let description: ConstraintDescription
internal init(_ description: ConstraintDescription) {
self.description = description
}
@discardableResult
public func labeled(_ label: String) -> ConstraintMakerFinalizable {
self.description.label = label
return self
}
public var constraint: Constraint {
return self.description.constraint!
}
}

View File

@ -0,0 +1,67 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
public class ConstraintMakerPriortizable: ConstraintMakerFinalizable {
@discardableResult
public func priority(_ amount: ConstraintPriorityTarget) -> ConstraintMakerFinalizable {
self.description.priority = amount
return self
}
@available(*, deprecated:0.40.0, message:"Use priority(_ amount: ConstraintPriorityTarget) instead.")
@discardableResult
public func priorityRequired() -> ConstraintMakerFinalizable {
return self.priority(1000)
}
@available(*, deprecated:0.40.0, message:"Use priority(_ amount: ConstraintPriorityTarget) instead.")
@discardableResult
public func priorityHigh() -> ConstraintMakerFinalizable {
return self.priority(750)
}
@available(*, deprecated:0.40.0, message:"Use priority(_ amount: ConstraintPriorityTarget) instead.")
@discardableResult
public func priorityMedium() -> ConstraintMakerFinalizable {
#if os(iOS) || os(tvOS)
return self.priority(500)
#else
return self.priority(501)
#endif
}
@available(*, deprecated:0.40.0, message:"Use priority(_ amount: ConstraintPriorityTarget) instead.")
@discardableResult
public func priorityLow() -> ConstraintMakerFinalizable {
return self.priority(250)
}
}

View File

@ -0,0 +1,95 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
public class ConstraintMakerRelatable {
internal let description: ConstraintDescription
internal init(_ description: ConstraintDescription) {
self.description = description
}
internal func relatedTo(_ other: ConstraintRelatableTarget, relation: ConstraintRelation, file: String, line: UInt) -> ConstraintMakerEditable {
let related: ConstraintItem
let constant: ConstraintConstantTarget
if let other = other as? ConstraintItem {
guard other.attributes == ConstraintAttributes.none ||
other.attributes.layoutAttributes.count <= 1 ||
other.attributes.layoutAttributes == self.description.attributes.layoutAttributes ||
other.attributes == .edges && self.description.attributes == .margins ||
other.attributes == .margins && self.description.attributes == .edges else {
fatalError("Cannot constraint to multiple non identical attributes. (\(file), \(line))");
}
related = other
constant = 0.0
} else if let other = other as? ConstraintView {
related = ConstraintItem(target: other, attributes: ConstraintAttributes.none)
constant = 0.0
} else if let other = other as? ConstraintConstantTarget {
related = ConstraintItem(target: nil, attributes: ConstraintAttributes.none)
constant = other
} else {
fatalError("Invalid constraint. (\(file), \(line))")
}
let editable = ConstraintMakerEditable(self.description)
editable.description.sourceLocation = (file, line)
editable.description.relation = relation
editable.description.related = related
editable.description.constant = constant
return editable
}
@discardableResult
public func equalTo(_ other: ConstraintRelatableTarget, _ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable {
return self.relatedTo(other, relation: .equal, file: file, line: line)
}
@discardableResult
public func equalToSuperview(_ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable {
guard let other = self.description.view.superview else {
fatalError("Expected superview but found nil when attempting make constraint `equalToSuperview`.")
}
return self.relatedTo(other, relation: .equal, file: file, line: line)
}
@discardableResult
public func lessThanOrEqualTo(_ other: ConstraintRelatableTarget, _ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable {
return self.relatedTo(other, relation: .lessThanOrEqual, file: file, line: line)
}
@discardableResult
public func greaterThanOrEqualTo(_ other: ConstraintRelatableTarget, _ file: String = #file, line: UInt = #line) -> ConstraintMakerEditable {
return self.relatedTo(other, relation: .greaterThanOrEqual, file: file, line: line)
}
}

View File

@ -0,0 +1,75 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
public protocol ConstraintMultiplierTarget {
var constraintMultiplierTargetValue: CGFloat { get }
}
extension Int: ConstraintMultiplierTarget {
public var constraintMultiplierTargetValue: CGFloat {
return CGFloat(self)
}
}
extension UInt: ConstraintMultiplierTarget {
public var constraintMultiplierTargetValue: CGFloat {
return CGFloat(self)
}
}
extension Float: ConstraintMultiplierTarget {
public var constraintMultiplierTargetValue: CGFloat {
return CGFloat(self)
}
}
extension Double: ConstraintMultiplierTarget {
public var constraintMultiplierTargetValue: CGFloat {
return CGFloat(self)
}
}
extension CGFloat: ConstraintMultiplierTarget {
public var constraintMultiplierTargetValue: CGFloat {
return self
}
}

View File

@ -0,0 +1,69 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
public protocol ConstraintOffsetTarget: ConstraintConstantTarget {
}
extension Int: ConstraintOffsetTarget {
}
extension UInt: ConstraintOffsetTarget {
}
extension Float: ConstraintOffsetTarget {
}
extension Double: ConstraintOffsetTarget {
}
extension CGFloat: ConstraintOffsetTarget {
}
extension ConstraintOffsetTarget {
internal var constraintOffsetTargetValue: CGFloat {
let offset: CGFloat
if let amount = self as? Float {
offset = CGFloat(amount)
} else if let amount = self as? Double {
offset = CGFloat(amount)
} else if let amount = self as? CGFloat {
offset = CGFloat(amount)
} else if let amount = self as? Int {
offset = CGFloat(amount)
} else if let amount = self as? UInt {
offset = CGFloat(amount)
} else {
offset = 0.0
}
return offset
}
}

View File

@ -0,0 +1,75 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
public protocol ConstraintPriorityTarget {
var constraintPriorityTargetValue: Float { get }
}
extension Int: ConstraintPriorityTarget {
public var constraintPriorityTargetValue: Float {
return Float(self)
}
}
extension UInt: ConstraintPriorityTarget {
public var constraintPriorityTargetValue: Float {
return Float(self)
}
}
extension Float: ConstraintPriorityTarget {
public var constraintPriorityTargetValue: Float {
return self
}
}
extension Double: ConstraintPriorityTarget {
public var constraintPriorityTargetValue: Float {
return Float(self)
}
}
extension CGFloat: ConstraintPriorityTarget {
public var constraintPriorityTargetValue: Float {
return Float(self)
}
}

View File

@ -1,7 +1,7 @@
//
// SnapKit
//
// Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -22,17 +22,41 @@
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
public typealias EdgeInsets = UIEdgeInsets
public func EdgeInsetsMake(top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat) -> EdgeInsets {
return EdgeInsets(top: top, left: left, bottom: bottom, right: right)
}
public let EdgeInsetsZero = EdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
import UIKit
#else
import AppKit
public typealias EdgeInsets = NSEdgeInsets
public func EdgeInsetsMake(top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat) -> EdgeInsets {
return EdgeInsets(top: top, left: left, bottom: bottom, right: right)
}
public let EdgeInsetsZero = EdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
import AppKit
#endif
public protocol ConstraintRelatableTarget {
}
extension Int: ConstraintRelatableTarget {
}
extension UInt: ConstraintRelatableTarget {
}
extension Float: ConstraintRelatableTarget {
}
extension Double: ConstraintRelatableTarget {
}
extension CGFloat: ConstraintRelatableTarget {
}
extension CGSize: ConstraintRelatableTarget {
}
extension CGPoint: ConstraintRelatableTarget {
}
extension ConstraintInsets: ConstraintRelatableTarget {
}
extension ConstraintItem: ConstraintRelatableTarget {
}
extension ConstraintView: ConstraintRelatableTarget {
}

View File

@ -1,7 +1,7 @@
//
// SnapKit
//
// Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -22,26 +22,26 @@
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
import UIKit
#else
import AppKit
import AppKit
#endif
/**
Used to define `NSLayoutRelation`
*/
internal enum ConstraintRelation: Int {
case Equal = 1, LessThanOrEqualTo, GreaterThanOrEqualTo
case equal = 1
case lessThanOrEqual
case greaterThanOrEqual
internal var layoutRelation: NSLayoutRelation {
get {
switch(self) {
case .LessThanOrEqualTo:
return .LessThanOrEqual
case .GreaterThanOrEqualTo:
return .GreaterThanOrEqual
default:
return .Equal
case .equal:
return .equal
case .lessThanOrEqual:
return .lessThanOrEqual
case .greaterThanOrEqual:
return .greaterThanOrEqual
}
}
}

View File

@ -0,0 +1,152 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
public extension ConstraintView {
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
public var snp_left: ConstraintItem { return self.snp.left }
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
public var snp_top: ConstraintItem { return self.snp.top }
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
public var snp_right: ConstraintItem { return self.snp.right }
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
public var snp_bottom: ConstraintItem { return self.snp.bottom }
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
public var snp_leading: ConstraintItem { return self.snp.leading }
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
public var snp_trailing: ConstraintItem { return self.snp.trailing }
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
public var snp_width: ConstraintItem { return self.snp.width }
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
public var snp_height: ConstraintItem { return self.snp.height }
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
public var snp_centerX: ConstraintItem { return self.snp.centerX }
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
public var snp_centerY: ConstraintItem { return self.snp.centerY }
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
public var snp_baseline: ConstraintItem { return self.snp.baseline }
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
@available(iOS 8.0, OSX 10.11, *)
public var snp_lastBaseline: ConstraintItem { return self.snp.lastBaseline }
@available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.")
@available(iOS 8.0, OSX 10.11, *)
public var snp_firstBaseline: ConstraintItem { return self.snp.firstBaseline }
@available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.")
@available(iOS 8.0, *)
public var snp_leftMargin: ConstraintItem { return self.snp.leftMargin }
@available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.")
@available(iOS 8.0, *)
public var snp_topMargin: ConstraintItem { return self.snp.topMargin }
@available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.")
@available(iOS 8.0, *)
public var snp_rightMargin: ConstraintItem { return self.snp.rightMargin }
@available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.")
@available(iOS 8.0, *)
public var snp_bottomMargin: ConstraintItem { return self.snp.bottomMargin }
@available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.")
@available(iOS 8.0, *)
public var snp_leadingMargin: ConstraintItem { return self.snp.leadingMargin }
@available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.")
@available(iOS 8.0, *)
public var snp_trailingMargin: ConstraintItem { return self.snp.trailingMargin }
@available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.")
@available(iOS 8.0, *)
public var snp_centerXWithinMargins: ConstraintItem { return self.snp.centerXWithinMargins }
@available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.")
@available(iOS 8.0, *)
public var snp_centerYWithinMargins: ConstraintItem { return self.snp.centerYWithinMargins }
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
public var snp_edges: ConstraintItem { return self.snp.edges }
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
public var snp_size: ConstraintItem { return self.snp.size }
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
public var snp_center: ConstraintItem { return self.snp.center }
@available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.")
@available(iOS 8.0, *)
public var snp_margins: ConstraintItem { return self.snp.margins }
@available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.")
@available(iOS 8.0, *)
public var snp_centerWithinMargins: ConstraintItem { return self.snp.centerWithinMargins }
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
public func snp_prepareConstraints(_ closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] {
return self.snp.prepareConstraints(closure)
}
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
public func snp_makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
self.snp.makeConstraints(closure)
}
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
public func snp_remakeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
self.snp.remakeConstraints(closure)
}
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
public func snp_updateConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
self.snp.updateConstraints(closure)
}
@available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
public func snp_removeConstraints() {
self.snp.removeConstraints()
}
public var snp: ConstraintViewDSL {
return ConstraintViewDSL(view: self)
}
}

View File

@ -0,0 +1,35 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
#if os(iOS) || os(tvOS)
public typealias ConstraintView = UIView
#else
public typealias ConstraintView = NSView
#endif

View File

@ -0,0 +1,135 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
public struct ConstraintViewDSL: ConstraintAttributesDSL {
@discardableResult
public func prepareConstraints(_ closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] {
return ConstraintMaker.prepareConstraints(view: self.view, closure: closure)
}
public func makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
ConstraintMaker.makeConstraints(view: self.view, closure: closure)
}
public func remakeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
ConstraintMaker.remakeConstraints(view: self.view, closure: closure)
}
public func updateConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
ConstraintMaker.updateConstraints(view: self.view, closure: closure)
}
public func removeConstraints() {
ConstraintMaker.removeConstraints(view: self.view)
}
public var contentHuggingHorizontalPriority: Float {
get {
return self.view.contentHuggingPriority(for: .horizontal)
}
set {
self.view.setContentHuggingPriority(newValue, for: .horizontal)
}
}
public var contentHuggingVerticalPriority: Float {
get {
return self.view.contentHuggingPriority(for: .vertical)
}
set {
self.view.setContentHuggingPriority(newValue, for: .vertical)
}
}
public var contentCompressionResistanceHorizontalPriority: Float {
get {
return self.view.contentCompressionResistancePriority(for: .horizontal)
}
set {
self.view.setContentHuggingPriority(newValue, for: .horizontal)
}
}
public var contentCompressionResistanceVerticalPriority: Float {
get {
return self.view.contentCompressionResistancePriority(for: .vertical)
}
set {
self.view.setContentCompressionResistancePriority(newValue, for: .vertical)
}
}
public var target: AnyObject? {
return self.view
}
internal let view: ConstraintView
internal init(view: ConstraintView) {
self.view = view
}
internal var layoutConstraints: [LayoutConstraint] {
return self.layoutConstraintsHashTable.allObjects
}
internal func add(layoutConstraints: [LayoutConstraint]) {
let hashTable = self.layoutConstraintsHashTable
for layoutConstraint in layoutConstraints {
hashTable.add(layoutConstraint)
}
}
internal func remove(layoutConstraints: [LayoutConstraint]) {
let hashTable = self.layoutConstraintsHashTable
for layoutConstraint in layoutConstraints {
hashTable.remove(layoutConstraint)
}
}
private var layoutConstraintsHashTable: NSHashTable<LayoutConstraint> {
let layoutConstraints: NSHashTable<LayoutConstraint>
if let existing = objc_getAssociatedObject(self.view, &layoutConstraintsKey) as? NSHashTable<LayoutConstraint> {
layoutConstraints = existing
} else {
layoutConstraints = NSHashTable<LayoutConstraint>.weakObjects()
objc_setAssociatedObject(self.view, &layoutConstraintsKey, layoutConstraints, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
return layoutConstraints
}
}
private var layoutConstraintsKey: UInt8 = 0

View File

@ -1,7 +1,7 @@
//
// SnapKit
//
// Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -22,75 +22,47 @@
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
import UIKit
#else
import AppKit
import AppKit
#endif
/**
Used to allow adding a snp_label to a View for debugging purposes
*/
public extension View {
public var snp_label: String? {
get {
return objc_getAssociatedObject(self, &labelKey) as? String
}
set {
objc_setAssociatedObject(self, &labelKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_COPY_NONATOMIC)
}
}
}
/**
Used to allow adding a snp_label to a LayoutConstraint for debugging purposes
*/
public extension LayoutConstraint {
public var snp_label: String? {
get {
return objc_getAssociatedObject(self, &labelKey) as? String
}
set {
objc_setAssociatedObject(self, &labelKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_COPY_NONATOMIC)
}
}
override public var description: String {
var description = "<"
description += descriptionForObject(self)
if let firstItem: AnyObject = self.firstItem {
if let firstItem = conditionalOptional(from: self.firstItem) {
description += " \(descriptionForObject(firstItem))"
}
if self.firstAttribute != .NotAnAttribute {
description += ".\(self.firstAttribute.snp_description)"
if self.firstAttribute != .notAnAttribute {
description += ".\(descriptionForAttribute(self.firstAttribute))"
}
description += " \(self.relation.snp_description)"
description += " \(descriptionForRelation(self.relation))"
if let secondItem: AnyObject = self.secondItem {
if let secondItem = self.secondItem {
description += " \(descriptionForObject(secondItem))"
}
if self.secondAttribute != .NotAnAttribute {
description += ".\(self.secondAttribute.snp_description)"
if self.secondAttribute != .notAnAttribute {
description += ".\(descriptionForAttribute(self.secondAttribute))"
}
if self.multiplier != 1.0 {
description += " * \(self.multiplier)"
}
if self.secondAttribute == .NotAnAttribute {
if self.secondAttribute == .notAnAttribute {
description += " \(self.constant)"
} else {
if self.constant > 0.0 {
description += " + \(self.constant)"
} else if self.constant < 0.0 {
description += " - \(CGFloat.abs(self.constant))"
description += " - \(abs(self.constant))"
}
}
@ -103,97 +75,86 @@ public extension LayoutConstraint {
return description
}
internal var snp_makerFile: String? {
return self.snp_constraint?.makerFile
}
internal var snp_makerLine: UInt? {
return self.snp_constraint?.makerLine
}
}
private var labelKey = ""
private func descriptionForRelation(_ relation: NSLayoutRelation) -> String {
switch relation {
case .equal: return "=="
case .greaterThanOrEqual: return ">="
case .lessThanOrEqual: return "<="
}
}
private func descriptionForObject(object: AnyObject) -> String {
let pointerDescription = NSString(format: "%p", ObjectIdentifier(object).uintValue)
private func descriptionForAttribute(_ attribute: NSLayoutAttribute) -> String {
#if os(iOS) || os(tvOS)
switch attribute {
case .notAnAttribute: return "notAnAttribute"
case .top: return "top"
case .left: return "left"
case .bottom: return "bottom"
case .right: return "right"
case .leading: return "leading"
case .trailing: return "trailing"
case .width: return "width"
case .height: return "height"
case .centerX: return "centerX"
case .centerY: return "centerY"
case .lastBaseline: return "lastBaseline"
case .firstBaseline: return "firstBaseline"
case .topMargin: return "topMargin"
case .leftMargin: return "leftMargin"
case .bottomMargin: return "bottomMargin"
case .rightMargin: return "rightMargin"
case .leadingMargin: return "leadingMargin"
case .trailingMargin: return "trailingMargin"
case .centerXWithinMargins: return "centerXWithinMargins"
case .centerYWithinMargins: return "centerYWithinMargins"
}
#else
switch attribute {
case .notAnAttribute: return "notAnAttribute"
case .top: return "top"
case .left: return "left"
case .bottom: return "bottom"
case .right: return "right"
case .leading: return "leading"
case .trailing: return "trailing"
case .width: return "width"
case .height: return "height"
case .centerX: return "centerX"
case .centerY: return "centerY"
case .lastBaseline: return "lastBaseline"
case .firstBaseline: return "firstBaseline"
}
#endif
}
private func conditionalOptional<T>(from object: Optional<T>) -> Optional<T> {
return object
}
private func conditionalOptional<T>(from object: T) -> Optional<T> {
return Optional.some(object)
}
private func descriptionForObject(_ object: AnyObject) -> String {
let pointerDescription = String(format: "%p", UInt(bitPattern: ObjectIdentifier(object)))
var desc = ""
desc += object.dynamicType.description()
desc += type(of: object).description()
if let object = object as? View {
desc += ":\(object.snp_label ?? pointerDescription)"
if let object = object as? ConstraintView {
desc += ":\(object.snp.label ?? pointerDescription)"
} else if let object = object as? LayoutConstraint {
desc += ":\(object.snp_label ?? pointerDescription)"
desc += ":\(object.label ?? pointerDescription)"
} else {
desc += ":\(pointerDescription)"
}
if let object = object as? LayoutConstraint, let file = object.snp_makerFile, let line = object.snp_makerLine {
desc += "@\(file)#\(line)"
if let object = object as? LayoutConstraint, let file = object.constraint?.sourceLocation.0, let line = object.constraint?.sourceLocation.1 {
desc += "@\((file as NSString).lastPathComponent)#\(line)"
}
desc += ""
return desc
}
private extension NSLayoutRelation {
private var snp_description: String {
switch self {
case .Equal: return "=="
case .GreaterThanOrEqual: return ">="
case .LessThanOrEqual: return "<="
}
}
}
private extension NSLayoutAttribute {
private var snp_description: String {
#if os(iOS) || os(tvOS)
switch self {
case .NotAnAttribute: return "notAnAttribute"
case .Top: return "top"
case .Left: return "left"
case .Bottom: return "bottom"
case .Right: return "right"
case .Leading: return "leading"
case .Trailing: return "trailing"
case .Width: return "width"
case .Height: return "height"
case .CenterX: return "centerX"
case .CenterY: return "centerY"
case .LastBaseline: return "baseline"
case .FirstBaseline: return "firstBaseline"
case .TopMargin: return "topMargin"
case .LeftMargin: return "leftMargin"
case .BottomMargin: return "bottomMargin"
case .RightMargin: return "rightMargin"
case .LeadingMargin: return "leadingMargin"
case .TrailingMargin: return "trailingMargin"
case .CenterXWithinMargins: return "centerXWithinMargins"
case .CenterYWithinMargins: return "centerYWithinMargins"
}
#else
switch self {
case .NotAnAttribute: return "notAnAttribute"
case .Top: return "top"
case .Left: return "left"
case .Bottom: return "bottom"
case .Right: return "right"
case .Leading: return "leading"
case .Trailing: return "trailing"
case .Width: return "width"
case .Height: return "height"
case .CenterX: return "centerX"
case .CenterY: return "centerY"
case .LastBaseline: return "baseline"
default: return "default"
}
#endif
}
}

View File

@ -1,7 +1,7 @@
//
// SnapKit
//
// Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -22,42 +22,36 @@
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
import UIKit
#else
import AppKit
import AppKit
#endif
/**
Used to add extra information to the actual `NSLayoutConstraint`'s that will UIKit/AppKit will utilize
*/
public class LayoutConstraint: NSLayoutConstraint {
internal var snp_constraint: Constraint? = nil
public var label: String? {
get {
return self.identifier
}
set {
self.identifier = newValue
}
}
internal var constraint: Constraint! = nil
}
internal func ==(left: LayoutConstraint, right: LayoutConstraint) -> Bool {
if left.firstItem !== right.firstItem {
return false
}
if left.secondItem !== right.secondItem {
return false
}
if left.firstAttribute != right.firstAttribute {
return false
}
if left.secondAttribute != right.secondAttribute {
return false
}
if left.relation != right.relation {
return false
}
if left.priority != right.priority {
return false
}
if left.multiplier != right.multiplier {
internal func ==(lhs: LayoutConstraint, rhs: LayoutConstraint) -> Bool {
guard lhs.firstItem === rhs.firstItem &&
lhs.secondItem === rhs.secondItem &&
lhs.firstAttribute == rhs.firstAttribute &&
lhs.secondAttribute == rhs.secondAttribute &&
lhs.relation == rhs.relation &&
lhs.priority == rhs.priority &&
lhs.multiplier == rhs.multiplier else {
return false
}
return true
}

View File

@ -0,0 +1,36 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#endif
@available(iOS 9.0, *)
public extension ConstraintLayoutGuide {
public var snp: ConstraintLayoutGuideDSL {
return ConstraintLayoutGuideDSL(guide: self)
}
}

View File

@ -0,0 +1,36 @@
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
#endif
@available(iOS 8.0, *)
public extension ConstraintLayoutSupport {
public var snp: ConstraintLayoutSupportDSL {
return ConstraintLayoutSupportDSL(support: self)
}
}

View File

@ -1,183 +0,0 @@
//
// SnapKit
//
// Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS)
import UIKit
public typealias View = UIView
#else
import AppKit
public typealias View = NSView
#endif
/**
Used to expose public API on views
*/
public extension View {
/// left edge
public var snp_left: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Left) }
/// top edge
public var snp_top: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Top) }
/// right edge
public var snp_right: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Right) }
/// bottom edge
public var snp_bottom: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Bottom) }
/// leading edge
public var snp_leading: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Leading) }
/// trailing edge
public var snp_trailing: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Trailing) }
/// width dimension
public var snp_width: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Width) }
/// height dimension
public var snp_height: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Height) }
/// centerX position
public var snp_centerX: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterX) }
/// centerY position
public var snp_centerY: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterY) }
/// baseline position
public var snp_baseline: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Baseline) }
/// first baseline position
@available(iOS 8.0, *)
public var snp_firstBaseline: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.FirstBaseline) }
/// left margin
@available(iOS 8.0, *)
public var snp_leftMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.LeftMargin) }
/// right margin
@available(iOS 8.0, *)
public var snp_rightMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.RightMargin) }
/// top margin
@available(iOS 8.0, *)
public var snp_topMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.TopMargin) }
/// bottom margin
@available(iOS 8.0, *)
public var snp_bottomMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.BottomMargin) }
/// leading margin
@available(iOS 8.0, *)
public var snp_leadingMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.LeadingMargin) }
/// trailing margin
@available(iOS 8.0, *)
public var snp_trailingMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.TrailingMargin) }
/// centerX within margins
@available(iOS 8.0, *)
public var snp_centerXWithinMargins: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterXWithinMargins) }
/// centerY within margins
@available(iOS 8.0, *)
public var snp_centerYWithinMargins: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterYWithinMargins) }
// top + left + bottom + right edges
public var snp_edges: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Edges) }
// width + height dimensions
public var snp_size: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Size) }
// centerX + centerY positions
public var snp_center: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Center) }
// top + left + bottom + right margins
@available(iOS 8.0, *)
public var snp_margins: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Margins) }
// centerX + centerY within margins
@available(iOS 8.0, *)
public var snp_centerWithinMargins: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterWithinMargins) }
/**
Prepares constraints with a `ConstraintMaker` and returns the made constraints but does not install them.
- parameter closure that will be passed the `ConstraintMaker` to make the constraints with
- returns: the constraints made
*/
public func snp_prepareConstraints(file: String = #file, line: UInt = #line, @noescape closure: (make: ConstraintMaker) -> Void) -> [Constraint] {
return ConstraintMaker.prepareConstraints(view: self, file: file, line: line, closure: closure)
}
/**
Makes constraints with a `ConstraintMaker` and installs them along side any previous made constraints.
- parameter closure that will be passed the `ConstraintMaker` to make the constraints with
*/
public func snp_makeConstraints(file: String = #file, line: UInt = #line, @noescape closure: (make: ConstraintMaker) -> Void) -> Void {
ConstraintMaker.makeConstraints(view: self, file: file, line: line, closure: closure)
}
/**
Updates constraints with a `ConstraintMaker` that will replace existing constraints that match and install new ones.
For constraints to match only the constant can be updated.
- parameter closure that will be passed the `ConstraintMaker` to update the constraints with
*/
public func snp_updateConstraints(file: String = #file, line: UInt = #line, @noescape closure: (make: ConstraintMaker) -> Void) -> Void {
ConstraintMaker.updateConstraints(view: self, file: file, line: line, closure: closure)
}
/**
Remakes constraints with a `ConstraintMaker` that will first remove all previously made constraints and make and install new ones.
- parameter closure that will be passed the `ConstraintMaker` to remake the constraints with
*/
public func snp_remakeConstraints(file: String = #file, line: UInt = #line, @noescape closure: (make: ConstraintMaker) -> Void) -> Void {
ConstraintMaker.remakeConstraints(view: self, file: file, line: line, closure: closure)
}
/**
Removes all previously made constraints.
*/
public func snp_removeConstraints() {
ConstraintMaker.removeConstraints(view: self)
}
internal var snp_installedLayoutConstraints: [LayoutConstraint] {
get {
if let constraints = objc_getAssociatedObject(self, &installedLayoutConstraintsKey) as? [LayoutConstraint] {
return constraints
}
return []
}
set {
objc_setAssociatedObject(self, &installedLayoutConstraintsKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
private var installedLayoutConstraintsKey = ""

View File

@ -13,7 +13,7 @@ extension View {
#endif
import XCTest
import SnapKit
@testable import SnapKit
class SnapKitTests: XCTestCase {
@ -29,37 +29,21 @@ class SnapKitTests: XCTestCase {
super.tearDown()
}
func testLayoutGuideConstraints() {
#if os(iOS) || os(tvOS)
let vc = UIViewController()
vc.view = UIView(frame: CGRectMake(0, 0, 300, 300))
vc.view.addSubview(self.container)
self.container.snp_makeConstraints { (make) -> Void in
make.top.equalTo(vc.snp_topLayoutGuideBottom)
make.bottom.equalTo(vc.snp_bottomLayoutGuideTop)
}
XCTAssertEqual(vc.view.snp_constraints.count, 6, "Should have 6 constraints installed")
#endif
}
func testMakeConstraints() {
let v1 = View()
let v2 = View()
self.container.addSubview(v1)
self.container.addSubview(v2)
v1.snp_makeConstraints { (make) -> Void in
make.top.equalTo(v2.snp_top).offset(50)
make.left.equalTo(v2.snp_top).offset(50)
v1.snp.makeConstraints { (make) -> Void in
make.top.equalTo(v2.snp.top).offset(50)
make.left.equalTo(v2.snp.top).offset(50)
return
}
XCTAssertEqual(self.container.snp_constraints.count, 2, "Should have 2 constraints installed")
v2.snp_makeConstraints { (make) -> Void in
v2.snp.makeConstraints { (make) -> Void in
make.edges.equalTo(v1)
return
}
@ -68,22 +52,44 @@ class SnapKitTests: XCTestCase {
}
func testMakeImpliedSuperviewConstraints() {
let v1 = View()
let v2 = View()
self.container.addSubview(v1)
self.container.addSubview(v2)
v1.snp.makeConstraints { (make) -> Void in
make.top.equalTo(50.0)
make.left.equalTo(50.0)
return
}
XCTAssertEqual(self.container.snp_constraints.count, 2, "Should have 2 constraints installed")
v2.snp.makeConstraints { (make) -> Void in
make.edges.equalTo(v1)
return
}
XCTAssertEqual(self.container.snp_constraints.count, 6, "Should have 6 constraints installed")
}
func testUpdateConstraints() {
let v1 = View()
let v2 = View()
self.container.addSubview(v1)
self.container.addSubview(v2)
v1.snp_makeConstraints { (make) -> Void in
make.top.equalTo(v2.snp_top).offset(50)
make.left.equalTo(v2.snp_top).offset(50)
v1.snp.makeConstraints { (make) -> Void in
make.top.equalTo(v2.snp.top).offset(50)
make.left.equalTo(v2.snp.top).offset(50)
return
}
XCTAssertEqual(self.container.snp_constraints.count, 2, "Should have 2 constraints installed")
v1.snp_updateConstraints { (make) -> Void in
make.top.equalTo(v2.snp_top).offset(15)
v1.snp.updateConstraints { (make) -> Void in
make.top.equalTo(v2.snp.top).offset(15)
return
}
@ -91,21 +97,22 @@ class SnapKitTests: XCTestCase {
}
func testRemakeConstraints() {
let v1 = View()
let v2 = View()
self.container.addSubview(v1)
self.container.addSubview(v2)
v1.snp_makeConstraints { (make) -> Void in
make.top.equalTo(v2.snp_top).offset(50)
make.left.equalTo(v2.snp_top).offset(50)
v1.snp.makeConstraints { (make) -> Void in
make.top.equalTo(v2.snp.top).offset(50)
make.left.equalTo(v2.snp.top).offset(50)
return
}
XCTAssertEqual(self.container.snp_constraints.count, 2, "Should have 2 constraints installed")
v1.snp_remakeConstraints { (make) -> Void in
v1.snp.remakeConstraints { (make) -> Void in
make.edges.equalTo(v2)
return
}
@ -120,15 +127,15 @@ class SnapKitTests: XCTestCase {
self.container.addSubview(v1)
self.container.addSubview(v2)
v1.snp_makeConstraints { (make) -> Void in
make.top.equalTo(v2.snp_top).offset(50)
make.left.equalTo(v2.snp_top).offset(50)
v1.snp.makeConstraints { (make) -> Void in
make.top.equalTo(v2.snp.top).offset(50)
make.left.equalTo(v2.snp.top).offset(50)
return
}
XCTAssertEqual(self.container.snp_constraints.count, 2, "Should have 2 constraints installed")
v1.snp_removeConstraints()
v1.snp.removeConstraints()
XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints installed")
@ -140,7 +147,7 @@ class SnapKitTests: XCTestCase {
self.container.addSubview(v1)
self.container.addSubview(v2)
let constraints = v1.snp_prepareConstraints { (make) -> Void in
let constraints = v1.snp.prepareConstraints { (make) -> Void in
make.edges.equalTo(v2)
return
}
@ -148,26 +155,26 @@ class SnapKitTests: XCTestCase {
XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints installed")
for constraint in constraints {
constraint.install()
constraint.activate()
}
XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints installed")
for constraint in constraints {
constraint.uninstall()
constraint.deactivate()
}
XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints installed")
}
func testReinstallConstraints() {
func testReactivateConstraints() {
let v1 = View()
let v2 = View()
self.container.addSubview(v1)
self.container.addSubview(v2)
let constraints = v1.snp_prepareConstraints { (make) -> Void in
let constraints = v1.snp.prepareConstraints { (make) -> Void in
make.edges.equalTo(v2)
return
}
@ -176,16 +183,16 @@ class SnapKitTests: XCTestCase {
XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints installed")
for constraint in constraints {
constraint.install()
constraint.activate()
}
XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints installed")
for constraint in constraints {
constraint.install()
constraint.deactivate()
}
XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 0 constraints installed")
XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints installed")
}
func testActivateDeactivateConstraints() {
@ -197,9 +204,9 @@ class SnapKitTests: XCTestCase {
var c1: Constraint? = nil
var c2: Constraint? = nil
v1.snp_prepareConstraints { (make) -> Void in
c1 = make.top.equalTo(v2.snp_top).offset(50).constraint
c2 = make.left.equalTo(v2.snp_top).offset(50).constraint
v1.snp.prepareConstraints { (make) -> Void in
c1 = make.top.equalTo(v2.snp.top).offset(50).constraint
c2 = make.left.equalTo(v2.snp.top).offset(50).constraint
return
}
@ -215,11 +222,6 @@ class SnapKitTests: XCTestCase {
XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints")
c1?.uninstall()
c2?.uninstall()
XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints")
c1?.activate()
c2?.activate()
@ -227,12 +229,127 @@ class SnapKitTests: XCTestCase {
}
func testEdgeConstraints() {
let view = View()
self.container.addSubview(view)
view.snp.makeConstraints { (make) -> Void in
make.edges.equalTo(self.container).offset(50.0)
}
XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints")
let constraints = self.container.snp_constraints as! [NSLayoutConstraint]
XCTAssertEqual(constraints[0].constant, 50, "Should be 50")
XCTAssertEqual(constraints[1].constant, 50, "Should be 50")
XCTAssertEqual(constraints[2].constant, 50, "Should be 50")
XCTAssertEqual(constraints[3].constant, 50, "Should be 50")
}
func testUpdateReferencedConstraints() {
let v1 = View()
let v2 = View()
self.container.addSubview(v1)
self.container.addSubview(v2)
var c1: Constraint! = nil
var c2: Constraint! = nil
v1.snp.makeConstraints { (make) -> Void in
c1 = make.top.equalTo(v2).offset(50).constraint
c2 = make.bottom.equalTo(v2).offset(25).constraint
return
}
XCTAssertEqual(self.container.snp_constraints.count, 2, "Should have 2 constraints")
let constraints = (self.container.snp_constraints as! [NSLayoutConstraint]).sorted { $0.constant > $1.constant }
XCTAssertEqual(constraints[0].constant, 50, "Should be 50")
XCTAssertEqual(constraints[1].constant, 25, "Should be 25")
c1.update(offset: 15)
c2.update(offset: 20)
XCTAssertEqual(self.container.snp_constraints.count, 2, "Should have 2 constraints")
XCTAssertEqual(constraints[0].constant, 15, "Should be 15")
XCTAssertEqual(constraints[1].constant, 20, "Should be 20")
c1.update(inset: 15)
c2.update(inset: 20)
XCTAssertEqual(self.container.snp_constraints.count, 2, "Should have 2 constraints")
XCTAssertEqual(constraints[0].constant, 15, "Should be 15")
XCTAssertEqual(constraints[1].constant, -20, "Should be -20")
}
func testInsetsAsConstraintsConstant() {
let view = View()
self.container.addSubview(view)
view.snp.makeConstraints { (make) -> Void in
make.edges.equalTo(self.container).inset(50.0)
}
XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints")
let constraints = (self.container.snp_constraints as! [NSLayoutConstraint]).sorted { $0.constant > $1.constant }
XCTAssertEqual(constraints[0].constant, 50, "Should be 50")
XCTAssertEqual(constraints[1].constant, 50, "Should be 50")
XCTAssertEqual(constraints[2].constant, -50, "Should be -50")
XCTAssertEqual(constraints[3].constant, -50, "Should be -50")
}
func testConstraintInsetsAsImpliedEqualToConstraints() {
let view = View()
self.container.addSubview(view)
view.snp.makeConstraints { (make) -> Void in
make.edges.equalTo(ConstraintInsets(top: 25, left: 25, bottom: 25, right: 25))
}
XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints")
let constraints = (self.container.snp_constraints as! [NSLayoutConstraint]).sorted { $0.constant > $1.constant }
XCTAssertEqual(constraints[0].constant, 25, "Should be 25")
XCTAssertEqual(constraints[1].constant, 25, "Should be 25")
XCTAssertEqual(constraints[2].constant, -25, "Should be -25")
XCTAssertEqual(constraints[3].constant, -25, "Should be -25")
}
func testConstraintInsetsAsConstraintsConstant() {
let view = View()
self.container.addSubview(view)
view.snp.makeConstraints { (make) -> Void in
make.edges.equalTo(self.container).inset(ConstraintInsets(top: 25, left: 25, bottom: 25, right: 25))
}
XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints")
let constraints = (self.container.snp_constraints as! [NSLayoutConstraint]).sorted { $0.constant > $1.constant }
XCTAssertEqual(constraints[0].constant, 25, "Should be 25")
XCTAssertEqual(constraints[1].constant, 25, "Should be 25")
XCTAssertEqual(constraints[2].constant, -25, "Should be -25")
XCTAssertEqual(constraints[3].constant, -25, "Should be -25")
}
func testSizeConstraints() {
let view = View()
self.container.addSubview(view)
view.snp_makeConstraints { (make) -> Void in
make.size.equalTo(CGSizeMake(50, 50))
view.snp.makeConstraints { (make) -> Void in
make.size.equalTo(CGSize(width: 50, height: 50))
make.left.top.equalTo(self.container)
}
@ -240,11 +357,32 @@ class SnapKitTests: XCTestCase {
XCTAssertEqual(self.container.snp_constraints.count, 2, "Should have 2 constraints")
let constraints = view.snp_constraints as! [NSLayoutConstraint]
XCTAssertEqual(constraints[0].firstAttribute, NSLayoutAttribute.Width, "Should be width")
XCTAssertEqual(constraints[1].firstAttribute, NSLayoutAttribute.Height, "Should be height")
// no guarantee which order the constraints are in, but we should test their couple
let widthHeight = (NSLayoutAttribute.width.rawValue, NSLayoutAttribute.height.rawValue)
let heightWidth = (widthHeight.1, widthHeight.0)
let firstSecond = (constraints[0].firstAttribute.rawValue, constraints[1].firstAttribute.rawValue)
// constraint values are correct in either width, height or height, width order
XCTAssertTrue(firstSecond == widthHeight || firstSecond == heightWidth, "2 contraint values should match")
XCTAssertEqual(constraints[0].constant, 50, "Should be 50")
XCTAssertEqual(constraints[1].constant, 50, "Should be 50")
}
func testCenterConstraints() {
let view = View()
self.container.addSubview(view)
view.snp.makeConstraints { (make) -> Void in
make.center.equalTo(self.container).offset(50.0)
}
XCTAssertEqual(self.container.snp_constraints.count, 2, "Should have 2 constraints")
let constraints = self.container.snp_constraints as! [NSLayoutConstraint]
XCTAssertEqual(constraints[0].constant, 50, "Should be 50")
XCTAssertEqual(constraints[1].constant, 50, "Should be 50")
}
@ -254,64 +392,90 @@ class SnapKitTests: XCTestCase {
let view = View()
self.container.addSubview(view)
view.snp_makeConstraints { (make) -> Void in
make.top.equalTo(self.container.snp_top).labeled(identifier)
view.snp.makeConstraints { (make) -> Void in
make.top.equalTo(self.container.snp.top).labeled(identifier)
}
let constraints = container.snp_constraints as! [NSLayoutConstraint]
XCTAssertEqual(constraints[0].identifier, identifier, "Identifier should be 'Test'")
}
func testSuperviewConstraints() {
#if os(iOS) || os(tvOS)
func testEdgesToMargins() {
var fromAttributes = Set<NSLayoutAttribute>()
var toAttributes = Set<NSLayoutAttribute>()
let view = View()
self.container.addSubview(view)
container.addSubview(view)
view.snp_makeConstraints { (make) -> Void in
make.top.equalToSuperview().inset(10)
make.bottom.equalToSuperview().inset(10)
view.snp.remakeConstraints { (make) -> Void in
make.edges.equalTo(self.container.snp.margins)
}
XCTAssertEqual(container.snp_constraints.count, 2, "Should have 2 constraints")
XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints")
let constraints = container.snp_constraints as! [NSLayoutConstraint]
XCTAssertEqual(constraints[0].firstAttribute, NSLayoutAttribute.Top, "Should be top")
XCTAssertEqual(constraints[1].firstAttribute, NSLayoutAttribute.Bottom, "Should be bottom")
XCTAssertEqual(constraints[0].secondAttribute, NSLayoutAttribute.Top, "Should be top")
XCTAssertEqual(constraints[1].secondAttribute, NSLayoutAttribute.Bottom, "Should be bottom")
XCTAssertEqual(constraints[0].firstItem as? View, view, "Should be added subview")
XCTAssertEqual(constraints[1].firstItem as? View, view, "Should be added subview")
XCTAssertEqual(constraints[0].secondItem as? View, container, "Should be containerView")
XCTAssertEqual(constraints[1].secondItem as? View, container, "Should be containerView")
XCTAssertEqual(constraints[0].constant, 10, "Should be 10")
XCTAssertEqual(constraints[1].constant, -10, "Should be 10")
}
func testNativeConstraints() {
let view = View()
container.addSubview(view)
var topNativeConstraints: [LayoutConstraint]!
var topNativeConstraint: LayoutConstraint?
var sizeNativeConstraints: [LayoutConstraint]!
view.snp_makeConstraints { (make) -> Void in
let topConstraint = make.top.equalToSuperview().inset(10).constraint
topNativeConstraints = topConstraint.layoutConstraints
topNativeConstraint = topConstraint.layoutConstraints.first
let sizeConstraints = make.size.equalTo(50).constraint
sizeNativeConstraints = sizeConstraints.layoutConstraints
for constraint in (container.snp_constraints as! [NSLayoutConstraint]) {
fromAttributes.insert(constraint.firstAttribute)
toAttributes.insert(constraint.secondAttribute)
}
XCTAssertEqual(topNativeConstraints.count, 1, "make.top should creates one native constraint")
XCTAssertEqual(topNativeConstraint?.constant, 10, "topNativeConstraint.constant is set to 10")
XCTAssertEqual(sizeNativeConstraints.count, 2, "make.tosize should create two native constraint")
XCTAssertEqual(sizeNativeConstraints[0].constant, 50, "sizeNativeConstraints should set size[0] to 50")
XCTAssertEqual(sizeNativeConstraints[1].constant, 50, "sizeNativeConstraints should set size[1] to 50")
XCTAssert(fromAttributes == [.top, .left, .bottom, .right])
XCTAssert(toAttributes == [.topMargin, .leftMargin, .bottomMargin, .rightMargin])
fromAttributes.removeAll()
toAttributes.removeAll()
view.snp.remakeConstraints { (make) -> Void in
make.margins.equalTo(self.container.snp.edges)
}
XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints")
for constraint in (container.snp_constraints as! [NSLayoutConstraint]) {
fromAttributes.insert(constraint.firstAttribute)
toAttributes.insert(constraint.secondAttribute)
}
XCTAssert(toAttributes == [.top, .left, .bottom, .right])
XCTAssert(fromAttributes == [.topMargin, .leftMargin, .bottomMargin, .rightMargin])
}
func testEdgesToEdges() {
var fromAttributes = Set<NSLayoutAttribute>()
var toAttributes = Set<NSLayoutAttribute>()
let view = View()
self.container.addSubview(view)
view.snp.remakeConstraints { (make) -> Void in
make.edges.equalTo(self.container.snp.edges)
}
XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints")
for constraint in (container.snp_constraints as! [NSLayoutConstraint]) {
fromAttributes.insert(constraint.firstAttribute)
toAttributes.insert(constraint.secondAttribute)
}
XCTAssert(fromAttributes == [.top, .left, .bottom, .right])
XCTAssert(toAttributes == [.top, .left, .bottom, .right])
}
func testLayoutGuideConstraints() {
let vc = UIViewController()
vc.view = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
vc.view.addSubview(self.container)
self.container.snp.makeConstraints { (make) -> Void in
make.top.equalTo(vc.topLayoutGuide.snp.bottom)
make.bottom.equalTo(vc.bottomLayoutGuide.snp.top)
}
XCTAssertEqual(vc.view.snp_constraints.count, 6, "Should have 6 constraints installed")
}
#endif
}