Implement new width/height constraints (#11)
* Add width/height constraints * Fix height/width constraints * Add OwnConstraint protocol * Add tests for Width/ Height constraints * Move constraints tests to GluonTests folder * Fix Height constraint test * Remove GluonTestRenderer import in Constraints test
This commit is contained in:
parent
1ec2379b29
commit
a33f78ade1
|
@ -156,7 +156,7 @@ struct Counter: LeafComponent {
|
|||
Label.node(.init(alignment: .center), "\(count.value)"),
|
||||
|
||||
Slider.node(.init(
|
||||
Style(.width(Constraint.Size.Attribute.width.equal(to: .parent))),
|
||||
Style(Width.equal(to: .parent)),
|
||||
value: sliding.value,
|
||||
valueHandler: Handler(sliding.set)
|
||||
)),
|
||||
|
|
|
@ -14,9 +14,9 @@ EXTERNAL SOURCES:
|
|||
:path: ".."
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Gluon: 8ef129fb2e2e327cbe9a369b828d9389249a57a0
|
||||
GluonUIKit: 584115b877c27d2b953e465c8bedc81f2eff8195
|
||||
Gluon: 90e9ffe670c2b289f2532df012b1fce70c117537
|
||||
GluonUIKit: ec59ef077207048bffbb3d322fab2918e0f53fe4
|
||||
|
||||
PODFILE CHECKSUM: 506176d9f57e313b696258608414e29b871b813e
|
||||
|
||||
COCOAPODS: 1.6.0.beta.2
|
||||
COCOAPODS: 1.5.3
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
A62891FB21F5DB83001BE090 /* Switch.swift in Sources */ = {isa = PBXBuildFile; fileRef = A62891F721F5DAEE001BE090 /* Switch.swift */; };
|
||||
A62891FF21F5F07F001BE090 /* Stepper.swift in Sources */ = {isa = PBXBuildFile; fileRef = A62891FE21F5F07F001BE090 /* Stepper.swift */; };
|
||||
A628920021F5F0B2001BE090 /* Stepper.swift in Sources */ = {isa = PBXBuildFile; fileRef = A62891FC21F5F075001BE090 /* Stepper.swift */; };
|
||||
A633560521F9CBBC00BCC525 /* ConstraintTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A633560321F9CBAC00BCC525 /* ConstraintTests.swift */; };
|
||||
D126CB7121ECAF850097300E /* Constraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D126CB7021ECAF850097300E /* Constraint.swift */; };
|
||||
D144FB9921E8A56D001020F3 /* ViewControllerBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = D144FB9821E8A56D001020F3 /* ViewControllerBox.swift */; };
|
||||
D163F9D621F27F8C00BA464B /* GluonViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D163F9D521F27F8C00BA464B /* GluonViewController.swift */; };
|
||||
|
@ -140,6 +141,7 @@
|
|||
A62891F921F5DB02001BE090 /* Switch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Switch.swift; sourceTree = "<group>"; };
|
||||
A62891FC21F5F075001BE090 /* Stepper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stepper.swift; sourceTree = "<group>"; };
|
||||
A62891FE21F5F07F001BE090 /* Stepper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stepper.swift; sourceTree = "<group>"; };
|
||||
A633560321F9CBAC00BCC525 /* ConstraintTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConstraintTests.swift; sourceTree = "<group>"; };
|
||||
D126CB7021ECAF850097300E /* Constraint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constraint.swift; sourceTree = "<group>"; };
|
||||
D126CB7221ECE1400097300E /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||
D144FB9821E8A56D001020F3 /* ViewControllerBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewControllerBox.swift; sourceTree = "<group>"; };
|
||||
|
@ -465,6 +467,7 @@
|
|||
OBJ_78 /* GluonTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A633560321F9CBAC00BCC525 /* ConstraintTests.swift */,
|
||||
OBJ_79 /* ReconcilerTests.swift */,
|
||||
OBJ_80 /* XCTestManifests.swift */,
|
||||
D1E8755421EF2ED200D4A7BA /* HooksTests.swift */,
|
||||
|
@ -652,6 +655,7 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 0;
|
||||
files = (
|
||||
A633560521F9CBBC00BCC525 /* ConstraintTests.swift in Sources */,
|
||||
D1E8755521EF2ED200D4A7BA /* HooksTests.swift in Sources */,
|
||||
OBJ_153 /* ReconcilerTests.swift in Sources */,
|
||||
OBJ_154 /* XCTestManifests.swift in Sources */,
|
||||
|
|
|
@ -17,12 +17,69 @@ public struct Edges: Equatable {
|
|||
}
|
||||
}
|
||||
|
||||
public struct Width: Equatable {
|
||||
public let target: Constraint.OwnTarget
|
||||
public let constant: Double
|
||||
public let multiplier: Double
|
||||
|
||||
public static func equal(
|
||||
to target: Constraint.Target,
|
||||
constant: Double = 0,
|
||||
multiplier: Double = 1
|
||||
) -> Constraint {
|
||||
return .width(Width(
|
||||
target: .external(target), constant: constant, multiplier: multiplier
|
||||
))
|
||||
}
|
||||
|
||||
public static func equal(
|
||||
to target: Constraint.OwnTarget,
|
||||
constant: Double = 0,
|
||||
multiplier: Double = 1
|
||||
) -> Constraint {
|
||||
return .width(Width(
|
||||
target: target, constant: constant, multiplier: multiplier
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
public struct Height: Equatable {
|
||||
public let target: Constraint.OwnTarget
|
||||
public let constant: Double
|
||||
public let multiplier: Double
|
||||
|
||||
public static func equal(
|
||||
to target: Constraint.Target,
|
||||
constant: Double = 0,
|
||||
multiplier: Double = 1
|
||||
) -> Constraint {
|
||||
return .height(Height(
|
||||
target: .external(target), constant: constant, multiplier: multiplier
|
||||
))
|
||||
}
|
||||
|
||||
public static func equal(
|
||||
to target: Constraint.OwnTarget,
|
||||
constant: Double = 0,
|
||||
multiplier: Double = 1
|
||||
) -> Constraint {
|
||||
return .height(Height(
|
||||
target: target, constant: constant, multiplier: multiplier
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
public enum Constraint: Equatable {
|
||||
public enum Target {
|
||||
case next
|
||||
case parent
|
||||
}
|
||||
|
||||
public enum OwnTarget: Equatable {
|
||||
case external(Target)
|
||||
case own
|
||||
}
|
||||
|
||||
public struct HorizontalLocation: Equatable {
|
||||
public enum Attribute {
|
||||
case left
|
||||
|
@ -128,8 +185,8 @@ public enum Constraint: Equatable {
|
|||
case centerX(HorizontalLocation)
|
||||
case centerY(VerticalLocation)
|
||||
|
||||
case height(Size)
|
||||
case width(Size)
|
||||
case width(Width)
|
||||
case height(Height)
|
||||
|
||||
case edges(Edges)
|
||||
case leading(HorizontalLocation)
|
||||
|
|
|
@ -14,16 +14,14 @@ extension UIView {
|
|||
next: UIView?
|
||||
) -> [NSLayoutConstraint] {
|
||||
switch prop {
|
||||
case let .height(size):
|
||||
return size.constraint(
|
||||
source: .height,
|
||||
case let .height(height):
|
||||
return height.constraint(
|
||||
current: self,
|
||||
parent: superview,
|
||||
next: next
|
||||
)
|
||||
case let .width(size):
|
||||
return size.constraint(
|
||||
source: .width,
|
||||
case let .width(width):
|
||||
return width.constraint(
|
||||
current: self,
|
||||
parent: superview,
|
||||
next: next
|
||||
|
|
|
@ -53,3 +53,62 @@ extension Constraint.Size {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
protocol OwnConstraint {
|
||||
var firstAnchor: KeyPath<UIView, NSLayoutDimension> { get }
|
||||
var secondAnchor: KeyPath<UIView, NSLayoutDimension> { get }
|
||||
var target: Constraint.OwnTarget { get }
|
||||
var constant: Double { get }
|
||||
var multiplier: Double { get }
|
||||
}
|
||||
|
||||
extension OwnConstraint {
|
||||
func constraint(
|
||||
current: UIView,
|
||||
parent: UIView?,
|
||||
next: UIView?
|
||||
) -> [NSLayoutConstraint] {
|
||||
switch target {
|
||||
case .own:
|
||||
return [current[keyPath: firstAnchor].constraint(
|
||||
equalToConstant: CGFloat(constant)
|
||||
)]
|
||||
case let .external(target):
|
||||
let secondView: UIView?
|
||||
switch target {
|
||||
case .next:
|
||||
secondView = next
|
||||
case .parent:
|
||||
secondView = parent
|
||||
}
|
||||
|
||||
guard let second = secondView?[keyPath: secondAnchor] else { return [] }
|
||||
|
||||
return [current[keyPath: firstAnchor].constraint(
|
||||
equalTo: second,
|
||||
multiplier: CGFloat(multiplier),
|
||||
constant: CGFloat(constant)
|
||||
)]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Height: OwnConstraint {
|
||||
var firstAnchor: KeyPath<UIView, NSLayoutDimension> {
|
||||
return \.heightAnchor
|
||||
}
|
||||
|
||||
var secondAnchor: KeyPath<UIView, NSLayoutDimension> {
|
||||
return \.heightAnchor
|
||||
}
|
||||
}
|
||||
|
||||
extension Width: OwnConstraint {
|
||||
var firstAnchor: KeyPath<UIView, NSLayoutDimension> {
|
||||
return \.widthAnchor
|
||||
}
|
||||
|
||||
var secondAnchor: KeyPath<UIView, NSLayoutDimension> {
|
||||
return \.widthAnchor
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// ConstraintsTests.swift
|
||||
// Gluon
|
||||
//
|
||||
// Created by Matvii Hodovaniuk on 1/24/19.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
@testable import Gluon
|
||||
|
||||
final class ConstraintTests: XCTestCase {
|
||||
func testWidth() {
|
||||
let style = Style(Width.equal(to: .parent))
|
||||
XCTAssertEqual(
|
||||
style.layout,
|
||||
.constraints(
|
||||
[
|
||||
Constraint.width(
|
||||
Width(target: .external(.parent), constant: 0.0, multiplier: 1.0)
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
func testHeight() {
|
||||
let style = Style(Height.equal(to: .parent))
|
||||
XCTAssertEqual(
|
||||
style.layout,
|
||||
.constraints(
|
||||
[
|
||||
Constraint.height(
|
||||
Height(target: .external(.parent), constant: 0.0, multiplier: 1.0)
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue