Commit 492b64fe by Orkhan Alikhanov

Reworked layout system

parent 091d4306
...@@ -174,6 +174,9 @@ ...@@ -174,6 +174,9 @@
9D054A6520D175AC00D0528D /* Material+UIButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D054A6320D175AC00D0528D /* Material+UIButton.swift */; }; 9D054A6520D175AC00D0528D /* Material+UIButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D054A6320D175AC00D0528D /* Material+UIButton.swift */; };
9D054A6620D175AC00D0528D /* Material+UILabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D054A6420D175AC00D0528D /* Material+UILabel.swift */; }; 9D054A6620D175AC00D0528D /* Material+UILabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D054A6420D175AC00D0528D /* Material+UILabel.swift */; };
9D39A81B20FE8ED100BA8FA1 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D39A81A20FE8ED100BA8FA1 /* ViewController.swift */; }; 9D39A81B20FE8ED100BA8FA1 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D39A81A20FE8ED100BA8FA1 /* ViewController.swift */; };
9D494A38217F6B63003D66F1 /* LayoutAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D494A37217F6B63003D66F1 /* LayoutAttribute.swift */; };
9D494A3A217F6B70003D66F1 /* LayoutAnchor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D494A39217F6B70003D66F1 /* LayoutAnchor.swift */; };
9D494A3C217F6B7D003D66F1 /* LayoutConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D494A3B217F6B7D003D66F1 /* LayoutConstraint.swift */; };
9D9089B92118914500605DC9 /* Editor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D9089B82118914500605DC9 /* Editor.swift */; }; 9D9089B92118914500605DC9 /* Editor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D9089B82118914500605DC9 /* Editor.swift */; };
9DE25DE02170D7AF000C04DF /* Dialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DE25DDF2170D7AF000C04DF /* Dialog.swift */; }; 9DE25DE02170D7AF000C04DF /* Dialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DE25DDF2170D7AF000C04DF /* Dialog.swift */; };
9DE25DE22170D7C0000C04DF /* DialogController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DE25DE12170D7C0000C04DF /* DialogController.swift */; }; 9DE25DE22170D7C0000C04DF /* DialogController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DE25DE12170D7C0000C04DF /* DialogController.swift */; };
...@@ -300,6 +303,9 @@ ...@@ -300,6 +303,9 @@
9D054A6320D175AC00D0528D /* Material+UIButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+UIButton.swift"; sourceTree = "<group>"; }; 9D054A6320D175AC00D0528D /* Material+UIButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+UIButton.swift"; sourceTree = "<group>"; };
9D054A6420D175AC00D0528D /* Material+UILabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+UILabel.swift"; sourceTree = "<group>"; }; 9D054A6420D175AC00D0528D /* Material+UILabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+UILabel.swift"; sourceTree = "<group>"; };
9D39A81A20FE8ED100BA8FA1 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; }; 9D39A81A20FE8ED100BA8FA1 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
9D494A37217F6B63003D66F1 /* LayoutAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutAttribute.swift; sourceTree = "<group>"; };
9D494A39217F6B70003D66F1 /* LayoutAnchor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutAnchor.swift; sourceTree = "<group>"; };
9D494A3B217F6B7D003D66F1 /* LayoutConstraint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutConstraint.swift; sourceTree = "<group>"; };
9D9089B82118914500605DC9 /* Editor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Editor.swift; sourceTree = "<group>"; }; 9D9089B82118914500605DC9 /* Editor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Editor.swift; sourceTree = "<group>"; };
9DE25DDF2170D7AF000C04DF /* Dialog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dialog.swift; sourceTree = "<group>"; }; 9DE25DDF2170D7AF000C04DF /* Dialog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dialog.swift; sourceTree = "<group>"; };
9DE25DE12170D7C0000C04DF /* DialogController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DialogController.swift; sourceTree = "<group>"; }; 9DE25DE12170D7C0000C04DF /* DialogController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DialogController.swift; sourceTree = "<group>"; };
...@@ -652,6 +658,9 @@ ...@@ -652,6 +658,9 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
96BCB7811CB40DC500C806FE /* Layout.swift */, 96BCB7811CB40DC500C806FE /* Layout.swift */,
9D494A39217F6B70003D66F1 /* LayoutAnchor.swift */,
9D494A37217F6B63003D66F1 /* LayoutAttribute.swift */,
9D494A3B217F6B7D003D66F1 /* LayoutConstraint.swift */,
); );
name = Layout; name = Layout;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -993,6 +1002,7 @@ ...@@ -993,6 +1002,7 @@
9DF352461FED210000B2A11B /* CheckButton.swift in Sources */, 9DF352461FED210000B2A11B /* CheckButton.swift in Sources */,
965E810A1DD4D5C800D61E4B /* Font.swift in Sources */, 965E810A1DD4D5C800D61E4B /* Font.swift in Sources */,
965E810B1DD4D5C800D61E4B /* RobotoFont.swift in Sources */, 965E810B1DD4D5C800D61E4B /* RobotoFont.swift in Sources */,
9D494A3C217F6B7D003D66F1 /* LayoutConstraint.swift in Sources */,
965E810C1DD4D5C800D61E4B /* DynamicFontType.swift in Sources */, 965E810C1DD4D5C800D61E4B /* DynamicFontType.swift in Sources */,
965E81101DD4D5C800D61E4B /* NavigationBar.swift in Sources */, 965E81101DD4D5C800D61E4B /* NavigationBar.swift in Sources */,
965E81111DD4D5C800D61E4B /* NavigationController.swift in Sources */, 965E81111DD4D5C800D61E4B /* NavigationController.swift in Sources */,
...@@ -1015,6 +1025,7 @@ ...@@ -1015,6 +1025,7 @@
965E81211DD4D5C800D61E4B /* TextStorage.swift in Sources */, 965E81211DD4D5C800D61E4B /* TextStorage.swift in Sources */,
965E81221DD4D5C800D61E4B /* TextView.swift in Sources */, 965E81221DD4D5C800D61E4B /* TextView.swift in Sources */,
965E80E71DD4C55200D61E4B /* Material+UIView.swift in Sources */, 965E80E71DD4C55200D61E4B /* Material+UIView.swift in Sources */,
9D494A38217F6B63003D66F1 /* LayoutAttribute.swift in Sources */,
96B8D22D20CF82D5008BD149 /* FABMenu.swift in Sources */, 96B8D22D20CF82D5008BD149 /* FABMenu.swift in Sources */,
965E80E81DD4C55200D61E4B /* Material+CALayer.swift in Sources */, 965E80E81DD4C55200D61E4B /* Material+CALayer.swift in Sources */,
965E80E91DD4C55200D61E4B /* Material+String.swift in Sources */, 965E80E91DD4C55200D61E4B /* Material+String.swift in Sources */,
...@@ -1054,6 +1065,7 @@ ...@@ -1054,6 +1065,7 @@
965E80D21DD4C50600D61E4B /* Color.swift in Sources */, 965E80D21DD4C50600D61E4B /* Color.swift in Sources */,
96BFC1541E5E486F0075DE1F /* SpringAnimation.swift in Sources */, 96BFC1541E5E486F0075DE1F /* SpringAnimation.swift in Sources */,
9D054A6620D175AC00D0528D /* Material+UILabel.swift in Sources */, 9D054A6620D175AC00D0528D /* Material+UILabel.swift in Sources */,
9D494A3A217F6B70003D66F1 /* LayoutAnchor.swift in Sources */,
965E80D31DD4C50600D61E4B /* Device.swift in Sources */, 965E80D31DD4C50600D61E4B /* Device.swift in Sources */,
965E80FD1DD4D59500D61E4B /* Toolbar.swift in Sources */, 965E80FD1DD4D59500D61E4B /* Toolbar.swift in Sources */,
965E80D41DD4C50600D61E4B /* Divider.swift in Sources */, 965E80D41DD4C50600D61E4B /* Divider.swift in Sources */,
......
/*
* Copyright (C) 2015 - 2018, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of CosmicMind nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import UIKit
public struct LayoutAnchor {
/// A weak reference to the view.
weak var view: UIView?
/// An array of LayoutAttribute for the view.
let attributes: [LayoutAttribute]
/**
An initializer taking view and anchor attributes.
- Parameter view: A UIView.
- Parameter attributes: An array of LayoutAtrribute.
*/
init(view: UIView?, attributes: [LayoutAttribute]) {
self.view = view
self.attributes = attributes
}
}
public extension Layout {
/// A layout anchor representing top of the view.
var top: LayoutAnchor {
return attribute(.top)
}
/// A layout anchor representing bottom of the view.
var bottom: LayoutAnchor {
return attribute(.bottom)
}
/// A layout anchor representing left of the view.
var left: LayoutAnchor {
return attribute(.left)
}
/// A layout anchor representing right of the view.
var right: LayoutAnchor {
return attribute(.right)
}
/// A layout anchor representing top-left of the view.
var topLeft: LayoutAnchor {
return attribute(.topLeft)
}
/// A layout anchor representing top-right of the view.
var topRight: LayoutAnchor {
return attribute(.topRight)
}
/// A layout anchor representing bottom-left of the view.
var bottomLeft: LayoutAnchor {
return attribute(.bottomLeft)
}
/// A layout anchor representing bottom-right of the view.
var bottomRight: LayoutAnchor {
return attribute(.bottomRight)
}
/// A layout anchor representing top and bottom of the view.
var topBottom: LayoutAnchor {
return attribute(.topBottom)
}
/// A layout anchor representing left and right of the view.
var leftRight: LayoutAnchor {
return attribute(.leftRight)
}
/// A layout anchor representing center of the view.
var center: LayoutAnchor {
return attribute(.center)
}
/// A layout anchor representing horizontal center of the view.
var centerX: LayoutAnchor {
return attribute(.centerX)
}
/// A layout anchor representing vertical center of the view.
var centerY: LayoutAnchor {
return attribute(.centerY)
}
/// A layout anchor representing top, left, bottom and right of the view.
var edges: LayoutAnchor {
return attribute(.edges)
}
/// A layout anchor representing width of the view.
var width: LayoutAnchor {
return attribute(.width)
}
/// A layout anchor representing height of the view.
var height: LayoutAnchor {
return attribute(.height)
}
}
private extension Layout {
/**
Creates LayoutAnchor with the given attribute.
- Parameter attribute: A LayoutAttribute.
- Returns: A LayoutAnchor.
*/
func attribute(_ attribute: LayoutAttribute) -> LayoutAnchor {
return LayoutAnchor(view: view, attributes: [attribute])
}
/**
Creates LayoutAnchor with the given attributes.
- Parameter attributes: An array of LayoutAttribute.
- Returns: A LayoutAnchor.
*/
func attribute(_ attributes: [LayoutAttribute]) -> LayoutAnchor {
return LayoutAnchor(view: view, attributes: attributes)
}
}
/*
* Copyright (C) 2015 - 2018, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of CosmicMind nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import UIKit
/// A typealias for NSLayoutConstraint.Attribute
internal typealias LayoutAttribute = NSLayoutConstraint.Attribute
internal extension Array where Element == LayoutAttribute {
/// A LayoutAttribute array containing top and left.
static var topLeft: [LayoutAttribute] {
return [.top, .left]
}
/// A LayoutAttribute array containing top and right.
static var topRight: [LayoutAttribute] {
return [.top, .right]
}
/// A LayoutAttribute array containing bottom and left.
static var bottomLeft: [LayoutAttribute] {
return [.bottom, .left]
}
/// A LayoutAttribute array containing bottom and right.
static var bottomRight: [LayoutAttribute] {
return [.bottom, .right]
}
/// A LayoutAttribute array containing left and right.
static var leftRight: [LayoutAttribute] {
return [.left, .right]
}
/// A LayoutAttribute array containing top and bottom.
static var topBottom: [LayoutAttribute] {
return [.top, .bottom]
}
/// A LayoutAttribute array containing centerX and centerY.
static var center: [LayoutAttribute] {
return [.centerX, .centerY]
}
/// A LayoutAttribute array containing top, left, bottom and right.
static var edges: [LayoutAttribute] {
return [.top, .left, .bottom, .right]
}
/// A LayoutAttribute array for constant height.
static var constantHeight: [LayoutAttribute] {
return [.height, .notAnAttribute]
}
/// A LayoutAttribute array for constant width.
static var constantWidth: [LayoutAttribute] {
return [.width, .notAnAttribute]
}
}
/*
* Copyright (C) 2015 - 2018, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of CosmicMind nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import UIKit
internal struct LayoutConstraint {
/// `From` anchor for the constraint.
private let fromAnchor: LayoutAnchor
/// `To` anchor for the constraint.
private let toAnchor: LayoutAnchor
/// An array of constants for the constraint.
private var constants: [CGFloat]
/**
An initializer taking `from` and `to` anchors and constants for the constraint.
- Parameter fromAnchor: A LayoutAnchor.
- Parameter toAnchor: A LayoutAnchor.
- Parameter constants: An array of CGFloat.
*/
init(fromAnchor: LayoutAnchor, toAnchor: LayoutAnchor, constants: [CGFloat]) {
self.fromAnchor = fromAnchor
self.toAnchor = toAnchor
self.constants = constants
}
}
internal extension LayoutConstraint {
/// Creates an array of NSLayoutConstraint from a LayoutConstraint.
var constraints: [NSLayoutConstraint] {
guard fromAnchor.attributes.count == toAnchor.attributes.count else {
fatalError("[Material Error: The number of attributes of anchors does not match.]")
}
guard fromAnchor.attributes.count == constants.count else {
fatalError("[Material Error: The number of constants does not match the number of constraints.]")
}
var v: [NSLayoutConstraint] = []
zip(zip(fromAnchor.attributes, toAnchor.attributes), constants).forEach {
v.append(NSLayoutConstraint(item: fromAnchor.view as Any,
attribute: $0.0,
relatedBy: .equal,
toItem: toAnchor.view,
attribute: $0.1,
multiplier: 1,
constant: $1))
}
return v
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment