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:
matvii 2019-01-24 15:47:47 +02:00 committed by GitHub
parent 1ec2379b29
commit a33f78ade1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 170 additions and 12 deletions

View File

@ -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)
)),

View File

@ -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

View File

@ -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 */,

View File

@ -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)

View File

@ -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

View File

@ -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
}
}

View File

@ -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)
),
]
)
)
}
}