From 57bab2f57d103b83ccaa048d9857ef6ae33e8699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=97=D0=BE=D0=BB=D0=BE=D1=82=D0=B0=D1=80=D0=B5=CC=88=D0=B2?= Date: Wed, 7 Mar 2018 04:58:04 +0300 Subject: [PATCH] Initial commit --- .gitignore | 39 ++ Example/AppDelegate.swift | 39 ++ Example/Base.lproj/LaunchScreen.storyboard | 31 + Example/Info.plist | 43 ++ Example/ViewController.swift | 74 +++ LICENSE | 19 + Other/Info.plist | 24 + Other/SuperPuperDuperLayout.h | 28 + README.md | 1 + Source/Layout.swift | 41 ++ .../CenterLayoutAttribute.swift | 70 +++ .../DimensionLayoutAttribute.swift | 48 ++ .../EdgesLayoutAttribute.swift | 80 +++ Source/LayoutAttributes/LayoutAttribute.swift | 95 +++ .../LayoutAttributeByCoordinateAxes.swift | 37 ++ .../SizeLayoutAttribute.swift | 92 +++ Source/LayoutDescription.swift | 80 +++ Source/LayoutFactories.swift | 142 +++++ Source/LayoutOptions/LayoutOptions.swift | 49 ++ .../LayoutOptionsForCenterConstraints.swift | 64 +++ .../LayoutOptionsForConstraintsOfEdges.swift | 76 +++ .../LayoutOptionsForConstraintsOfSize.swift | 64 +++ .../LayoutOptionsForSingleConstraint.swift | 35 ++ Source/LayoutTraits.swift | 69 +++ Source/Misc/Multiplier.swift | 36 ++ Source/RelatedElements.swift | 67 +++ SuperPuperDuperLayout.podspec | 13 + .../project.pbxproj | 542 ++++++++++++++++++ 28 files changed, 1998 insertions(+) create mode 100644 .gitignore create mode 100644 Example/AppDelegate.swift create mode 100644 Example/Base.lproj/LaunchScreen.storyboard create mode 100644 Example/Info.plist create mode 100644 Example/ViewController.swift create mode 100644 LICENSE create mode 100644 Other/Info.plist create mode 100644 Other/SuperPuperDuperLayout.h create mode 100644 README.md create mode 100644 Source/Layout.swift create mode 100644 Source/LayoutAttributes/CenterLayoutAttribute.swift create mode 100644 Source/LayoutAttributes/DimensionLayoutAttribute.swift create mode 100644 Source/LayoutAttributes/EdgesLayoutAttribute.swift create mode 100644 Source/LayoutAttributes/LayoutAttribute.swift create mode 100644 Source/LayoutAttributes/LayoutAttributeByCoordinateAxes.swift create mode 100644 Source/LayoutAttributes/SizeLayoutAttribute.swift create mode 100644 Source/LayoutDescription.swift create mode 100644 Source/LayoutFactories.swift create mode 100644 Source/LayoutOptions/LayoutOptions.swift create mode 100644 Source/LayoutOptions/LayoutOptionsForCenterConstraints.swift create mode 100644 Source/LayoutOptions/LayoutOptionsForConstraintsOfEdges.swift create mode 100644 Source/LayoutOptions/LayoutOptionsForConstraintsOfSize.swift create mode 100644 Source/LayoutOptions/LayoutOptionsForSingleConstraint.swift create mode 100644 Source/LayoutTraits.swift create mode 100644 Source/Misc/Multiplier.swift create mode 100644 Source/RelatedElements.swift create mode 100644 SuperPuperDuperLayout.podspec create mode 100644 SuperPuperDuperLayout.xcodeproj/project.pbxproj diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..222e8ec --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +# Mac OS X +.DS_Store + +# Xcode + +## Build generated +build/ +DerivedData + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata + +## Other +*.xccheckout +*.moved-aside +*.xcuserstate +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +.build/ + +# Carthage +Carthage/Build diff --git a/Example/AppDelegate.swift b/Example/AppDelegate.swift new file mode 100644 index 0000000..de503bb --- /dev/null +++ b/Example/AppDelegate.swift @@ -0,0 +1,39 @@ +// +// AppDelegate.swift +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + window = UIWindow(frame: UIScreen.main.bounds) + window?.backgroundColor = .black + window?.rootViewController = ViewController() + window?.makeKeyAndVisible() + return true + } +} diff --git a/Example/Base.lproj/LaunchScreen.storyboard b/Example/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..27a2cbe --- /dev/null +++ b/Example/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/Info.plist b/Example/Info.plist new file mode 100644 index 0000000..4222ac2 --- /dev/null +++ b/Example/Info.plist @@ -0,0 +1,43 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Example/ViewController.swift b/Example/ViewController.swift new file mode 100644 index 0000000..b6d7469 --- /dev/null +++ b/Example/ViewController.swift @@ -0,0 +1,74 @@ +// +// ViewController.swift +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +import UIKit +import SuperPuperDuperLayout + +extension CGSize { + init(square: CGFloat) { self.init(width: square, height: square) } +} + +class ViewController: UIViewController { + + //MARK: - Appearance + + private struct Appearance { + let avatarSize = CGSize(square: 50) + } + private let appearance = Appearance() + + + //MARK: - Views + + private lazy var avatarView: UIView = { + let view = UIView() + view.backgroundColor = UIColor.lightGray + view.layer.cornerRadius = appearance.avatarSize.width / 2 + return view + }() + + //MARK: - Life Cycle + + override func viewDidLoad() { + super.viewDidLoad() + view.backgroundColor = .white + hierarchy() + layout() + } + + //MARK: - Hierarchy + + private func hierarchy() { + view.addSubview(avatarView) + } + + //MARK: - Layout + + private func layout() { + Layout.to(view: avatarView) { + $0.size.equal.value(appearance.avatarSize) + $0.center.equalToSuperview.value(.init(horizontal: 0, vertical: 0)) + } + } +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d19e5a7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) + +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. diff --git a/Other/Info.plist b/Other/Info.plist new file mode 100644 index 0000000..1007fd9 --- /dev/null +++ b/Other/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/Other/SuperPuperDuperLayout.h b/Other/SuperPuperDuperLayout.h new file mode 100644 index 0000000..cac966f --- /dev/null +++ b/Other/SuperPuperDuperLayout.h @@ -0,0 +1,28 @@ +// +// SuperPuperDuperLayout.h +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +@import UIKit; + +FOUNDATION_EXPORT double SuperPuperDuperDataVersionNumber; +FOUNDATION_EXPORT const unsigned char SuperPuperDuperDataVersionString[]; diff --git a/README.md b/README.md new file mode 100644 index 0000000..8fdecc0 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# SuperPuperDuperLayout diff --git a/Source/Layout.swift b/Source/Layout.swift new file mode 100644 index 0000000..df7441b --- /dev/null +++ b/Source/Layout.swift @@ -0,0 +1,41 @@ +// +// Layout.swift +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +import UIKit + +public final class Layout { + open class func to(view: UIView, layout: ((ConstraintViewFactory) -> ())) { + let factory = ConstraintViewFactory(firstItem: LayoutDescription.Item(view: view)) + layout(factory) + factory.setup() + } + + @available(iOS 9.0, *) + open class func to(layoutGuide: UILayoutGuide, layout: ((ConstraintLayoutGuideFactory) -> ())) { + let factory = ConstraintLayoutGuideFactory(firstItem: LayoutDescription.Item(layoutGuide: layoutGuide)) + layout(factory) + factory.setup() + } + private init() {} +} diff --git a/Source/LayoutAttributes/CenterLayoutAttribute.swift b/Source/LayoutAttributes/CenterLayoutAttribute.swift new file mode 100644 index 0000000..461d570 --- /dev/null +++ b/Source/LayoutAttributes/CenterLayoutAttribute.swift @@ -0,0 +1,70 @@ +// +// CenterLayoutAttribute.swift +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +import UIKit + +open class CenterLayoutAttribute: LayoutAttribute { + internal convenience init(centerX: LayoutDescription, centerY: LayoutDescription?) { + self.init(layoutDescription: centerX) + self.centerYDescription = centerY + } + internal weak var centerYDescription: LayoutDescription? + + public required init(layoutDescription: LayoutDescription) { super.init(layoutDescription: layoutDescription) } + + internal override func relation(_ relation: NSLayoutRelation, to view: UIView) -> LayoutOptionsForCenterConstraints { + prepareLayoutDescription(layoutDescription, with: relation, to: LayoutDescription.Item(view: view)) + prepareLayoutDescription(centerYDescription, with: relation, to: LayoutDescription.Item(view: view)) + return LayoutOptionsForCenterConstraints(centerX: layoutDescription, centerY: centerYDescription) + } + + @available(iOS 9.0, *) + internal override func relation(_ relation: NSLayoutRelation, to layoutGuide: UILayoutGuide) -> LayoutOptionsForCenterConstraints { + prepareLayoutDescription(layoutDescription, with: relation, to: LayoutDescription.Item(layoutGuide: layoutGuide)) + prepareLayoutDescription(centerYDescription, with: relation, to: LayoutDescription.Item(layoutGuide: layoutGuide)) + return LayoutOptionsForCenterConstraints(centerX: layoutDescription, centerY: centerYDescription) + } + + internal func prepareLayoutDescription(_ layoutDescription: LayoutDescription?, with relation: NSLayoutRelation, to item: LayoutDescription.Item?) { + layoutDescription?.relation = relation + layoutDescription?.secondItem = item + if let l = layoutDescription { + l.secondAttribute = l.firstAttribute + } + } +} + +open class CenterViewLayoutAttribute: CenterLayoutAttribute, LayoutAttributeRelatedToSuperView { + public typealias RelationToSuperview = LayoutOptionsForCenterConstraints + + open var equalToSuperview: RelationToSuperview { return relation(.equal, to: layoutDescriptionItem(from: layoutDescription)) } + open var lessThanOrEqualSuperview: RelationToSuperview { return relation(.lessThanOrEqual, to: layoutDescriptionItem(from: layoutDescription)) } + open var greaterThanOrEqualSuperview: RelationToSuperview { return relation(.greaterThanOrEqual, to: layoutDescriptionItem(from: layoutDescription)) } + + internal func relation(_ relation: NSLayoutRelation, to item: LayoutDescription.Item?) -> LayoutOptionsForCenterConstraints { + prepareLayoutDescription(layoutDescription, with: relation, to: item) + prepareLayoutDescription(centerYDescription, with: relation, to: item) + return LayoutOptionsForCenterConstraints(centerX: layoutDescription, centerY: centerYDescription) + } +} diff --git a/Source/LayoutAttributes/DimensionLayoutAttribute.swift b/Source/LayoutAttributes/DimensionLayoutAttribute.swift new file mode 100644 index 0000000..597751c --- /dev/null +++ b/Source/LayoutAttributes/DimensionLayoutAttribute.swift @@ -0,0 +1,48 @@ +// +// DimensionLayoutAttribute.swift +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +import UIKit + +open class DimensionLayoutAttribute: LayoutAttribute { + open var equal: LayoutOptionsForSingleConstraint { + return optionsForSingleConstraint(for: .equal) + } + + open var lessThanOrEqual: LayoutOptionsForSingleConstraint { + return optionsForSingleConstraint(for: .lessThanOrEqual) + } + + open var greaterThanOrEqual: LayoutOptionsForSingleConstraint { + return optionsForSingleConstraint(for: .greaterThanOrEqual) + } + + private func optionsForSingleConstraint(for relation: NSLayoutRelation) -> LayoutOptionsForSingleConstraint { + layoutDescription.relation = relation + return LayoutOptionsForSingleConstraint(layoutDescription: layoutDescription) + } +} + +open class DimensionViewLayoutAttribute: DimensionLayoutAttribute, LayoutAttributeRelatedToSuperView { + public typealias RelationToSuperview = DimensionRelatedElement +} diff --git a/Source/LayoutAttributes/EdgesLayoutAttribute.swift b/Source/LayoutAttributes/EdgesLayoutAttribute.swift new file mode 100644 index 0000000..58bce29 --- /dev/null +++ b/Source/LayoutAttributes/EdgesLayoutAttribute.swift @@ -0,0 +1,80 @@ +// +// EdgesLayoutAttribute.swift +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +import UIKit + +open class EdgesLayoutAttribute: LayoutAttribute { + internal convenience init(top: LayoutDescription, bottom: LayoutDescription?, leading: LayoutDescription?, trailing: LayoutDescription?) { + self.init(layoutDescription: top) + self.bottom = bottom + self.leading = leading + self.trailing = trailing + } + internal weak var bottom: LayoutDescription? + internal weak var leading: LayoutDescription? + internal weak var trailing: LayoutDescription? + + public required init(layoutDescription: LayoutDescription) { super.init(layoutDescription: layoutDescription) } + + internal override func relation(_ relation: NSLayoutRelation, to view: UIView) -> LayoutOptionsForConstraintsOfEdges { + prepareLayoutDescription(layoutDescription, with: relation, to: LayoutDescription.Item(view: view)) + prepareLayoutDescription(bottom, with: relation, to: LayoutDescription.Item(view: view)) + prepareLayoutDescription(leading, with: relation, to: LayoutDescription.Item(view: view)) + prepareLayoutDescription(trailing, with: relation, to: LayoutDescription.Item(view: view)) + return LayoutOptionsForConstraintsOfEdges(top: layoutDescription, bottom: bottom, leading: leading, trailing: trailing) + } + + @available(iOS 9.0, *) + internal override func relation(_ relation: NSLayoutRelation, to layoutGuide: UILayoutGuide) -> LayoutOptionsForConstraintsOfEdges { + prepareLayoutDescription(layoutDescription, with: relation, to: LayoutDescription.Item(layoutGuide: layoutGuide)) + prepareLayoutDescription(bottom, with: relation, to: LayoutDescription.Item(layoutGuide: layoutGuide)) + prepareLayoutDescription(leading, with: relation, to: LayoutDescription.Item(layoutGuide: layoutGuide)) + prepareLayoutDescription(trailing, with: relation, to: LayoutDescription.Item(layoutGuide: layoutGuide)) + return LayoutOptionsForConstraintsOfEdges(top: layoutDescription, bottom: bottom, leading: leading, trailing: trailing) + } + + internal func prepareLayoutDescription(_ layoutDescription: LayoutDescription?, with relation: NSLayoutRelation, to item: LayoutDescription.Item?) { + layoutDescription?.relation = relation + layoutDescription?.secondItem = item + if let l = layoutDescription { + l.secondAttribute = l.firstAttribute + } + } +} + +open class EdgesViewLayoutAttribute: EdgesLayoutAttribute, LayoutAttributeRelatedToSuperView { + public typealias RelationToSuperview = LayoutOptionsForConstraintsOfEdges + + open var equalToSuperview: RelationToSuperview { return relation(.equal, to: layoutDescriptionItem(from: layoutDescription)) } + open var lessThanOrEqualSuperview: RelationToSuperview { return relation(.lessThanOrEqual, to: layoutDescriptionItem(from: layoutDescription)) } + open var greaterThanOrEqualSuperview: RelationToSuperview { return relation(.greaterThanOrEqual, to: layoutDescriptionItem(from: layoutDescription)) } + + internal func relation(_ relation: NSLayoutRelation, to item: LayoutDescription.Item?) -> LayoutOptionsForConstraintsOfEdges { + prepareLayoutDescription(layoutDescription, with: relation, to: item) + prepareLayoutDescription(bottom, with: relation, to: item) + prepareLayoutDescription(leading, with: relation, to: item) + prepareLayoutDescription(trailing, with: relation, to: item) + return LayoutOptionsForConstraintsOfEdges(top: layoutDescription, bottom: bottom, leading: leading, trailing: trailing) + } +} diff --git a/Source/LayoutAttributes/LayoutAttribute.swift b/Source/LayoutAttributes/LayoutAttribute.swift new file mode 100644 index 0000000..6c179d7 --- /dev/null +++ b/Source/LayoutAttributes/LayoutAttribute.swift @@ -0,0 +1,95 @@ +// +// LayoutAttribute.swift +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +import UIKit + +public protocol LayoutAttributeRelatedToSuperView { + associatedtype RelationToSuperview + var equalToSuperview: RelationToSuperview { get } + var lessThanOrEqualSuperview: RelationToSuperview { get } + var greaterThanOrEqualSuperview: RelationToSuperview { get } +} + +public extension LayoutAttributeRelatedToSuperView where Self: EditableItem, RelationToSuperview: EditableItem { + var equalToSuperview: RelationToSuperview { return relation(.equal, to: layoutDescriptionItem(from: layoutDescription)) } + var lessThanOrEqualSuperview: RelationToSuperview { return relation(.lessThanOrEqual, to: layoutDescriptionItem(from: layoutDescription)) } + var greaterThanOrEqualSuperview: RelationToSuperview { return relation(.greaterThanOrEqual, to: layoutDescriptionItem(from: layoutDescription)) } + + internal func layoutDescriptionItem(from layoutDescription: LayoutDescription?) -> LayoutDescription.Item? { + if let view = layoutDescription?.firstItem.someItem as? UIView { + return LayoutDescription.Item(view: view.superview) + } else { + guard #available(iOS 9.0, *) else { return nil } + return LayoutDescription.Item(view: (layoutDescription?.firstItem.someItem as? UILayoutGuide)?.owningView) + } + } + + internal func relation(_ relation: NSLayoutRelation, to item: LayoutDescription.Item?) -> RelationToSuperview { + layoutDescription.relation = relation + layoutDescription.secondItem = item + return RelationToSuperview(layoutDescription: layoutDescription) + } +} + +open class LayoutAttribute: EditableItem { + open func equal(to view: UIView) -> RelationToView { + return relation(.equal, to: view) + } + + open func lessThanOrEqual(to view: UIView) -> RelationToView { + return relation(.lessThanOrEqual, to: view) + } + + open func greaterThanOrEqual(to view: UIView) -> RelationToView { + return relation(.greaterThanOrEqual, to: view) + } + + internal func relation(_ relation: NSLayoutRelation, to view: UIView) -> RelationToView { + layoutDescription.relation = relation + layoutDescription.secondItem = LayoutDescription.Item(view: view) + return RelationToView(layoutDescription: layoutDescription) + } + + @available(iOS 9.0, *) + open func equal(to layoutGuide: UILayoutGuide) -> RelationToLayoutGuide { + return relation(.equal, to: layoutGuide) + } + + @available(iOS 9.0, *) + open func lessThanOrEqual(to layoutGuide: UILayoutGuide) -> RelationToLayoutGuide { + return relation(.lessThanOrEqual, to: layoutGuide) + } + + @available(iOS 9.0, *) + open func greaterThanOrEqual(to layoutGuide: UILayoutGuide) -> RelationToLayoutGuide { + return relation(.greaterThanOrEqual, to: layoutGuide) + } + + @available(iOS 9.0, *) + internal func relation(_ relation: NSLayoutRelation, to layoutGuide: UILayoutGuide) -> RelationToLayoutGuide { + layoutDescription.relation = relation + layoutDescription.secondItem = LayoutDescription.Item(layoutGuide: layoutGuide) + return RelationToLayoutGuide(layoutDescription: layoutDescription) + } +} diff --git a/Source/LayoutAttributes/LayoutAttributeByCoordinateAxes.swift b/Source/LayoutAttributes/LayoutAttributeByCoordinateAxes.swift new file mode 100644 index 0000000..5eef667 --- /dev/null +++ b/Source/LayoutAttributes/LayoutAttributeByCoordinateAxes.swift @@ -0,0 +1,37 @@ +// +// LayoutAttributeByCoordinateAxes.swift +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +import Foundation + +open class VerticalLayoutAttribute: LayoutAttribute {} + +open class VerticalViewLayoutAttribute: VerticalLayoutAttribute, LayoutAttributeRelatedToSuperView { + public typealias RelationToSuperview = VerticalRelatedExtendedElement +} + +open class HorizontalLayoutAttribute: LayoutAttribute {} + +open class HorizontalViewLayoutAttribute: VerticalLayoutAttribute, LayoutAttributeRelatedToSuperView { + public typealias RelationToSuperview = HorizontalRelatedElement +} diff --git a/Source/LayoutAttributes/SizeLayoutAttribute.swift b/Source/LayoutAttributes/SizeLayoutAttribute.swift new file mode 100644 index 0000000..bab185f --- /dev/null +++ b/Source/LayoutAttributes/SizeLayoutAttribute.swift @@ -0,0 +1,92 @@ +// +// SizeLayoutAttribute.swift +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +import UIKit + +open class SizeLayoutAttribute: LayoutAttribute { + internal convenience init(width: LayoutDescription, height: LayoutDescription?) { + self.init(layoutDescription: width) + self.heightDescription = height + } + internal weak var heightDescription: LayoutDescription? + + public required init(layoutDescription: LayoutDescription) { super.init(layoutDescription: layoutDescription) } + + internal override func relation(_ relation: NSLayoutRelation, to view: UIView) -> LayoutOptionsForConstraintsOfSize { + let options = super.relation(relation, to: view) + options.heightDescription = heightDescription + options.heightDescription?.relation = relation + options.heightDescription?.secondItem = LayoutDescription.Item(view: view) + return options + } + + @available(iOS 9.0, *) + internal override func relation(_ relation: NSLayoutRelation, to layoutGuide: UILayoutGuide) -> LayoutOptionsForConstraintsOfSize { + let options = super.relation(relation, to: layoutGuide) + options.heightDescription = heightDescription + options.heightDescription?.relation = relation + options.heightDescription?.secondItem = LayoutDescription.Item(layoutGuide: layoutGuide) + return options + } + + open var equal: LayoutOptionsForConstraintsOfSize { + return optionsForConstraintsOfSize(for: .equal) + } + + open var lessThanOrEqual: LayoutOptionsForConstraintsOfSize { + return optionsForConstraintsOfSize(for: .lessThanOrEqual) + } + + open var greaterThanOrEqual: LayoutOptionsForConstraintsOfSize { + return optionsForConstraintsOfSize(for: .greaterThanOrEqual) + } + + internal func optionsForConstraintsOfSize(for relation: NSLayoutRelation, to item: LayoutDescription.Item) -> LayoutOptionsForConstraintsOfSize { + layoutDescription.secondItem = item + heightDescription?.secondItem = item + return optionsForConstraintsOfSize(for: relation) + } + + internal func optionsForConstraintsOfSize(for relation: NSLayoutRelation) -> LayoutOptionsForConstraintsOfSize { + layoutDescription.relation = relation + heightDescription?.relation = relation + return LayoutOptionsForConstraintsOfSize(width: layoutDescription, height: heightDescription) + } +} + +open class SizeViewLayoutAttribute: SizeLayoutAttribute, LayoutAttributeRelatedToSuperView { + public typealias RelationToSuperview = LayoutOptionsForConstraintsOfSize + + open var equalToSuperview: RelationToSuperview { return relation(.equal, to: layoutDescriptionItem(from: layoutDescription)) } + open var lessThanOrEqualSuperview: RelationToSuperview { return relation(.lessThanOrEqual, to: layoutDescriptionItem(from: layoutDescription)) } + open var greaterThanOrEqualSuperview: RelationToSuperview { return relation(.greaterThanOrEqual, to: layoutDescriptionItem(from: layoutDescription)) } + + internal func relation(_ relation: NSLayoutRelation, to item: LayoutDescription.Item?) -> LayoutOptionsForConstraintsOfSize { + layoutDescription.relation = relation + layoutDescription.secondItem = item + heightDescription?.relation = relation + heightDescription?.secondItem = item + return LayoutOptionsForConstraintsOfSize(layoutDescription: layoutDescription) + } +} diff --git a/Source/LayoutDescription.swift b/Source/LayoutDescription.swift new file mode 100644 index 0000000..6291efb --- /dev/null +++ b/Source/LayoutDescription.swift @@ -0,0 +1,80 @@ +// +// LayoutDescription.swift +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +import UIKit + +open class LayoutDescription { + public final class Item { + public init(view: UIView?) { self.view = view } + public weak var view: UIView? + + @available(iOS 9.0, *) + public init(layoutGuide: UILayoutGuide?) { self.layoutGuide = layoutGuide } + + @available(iOS 9.0, *) + public var layoutGuide: UILayoutGuide? { + get { return _layoutGuide as? UILayoutGuide } + set { _layoutGuide = newValue } + } + private var _layoutGuide: AnyObject? + + public var someItem: Any? { + guard #available(iOS 9.0, *) else { return view } + return view != nil ? view : layoutGuide + } + } + + public init(firstItem: LayoutDescription.Item, firstAttribute: NSLayoutAttribute) { + self.firstItem = firstItem + self.firstAttribute = firstAttribute + } + open var firstItem: LayoutDescription.Item + open var firstAttribute: NSLayoutAttribute + open var relation: NSLayoutRelation? + open var secondItem: LayoutDescription.Item? + open var secondAttribute = NSLayoutAttribute.notAnAttribute + open var priority = UILayoutPriority.defaultHigh + open var multiplier = Float(1) + open var constant = CGFloat(0) + + open var nsLayoutConstraint: NSLayoutConstraint? { + guard let firstItem = firstItem.someItem else { return nil } + guard firstAttribute != .notAnAttribute else { return nil } + guard let relation = relation else { return nil } + guard secondItem == nil || secondAttribute != .notAnAttribute else { return nil } + if secondItem == nil { secondAttribute = firstAttribute } + return NSLayoutConstraint(item: firstItem, + attribute: firstAttribute, + relatedBy: relation, + toItem: secondItem?.someItem, + attribute: secondAttribute, + multiplier: CGFloat(multiplier), + constant: constant) + } +} + +open class EditableItem { + public required init(layoutDescription: LayoutDescription) { self.layoutDescription = layoutDescription } + internal unowned let layoutDescription: LayoutDescription +} diff --git a/Source/LayoutFactories.swift b/Source/LayoutFactories.swift new file mode 100644 index 0000000..f926cf7 --- /dev/null +++ b/Source/LayoutFactories.swift @@ -0,0 +1,142 @@ +// +// LayoutFactories.swift +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +import UIKit + +public extension VerticalAxisLayoutTraits where Self: ConstraintFactory, VerticalAttributeType: EditableItem { + var top: VerticalAttributeType { return VerticalAttributeType(layoutDescription: layoutDescription(for: .top)) } + var bottom: VerticalAttributeType { return VerticalAttributeType(layoutDescription: layoutDescription(for: .bottom)) } + var centerY: VerticalAttributeType { return VerticalAttributeType(layoutDescription: layoutDescription(for: .centerY)) } + var topMargin: VerticalAttributeType { return VerticalAttributeType(layoutDescription: layoutDescription(for: .topMargin)) } + var bottomMargin: VerticalAttributeType { return VerticalAttributeType(layoutDescription: layoutDescription(for: .bottomMargin)) } + var centerYWithinMargins: VerticalAttributeType { return VerticalAttributeType(layoutDescription: layoutDescription(for: .centerYWithinMargins)) } +} + +public extension VerticalAxisExtendedLayoutTraits where Self: ConstraintFactory, VerticalAttributeType: EditableItem { + var lastBaseline: VerticalAttributeType { return VerticalAttributeType(layoutDescription: layoutDescription(for: .lastBaseline)) } + var firstBaseline: VerticalAttributeType { return VerticalAttributeType(layoutDescription: layoutDescription(for: .firstBaseline)) } +} + +public extension HorizontalAxisLayoutTraits where Self: ConstraintFactory, HorizontalAttributeType: EditableItem { + var left: HorizontalAttributeType { return HorizontalAttributeType(layoutDescription: layoutDescription(for: .left)) } + var right: HorizontalAttributeType { return HorizontalAttributeType(layoutDescription: layoutDescription(for: .right)) } + var leading: HorizontalAttributeType { return HorizontalAttributeType(layoutDescription: layoutDescription(for: .leading)) } + var trailing: HorizontalAttributeType { return HorizontalAttributeType(layoutDescription: layoutDescription(for: .trailing)) } + var centerX: HorizontalAttributeType { return HorizontalAttributeType(layoutDescription: layoutDescription(for: .centerX)) } + var leftMargin: HorizontalAttributeType { return HorizontalAttributeType(layoutDescription: layoutDescription(for: .leftMargin)) } + var rightMargin: HorizontalAttributeType { return HorizontalAttributeType(layoutDescription: layoutDescription(for: .rightMargin)) } + var leadingMargin: HorizontalAttributeType { return HorizontalAttributeType(layoutDescription: layoutDescription(for: .leadingMargin)) } + var trailingMargin: HorizontalAttributeType { return HorizontalAttributeType(layoutDescription: layoutDescription(for: .trailingMargin)) } + var centerXWithinMargins: HorizontalAttributeType { return HorizontalAttributeType(layoutDescription: layoutDescription(for: .centerXWithinMargins)) } +} + +public extension DimensionLayoutTraits where Self: ConstraintFactory, DimensionAttributeType: EditableItem { + var width: DimensionAttributeType { return DimensionAttributeType(layoutDescription: layoutDescription(for: .width)) } + var height: DimensionAttributeType { return DimensionAttributeType(layoutDescription: layoutDescription(for: .height)) } +} + +open class ConstraintFactory { + public required init(firstItem: LayoutDescription.Item) { self.firstItem = firstItem } + internal var firstItem: LayoutDescription.Item + internal var layoutDescriptions = [LayoutDescription]() + + internal func setup() { + (firstItem.someItem as? UIView)?.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate(layoutDescriptions.flatMap { $0.nsLayoutConstraint }) + } + + fileprivate func layoutDescription(for attribute: NSLayoutAttribute) -> LayoutDescription { + let newLayoutDescription = LayoutDescription(firstItem: firstItem, firstAttribute: attribute) + layoutDescriptions.append(newLayoutDescription) + return newLayoutDescription + } +} + +open class ConstraintViewFactory: ConstraintFactory, VerticalAxisExtendedLayoutTraits, HorizontalAxisLayoutTraits, DimensionLayoutTraits, ExtendedLayoutTraits { + public typealias VerticalAttributeType = VerticalViewLayoutAttribute + public typealias HorizontalAttributeType = HorizontalViewLayoutAttribute + public typealias DimensionAttributeType = DimensionViewLayoutAttribute + + public typealias EdgesLayoutAttributeType = EdgesViewLayoutAttribute + public typealias SizeLayoutAttributeType = SizeViewLayoutAttribute + public typealias CenterLayoutAttributeType = CenterViewLayoutAttribute + + open var edges: EdgesLayoutAttributeType { + let topLayoutDescription = layoutDescription(for: .top) + let bottomLayoutDescription = layoutDescription(for: .bottom) + let leadingLayoutDescription = layoutDescription(for: .leading) + let trailingLayoutDescription = layoutDescription(for: .trailing) + return EdgesLayoutAttributeType(top: topLayoutDescription, + bottom: bottomLayoutDescription, + leading: leadingLayoutDescription, + trailing: trailingLayoutDescription) + } + + open var size: SizeLayoutAttributeType { + let widthLayoutDescription = layoutDescription(for: .width) + let heightLayoutDescription = layoutDescription(for: .height) + return SizeLayoutAttributeType(width: widthLayoutDescription, height: heightLayoutDescription) + } + + open var center: CenterLayoutAttributeType { + let centerXLayoutDescription = layoutDescription(for: .centerX) + let centerYLayoutDescription = layoutDescription(for: .centerY) + return CenterLayoutAttributeType(centerX: centerXLayoutDescription, centerY: centerYLayoutDescription) + } +} + +open class ConstraintLayoutGuideFactory: ConstraintFactory, VerticalAxisLayoutTraits, HorizontalAxisLayoutTraits, DimensionLayoutTraits, ExtendedLayoutTraits { + public typealias VerticalAttributeType = VerticalLayoutAttribute + public typealias HorizontalAttributeType = HorizontalLayoutAttribute + public typealias DimensionAttributeType = DimensionLayoutAttribute + + public typealias EdgesLayoutAttributeType = EdgesLayoutAttribute + public typealias SizeLayoutAttributeType = SizeLayoutAttribute + public typealias CenterLayoutAttributeType = CenterLayoutAttribute + + open var edges: EdgesLayoutAttributeType { + let topLayoutDescription = layoutDescription(for: .top) + let bottomLayoutDescription = layoutDescription(for: .bottom) + let leadingLayoutDescription = layoutDescription(for: .leading) + let trailingLayoutDescription = layoutDescription(for: .trailing) + layoutDescriptions.append(contentsOf: [topLayoutDescription, bottomLayoutDescription, leadingLayoutDescription, trailingLayoutDescription]) + return EdgesLayoutAttributeType(top: topLayoutDescription, + bottom: bottomLayoutDescription, + leading: leadingLayoutDescription, + trailing: trailingLayoutDescription) + } + + open var size: SizeLayoutAttributeType { + let widthLayoutDescription = layoutDescription(for: .width) + let heightLayoutDescription = layoutDescription(for: .height) + layoutDescriptions.append(contentsOf: [widthLayoutDescription, heightLayoutDescription]) + return SizeLayoutAttributeType(width: widthLayoutDescription, height: heightLayoutDescription) + } + + open var center: CenterLayoutAttributeType { + let centerXLayoutDescription = layoutDescription(for: .centerX) + let centerYLayoutDescription = layoutDescription(for: .centerY) + return CenterLayoutAttributeType(centerX: centerXLayoutDescription, centerY: centerYLayoutDescription) + } +} diff --git a/Source/LayoutOptions/LayoutOptions.swift b/Source/LayoutOptions/LayoutOptions.swift new file mode 100644 index 0000000..fc3f27e --- /dev/null +++ b/Source/LayoutOptions/LayoutOptions.swift @@ -0,0 +1,49 @@ +// +// LayoutOptions.swift +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +import UIKit + +open class LayoutOptions: EditableItem { + @discardableResult + open func priority(_ priority: UILayoutPriority) -> Self { + layoutDescription.priority = priority + return self + } + + @discardableResult + open func multiplier(_ m: Multiplier) -> Self { + return multiplier(m.rawValue) + } + + @discardableResult + open func multiplier(_ m: Float) -> Self { + layoutDescription.multiplier = m + return self + } + + @discardableResult + open func value(_ value: Value) -> Self { + return self + } +} diff --git a/Source/LayoutOptions/LayoutOptionsForCenterConstraints.swift b/Source/LayoutOptions/LayoutOptionsForCenterConstraints.swift new file mode 100644 index 0000000..f0596de --- /dev/null +++ b/Source/LayoutOptions/LayoutOptionsForCenterConstraints.swift @@ -0,0 +1,64 @@ +// +// LayoutOptionsForCenterConstraints.swift +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +import Foundation + +open class LayoutOptionsForCenterConstraints: LayoutOptions { + internal convenience init(centerX: LayoutDescription, centerY: LayoutDescription?) { + self.init(layoutDescription: centerX) + self.centerYDescription = centerY + } + internal weak var centerYDescription: LayoutDescription? + + public required init(layoutDescription: LayoutDescription) { super.init(layoutDescription: layoutDescription) } + + @discardableResult + open override func value(_ value: UIOffset) -> Self { + layoutDescription.constant = value.horizontal + centerYDescription?.constant = value.vertical + return self + } + + @discardableResult + open override func priority(_ priority: UILayoutPriority) -> Self { + super.priority(priority) + centerYDescription?.priority = priority + return self + } + + @discardableResult + open override func multiplier(_ m: Multiplier) -> Self { + return multiplier(m.rawValue) + } + + @discardableResult + open override func multiplier(_ m: Float) -> Self { + super.multiplier(m) + centerYDescription?.multiplier = m + return self + } + + open var nsCenterXLayoutConstraint: NSLayoutConstraint? { return layoutDescription.nsLayoutConstraint } + open var nsCenterYLayoutConstraint: NSLayoutConstraint? { return centerYDescription?.nsLayoutConstraint } +} diff --git a/Source/LayoutOptions/LayoutOptionsForConstraintsOfEdges.swift b/Source/LayoutOptions/LayoutOptionsForConstraintsOfEdges.swift new file mode 100644 index 0000000..e8d893d --- /dev/null +++ b/Source/LayoutOptions/LayoutOptionsForConstraintsOfEdges.swift @@ -0,0 +1,76 @@ +// +// LayoutOptionsForConstraintsOfEdges.swift +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +import UIKit + +open class LayoutOptionsForConstraintsOfEdges: LayoutOptions { + internal convenience init(top: LayoutDescription, bottom: LayoutDescription?, leading: LayoutDescription?, trailing: LayoutDescription?) { + self.init(layoutDescription: top) + self.bottom = bottom + self.leading = leading + self.trailing = trailing + } + internal weak var bottom: LayoutDescription? + internal weak var leading: LayoutDescription? + internal weak var trailing: LayoutDescription? + + public required init(layoutDescription: LayoutDescription) { super.init(layoutDescription: layoutDescription) } + + @discardableResult + open override func value(_ value: UIEdgeInsets) -> Self { + layoutDescription.constant = value.top + bottom?.constant = value.bottom + leading?.constant = value.left + trailing?.constant = value.right + return self + } + + @discardableResult + open override func priority(_ priority: UILayoutPriority) -> Self { + super.priority(priority) + bottom?.priority = priority + leading?.priority = priority + trailing?.priority = priority + return self + } + + @discardableResult + open override func multiplier(_ m: Multiplier) -> Self { + return multiplier(m.rawValue) + } + + @discardableResult + open override func multiplier(_ m: Float) -> Self { + super.multiplier(m) + bottom?.multiplier = m + leading?.multiplier = m + trailing?.multiplier = m + return self + } + + open var nsTopLayoutConstraint: NSLayoutConstraint? { return layoutDescription.nsLayoutConstraint } + open var nsBottomLayoutConstraint: NSLayoutConstraint? { return bottom?.nsLayoutConstraint } + open var nsLeadingLayoutConstraint: NSLayoutConstraint? { return leading?.nsLayoutConstraint } + open var nsTrailingLayoutConstraint: NSLayoutConstraint? { return trailing?.nsLayoutConstraint } +} diff --git a/Source/LayoutOptions/LayoutOptionsForConstraintsOfSize.swift b/Source/LayoutOptions/LayoutOptionsForConstraintsOfSize.swift new file mode 100644 index 0000000..b9619e2 --- /dev/null +++ b/Source/LayoutOptions/LayoutOptionsForConstraintsOfSize.swift @@ -0,0 +1,64 @@ +// +// LayoutOptionsForConstraintsOfSize.swift +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +import UIKit + +open class LayoutOptionsForConstraintsOfSize: LayoutOptions { + internal convenience init(width: LayoutDescription, height: LayoutDescription?) { + self.init(layoutDescription: width) + self.heightDescription = height + } + internal weak var heightDescription: LayoutDescription? + + public required init(layoutDescription: LayoutDescription) { super.init(layoutDescription: layoutDescription) } + + @discardableResult + open override func value(_ value: CGSize) -> Self { + layoutDescription.constant = value.width + heightDescription?.constant = value.height + return self + } + + @discardableResult + open override func priority(_ priority: UILayoutPriority) -> Self { + super.priority(priority) + heightDescription?.priority = priority + return self + } + + @discardableResult + open override func multiplier(_ m: Multiplier) -> Self { + return multiplier(m.rawValue) + } + + @discardableResult + open override func multiplier(_ m: Float) -> Self { + super.multiplier(m) + heightDescription?.multiplier = m + return self + } + + open var nsWidthLayoutConstraint: NSLayoutConstraint? { return layoutDescription.nsLayoutConstraint } + open var nsHeightLayoutConstraint: NSLayoutConstraint? { return heightDescription?.nsLayoutConstraint } +} diff --git a/Source/LayoutOptions/LayoutOptionsForSingleConstraint.swift b/Source/LayoutOptions/LayoutOptionsForSingleConstraint.swift new file mode 100644 index 0000000..ac56368 --- /dev/null +++ b/Source/LayoutOptions/LayoutOptionsForSingleConstraint.swift @@ -0,0 +1,35 @@ +// +// LayoutOptionsForSingleConstraint.swift +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +import UIKit + +open class LayoutOptionsForSingleConstraint: LayoutOptions { + @discardableResult + open override func value(_ value: CGFloat) -> Self { + layoutDescription.constant = value + return self + } + + open var nsLayoutConstraint: NSLayoutConstraint? { return layoutDescription.nsLayoutConstraint } +} diff --git a/Source/LayoutTraits.swift b/Source/LayoutTraits.swift new file mode 100644 index 0000000..e87332e --- /dev/null +++ b/Source/LayoutTraits.swift @@ -0,0 +1,69 @@ +// +// LayoutTraits.swift +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +import Foundation + +public protocol VerticalAxisLayoutTraits { + associatedtype VerticalAttributeType + var top: VerticalAttributeType { get } + var bottom: VerticalAttributeType { get } + var centerY: VerticalAttributeType { get } + var topMargin: VerticalAttributeType { get } + var bottomMargin: VerticalAttributeType { get } + var centerYWithinMargins: VerticalAttributeType { get } +} + +public protocol VerticalAxisExtendedLayoutTraits: VerticalAxisLayoutTraits { + var lastBaseline: VerticalAttributeType { get } + var firstBaseline: VerticalAttributeType { get } +} + +public protocol HorizontalAxisLayoutTraits { + associatedtype HorizontalAttributeType + var left: HorizontalAttributeType { get } + var right: HorizontalAttributeType { get } + var leading: HorizontalAttributeType { get } + var trailing: HorizontalAttributeType { get } + var centerX: HorizontalAttributeType { get } + var leftMargin: HorizontalAttributeType { get } + var rightMargin: HorizontalAttributeType { get } + var leadingMargin: HorizontalAttributeType { get } + var trailingMargin: HorizontalAttributeType { get } + var centerXWithinMargins: HorizontalAttributeType { get } +} + +public protocol DimensionLayoutTraits { + associatedtype DimensionAttributeType + var width: DimensionAttributeType { get } + var height: DimensionAttributeType { get } +} + +public protocol ExtendedLayoutTraits { + associatedtype EdgesLayoutAttributeType + associatedtype SizeLayoutAttributeType + associatedtype CenterLayoutAttributeType + var edges: EdgesLayoutAttributeType { get } + var size: SizeLayoutAttributeType { get } + var center: CenterLayoutAttributeType { get } +} diff --git a/Source/Misc/Multiplier.swift b/Source/Misc/Multiplier.swift new file mode 100644 index 0000000..134bbf0 --- /dev/null +++ b/Source/Misc/Multiplier.swift @@ -0,0 +1,36 @@ +// +// Multiplier.swift +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +import Foundation + +postfix operator % +public postfix func % (rhs: UInt8) -> Multiplier { + return Multiplier(rawValue: Float(rhs) / 100) +} + +public struct Multiplier: RawRepresentable { + public typealias RawValue = Float + public init(rawValue: Float) { self.rawValue = rawValue } + public var rawValue: Float +} diff --git a/Source/RelatedElements.swift b/Source/RelatedElements.swift new file mode 100644 index 0000000..a300608 --- /dev/null +++ b/Source/RelatedElements.swift @@ -0,0 +1,67 @@ +// +// RelatedElement.swift +// +// Copyright (c) 2018-Present Sugar And Candy ( https://github.com/SugarAndCandy ) +// +// 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. +// + +import UIKit + +open class RelatedElement: EditableItem { + fileprivate func layoutOptionsForSingleConstraintProvider(with attribute: NSLayoutAttribute) -> LayoutOptionsForSingleConstraint { + layoutDescription.secondAttribute = attribute + return LayoutOptionsForSingleConstraint(layoutDescription: layoutDescription) + } +} + +open class VerticalRelatedElement: RelatedElement, VerticalAxisLayoutTraits { + public typealias VerticalAttributeType = LayoutOptionsForSingleConstraint + open var top: VerticalAttributeType { return layoutOptionsForSingleConstraintProvider(with: .top) } + open var bottom: VerticalAttributeType { return layoutOptionsForSingleConstraintProvider(with: .bottom) } + open var centerY: VerticalAttributeType { return layoutOptionsForSingleConstraintProvider(with: .centerY) } + open var topMargin: VerticalAttributeType { return layoutOptionsForSingleConstraintProvider(with: .topMargin) } + open var bottomMargin: VerticalAttributeType { return layoutOptionsForSingleConstraintProvider(with: .bottomMargin) } + open var centerYWithinMargins: VerticalAttributeType { return layoutOptionsForSingleConstraintProvider(with: .centerYWithinMargins) } +} + +open class VerticalRelatedExtendedElement: VerticalRelatedElement, VerticalAxisExtendedLayoutTraits { + open var lastBaseline: VerticalAttributeType { return layoutOptionsForSingleConstraintProvider(with: .lastBaseline) } + open var firstBaseline: VerticalAttributeType { return layoutOptionsForSingleConstraintProvider(with: .firstBaseline) } +} + +open class HorizontalRelatedElement: RelatedElement, HorizontalAxisLayoutTraits { + public typealias HorizontalAttributeType = LayoutOptionsForSingleConstraint + open var left: HorizontalAttributeType { return layoutOptionsForSingleConstraintProvider(with: .left) } + open var right: HorizontalAttributeType { return layoutOptionsForSingleConstraintProvider(with: .right) } + open var leading: HorizontalAttributeType { return layoutOptionsForSingleConstraintProvider(with: .leading) } + open var trailing: HorizontalAttributeType { return layoutOptionsForSingleConstraintProvider(with: .trailing) } + open var centerX: HorizontalAttributeType { return layoutOptionsForSingleConstraintProvider(with: .centerX) } + open var leftMargin: HorizontalAttributeType { return layoutOptionsForSingleConstraintProvider(with: .leftMargin) } + open var rightMargin: HorizontalAttributeType { return layoutOptionsForSingleConstraintProvider(with: .rightMargin) } + open var leadingMargin: HorizontalAttributeType { return layoutOptionsForSingleConstraintProvider(with: .leadingMargin) } + open var trailingMargin: HorizontalAttributeType { return layoutOptionsForSingleConstraintProvider(with: .trailingMargin) } + open var centerXWithinMargins: HorizontalAttributeType { return layoutOptionsForSingleConstraintProvider(with: .centerXWithinMargins) } +} + +open class DimensionRelatedElement: RelatedElement, DimensionLayoutTraits { + public typealias DimensionAttributeType = LayoutOptionsForSingleConstraint + open var width: DimensionAttributeType { return layoutOptionsForSingleConstraintProvider(with: .width) } + open var height: DimensionAttributeType { return layoutOptionsForSingleConstraintProvider(with: .height) } +} diff --git a/SuperPuperDuperLayout.podspec b/SuperPuperDuperLayout.podspec new file mode 100644 index 0000000..a2b48a6 --- /dev/null +++ b/SuperPuperDuperLayout.podspec @@ -0,0 +1,13 @@ +Pod::Spec.new do |s| + s.name = 'SuperPuperDuperLayout' + s.version = '1.0.0' + s.license = 'MIT' + s.summary = 'Lightweight, elegant and safe wrapper over auto layout.' + s.description = 'Lightweight, elegant and safe wrapper over auto layout. Inspired by Layout Anchors ( https://developer.apple.com/documentation/uikit/nslayoutanchor ) and SnapKit ( https://github.com/SnapKit/SnapKit ). Without overheads such as «extension UIView», «extension UILayoutGuide», «objc_setAssociatedObjectAssociatedObject», «objc_getAssociatedObject» etc.' + s.homepage = 'https://github.com/SugarAndCandy/SuperPuperDuperLayout' + s.authors = { 'Alexander Zolotarev' => 'berez.rosha@gmail.com' } + s.social_media_url = 'https://twitter.com/zolotarev_s' + s.source = { :git => 'https://github.com/SugarAndCandy/SuperPuperDuperLayout.git', :tag => s.version } + s.ios.deployment_target = '8.0' + s.source_files = 'Source/*.swift' +end diff --git a/SuperPuperDuperLayout.xcodeproj/project.pbxproj b/SuperPuperDuperLayout.xcodeproj/project.pbxproj new file mode 100644 index 0000000..dc82437 --- /dev/null +++ b/SuperPuperDuperLayout.xcodeproj/project.pbxproj @@ -0,0 +1,542 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 48; + objects = { + +/* Begin PBXBuildFile section */ + 769CC039204ECAEA009F3445 /* SuperPuperDuperLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 769CC036204ECAEA009F3445 /* SuperPuperDuperLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 76CA41B4204ED57A00EC089B /* Multiplier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76CA41B3204ED57A00EC089B /* Multiplier.swift */; }; + 76CA41B7204ED5B000EC089B /* RelatedElements.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76CA41B6204ED5B000EC089B /* RelatedElements.swift */; }; + 76CA41BD204ED93100EC089B /* LayoutDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76CA41BC204ED93100EC089B /* LayoutDescription.swift */; }; + 76CA41BF204EF52A00EC089B /* Layout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76CA41BE204EF52A00EC089B /* Layout.swift */; }; + 76CA41C1204EF56400EC089B /* LayoutFactories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76CA41C0204EF56400EC089B /* LayoutFactories.swift */; }; + 76CA41C3204EF58200EC089B /* LayoutTraits.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76CA41C2204EF58200EC089B /* LayoutTraits.swift */; }; + 76CA41C9204EF5F100EC089B /* LayoutAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76CA41C8204EF5F100EC089B /* LayoutAttribute.swift */; }; + 76CA41CB204EF6F800EC089B /* LayoutAttributeByCoordinateAxes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76CA41CA204EF6F800EC089B /* LayoutAttributeByCoordinateAxes.swift */; }; + 76CA41CD204EF70A00EC089B /* DimensionLayoutAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76CA41CC204EF70A00EC089B /* DimensionLayoutAttribute.swift */; }; + 76CA41CF204EF74200EC089B /* SizeLayoutAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76CA41CE204EF74200EC089B /* SizeLayoutAttribute.swift */; }; + 76CA41D1204EF74F00EC089B /* EdgesLayoutAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76CA41D0204EF74F00EC089B /* EdgesLayoutAttribute.swift */; }; + 76CA41D4204EF81000EC089B /* LayoutOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76CA41D3204EF81000EC089B /* LayoutOptions.swift */; }; + 76CA41D6204EF83C00EC089B /* LayoutOptionsForSingleConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76CA41D5204EF83C00EC089B /* LayoutOptionsForSingleConstraint.swift */; }; + 76CA41D8204EF84F00EC089B /* LayoutOptionsForConstraintsOfSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76CA41D7204EF84F00EC089B /* LayoutOptionsForConstraintsOfSize.swift */; }; + 76CA41DA204EF86900EC089B /* LayoutOptionsForConstraintsOfEdges.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76CA41D9204EF86900EC089B /* LayoutOptionsForConstraintsOfEdges.swift */; }; + 76CA4259204F283300EC089B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76CA4258204F283300EC089B /* AppDelegate.swift */; }; + 76CA425B204F283300EC089B /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76CA425A204F283300EC089B /* ViewController.swift */; }; + 76CA4263204F283300EC089B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 76CA4261204F283300EC089B /* LaunchScreen.storyboard */; }; + 76CA4269204F72E000EC089B /* CenterLayoutAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76CA4268204F72E000EC089B /* CenterLayoutAttribute.swift */; }; + 76CA426B204F736F00EC089B /* LayoutOptionsForCenterConstraints.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76CA426A204F736F00EC089B /* LayoutOptionsForCenterConstraints.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 769CC02A204ECA6A009F3445 /* SuperPuperDuperLayout.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SuperPuperDuperLayout.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 769CC036204ECAEA009F3445 /* SuperPuperDuperLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SuperPuperDuperLayout.h; sourceTree = ""; }; + 769CC037204ECAEA009F3445 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 76CA41B3204ED57A00EC089B /* Multiplier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Multiplier.swift; sourceTree = ""; }; + 76CA41B6204ED5B000EC089B /* RelatedElements.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelatedElements.swift; sourceTree = ""; }; + 76CA41BC204ED93100EC089B /* LayoutDescription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutDescription.swift; sourceTree = ""; }; + 76CA41BE204EF52A00EC089B /* Layout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Layout.swift; sourceTree = ""; }; + 76CA41C0204EF56400EC089B /* LayoutFactories.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutFactories.swift; sourceTree = ""; }; + 76CA41C2204EF58200EC089B /* LayoutTraits.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutTraits.swift; sourceTree = ""; }; + 76CA41C8204EF5F100EC089B /* LayoutAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutAttribute.swift; sourceTree = ""; }; + 76CA41CA204EF6F800EC089B /* LayoutAttributeByCoordinateAxes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutAttributeByCoordinateAxes.swift; sourceTree = ""; }; + 76CA41CC204EF70A00EC089B /* DimensionLayoutAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DimensionLayoutAttribute.swift; sourceTree = ""; }; + 76CA41CE204EF74200EC089B /* SizeLayoutAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SizeLayoutAttribute.swift; sourceTree = ""; }; + 76CA41D0204EF74F00EC089B /* EdgesLayoutAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EdgesLayoutAttribute.swift; sourceTree = ""; }; + 76CA41D3204EF81000EC089B /* LayoutOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutOptions.swift; sourceTree = ""; }; + 76CA41D5204EF83C00EC089B /* LayoutOptionsForSingleConstraint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutOptionsForSingleConstraint.swift; sourceTree = ""; }; + 76CA41D7204EF84F00EC089B /* LayoutOptionsForConstraintsOfSize.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutOptionsForConstraintsOfSize.swift; sourceTree = ""; }; + 76CA41D9204EF86900EC089B /* LayoutOptionsForConstraintsOfEdges.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutOptionsForConstraintsOfEdges.swift; sourceTree = ""; }; + 76CA4256204F283300EC089B /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 76CA4258204F283300EC089B /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 76CA425A204F283300EC089B /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 76CA4262204F283300EC089B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 76CA4264204F283300EC089B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 76CA4268204F72E000EC089B /* CenterLayoutAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CenterLayoutAttribute.swift; sourceTree = ""; }; + 76CA426A204F736F00EC089B /* LayoutOptionsForCenterConstraints.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutOptionsForCenterConstraints.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 769CC026204ECA6A009F3445 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 76CA4253204F283300EC089B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 769CC020204ECA6A009F3445 = { + isa = PBXGroup; + children = ( + 769CC035204ECAEA009F3445 /* Other */, + 769CC038204ECAEA009F3445 /* Source */, + 76CA4257204F283300EC089B /* Example */, + 769CC02B204ECA6A009F3445 /* Products */, + ); + sourceTree = ""; + }; + 769CC02B204ECA6A009F3445 /* Products */ = { + isa = PBXGroup; + children = ( + 769CC02A204ECA6A009F3445 /* SuperPuperDuperLayout.framework */, + 76CA4256204F283300EC089B /* Example.app */, + ); + name = Products; + sourceTree = ""; + }; + 769CC035204ECAEA009F3445 /* Other */ = { + isa = PBXGroup; + children = ( + 769CC036204ECAEA009F3445 /* SuperPuperDuperLayout.h */, + 769CC037204ECAEA009F3445 /* Info.plist */, + ); + path = Other; + sourceTree = ""; + }; + 769CC038204ECAEA009F3445 /* Source */ = { + isa = PBXGroup; + children = ( + 76CA41B2204ED52900EC089B /* Misc */, + 76CA41D2204EF80300EC089B /* LayoutOptions */, + 76CA41C7204EF5E900EC089B /* LayoutAttributes */, + 76CA41B6204ED5B000EC089B /* RelatedElements.swift */, + 76CA41BC204ED93100EC089B /* LayoutDescription.swift */, + 76CA41BE204EF52A00EC089B /* Layout.swift */, + 76CA41C0204EF56400EC089B /* LayoutFactories.swift */, + 76CA41C2204EF58200EC089B /* LayoutTraits.swift */, + ); + path = Source; + sourceTree = ""; + }; + 76CA41B2204ED52900EC089B /* Misc */ = { + isa = PBXGroup; + children = ( + 76CA41B3204ED57A00EC089B /* Multiplier.swift */, + ); + path = Misc; + sourceTree = ""; + }; + 76CA41C7204EF5E900EC089B /* LayoutAttributes */ = { + isa = PBXGroup; + children = ( + 76CA41C8204EF5F100EC089B /* LayoutAttribute.swift */, + 76CA41CA204EF6F800EC089B /* LayoutAttributeByCoordinateAxes.swift */, + 76CA41CC204EF70A00EC089B /* DimensionLayoutAttribute.swift */, + 76CA41CE204EF74200EC089B /* SizeLayoutAttribute.swift */, + 76CA41D0204EF74F00EC089B /* EdgesLayoutAttribute.swift */, + 76CA4268204F72E000EC089B /* CenterLayoutAttribute.swift */, + ); + path = LayoutAttributes; + sourceTree = ""; + }; + 76CA41D2204EF80300EC089B /* LayoutOptions */ = { + isa = PBXGroup; + children = ( + 76CA41D3204EF81000EC089B /* LayoutOptions.swift */, + 76CA41D5204EF83C00EC089B /* LayoutOptionsForSingleConstraint.swift */, + 76CA41D7204EF84F00EC089B /* LayoutOptionsForConstraintsOfSize.swift */, + 76CA41D9204EF86900EC089B /* LayoutOptionsForConstraintsOfEdges.swift */, + 76CA426A204F736F00EC089B /* LayoutOptionsForCenterConstraints.swift */, + ); + path = LayoutOptions; + sourceTree = ""; + }; + 76CA4257204F283300EC089B /* Example */ = { + isa = PBXGroup; + children = ( + 76CA4258204F283300EC089B /* AppDelegate.swift */, + 76CA425A204F283300EC089B /* ViewController.swift */, + 76CA4261204F283300EC089B /* LaunchScreen.storyboard */, + 76CA4264204F283300EC089B /* Info.plist */, + ); + path = Example; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 769CC027204ECA6A009F3445 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 769CC039204ECAEA009F3445 /* SuperPuperDuperLayout.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 769CC029204ECA6A009F3445 /* SuperPuperDuperLayout */ = { + isa = PBXNativeTarget; + buildConfigurationList = 769CC032204ECA6A009F3445 /* Build configuration list for PBXNativeTarget "SuperPuperDuperLayout" */; + buildPhases = ( + 769CC025204ECA6A009F3445 /* Sources */, + 769CC026204ECA6A009F3445 /* Frameworks */, + 769CC027204ECA6A009F3445 /* Headers */, + 769CC028204ECA6A009F3445 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SuperPuperDuperLayout; + productName = SuperPuperDuperLayout; + productReference = 769CC02A204ECA6A009F3445 /* SuperPuperDuperLayout.framework */; + productType = "com.apple.product-type.framework"; + }; + 76CA4255204F283300EC089B /* Example */ = { + isa = PBXNativeTarget; + buildConfigurationList = 76CA4267204F283300EC089B /* Build configuration list for PBXNativeTarget "Example" */; + buildPhases = ( + 76CA4252204F283300EC089B /* Sources */, + 76CA4253204F283300EC089B /* Frameworks */, + 76CA4254204F283300EC089B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Example; + productName = Example; + productReference = 76CA4256204F283300EC089B /* Example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 769CC021204ECA6A009F3445 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 0920; + ORGANIZATIONNAME = "Sugar And Candy"; + TargetAttributes = { + 769CC029204ECA6A009F3445 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 0920; + ProvisioningStyle = Automatic; + }; + 76CA4255204F283300EC089B = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 769CC024204ECA6A009F3445 /* Build configuration list for PBXProject "SuperPuperDuperLayout" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 769CC020204ECA6A009F3445; + productRefGroup = 769CC02B204ECA6A009F3445 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 769CC029204ECA6A009F3445 /* SuperPuperDuperLayout */, + 76CA4255204F283300EC089B /* Example */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 769CC028204ECA6A009F3445 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 76CA4254204F283300EC089B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 76CA4263204F283300EC089B /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 769CC025204ECA6A009F3445 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 76CA41D4204EF81000EC089B /* LayoutOptions.swift in Sources */, + 76CA41D8204EF84F00EC089B /* LayoutOptionsForConstraintsOfSize.swift in Sources */, + 76CA41B7204ED5B000EC089B /* RelatedElements.swift in Sources */, + 76CA41D6204EF83C00EC089B /* LayoutOptionsForSingleConstraint.swift in Sources */, + 76CA426B204F736F00EC089B /* LayoutOptionsForCenterConstraints.swift in Sources */, + 76CA41BF204EF52A00EC089B /* Layout.swift in Sources */, + 76CA41C3204EF58200EC089B /* LayoutTraits.swift in Sources */, + 76CA41BD204ED93100EC089B /* LayoutDescription.swift in Sources */, + 76CA41C1204EF56400EC089B /* LayoutFactories.swift in Sources */, + 76CA41CD204EF70A00EC089B /* DimensionLayoutAttribute.swift in Sources */, + 76CA4269204F72E000EC089B /* CenterLayoutAttribute.swift in Sources */, + 76CA41D1204EF74F00EC089B /* EdgesLayoutAttribute.swift in Sources */, + 76CA41B4204ED57A00EC089B /* Multiplier.swift in Sources */, + 76CA41CB204EF6F800EC089B /* LayoutAttributeByCoordinateAxes.swift in Sources */, + 76CA41C9204EF5F100EC089B /* LayoutAttribute.swift in Sources */, + 76CA41DA204EF86900EC089B /* LayoutOptionsForConstraintsOfEdges.swift in Sources */, + 76CA41CF204EF74200EC089B /* SizeLayoutAttribute.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 76CA4252204F283300EC089B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 76CA425B204F283300EC089B /* ViewController.swift in Sources */, + 76CA4259204F283300EC089B /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 76CA4261204F283300EC089B /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 76CA4262204F283300EC089B /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 769CC030204ECA6A009F3445 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 769CC031204ECA6A009F3445 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 769CC033204ECA6A009F3445 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "$(SRCROOT)/Other/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.SuperPuperDuperLayout; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 769CC034204ECA6A009F3445 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "$(SRCROOT)/Other/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.SuperPuperDuperLayout; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 76CA4265204F283300EC089B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = Example/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.SuperPuperDuperLayout; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 76CA4266204F283300EC089B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = Example/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.SuperPuperDuperLayout; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 769CC024204ECA6A009F3445 /* Build configuration list for PBXProject "SuperPuperDuperLayout" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 769CC030204ECA6A009F3445 /* Debug */, + 769CC031204ECA6A009F3445 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 769CC032204ECA6A009F3445 /* Build configuration list for PBXNativeTarget "SuperPuperDuperLayout" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 769CC033204ECA6A009F3445 /* Debug */, + 769CC034204ECA6A009F3445 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 76CA4267204F283300EC089B /* Build configuration list for PBXNativeTarget "Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 76CA4265204F283300EC089B /* Debug */, + 76CA4266204F283300EC089B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 769CC021204ECA6A009F3445 /* Project object */; +}