@@ -43,27 +54,34 @@
[Pin initPinLayout];
[Pin layoutDirection:LayoutDirectionLtr];
Pin.safeAreaInsetsDidChangeMode = PinSafeAreaInsetsDidChangeModeAlways;
- Pin.layoutDirection = LayoutDirectionLtr;
Pin.logWarnings = true;
});
it(@"basic pinlayout calls", ^{
- [[[aView pinObjc] top:10] layout];
+ aView.pinObjc.topValue(10).layout();
expect(@(aView.frame)).to(equal(@(CGRectMake(40, 10, 100, 60))));
});
it(@"using Pin.logMissingLayoutCalls", ^{
Pin.logMissingLayoutCalls = true;
- [[aView pinObjc] top:10];
+ aView.pinObjc.topValue(10);
//expect(Pin.lastWarningText).to(contain(@"PinLayout commands have been issued without calling the 'layout()' method to complete the layout"));
});
it(@"using Pin.logMissingLayoutCalls set to false", ^{
Pin.logMissingLayoutCalls = false;
- [[[aView pinObjc] top:10] layout];
+ aView.pinObjc.topValue(10).layout();
expect(@(aView.frame)).to(equal(@(CGRectMake(40, 10, 100, 60))));
expect(Pin.lastWarningText).to(beNil());
});
+
+ it(@"check the access to PinLayout methods from objective-c", ^{
+ rootView.pinObjc.wrapContent().layout();
+ rootView.pinObjc.wrapContentInsets(UIEdgeInsetsMake(0, 0, 0, 0)).layout();
+ rootView.pinObjc.wrapContentTypeInsets(WrapTypeAll, UIEdgeInsetsMake(0, 0, 0, 0)).layout();
+ rootView.pinObjc.wrapContentPadding(10).layout();
+ rootView.pinObjc.wrapContentTypePadding(WrapTypeHorizontally, 10).layout();
+ });
});
});
diff --git a/Tests/Common/PinEdgesSpec.swift b/Tests/Common/PinEdgesSpec.swift
index 774d7fb6..65085978 100644
--- a/Tests/Common/PinEdgesSpec.swift
+++ b/Tests/Common/PinEdgesSpec.swift
@@ -592,11 +592,11 @@ class PinEdgesSpec: QuickSpec {
}
it("should warn") {
aView.pin.left(10).horizontally(20)
- expect(Pin.lastWarningText).to(contain(["horizontally(20.0) left coordinate", "won't be applied", "already been set to 10"]))
+ expect(Pin.lastWarningText).to(contain(["horizontally(20) left coordinate", "won't be applied", "already been set to 10"]))
}
it("should warn") {
aView.pin.right(10).horizontally(20)
- expect(Pin.lastWarningText).to(contain(["horizontally(20.0) right coordinate", "won't be applied", "already been set to 10"]))
+ expect(Pin.lastWarningText).to(contain(["horizontally(20) right coordinate", "won't be applied", "already been set to 10"]))
}
it("should warn") {
aView.pin.left(10).horizontally(10%)
@@ -658,11 +658,11 @@ class PinEdgesSpec: QuickSpec {
}
it("should warn") {
aView.pin.top(10).vertically(20)
- expect(Pin.lastWarningText).to(contain(["vertically(20.0) top coordinate", "won't be applied", "already been set to 10"]))
+ expect(Pin.lastWarningText).to(contain(["vertically(20) top coordinate", "won't be applied", "already been set to 10"]))
}
it("should warn") {
aView.pin.bottom(10).vertically(20)
- expect(Pin.lastWarningText).to(contain(["vertically(20.0) bottom coordinate", "won't be applied", "already been set to 10"]))
+ expect(Pin.lastWarningText).to(contain(["vertically(20) bottom coordinate", "won't be applied", "already been set to 10"]))
}
it("should warn") {
aView.pin.top(10).vertically(10%)
diff --git a/Tests/Common/PinPointCoordinatesSpec.swift b/Tests/Common/PinPointCoordinatesSpec.swift
index 805b93c8..8cc3c6ac 100644
--- a/Tests/Common/PinPointCoordinatesSpec.swift
+++ b/Tests/Common/PinPointCoordinatesSpec.swift
@@ -123,6 +123,11 @@ class PinPointCoordinatesSpec: QuickSpec {
aView.pin.topLeft()
expect(aView.frame).to(equal(CGRect(x: 0.0, y: 0.0, width: 100.0, height: 60.0)))
}
+
+ it("should position the aView's topLeft corner on its parent's topLeft corner") {
+ aView.pin.topLeft(10)
+ expect(aView.frame).to(equal(CGRect(x: 10.0, y: 10.0, width: 100.0, height: 60.0)))
+ }
it("should position the aViewChild's topLeft corner on the specified view's topLeft corner") {
aViewChild.pin.topLeft(to: aView.anchor.topLeft)
@@ -190,6 +195,11 @@ class PinPointCoordinatesSpec: QuickSpec {
aView.pin.topCenter()
expect(aView.frame).to(equal(CGRect(x: 150.0, y: 0.0, width: 100.0, height: 60.0)))
}
+
+ it("should position the aView's topCenter corner on its parent's topCenter corner") {
+ aView.pin.topCenter(10)
+ expect(aView.frame).to(equal(CGRect(x: 150.0, y: 10.0, width: 100.0, height: 60.0)))
+ }
it("should position the aViewChild's topCenter corner on the specified view's topCenter corner") {
aViewChild.pin.topCenter(to: aView.anchor.topLeft)
@@ -257,6 +267,11 @@ class PinPointCoordinatesSpec: QuickSpec {
aView.pin.topRight()
expect(aView.frame).to(equal(CGRect(x: 300.0, y: 0.0, width: 100.0, height: 60.0)))
}
+
+ it("should position the aView's topRight corner at the specified position") {
+ aView.pin.topRight(10)
+ expect(aView.frame).to(equal(CGRect(x: 290.0, y: 10.0, width: 100.0, height: 60.0)))
+ }
it("should position the aView's topRight corner at the specified position") {
aViewChild.pin.topRight(to: aView.anchor.topLeft)
@@ -319,6 +334,11 @@ class PinPointCoordinatesSpec: QuickSpec {
aView.pin.centerLeft()
expect(aView.frame).to(equal(CGRect(x: 0.0, y: 170.0, width: 100.0, height: 60.0)))
}
+
+ it("should position the aView's centerLeft corner at the specified position") {
+ aView.pin.centerLeft(10)
+ expect(aView.frame).to(equal(CGRect(x: 10.0, y: 170.0, width: 100.0, height: 60.0)))
+ }
it("should position the aView's centerLeft corner at the specified position") {
aViewChild.pin.centerLeft(to: aView.anchor.topLeft)
@@ -386,6 +406,11 @@ class PinPointCoordinatesSpec: QuickSpec {
aView.pin.center()
expect(aView.frame).to(equal(CGRect(x: 150.0, y: 170.0, width: 100.0, height: 60.0)))
}
+
+ it("should position the aView's center corner at the specified position") {
+ aView.pin.center(10)
+ expect(aView.frame).to(equal(CGRect(x: 160.0, y: 180.0, width: 100.0, height: 60.0)))
+ }
it("should position the aView's center corner at the specified position") {
aViewChild.pin.center(to: aView.anchor.topLeft)
@@ -444,6 +469,11 @@ class PinPointCoordinatesSpec: QuickSpec {
expect(aView.frame).to(equal(CGRect(x: 300.0, y: 170.0, width: 100.0, height: 60.0)))
}
+ it("should position the aView's centerRight corner at the specified position") {
+ aView.pin.centerRight(10)
+ expect(aView.frame).to(equal(CGRect(x: 290.0, y: 170.0, width: 100.0, height: 60.0)))
+ }
+
it("should position the aView's centerRight corner at the specified position") {
aViewChild.pin.centerRight(to: aView.anchor.topLeft)
expect(aViewChild.frame).to(equal(CGRect(x: -50.0, y: -15.0, width: 50.0, height: 30.0)))
@@ -501,6 +531,11 @@ class PinPointCoordinatesSpec: QuickSpec {
expect(aView.frame).to(equal(CGRect(x: 0.0, y: 340.0, width: 100.0, height: 60.0)))
}
+ it("should position the aView's bottomLeft corner at the specified position") {
+ aView.pin.bottomLeft(10)
+ expect(aView.frame).to(equal(CGRect(x: 10.0, y: 330.0, width: 100.0, height: 60.0)))
+ }
+
it("should position the aView's bottomLeft corner at the specified position") {
aViewChild.pin.bottomLeft(to: aView.anchor.topLeft)
expect(aViewChild.frame).to(equal(CGRect(x: 0.0, y: -30.0, width: 50.0, height: 30.0)))
@@ -558,6 +593,11 @@ class PinPointCoordinatesSpec: QuickSpec {
expect(aView.frame).to(equal(CGRect(x: 150.0, y: 340.0, width: 100.0, height: 60.0)))
}
+ it("should position the aView's bottomCenter corner at the specified position") {
+ aView.pin.bottomCenter(10)
+ expect(aView.frame).to(equal(CGRect(x: 150.0, y: 330.0, width: 100.0, height: 60.0)))
+ }
+
it("should position the aView's bottomCenter corner at the specified position") {
aViewChild.pin.bottomCenter(to: aView.anchor.topLeft)
expect(aViewChild.frame).to(equal(CGRect(x: -25.0, y: -30.0, width: 50.0, height: 30.0)))
@@ -615,6 +655,11 @@ class PinPointCoordinatesSpec: QuickSpec {
expect(aView.frame).to(equal(CGRect(x: 300.0, y: 340.0, width: 100.0, height: 60.0)))
}
+ it("should position the aView's bottomRight corner at the specified position") {
+ aView.pin.bottomRight(10)
+ expect(aView.frame).to(equal(CGRect(x: 290.0, y: 330.0, width: 100.0, height: 60.0)))
+ }
+
it("should position the aView's bottomRight corner at the specified position") {
aViewChild.pin.bottomRight(to: aView.anchor.topLeft)
expect(aViewChild.frame).to(equal(CGRect(x: -50.0, y: -30.0, width: 50.0, height: 30.0)))
diff --git a/Tests/Common/RTLSpec.swift b/Tests/Common/RTLSpec.swift
index a2e1c8e2..8fd53122 100644
--- a/Tests/Common/RTLSpec.swift
+++ b/Tests/Common/RTLSpec.swift
@@ -626,5 +626,13 @@ class RTLSpec: QuickSpec {
expect(aView.frame).to(equal(CGRect(x: 160.0, y: 200.0, width: 100.0, height: 60.0)))
}
}
+
+ // TODO
+// cView.pin.verticallyBetween(aView, and: bView, aligned: .start)
+// cView.pin.verticallyBetween(bView, and: aView, aligned: .start)
+//
+// cView.pin.verticallyBetween(aView, and: bView, aligned: .end)
+// cView.pin.verticallyBetween(bView, and: aView, aligned: .end)
+
}
}
diff --git a/Tests/Common/RelativePositionMultipleViewsSpec.swift b/Tests/Common/RelativePositionMultipleViewsSpec.swift
index 67229d40..a5e67bc5 100644
--- a/Tests/Common/RelativePositionMultipleViewsSpec.swift
+++ b/Tests/Common/RelativePositionMultipleViewsSpec.swift
@@ -46,8 +46,9 @@ class RelativePositionMultipleViewsSpec: QuickSpec {
*/
beforeEach {
+ _pinlayoutSetUnitTest(scale: 2)
Pin.lastWarningText = nil
-
+
viewController = PViewController()
viewController.view = BasicView()
@@ -71,6 +72,10 @@ class RelativePositionMultipleViewsSpec: QuickSpec {
bViewChild.frame = CGRect(x: 40, y: 10, width: 60, height: 20)
bView.addSubview(bViewChild)
}
+
+ afterEach {
+ _pinlayoutSetUnitTest(scale: nil)
+ }
//
// above(of: UIViews.....) warnings
@@ -80,21 +85,39 @@ class RelativePositionMultipleViewsSpec: QuickSpec {
let unatachedView = PView()
bViewChild.pin.above(of: unatachedView)
expect(bViewChild.frame).to(equal(CGRect(x: 40, y: 10, width: 60, height: 20)))
- expect(Pin.lastWarningText).to(contain(["above", "won't be applied", "no valid references"]))
+ expect(Pin.lastWarningText).to(contain(["above(of: (", ")", "won't be applied",
+ "must be added as a sub-view before being used as a reference."]))
+ }
+
+ it("should warns the view bottom edge") {
+ let unatachedView = PView()
+ bViewChild.pin.above(of: unatachedView, aligned: .left)
+ expect(bViewChild.frame).to(equal(CGRect(x: 40, y: 10, width: 60, height: 20)))
+ expect(Pin.lastWarningText).to(contain(["above(of: ", ", aligned: .left)", "won't be applied",
+ "must be added as a sub-view before being used as a reference."]))
}
it("should warns the view bottom edge") {
let unatachedView = PView()
bViewChild.pin.above(of: [aView, unatachedView])
expect(bViewChild.frame).to(equal(CGRect(x: 40.0, y: -40.0, width: 60.0, height: 20.0)))
- expect(Pin.lastWarningText).to(contain(["above", "won't be applied", "the reference view", "must be added", "as a reference"]))
+ expect(Pin.lastWarningText).to(contain(["above", "won't be applied", "the reference view",
+ "must be added as a sub-view before being used as a reference."]))
}
it("Should warn, but the view should be anyway layout it above") {
let unatachedView = PView()
bViewChild.pin.above(of: [aView, unatachedView])
expect(bViewChild.frame).to(equal(CGRect(x: 40.0, y: -40.0, width: 60.0, height: 20.0)))
- expect(Pin.lastWarningText).to(contain(["above", "won't be applied", "the reference view", "must be added", "as a reference"]))
+ expect(Pin.lastWarningText).to(contain(["above(of: [", "])", "won't be applied",
+ "the reference view", "must be added", "as a reference"]))
+ }
+
+ it("Should warn, but the view should be anyway layout it above") {
+ let unatachedView = PView()
+ bViewChild.pin.above(of: [aView, unatachedView], aligned: .center)
+ expect(bViewChild.frame).to(equal(CGRect(x: -100.0, y: -40.0, width: 60.0, height: 20.0)))
+ expect(Pin.lastWarningText).to(contain(["above(of: [", "], aligned: .center)", "won't be applied", "the reference view", "must be added", "as a reference"]))
}
}
diff --git a/Tests/Common/WarningSpec.swift b/Tests/Common/WarningSpec.swift
index aafecc55..25fadfd3 100644
--- a/Tests/Common/WarningSpec.swift
+++ b/Tests/Common/WarningSpec.swift
@@ -33,11 +33,8 @@ class WarningSpec: QuickSpec {
- aView
*/
- beforeSuite {
- _pinlayoutSetUnitTest(displayScale: 2)
- }
-
beforeEach {
+ _pinlayoutSetUnitTest(scale: 2)
Pin.lastWarningText = nil
viewController = PViewController()
@@ -52,6 +49,10 @@ class WarningSpec: QuickSpec {
aView.sizeThatFitsExpectedArea = 40 * 40
rootView.addSubview(aView)
}
+
+ afterEach {
+ _pinlayoutSetUnitTest(scale: nil)
+ }
//
// pinEdges warnings
diff --git a/Tests/Common/WrapContentSpec.swift b/Tests/Common/WrapContentSpec.swift
new file mode 100644
index 00000000..126c4b54
--- /dev/null
+++ b/Tests/Common/WrapContentSpec.swift
@@ -0,0 +1,377 @@
+// Copyright (c) 2018 Luc Dion
+// 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 Quick
+import Nimble
+import PinLayout
+
+class WrapContentSpec: QuickSpec {
+ override func spec() {
+ var viewController: PViewController!
+ var rootView: BasicView!
+
+ /*
+ root
+ |
+ - aView
+ | |
+ | |- aViewChild
+ |- aViewChild2
+ |- aViewChild3
+ */
+ var aView: BasicView!
+ var aViewChild: BasicView!
+ var aViewChild2: BasicView!
+ var aViewChild3: BasicView!
+
+ beforeEach {
+ _pinlayoutSetUnitTest(scale: 2)
+ Pin.lastWarningText = nil
+
+ viewController = PViewController()
+ viewController.view = BasicView()
+
+ rootView = BasicView()
+ viewController.view.addSubview(rootView)
+
+ aView = BasicView()
+ aView.sizeThatFitsExpectedArea = 40 * 40
+ rootView.addSubview(aView)
+
+ aViewChild = BasicView()
+ aView.addSubview(aViewChild)
+
+ aViewChild2 = BasicView()
+ aView.addSubview(aViewChild2)
+
+ aViewChild3 = BasicView()
+ aView.addSubview(aViewChild3)
+
+ rootView.frame = CGRect(x: 0, y: 100, width: 400, height: 400)
+ }
+
+ afterEach {
+ _pinlayoutSetUnitTest(scale: nil)
+ }
+
+ describe("wrapContent") {
+ it("wrap and update subviews position") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 260, y: 120, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 360, y: 120, width: 60, height: 60)
+
+ aView.pin.wrapContent()
+
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 260.0, height: 60.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 0.0, y: 0.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 100.0, y: 0.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 200.0, y: 0.0, width: 60.0, height: 60.0)))
+ }
+
+ it("wrapContent(.all) should have the same result") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 260, y: 120, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 360, y: 120, width: 60, height: 60)
+
+ aView.pin.wrapContent(.all)
+
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 260.0, height: 60.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 0.0, y: 0.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 100.0, y: 0.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 200.0, y: 0.0, width: 60.0, height: 60.0)))
+ }
+
+ it("wrapContent(.width) + wrapContent(.height) should have the same result") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 260, y: 120, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 360, y: 120, width: 60, height: 60)
+
+ aView.pin.wrapContent(.horizontally)
+ aView.pin.wrapContent(.vertically)
+
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 260.0, height: 60.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 0.0, y: 0.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 100.0, y: 0.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 200.0, y: 0.0, width: 60.0, height: 60.0)))
+ }
+
+ it("wrapContent(.all) and update subviews position") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 260, y: 120, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 360, y: 120, width: 60, height: 60)
+
+ aView.pin.wrapContent(.all)
+
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 260.0, height: 60.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 0.0, y: 0.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 100.0, y: 0.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 200.0, y: 0.0, width: 60.0, height: 60.0)))
+ }
+
+ it("wrapContent(.width) and update subviews position") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 260, y: 120, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 360, y: 120, width: 60, height: 60)
+
+ aView.pin.wrapContent(.horizontally)
+
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 260.0, height: 100.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 0.0, y: 120.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 100.0, y: 120.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 200.0, y: 120.0, width: 60.0, height: 60.0)))
+ }
+ it("wrapContent(.height) and update subviews position") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 260, y: 120, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 360, y: 120, width: 60, height: 60)
+
+ aView.pin.wrapContent(.vertically)
+
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 200.0, height: 60.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 160.0, y: 0.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 260.0, y: 0.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 360.0, y: 0.0, width: 60.0, height: 60.0)))
+ }
+ it("wrap and update subviews position") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 180, y: 140, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 220, y: 180, width: 60, height: 60)
+
+ aView.pin.wrapContent()
+
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 120.0, height: 120.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 0.0, y: 0.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 20.0, y: 20.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 60.0, y: 60.0, width: 60.0, height: 60.0)))
+ }
+
+ it("wrap when views are of size zero") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 0, height: 0)
+ aViewChild2.frame = CGRect(x: 180, y: 140, width: 0, height: 0)
+ aViewChild3.frame = CGRect(x: 220, y: 180, width: 0, height: 0)
+
+ aView.pin.wrapContent()
+
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 60.0, height: 60.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 0.0, y: 0.0, width: 0.0, height: 0.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 20.0, y: 20.0, width: 0.0, height: 0.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 60.0, y: 60.0, width: 0.0, height: 0.0)))
+ }
+
+ it("wrap with subviews with negative position") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: -40, y: -40, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 350, y: 120, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 350, y: -100, width: 60, height: 60)
+
+ aView.pin.wrapContent()
+
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 450.0, height: 280.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 0.0, y: 60.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 390.0, y: 220.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 390.0, y: 0.0, width: 60.0, height: 60.0)))
+ }
+ }
+
+ describe("wrapContent with padding") {
+ it("wrap and update subviews position") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 260, y: 120, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 360, y: 120, width: 60, height: 60)
+
+ aView.pin.wrapContent(padding: 10)
+
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 280.0, height: 80.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 10.0, y: 10.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 110.0, y: 10.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 210.0, y: 10.0, width: 60.0, height: 60.0)))
+
+ }
+ it("wrap and update subviews position + center") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 260, y: 120, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 360, y: 120, width: 60, height: 60)
+
+ aView.pin.wrapContent(padding: 10).center()
+
+ expect(aView.frame).to(equal(CGRect(x: 60.0, y: 160.0, width: 280.0, height: 80.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 10.0, y: 10.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 110.0, y: 10.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 210.0, y: 10.0, width: 60.0, height: 60.0)))
+ }
+
+ it("wrap horizontally + padding") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 260, y: 120, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 360, y: 120, width: 60, height: 60)
+
+ aView.pin.wrapContent(.horizontally, padding: 10)
+
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 280.0, height: 100.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 10.0, y: 120.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 110.0, y: 120.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 210.0, y: 120.0, width: 60.0, height: 60.0)))
+ }
+
+ it("wrap vertically + padding") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 260, y: 120, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 360, y: 140, width: 60, height: 60)
+
+ aView.pin.wrapContent(.vertically, padding: 10)
+
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 200.0, height: 100.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 160.0, y: 10.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 260.0, y: 10.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 360.0, y: 30.0, width: 60.0, height: 60.0)))
+ }
+
+ it("wrap horizontally + negative padding") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 260, y: 120, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 360, y: 160, width: 60, height: 60)
+ aView.pin.wrapContent(.horizontally, padding: -10)
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 240.0, height: 100.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: -10.0, y: 120.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 90.0, y: 120.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 190.0, y: 160.0, width: 60.0, height: 60.0)))
+ }
+
+ it("wrap vertically + negative padding") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 260, y: 120, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 360, y: 160, width: 60, height: 60)
+
+ aView.pin.wrapContent(.vertically, padding: -10)
+
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 200.0, height: 80.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 160.0, y: -10.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 260.0, y: -10.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 360.0, y: 30.0, width: 60.0, height: 60.0)))
+ }
+
+ it("wrap all + padding UIEdgeInsets") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 260, y: 120, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 360, y: 140, width: 60, height: 60)
+ aView.pin.wrapContent(padding: PEdgeInsets(top: 10, left: 20, bottom: 30, right: 40))
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 320.0, height: 120.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 120.0, y: 10.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 220.0, y: 30.0, width: 60.0, height: 60.0)))
+ }
+
+ it("wrap all + padding UIEdgeInsets") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 260, y: 120, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 360, y: 140, width: 60, height: 60)
+ aView.pin.wrapContent(.all, padding: PEdgeInsets(top: 10, left: 20, bottom: 30, right: 40))
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 320.0, height: 120.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 120.0, y: 10.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 220.0, y: 30.0, width: 60.0, height: 60.0)))
+
+ }
+
+ it("wrap horizontally + padding PEdgeInsets") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 260, y: 120, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 360, y: 140, width: 60, height: 60)
+ aView.pin.wrapContent(.horizontally, padding: PEdgeInsets(top: 10, left: 20, bottom: 30, right: 40))
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 320.0, height: 100.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 20.0, y: 120.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 120.0, y: 120.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 220.0, y: 140.0, width: 60.0, height: 60.0)))
+
+ }
+
+ it("wrap vertically + padding PEdgeInsets") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 260, y: 120, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 360, y: 140, width: 60, height: 60)
+ aView.pin.wrapContent(.vertically, padding: PEdgeInsets(top: 10, left: 20, bottom: 30, right: 40))
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 200.0, height: 120.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 160.0, y: 10.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 260.0, y: 10.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 360.0, y: 30.0, width: 60.0, height: 60.0)))
+
+ }
+
+ it("wrap all + negative padding PEdgeInsets") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 260, y: 120, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 360, y: 140, width: 60, height: 60)
+ aView.pin.wrapContent(.all, padding: PEdgeInsets(top: -10, left: -20, bottom: -30, right: -40))
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 200.0, height: 40.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: -20.0, y: -10.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 80.0, y: -10.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 180.0, y: 10.0, width: 60.0, height: 60.0)))
+ }
+ }
+
+ describe("wrapContent + min/max") {
+ it("wrap all + maxWidth + maxHeight") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 260, y: 130, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 360, y: 140, width: 60, height: 60)
+
+ aView.pin.wrapContent().maxWidth(200).maxHeight(50)
+
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 200.0, height: 50.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 0.0, y: 0.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 100.0, y: 10.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 200.0, y: 20.0, width: 60.0, height: 60.0)))
+ }
+
+ it("wrap all + minWidth + minHeight") {
+ aView.frame = CGRect(x: 20, y: 10, width: 200, height: 100)
+ aViewChild.frame = CGRect(x: 160, y: 120, width: 100, height: 40)
+ aViewChild2.frame = CGRect(x: 260, y: 130, width: 60, height: 60)
+ aViewChild3.frame = CGRect(x: 360, y: 140, width: 60, height: 60)
+
+ aView.pin.wrapContent().minWidth(300).minHeight(100)
+
+ expect(aView.frame).to(equal(CGRect(x: 20.0, y: 10.0, width: 300.0, height: 100.0)))
+ expect(aViewChild.frame).to(equal(CGRect(x: 0.0, y: 0.0, width: 100.0, height: 40.0)))
+ expect(aViewChild2.frame).to(equal(CGRect(x: 100.0, y: 10.0, width: 60.0, height: 60.0)))
+ expect(aViewChild3.frame).to(equal(CGRect(x: 200.0, y: 20.0, width: 60.0, height: 60.0)))
+ }
+ }
+ }
+}
diff --git a/Tests/RectNimbleMatcher.swift b/Tests/RectNimbleMatcher.swift
index 10968f76..af174cf3 100644
--- a/Tests/RectNimbleMatcher.swift
+++ b/Tests/RectNimbleMatcher.swift
@@ -23,19 +23,19 @@ public func beCloseTo(_ expectedValue: CGRect, within delta: CGFloat = 0.00001)
let errorMessage = "be close to <\(stringify(expectedValue))> (each within \(stringify(delta)))"
return Predicate.simple(errorMessage) { actualExpression in
if let actual = try actualExpression.evaluate() {
- if fabs(actual.origin.x - expectedValue.origin.x) > delta {
+ if abs(actual.origin.x - expectedValue.origin.x) > delta {
return .doesNotMatch
}
- if fabs(actual.origin.y - expectedValue.origin.y) > delta {
+ if abs(actual.origin.y - expectedValue.origin.y) > delta {
return .doesNotMatch
}
- if fabs(actual.size.width - expectedValue.size.width) > delta {
+ if abs(actual.size.width - expectedValue.size.width) > delta {
return .doesNotMatch
}
- if fabs(actual.size.height - expectedValue.size.height) > delta {
+ if abs(actual.size.height - expectedValue.size.height) > delta {
return .doesNotMatch
}
diff --git a/Tests/UIImage+Color.swift b/Tests/UIImage+Color.swift
index 14fb98b5..be71c723 100644
--- a/Tests/UIImage+Color.swift
+++ b/Tests/UIImage+Color.swift
@@ -17,11 +17,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-
import UIKit
public extension UIImage {
- public convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) {
+ convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) {
let rect = CGRect(origin: .zero, size: size)
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
color.setFill()
diff --git a/Tests/iOS/PinSafeAreaTests.swift b/Tests/iOS/PinSafeAreaTests.swift
index 8858048e..74b11cae 100644
--- a/Tests/iOS/PinSafeAreaTests.swift
+++ b/Tests/iOS/PinSafeAreaTests.swift
@@ -45,6 +45,7 @@ class PinSafeAreaSpec: QuickSpec {
window = UIWindow()
window.rootViewController = viewController
window.addSubview(viewController.view)
+ window.makeKeyAndVisible();
// Testing UIViewController's layout methods is kind of bad
// but needed in our case so we need to wait some time
@@ -54,29 +55,29 @@ class PinSafeAreaSpec: QuickSpec {
describe("using opaque NavigationBar") {
it("testOpaqueNavigationBar") {
let mainView = viewController.mainView
+ mainView.layoutOffsetViewClosure = { _, _ in }
+ navigationController.navigationBar.isTranslucent = true
+
+ setupWindow(with: navigationController)
+ let safeAreaInsetsWhenTranslucent = mainView.safeAreaInsets
+ let screenSizeWhenTranslucent = mainView.frame.size
mainView.layoutOffsetViewClosure = { (_ offsetView: UIView, _ parent: UIView) in
offsetView.pin.top(10).width(100).height(100)
}
- navigationController.navigationBar.barStyle = .blackOpaque
navigationController.navigationBar.isTranslucent = false
setupWindow(with: navigationController)
-
- let expectedSafeAreaInsets = UIEdgeInsets.zero
+
+ let expectedSafeAreaInsets = mainView.safeAreaInsets
let expectedOffsetViewSafeAreaInsets = UIEdgeInsets.zero
- if #available(iOS 11.0, tvOS 11.0, *) {
- expect(viewController.view.safeAreaInsets).to(equal(expectedSafeAreaInsets))
- expect(mainView.offsetView.safeAreaInsets).to(equal(expectedOffsetViewSafeAreaInsets))
- }
-
expect(mainView.pin.safeArea).to(equal(expectedSafeAreaInsets))
expect(mainView.offsetView.pin.safeArea).to(equal(expectedOffsetViewSafeAreaInsets))
- expect(mainView.safeAreaInsetsDidChangeCalledCount).to(equal(0))
+ expect(mainView.safeAreaInsetsDidChangeCalledCount) > 0
let screenSize = mainView.frame.size
- expect(mainView.frame).to(equal(CGRect(x: 0, y: 44, width: screenSize.width, height: screenSize.height)))
+ expect(mainView.frame).to(equal(CGRect(x: 0, y: safeAreaInsetsWhenTranslucent.top, width: screenSize.width, height: screenSizeWhenTranslucent.height - safeAreaInsetsWhenTranslucent.top)))
expect(mainView.offsetView.frame).to(equal(CGRect(x: 0, y: 10, width: 100, height: 100)))
}
}
@@ -84,100 +85,78 @@ class PinSafeAreaSpec: QuickSpec {
describe("using translucent NavigationBar") {
it("default") {
let mainView = viewController.mainView
- var expectedSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 1 } else { return 3 }
- }
mainView.layoutOffsetViewClosure = { (_ offsetView: UIView, _ parent: UIView) in
offsetView.pin.all().margin(parent.pin.safeArea)
}
- let expectedSafeAreaInsets = UIEdgeInsets(top: 44, left: 0, bottom: 0, right: 0)
- let expectedOffsetViewSafeAreaInsets = UIEdgeInsets.zero
-
- navigationController.navigationBar.barStyle = .blackTranslucent
+ navigationController.navigationBar.isTranslucent = true
setupWindow(with: navigationController)
- if #available(iOS 11.0, tvOS 11.0, *) {
- XCTAssertEqual(viewController.view.safeAreaInsets, expectedSafeAreaInsets)
- XCTAssertEqual(mainView.offsetView.safeAreaInsets, expectedOffsetViewSafeAreaInsets)
- }
+ let expectedSafeAreaInsets = mainView.safeAreaInsets
+ let expectedOffsetViewSafeAreaInsets = UIEdgeInsets.zero
+
XCTAssertEqual(mainView.pin.safeArea, expectedSafeAreaInsets)
XCTAssertEqual(mainView.offsetView.pin.safeArea, expectedOffsetViewSafeAreaInsets)
- expect(mainView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSafeAreaInsetsDidChangeCalledCount))
-
+ expect(mainView.safeAreaInsetsDidChangeCalledCount) > 0
+
let screenSize = mainView.frame.size
XCTAssertEqual(mainView.frame, CGRect(x: 0, y: 0, width: screenSize.width, height: screenSize.height))
- XCTAssertEqual(mainView.offsetView.frame, CGRect(x: 0, y: 44, width: screenSize.width, height: screenSize.height - 44))
+ XCTAssertEqual(mainView.offsetView.frame, CGRect(x: 0, y: expectedSafeAreaInsets.top, width: screenSize.width, height: screenSize.height - (expectedSafeAreaInsets.top + expectedSafeAreaInsets.bottom)))
}
it("with OffsetView") {
+ let offsetViewTop = CGFloat(10)
let mainView = viewController.mainView
- var expectedSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 1 } else { return 3 }
- }
mainView.layoutOffsetViewClosure = { (_ offsetView: UIView, _ parent: UIView) in
- offsetView.pin.top(10).width(100).height(100)
+ offsetView.pin.top(offsetViewTop).width(100).height(100)
}
- let expectedSafeAreaInsets = UIEdgeInsets(top: 44, left: 0, bottom: 0, right: 0)
- let expectedOffsetViewSafeAreaInsets = UIEdgeInsets(top: 34, left: 0, bottom: 0, right: 0)
-
- navigationController.navigationBar.barStyle = .blackTranslucent
+ navigationController.navigationBar.isTranslucent = true
setupWindow(with: navigationController)
+
+ let expectedSafeAreaInsets = mainView.safeAreaInsets
+ let expectedOffsetViewSafeAreaInsets = UIEdgeInsets(
+ top: mainView.safeAreaInsets.top - offsetViewTop,
+ left: .zero,
+ bottom: .zero,
+ right: .zero
+ )
- if #available(iOS 11.0, tvOS 11.0, *) {
- XCTAssertEqual(viewController.view.safeAreaInsets, expectedSafeAreaInsets)
- XCTAssertEqual(mainView.offsetView.safeAreaInsets, expectedOffsetViewSafeAreaInsets)
- }
XCTAssertEqual(mainView.pin.safeArea, expectedSafeAreaInsets)
XCTAssertEqual(mainView.offsetView.pin.safeArea, expectedOffsetViewSafeAreaInsets)
let screenSize = mainView.frame.size
XCTAssertEqual(mainView.frame, CGRect(x: 0, y: 0, width: screenSize.width, height: screenSize.height))
- XCTAssertEqual(mainView.offsetView.frame, CGRect(x: 0, y: 10, width: 100, height: 100))
- expect(mainView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSafeAreaInsetsDidChangeCalledCount))
+ XCTAssertEqual(mainView.offsetView.frame, CGRect(x: 0, y: offsetViewTop, width: 100, height: 100))
+ expect(mainView.safeAreaInsetsDidChangeCalledCount) > 0
}
it("with OffsetView and AdditionalSafeAreaInsets") {
let mainView = viewController.mainView
- var expectedSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 2 } else { return 3 }
- }
mainView.layoutOffsetViewClosure = { (_ offsetView: UIView, _ parent: UIView) in
offsetView.pin.all().margin(parent.pin.safeArea)
}
- navigationController.navigationBar.barStyle = .blackTranslucent
+ navigationController.navigationBar.isTranslucent = true
+ viewController.additionalSafeAreaInsets = UIEdgeInsets(top: 10, left: 10, bottom: 30, right: 0)
setupWindow(with: navigationController)
- let expectedSafeAreaInsets: UIEdgeInsets
- let expectedOffsetViewSafeAreaInsets: UIEdgeInsets
- let expectedOffsetViewFrame: CGRect
let screenSize = mainView.frame.size
+ let expectedSafeAreaInsets = mainView.safeAreaInsets
+ let expectedOffsetViewSafeAreaInsets = UIEdgeInsets.zero
+ let expectedOffsetViewFrame = CGRect(
+ x: expectedSafeAreaInsets.left,
+ y: expectedSafeAreaInsets.top,
+ width: screenSize.width - (expectedSafeAreaInsets.left + expectedSafeAreaInsets.right),
+ height: screenSize.height - (expectedSafeAreaInsets.top + expectedSafeAreaInsets.bottom)
+ )
- if #available(iOS 11.0, tvOS 11.0, *) {
- viewController.additionalSafeAreaInsets = UIEdgeInsets(top: 10, left: 10, bottom: 30, right: 0)
- expectedSafeAreaInsets = UIEdgeInsets(top: 54, left: 10, bottom: 30, right: 0)
- expectedOffsetViewSafeAreaInsets = UIEdgeInsets.zero
- expectedOffsetViewFrame = CGRect(x: 0, y: 44, width: screenSize.width,
- height: screenSize.height - 44)
- } else {
- expectedSafeAreaInsets = UIEdgeInsets(top: 44, left: 0, bottom: 0, right: 0)
- expectedOffsetViewSafeAreaInsets = UIEdgeInsets.zero
- expectedOffsetViewFrame = CGRect(x: 0, y: 44, width: screenSize.width,
- height: screenSize.height - expectedSafeAreaInsets.top)
- }
-
- if #available(iOS 11.0, tvOS 11.0, *) {
- XCTAssertEqual(viewController.view.safeAreaInsets, expectedSafeAreaInsets)
- XCTAssertEqual(mainView.offsetView.safeAreaInsets, expectedOffsetViewSafeAreaInsets)
- }
XCTAssertEqual(mainView.pin.safeArea, expectedSafeAreaInsets)
XCTAssertEqual(mainView.offsetView.pin.safeArea, expectedOffsetViewSafeAreaInsets)
- expect(mainView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSafeAreaInsetsDidChangeCalledCount))
+ expect(mainView.safeAreaInsetsDidChangeCalledCount) > 0
XCTAssertEqual(mainView.frame, CGRect(x: 0, y: 0, width: screenSize.width, height: screenSize.height))
XCTAssertEqual(mainView.offsetView.frame, expectedOffsetViewFrame)
@@ -185,34 +164,29 @@ class PinSafeAreaSpec: QuickSpec {
it("with OffsetView and AdditionalSafeAreaInsets 2") {
let mainView = viewController.mainView
- var expectedSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 1 } else { return 3 }
- }
+ let offsetViewTop = CGFloat(10)
mainView.layoutOffsetViewClosure = { (_ offsetView: UIView, _ parent: UIView) in
- offsetView.pin.top(10).width(100).height(100)
+ offsetView.pin.top(offsetViewTop).width(100).height(100)
}
- let expectedSafeAreaInsets: UIEdgeInsets
- let expectedOffsetViewSafeAreaInsets: UIEdgeInsets
- if #available(iOS 11.0, tvOS 11.0, *) {
- viewController.additionalSafeAreaInsets = UIEdgeInsets(top: 10, left: 10, bottom: 30, right: 0)
- expectedSafeAreaInsets = UIEdgeInsets(top: 54, left: 10, bottom: 30, right: 0)
- expectedOffsetViewSafeAreaInsets = UIEdgeInsets(top: 44, left: 10, bottom: 0, right: 0)
- } else {
- expectedSafeAreaInsets = UIEdgeInsets(top: 44, left: 0, bottom: 0, right: 0)
- expectedOffsetViewSafeAreaInsets = UIEdgeInsets(top: 34, left: 0, bottom: 0, right: 0)
- }
- navigationController.navigationBar.barStyle = .blackTranslucent
+ navigationController.navigationBar.isTranslucent = true
setupWindow(with: navigationController)
-
- if #available(iOS 11.0, tvOS 11.0, *) {
- XCTAssertEqual(viewController.view.safeAreaInsets, expectedSafeAreaInsets)
- XCTAssertEqual(mainView.offsetView.safeAreaInsets, expectedOffsetViewSafeAreaInsets)
- }
+
+ let expectedSafeAreaInsets = mainView.safeAreaInsets
+ let expectedOffsetViewSafeAreaInsets = UIEdgeInsets(
+ top: expectedSafeAreaInsets.top - offsetViewTop,
+ left: .zero,
+ bottom: .zero,
+ right: .zero
+ )
+
+ XCTAssertEqual(viewController.view.safeAreaInsets, expectedSafeAreaInsets)
+ XCTAssertEqual(mainView.offsetView.safeAreaInsets, expectedOffsetViewSafeAreaInsets)
+
XCTAssertEqual(mainView.pin.safeArea, expectedSafeAreaInsets)
XCTAssertEqual(mainView.offsetView.pin.safeArea, expectedOffsetViewSafeAreaInsets)
- expect(mainView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSafeAreaInsetsDidChangeCalledCount))
+ expect(mainView.safeAreaInsetsDidChangeCalledCount) > 0
}
}
}
@@ -277,6 +251,7 @@ class PinSafeAreaMoreTestsSpec: QuickSpec {
window = UIWindow()
window.rootViewController = viewController
window.addSubview(viewController.view)
+ window.makeKeyAndVisible();
// Testing UIViewController's layout methods is kind of bad
// but needed in our case so we need to wait some time
@@ -286,144 +261,163 @@ class PinSafeAreaMoreTestsSpec: QuickSpec {
describe("navigationbar + subview") {
it("transluscent navigationbar 1") {
let mainView = viewController.mainView
- var expectedSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 1 } else { return 3 }
- }
- var expectedSubViewSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 1 } else { return 2 }
- }
-
+ let subViewTop = CGFloat(10)
+
mainView.layoutOffsetViewClosure = { (_ subView: UIView, _ parent: UIView) in
- subView.pin.top(10).left(10).size(100)
+ subView.pin.top(subViewTop).left(10).size(100)
}
- navigationController.navigationBar.barStyle = .blackTranslucent
+ navigationController.navigationBar.isTranslucent = true
setupWindow(with: navigationController)
+
+ let expectedSafeAreaInsets = mainView.safeAreaInsets
+ let expectedSubViewSafeAreaInsets = UIEdgeInsets(
+ top: expectedSafeAreaInsets.top - subViewTop,
+ left: .zero,
+ bottom: .zero,
+ right: .zero
+ )
// MATCH safeAreaInsets!
- expect(mainView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSafeAreaInsetsDidChangeCalledCount))
- expect(mainView.subView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSubViewSafeAreaInsetsDidChangeCalledCount))
+ expect(mainView.safeAreaInsetsDidChangeCalledCount) > 0
+ expect(mainView.subView.safeAreaInsetsDidChangeCalledCount) > 0
- expect(mainView.pin.safeArea).to(equal(UIEdgeInsets(top: 44.0, left: 0.0, bottom: 0.0, right: 0.0)))
- expect(mainView.subView.pin.safeArea).to(equal(UIEdgeInsets(top: 34.0, left: 0.0, bottom: 0.0, right: 0.0)))
+ expect(mainView.pin.safeArea).to(equal(expectedSafeAreaInsets))
+ expect(mainView.subView.pin.safeArea).to(equal(expectedSubViewSafeAreaInsets))
expect(mainView.subView.subViewB!.pin.safeArea).to(equal(UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)))
expect(mainView.subView.frame).to(equal(CGRect(x: 10, y: 10, width: 100, height: 100)))
- expect(mainView.subView.subViewB!.frame).to(equal(CGRect(x: 0, y: 34, width: 40, height: 40)))
+ expect(mainView.subView.subViewB!.frame).to(equal(CGRect(x: 0, y: expectedSubViewSafeAreaInsets.top, width: 40, height: 40)))
}
it("transluscent navigationbar 2") {
let mainView = viewController.mainView
- var expectedSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 1 } else { return 3 }
- }
- var expectedSubViewSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 1 } else { return 2 }
- }
+ let subViewTop = CGFloat(10)
+ let subViewLeft = CGFloat(-10)
mainView.layoutOffsetViewClosure = { (_ subView: UIView, _ parent: UIView) in
- subView.pin.top(10).left(-10).size(100)
+ subView.pin.top(subViewTop).left(subViewLeft).size(100)
}
- navigationController.navigationBar.barStyle = .blackTranslucent
+ navigationController.navigationBar.isTranslucent = true
setupWindow(with: navigationController)
+
+ let expectedSafeAreaInsets = mainView.safeAreaInsets
+ let expectedSubViewSafeAreaInsets = UIEdgeInsets(
+ top: expectedSafeAreaInsets.top - subViewTop,
+ left: .zero,
+ bottom: .zero,
+ right: .zero
+ )
// MATCH safeAreaInsets!
- expect(mainView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSafeAreaInsetsDidChangeCalledCount))
- expect(mainView.subView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSubViewSafeAreaInsetsDidChangeCalledCount))
+ expect(mainView.safeAreaInsetsDidChangeCalledCount) > 0
+ expect(mainView.subView.safeAreaInsetsDidChangeCalledCount) > 0
- expect(mainView.pin.safeArea).to(equal(UIEdgeInsets(top: 44.0, left: 0.0, bottom: 0.0, right: 0.0)))
- expect(mainView.subView.pin.safeArea).to(equal(UIEdgeInsets(top: 34.0, left: 0.0, bottom: 0.0, right: 0.0)))
+ expect(mainView.pin.safeArea).to(equal(expectedSafeAreaInsets))
+ expect(mainView.subView.pin.safeArea).to(equal(expectedSubViewSafeAreaInsets))
expect(mainView.subView.subViewB!.pin.safeArea).to(equal(UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)))
- expect(mainView.subView.frame).to(equal(CGRect(x: -10, y: 10, width: 100, height: 100)))
- expect(mainView.subView.subViewB!.frame).to(equal(CGRect(x: 0, y: 34, width: 40, height: 40)))
+ expect(mainView.subView.frame).to(equal(CGRect(x: subViewLeft, y: subViewTop, width: 100, height: 100)))
+ expect(mainView.subView.subViewB!.frame).to(equal(CGRect(x: 0, y: expectedSubViewSafeAreaInsets.top, width: 40, height: 40)))
}
it("transluscent navigationbar 3") {
let mainView = viewController.mainView
- var expectedSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 1 } else { return 3 }
- }
- var expectedSubViewSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 1 } else { return 2 }
- }
+ let subViewTop = CGFloat(10)
+ let subViewRight = CGFloat(10)
mainView.layoutOffsetViewClosure = { (_ subView: UIView, _ parent: UIView) in
- subView.pin.top(10).right(10).size(100)
+ subView.pin.top(subViewTop).right(subViewRight).size(100)
}
- navigationController.navigationBar.barStyle = .blackTranslucent
+ navigationController.navigationBar.isTranslucent = true
setupWindow(with: navigationController)
+
+ let expectedSafeAreaInsets = mainView.safeAreaInsets
+ let expectedSubViewSafeAreaInsets = UIEdgeInsets(
+ top: expectedSafeAreaInsets.top - subViewTop,
+ left: .zero,
+ bottom: .zero,
+ right: .zero
+ )
// MATCH safeAreaInsets!
- expect(mainView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSafeAreaInsetsDidChangeCalledCount))
- expect(mainView.subView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSubViewSafeAreaInsetsDidChangeCalledCount))
+ expect(mainView.safeAreaInsetsDidChangeCalledCount) > 0
+ expect(mainView.subView.safeAreaInsetsDidChangeCalledCount) > 0
- expect(mainView.pin.safeArea).to(equal(UIEdgeInsets(top: 44.0, left: 0.0, bottom: 0.0, right: 0.0)))
- expect(mainView.subView.pin.safeArea).to(equal(UIEdgeInsets(top: 34.0, left: 0.0, bottom: 0.0, right: 0.0)))
+ expect(mainView.pin.safeArea).to(equal(expectedSafeAreaInsets))
+ expect(mainView.subView.pin.safeArea).to(equal(expectedSubViewSafeAreaInsets))
expect(mainView.subView.subViewB!.pin.safeArea).to(equal(UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)))
let screenSize = mainView.frame.size
- expect(mainView.subView.frame).to(equal(CGRect(x: screenSize.width - 100 - 10, y: 10, width: 100, height: 100)))
- expect(mainView.subView.subViewB!.frame).to(equal(CGRect(x: 0, y: 34, width: 40, height: 40)))
+ expect(mainView.subView.frame).to(equal(CGRect(x: screenSize.width - 100 - subViewRight, y: subViewTop, width: 100, height: 100)))
+ expect(mainView.subView.subViewB!.frame).to(equal(CGRect(x: 0, y: expectedSubViewSafeAreaInsets.top, width: 40, height: 40)))
}
it("transluscent navigationbar 4") {
let mainView = viewController.mainView
- var expectedSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 1 } else { return 3 }
- }
- var expectedSubViewSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 1 } else { return 2 }
- }
-
+ let subViewTop = CGFloat(10)
+ let subViewRight = CGFloat(-10)
+
mainView.layoutOffsetViewClosure = { (_ subView: UIView, _ parent: UIView) in
- subView.pin.top(10).right(-10).size(100)
+ subView.pin.top(subViewTop).right(subViewRight).size(100)
}
- navigationController.navigationBar.barStyle = .blackTranslucent
+ navigationController.navigationBar.isTranslucent = true
setupWindow(with: navigationController)
+
+ let expectedSafeAreaInsets = mainView.safeAreaInsets
+ let expectedSubViewSafeAreaInsets = UIEdgeInsets(
+ top: expectedSafeAreaInsets.top - subViewTop,
+ left: .zero,
+ bottom: .zero,
+ right: .zero
+ )
// MATCH safeAreaInsets!
- expect(mainView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSafeAreaInsetsDidChangeCalledCount))
- expect(mainView.subView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSubViewSafeAreaInsetsDidChangeCalledCount))
+ expect(mainView.safeAreaInsetsDidChangeCalledCount) > 0
+ expect(mainView.subView.safeAreaInsetsDidChangeCalledCount) > 0
- expect(mainView.pin.safeArea).to(equal(UIEdgeInsets(top: 44.0, left: 0.0, bottom: 0.0, right: 0.0)))
- expect(mainView.subView.pin.safeArea).to(equal(UIEdgeInsets(top: 34.0, left: 0.0, bottom: 0.0, right: 0.0)))
+ expect(mainView.pin.safeArea).to(equal(expectedSafeAreaInsets))
+ expect(mainView.subView.pin.safeArea).to(equal(expectedSubViewSafeAreaInsets))
expect(mainView.subView.subViewB!.pin.safeArea).to(equal(UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)))
let screenSize = mainView.frame.size
- expect(mainView.subView.frame).to(equal(CGRect(x: screenSize.width - 100 + 10, y: 10, width: 100, height: 100)))
- expect(mainView.subView.subViewB!.frame).to(equal(CGRect(x: 0, y: 34, width: 40, height: 40)))
+ expect(mainView.subView.frame).to(equal(CGRect(x: screenSize.width - 100 - subViewRight, y: subViewTop, width: 100, height: 100)))
+ expect(mainView.subView.subViewB!.frame).to(equal(CGRect(x: 0, y: expectedSubViewSafeAreaInsets.top, width: 40, height: 40)))
}
it("transluscent navigationbar 5") {
let mainView = viewController.mainView
- var expectedSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 1 } else { return 3 }
- }
- var expectedSubViewSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 2 } else { return 1 }
- }
-
+ let subViewTop = CGFloat(-20)
+ let subViewLeft = CGFloat(-10)
+
mainView.layoutOffsetViewClosure = { (_ subView: UIView, _ parent: UIView) in
- subView.pin.top(-20).left(-10).size(100)
+ subView.pin.top(subViewTop).left(subViewLeft).size(100)
}
- navigationController.navigationBar.barStyle = .blackTranslucent
+ navigationController.navigationBar.isTranslucent = true
setupWindow(with: navigationController)
+
+ let expectedSafeAreaInsets = mainView.safeAreaInsets
+ let expectedSubViewSafeAreaInsets = UIEdgeInsets(
+ top: expectedSafeAreaInsets.top,
+ left: .zero,
+ bottom: .zero,
+ right: .zero
+ )
// MATCH safeAreaInsets!
- expect(mainView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSafeAreaInsetsDidChangeCalledCount))
- expect(mainView.subView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSubViewSafeAreaInsetsDidChangeCalledCount))
+ expect(mainView.safeAreaInsetsDidChangeCalledCount) > 0
+ expect(mainView.subView.safeAreaInsetsDidChangeCalledCount) > 0
- expect(mainView.pin.safeArea).to(equal(UIEdgeInsets(top: 44.0, left: 0.0, bottom: 0.0, right: 0.0)))
- expect(mainView.subView.pin.safeArea).to(equal(UIEdgeInsets(top: 44.0, left: 0.0, bottom: 0.0, right: 0.0)))
+ expect(mainView.pin.safeArea).to(equal(expectedSafeAreaInsets))
+ expect(mainView.subView.pin.safeArea).to(equal(expectedSubViewSafeAreaInsets))
expect(mainView.subView.subViewB!.pin.safeArea).to(equal(UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)))
- expect(mainView.subView.frame).to(equal(CGRect(x: -10, y: -20, width: 100, height: 100)))
- expect(mainView.subView.subViewB!.frame).to(equal(CGRect(x: 0, y: 44, width: 40, height: 40)))
+ expect(mainView.subView.frame).to(equal(CGRect(x: subViewLeft, y: subViewTop, width: 100, height: 100)))
+ expect(mainView.subView.subViewB!.frame).to(equal(CGRect(x: 0, y: expectedSubViewSafeAreaInsets.top, width: 40, height: 40)))
}
}
}
@@ -436,11 +430,13 @@ class PinSafeAreaWithOptInModeSpec: QuickSpec {
var window: UIWindow!
beforeEach {
+ Pin.safeAreaInsetsDidChangeMode = .optIn
viewController = TestViewController2()
navigationController = UINavigationController(rootViewController: viewController)
}
afterEach {
+ Pin.safeAreaInsetsDidChangeMode = .disable
viewController = nil
navigationController = nil
window = nil
@@ -450,6 +446,7 @@ class PinSafeAreaWithOptInModeSpec: QuickSpec {
window = UIWindow()
window.rootViewController = viewController
window.addSubview(viewController.view)
+ window.makeKeyAndVisible();
// Testing UIViewController's layout methods is kind of bad
// but needed in our case so we need to wait some time
@@ -459,30 +456,45 @@ class PinSafeAreaWithOptInModeSpec: QuickSpec {
describe("using Pin.safeAreaInsetsDidChangeMode = .optIn") {
it("should not call safeAreaInsetsDidChange()") {
let mainView = viewController.mainView
- var expectedSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 1 } else { return 0 }
- }
- var expectedSubViewSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 1 } else { return 0 }
- }
+ let subViewTop = CGFloat(10)
+ let subViewLeft = CGFloat(10)
mainView.layoutOffsetViewClosure = { (_ subView: UIView, _ parent: UIView) in
- subView.pin.top(10).left(10).size(100)
+ subView.pin.top(subViewTop).left(subViewLeft).size(100)
}
- navigationController.navigationBar.barStyle = .blackTranslucent
+ navigationController.navigationBar.isTranslucent = true
setupWindow(with: navigationController)
-
+
+ let expectedSafeAreaInsets = mainView.safeAreaInsets
+ let expectedSubViewSafeAreaInsets = UIEdgeInsets(
+ top: expectedSafeAreaInsets.top - subViewTop,
+ left: .zero,
+ bottom: .zero,
+ right: .zero
+ )
+
// MATCH safeAreaInsets!
- expect(mainView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSafeAreaInsetsDidChangeCalledCount))
- expect(mainView.subView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSubViewSafeAreaInsetsDidChangeCalledCount))
+ if #available(iOS 11.0, tvOS 11.0, *) {
+ expect(mainView.safeAreaInsetsDidChangeCalledCount) > 0
+ expect(mainView.subView.safeAreaInsetsDidChangeCalledCount) > 0
+ } else {
+ // Should equal 0, because in optIn mode 'safeAreaInsetsDidChange' is called
+ // only if the UIView implement the PinSafeAreaInsetsUpdate protocol. Which is
+ // not the case with TestView2.
+ expect(mainView.safeAreaInsetsDidChangeCalledCount) == 0
+ expect(mainView.subView.safeAreaInsetsDidChangeCalledCount) == 0
+ }
- expect(mainView.pin.safeArea).to(equal(UIEdgeInsets(top: 44.0, left: 0.0, bottom: 0.0, right: 0.0)))
- expect(mainView.subView.pin.safeArea).to(equal(UIEdgeInsets(top: 34.0, left: 0.0, bottom: 0.0, right: 0.0)))
+ expect(mainView.safeAreaInsetsDidChangeCalledCount) > 0
+ expect(mainView.subView.safeAreaInsetsDidChangeCalledCount) > 0
+
+ expect(mainView.pin.safeArea).to(equal(expectedSafeAreaInsets))
+ expect(mainView.subView.pin.safeArea).to(equal(expectedSubViewSafeAreaInsets))
expect(mainView.subView.subViewB!.pin.safeArea).to(equal(UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)))
- expect(mainView.subView.frame).to(equal(CGRect(x: 10, y: 10, width: 100, height: 100)))
- expect(mainView.subView.subViewB!.frame).to(equal(CGRect(x: 0, y: 34, width: 40, height: 40)))
+ expect(mainView.subView.frame).to(equal(CGRect(x: subViewLeft, y: subViewTop, width: 100, height: 100)))
+ expect(mainView.subView.subViewB!.frame).to(equal(CGRect(x: 0, y: expectedSubViewSafeAreaInsets.top, width: 40, height: 40)))
}
}
}
@@ -509,6 +521,7 @@ class PinSafeAreaWithOptInInsetsUpdateModeSpec: QuickSpec {
window = UIWindow()
window.rootViewController = viewController
window.addSubview(viewController.view)
+ window.makeKeyAndVisible();
// Testing UIViewController's layout methods is kind of bad
// but needed in our case so we need to wait some time
@@ -520,30 +533,34 @@ class PinSafeAreaWithOptInInsetsUpdateModeSpec: QuickSpec {
Pin.safeAreaInsetsDidChangeMode = .optIn
let mainView = viewController.mainView
- var expectedSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 1 } else { return 3 }
- }
- var expectedSubViewSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 1 } else { return 0 }
- }
-
+ let subViewTop = CGFloat(10)
+ let subViewLeft = CGFloat(10)
+
mainView.layoutOffsetViewClosure = { (_ subView: UIView, _ parent: UIView) in
- subView.pin.top(10).left(10).size(100)
+ subView.pin.top(subViewTop).left(subViewLeft).size(100)
}
- navigationController.navigationBar.barStyle = .blackTranslucent
+ navigationController.navigationBar.isTranslucent = true
setupWindow(with: navigationController)
+
+ let expectedSafeAreaInsets = mainView.safeAreaInsets
+ let expectedSubViewSafeAreaInsets = UIEdgeInsets(
+ top: expectedSafeAreaInsets.top - subViewTop,
+ left: .zero,
+ bottom: .zero,
+ right: .zero
+ )
// MATCH safeAreaInsets!
- expect(mainView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSafeAreaInsetsDidChangeCalledCount))
- expect(mainView.subView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSubViewSafeAreaInsetsDidChangeCalledCount))
+ expect(mainView.safeAreaInsetsDidChangeCalledCount) > 0
+ expect(mainView.subView.safeAreaInsetsDidChangeCalledCount) > 0
- expect(mainView.pin.safeArea).to(equal(UIEdgeInsets(top: 44.0, left: 0.0, bottom: 0.0, right: 0.0)))
- expect(mainView.subView.pin.safeArea).to(equal(UIEdgeInsets(top: 34.0, left: 0.0, bottom: 0.0, right: 0.0)))
+ expect(mainView.pin.safeArea).to(equal(expectedSafeAreaInsets))
+ expect(mainView.subView.pin.safeArea).to(equal(expectedSubViewSafeAreaInsets))
expect(mainView.subView.subViewB!.pin.safeArea).to(equal(UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)))
expect(mainView.subView.frame).to(equal(CGRect(x: 10, y: 10, width: 100, height: 100)))
- expect(mainView.subView.subViewB!.frame).to(equal(CGRect(x: 0, y: 34, width: 40, height: 40)))
+ expect(mainView.subView.subViewB!.frame).to(equal(CGRect(x: 0, y: expectedSubViewSafeAreaInsets.top, width: 40, height: 40)))
}
}
}
@@ -577,6 +594,7 @@ class PinSafeAreaTabBarControllerSpec: QuickSpec {
window = UIWindow()
window.rootViewController = viewController
window.addSubview(viewController.view)
+ window.makeKeyAndVisible();
// Testing UIViewController's layout methods is kind of bad
// but needed in our case so we need to wait some time
@@ -586,63 +604,64 @@ class PinSafeAreaTabBarControllerSpec: QuickSpec {
describe("navigationbar + tabbar + subview") {
it("translucent navigation bar") {
let mainView = viewController.mainView
- var expectedSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 2 } else { return 4 }
- }
- var expectedSubViewSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 1 } else { return 2 }
- }
+ let subViewTop = CGFloat(10)
+ let subViewLeft = CGFloat(10)
mainView.layoutOffsetViewClosure = { (_ subView: UIView, _ parent: UIView) in
- subView.pin.top(10).left(10).size(100)
+ subView.pin.top(subViewTop).left(subViewLeft).size(100)
}
- navigationController.navigationBar.barStyle = .blackTranslucent
+ navigationController.navigationBar.isTranslucent = true
setupWindow(with: navigationController)
+
+ let expectedSafeAreaInsets = mainView.safeAreaInsets
+ let expectedSubViewSafeAreaInsets = UIEdgeInsets(
+ top: expectedSafeAreaInsets.top - subViewTop,
+ left: .zero,
+ bottom: .zero,
+ right: .zero
+ )
// MATCH safeAreaInsets!
- expect(mainView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSafeAreaInsetsDidChangeCalledCount))
- expect(mainView.subView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSubViewSafeAreaInsetsDidChangeCalledCount))
+ expect(mainView.safeAreaInsetsDidChangeCalledCount) > 0
+ expect(mainView.subView.safeAreaInsetsDidChangeCalledCount) > 0
- expect(mainView.pin.safeArea).to(equal(UIEdgeInsets(top: 44.0, left: 0.0, bottom: 49.0, right: 0.0)))
- expect(mainView.subView.pin.safeArea).to(equal(UIEdgeInsets(top: 34.0, left: 0.0, bottom: 0.0, right: 0.0)))
+ expect(mainView.pin.safeArea).to(equal(expectedSafeAreaInsets))
+ expect(mainView.subView.pin.safeArea).to(equal(expectedSubViewSafeAreaInsets))
expect(mainView.subView.subViewB!.pin.safeArea).to(equal(UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)))
let screenSize = mainView.frame.size
expect(mainView.frame).to(equal(CGRect(x: 0, y: 0, width: screenSize.width, height: screenSize.height)))
- expect(mainView.subView.frame).to(equal(CGRect(x: 10, y: 10, width: 100, height: 100)))
- expect(mainView.subView.subViewB!.frame).to(equal(CGRect(x: 0, y: 34, width: 40, height: 40)))
+ expect(mainView.subView.frame).to(equal(CGRect(x: subViewLeft, y: subViewTop, width: 100, height: 100)))
+ expect(mainView.subView.subViewB!.frame).to(equal(CGRect(x: 0, y: expectedSubViewSafeAreaInsets.top, width: 40, height: 40)))
}
}
describe("navigationbar + tabbar + subview") {
it("transluscent navigationbar 2") {
let mainView = viewController.mainView
- var expectedSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 2 } else { return 4 }
- }
- var expectedSubViewSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 1 } else { return 2 }
- }
mainView.layoutOffsetViewClosure = { (_ subView: UIView, _ parent: UIView) in
subView.pin.all()
}
- navigationController.navigationBar.barStyle = .blackTranslucent
+ navigationController.navigationBar.isTranslucent = true
setupWindow(with: navigationController)
+
+ let expectedSafeAreaInsets = mainView.safeAreaInsets
+ let expectedSubViewSafeAreaInsets = expectedSafeAreaInsets
// MATCH safeAreaInsets!
- expect(mainView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSafeAreaInsetsDidChangeCalledCount))
- expect(mainView.subView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSubViewSafeAreaInsetsDidChangeCalledCount))
+ expect(mainView.safeAreaInsetsDidChangeCalledCount) > 0
+ expect(mainView.subView.safeAreaInsetsDidChangeCalledCount) > 0
- expect(mainView.pin.safeArea).to(equal(UIEdgeInsets(top: 44.0, left: 0.0, bottom: 49.0, right: 0.0)))
- expect(mainView.subView.pin.safeArea).to(equal(UIEdgeInsets(top: 44.0, left: 0.0, bottom: 49.0, right: 0.0)))
+ expect(mainView.pin.safeArea).to(equal(expectedSafeAreaInsets))
+ expect(mainView.subView.pin.safeArea).to(equal(expectedSubViewSafeAreaInsets))
expect(mainView.subView.subViewB!.pin.safeArea).to(equal(UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)))
let screenSize = mainView.frame.size
expect(mainView.subView.frame).to(equal(CGRect(x: 0, y: 0, width: screenSize.width, height: screenSize.height)))
- expect(mainView.subView.subViewB!.frame).to(equal(CGRect(x: 0, y: 44, width: 40, height: 40)))
+ expect(mainView.subView.subViewB!.frame).to(equal(CGRect(x: 0, y: expectedSubViewSafeAreaInsets.top, width: 40, height: 40)))
}
}
}
@@ -671,6 +690,7 @@ class PinSafeAreaScrollViewControllerSpec: QuickSpec {
window = UIWindow()
window.rootViewController = viewController
window.addSubview(viewController.view)
+ window.makeKeyAndVisible();
// Testing UIViewController's layout methods is kind of bad
// but needed in our case so we need to wait some time
@@ -680,18 +700,17 @@ class PinSafeAreaScrollViewControllerSpec: QuickSpec {
describe("navigationbar + scrollview") {
it("translucent navigation bar") {
let mainView = viewController.mainView
- var expectedSafeAreaInsetsDidChangeCalledCount: Int {
- if #available(iOS 11.0, tvOS 11.0, *) { return 1 } else { return 3 }
- }
- navigationController.navigationBar.barStyle = .blackTranslucent
+ navigationController.navigationBar.isTranslucent = true
setupWindow(with: navigationController)
+
+ let expectedSafeAreaInsets = mainView.safeAreaInsets
// MATCH safeAreaInsets!
- expect(mainView.safeAreaInsetsDidChangeCalledCount).to(equal(expectedSafeAreaInsetsDidChangeCalledCount))
+ expect(mainView.safeAreaInsetsDidChangeCalledCount) > 0
expect(mainView.subView.safeAreaInsetsDidChangeCalledCount).to(equal(0))
- expect(mainView.pin.safeArea).to(equal(UIEdgeInsets(top: 44.0, left: 0.0, bottom: 0.0, right: 0.0)))
+ expect(mainView.pin.safeArea).to(equal(expectedSafeAreaInsets))
// subView is inside a UIScrollView, its safeArea should be .zero
expect(mainView.subView.pin.safeArea).to(equal(UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)))
@@ -705,7 +724,6 @@ class PinSafeAreaScrollViewControllerSpec: QuickSpec {
}
}
-
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
fileprivate class TestViewController2: UIViewController {
var mainView: TestView2 { return self.view as! TestView2 }
@@ -739,7 +757,7 @@ class TestView2: UIView {
layoutSubView()
}
- fileprivate func layoutSubView() {
+ private func layoutSubView() {
assert(layoutOffsetViewClosure != nil)
layoutOffsetViewClosure?(subView, self)
@@ -787,7 +805,6 @@ fileprivate class TestScrollViewController: UIViewController {
}
}
-
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
fileprivate class TestInsetsUpdateViewController: UIViewController {
var mainView: TestInsetsUpdateView { return self.view as! TestInsetsUpdateView }
@@ -821,7 +838,7 @@ class TestInsetsUpdateView: UIView, PinSafeAreaInsetsUpdate {
layoutSubView()
}
- fileprivate func layoutSubView() {
+ private func layoutSubView() {
assert(layoutOffsetViewClosure != nil)
layoutOffsetViewClosure?(subView, self)
@@ -830,7 +847,6 @@ class TestInsetsUpdateView: UIView, PinSafeAreaInsetsUpdate {
}
}
-
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class TestScrollView: UIView {
let scrollView = UIScrollView()
@@ -858,7 +874,7 @@ class TestScrollView: UIView {
layoutSubView()
}
- fileprivate func layoutSubView() {
+ private func layoutSubView() {
super.layoutSubviews()
scrollView.pin.all()
diff --git a/Tests/iOS/ReadableLayoutMarginsSpec.swift b/Tests/iOS/ReadableLayoutMarginsSpec.swift
new file mode 100644
index 00000000..deaaac3e
--- /dev/null
+++ b/Tests/iOS/ReadableLayoutMarginsSpec.swift
@@ -0,0 +1,137 @@
+// Copyright (c) 2017 Luc Dion
+// 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 Quick
+import Nimble
+import PinLayout
+
+class ReadableLayoutMargins: QuickSpec {
+ override func spec() {
+ var viewController: PViewController!
+ var window: UIWindow!
+
+ var rootView: BasicView!
+ var aView: BasicView!
+
+ var bView: BasicView!
+ var bViewChild: BasicView!
+
+ /*
+ root
+ |
+ |- aView
+ | |
+ | - aViewChild
+ |
+ - bView
+ |
+ - bViewChild
+ */
+
+ beforeEach {
+ viewController = PViewController()
+ viewController.view = BasicView()
+
+ rootView = BasicView()
+ viewController.view.addSubview(rootView)
+
+ aView = BasicView()
+ rootView.addSubview(aView)
+
+ bView = BasicView()
+ rootView.addSubview(bView)
+
+ bViewChild = BasicView()
+ bView.addSubview(bViewChild)
+
+ rootView.frame = CGRect(x: 0, y: 0, width: 400, height: 400)
+ aView.frame = CGRect(x: 140, y: 100, width: 200, height: 120)
+ bView.frame = CGRect(x: 0, y: 0, width: 100, height: 50)
+ bViewChild.frame = CGRect(x: 40, y: 10, width: 60, height: 20)
+ }
+
+ func setupWindow(with viewController: UIViewController) {
+ window = UIWindow()
+ window.rootViewController = viewController
+ window.addSubview(viewController.view)
+ window.makeKeyAndVisible();
+
+ // Testing UIViewController's layout methods is kind of bad
+ // but needed in our case so we need to wait some time
+ RunLoop.current.run(until: Date().addingTimeInterval(0.2))
+ }
+
+ describe("Using pin.readableMargins") {
+ it("test") {
+ setupWindow(with: viewController)
+
+ aView.pin.all(rootView.pin.readableMargins)
+
+ expect(aView.frame).to(equal(rootView.readableContentGuide.layoutFrame))
+ }
+ }
+
+ describe("Using pin.layoutMargins") {
+ it("test") {
+ setupWindow(with: viewController)
+
+ aView.pin.all(rootView.pin.layoutMargins)
+
+ let layoutMargins = rootView.layoutMargins
+ let aViewFrame = CGRect(
+ x: layoutMargins.left,
+ y: layoutMargins.top,
+ width: rootView.frame.width - (layoutMargins.left + layoutMargins.right),
+ height: rootView.frame.height - (layoutMargins.top + layoutMargins.bottom)
+ )
+ expect(aView.frame).to(equal(aViewFrame))
+ }
+ }
+
+ #if os(iOS)
+ describe("Using pin.keyboardArea") {
+ it("test") {
+ setupWindow(with: viewController)
+
+ rootView.pin.top(0).horizontally()
+ rootView.pin.bottom(rootView.pin.keyboardArea.height)
+
+ let keyboardLayoutFrame: CGRect
+
+ if #available(iOS 15, *) {
+ keyboardLayoutFrame = rootView.keyboardLayoutGuide.layoutFrame
+ } else {
+ keyboardLayoutFrame = .zero
+ }
+
+ let screenSize = viewController.view.frame
+ let expectedRootViewFrame = CGRect(
+ x: .zero,
+ y: .zero,
+ width: screenSize.width,
+ height: screenSize.height - keyboardLayoutFrame.height
+ )
+
+ expect(rootView.frame).to(equal(expectedRootViewFrame))
+ expect(rootView.pin.keyboardArea).to(equal(keyboardLayoutFrame))
+ }
+ }
+ #endif
+ }
+}
diff --git a/Tests/iOS/Types+UIKit.swift b/Tests/iOS/Types+UIKit.swift
index 534a2e89..c8e42d5c 100644
--- a/Tests/iOS/Types+UIKit.swift
+++ b/Tests/iOS/Types+UIKit.swift
@@ -1,10 +1,21 @@
+// Copyright (c) 2018 Luc Dion
+// 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:
//
-// Types+UIKit.swift
-// PinLayoutTests-macOS
-//
-// Created by Luc Dion on 2018-04-18.
-// Copyright © 2018 mcswiftlayyout.mirego.com. All rights reserved.
+// 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
@@ -13,3 +24,4 @@ typealias PScrollView = UIScrollView
typealias PEdgeInsets = UIEdgeInsets
typealias PViewController = UIViewController
typealias PColor = UIColor
+typealias PLabel = UILabel
diff --git a/Tests/macOS/PinLayoutTestMacOS.swift b/Tests/macOS/PinLayoutTestMacOS.swift
index 8fd080be..b011e88d 100644
--- a/Tests/macOS/PinLayoutTestMacOS.swift
+++ b/Tests/macOS/PinLayoutTestMacOS.swift
@@ -1,10 +1,21 @@
+// Copyright (c) 2018 Luc Dion
+// 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:
//
-// PinLayoutTestMacOS.swift
-// PinLayoutTestMacOS
-//
-// Created by Luc Dion on 2018-04-16.
-// Copyright © 2018 mcswiftlayyout.mirego.com. All rights reserved.
+// 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 XCTest
diff --git a/Tests/macOS/Types+Appkit.swift b/Tests/macOS/Types+Appkit.swift
index f30f15c9..22be7050 100644
--- a/Tests/macOS/Types+Appkit.swift
+++ b/Tests/macOS/Types+Appkit.swift
@@ -1,10 +1,21 @@
+// Copyright (c) 2018 Luc Dion
+// 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:
//
-// Types+Appkit.swift
-// PinLayoutTests-macOS
-//
-// Created by Luc Dion on 2018-04-18.
-// Copyright © 2018 mcswiftlayyout.mirego.com. All rights reserved.
+// 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 AppKit
diff --git a/build-ci.sh b/build-ci.sh
deleted file mode 100755
index 429830f0..00000000
--- a/build-ci.sh
+++ /dev/null
@@ -1,100 +0,0 @@
-
-DERIVED_DATA=${1:-/tmp/PinLayout}
-
-set -o pipefail &&
-
-rm -rf $DERIVED_DATA &&
-
-echo "===============================" &&
-echo "fastlane iOS travis" &&
-echo "===============================" &&
-time bundle exec fastlane ios travis &&
-
-
-# echo "===============================" &&
-# echo "fastlane macOS travis" &&
-# echo "===============================" &&
-# #time bundle exec fastlane mac travis &&
-
-
-# echo "===============================" &&
-# echo "iOS unit test" &&
-# echo "===============================" &&
-# time xcodebuild build test -workspace PinLayout.xcworkspace -scheme PinLayout-iOS -derivedDataPath $DERIVED_DATA -sdk iphonesimulator11.3 \
-# -destination 'platform=iOS Simulator,name=iPhone 7 Plus,OS=11.3' \
-# -destination 'platform=iOS Simulator,name=iPhone 7,OS=11.3' \
-# -destination 'platform=iOS Simulator,name=iPhone 6,OS=10.2'\
-# | xcpretty &&
-
-
-# echo "===============================" &&
-# echo "macOS unit test" &&
-# echo "===============================" &&
-# time xcodebuild clean test -workspace PinLayout.xcworkspace -scheme PinLayout-macOS -derivedDataPath $DERIVED_DATA -sdk macosx10.13 \
-# | xcpretty
-
-
-# echo "===============================" &&
-# echo " Cocoapods: iOS Empty project" &&
-# echo "===============================" &&
-# cd TestProjects/cocoapods/ios &&
-# rm -rf $DERIVED_DATA &&
-# pod install &&
-# time xcodebuild clean build -workspace PinLayout-iOS.xcworkspace -scheme PinLayout-iOS -sdk iphonesimulator11.3 -derivedDataPath $DERIVED_DATA \
-# -destination 'platform=iOS Simulator,name=iPhone 7,OS=11.3' \
-# | xcpretty &&
-# cd ../../..
-
-
-# echo "===============================" &&
-# echo " Cocoapods: macOS Empty project" &&
-# echo "===============================" &&
-# cd TestProjects/cocoapods/macos &&
-# rm -rf $DERIVED_DATA &&
-# pod install &&
-# time xcodebuild clean build -workspace PinLayout-macOS.xcworkspace -scheme PinLayout-macOS -sdk macosx10.13 -derivedDataPath $DERIVED_DATA \
-# | xcpretty &&
-# cd ../../..
-
-
-# echo "===============================" &&
-# echo " Cocoapods: tvOS Empty project" &&
-# echo "===============================" &&
-# cd TestProjects/cocoapods/tvos &&
-# rm -rf $DERIVED_DATA &&
-# pod install &&
-# time xcodebuild clean build -workspace PinLayout-tvOS.xcworkspace -scheme PinLayout-tvOS -sdk appletvsimulator11.3 -derivedDataPath $DERIVED_DATA \
-# -destination 'platform=tvOS Simulator,name=Apple TV,OS=11.3' \
-# | xcpretty &&
-# cd ../../..
-
-
-echo "===============================" &&
-echo " Carthage: iOS Empty project" &&
-echo "===============================" &&
-cd TestProjects/carthage/ios &&
-rm -rf $DERIVED_DATA &&
-rm Cartfile &&
-echo "git \"$TRAVIS_BUILD_DIR\" \"$TRAVIS_BRANCH\"" > Cartfile &&
-carthage update --use-ssh --platform iOS &&
-time xcodebuild clean build -project PinLayout-Carthage-iOS.xcodeproj -scheme PinLayout-Carthage-iOS -sdk iphonesimulator11.3 -derivedDataPath $DERIVED_DATA \
- -destination 'platform=iOS Simulator,name=iPhone 7,OS=11.3' \
- | xcpretty &&
-cd ../../..
-
-
-# echo "==========================================" &&
-# echo " Swift Package Manager: iOS Empty project " &&
-# echo "==========================================" &&
-# cd TestProjects/swift-package-manager/ios &&
-# rm -rf $DERIVED_DATA &&
-# rm -rf .build &&
-# rm Package.pins
-# swift package show-dependencies --format json &&
-# time xcodebuild clean build -project PinLayout-Carthage-iOS.xcodeproj -scheme PinLayout-Carthage-iOS -sdk iphonesimulator11.3 -derivedDataPath $DERIVED_DATA \
-# -destination 'platform=iOS Simulator,name=iPhone 7,OS=11.3' \
-# | xcpretty &&
-# cd ../../..
-#
-# #OTHER_SWIFT_FLAGS='-Xfrontend -debug-time-function-bodies'
-# xcodebuild clean test -workspace PinLayout.xcworkspace -scheme PinLayout-macOS -derivedDataPath $DERIVED_DATA -sdk macosx10.13 &&
diff --git a/docs/Benchmark.md b/docs/Benchmark.md
index 9cef165e..c6b6e7e7 100644
--- a/docs/Benchmark.md
+++ b/docs/Benchmark.md
@@ -15,14 +15,15 @@
##### LayoutKit Benchmark
PinLayout and [FlexLayout](https://github.com/layoutBox/FlexLayout) performance has been benchmarked using [Layout Framework Benchmark](https://github.com/layoutBox/LayoutFrameworkBenchmark).
-The benchmark includes the following layout frameworks:
+The benchmark includes also many other layout frameworks, including:
* Auto layout
* [FlexLayout](https://github.com/layoutBox/FlexLayout)
* [LayoutKit](https://github.com/linkedin/LayoutKit)
* Manual layout (i.e. set UIView's frame directly)
-* [PinLayout](https://github.com/mirego/PinLayout)
+* [PinLayout](https://github.com/layoutBox/PinLayout)
* UIStackViews
+* ...
### Benchmark
@@ -32,7 +33,7 @@ As you can see in the following chart, PinLayout are faster or equal to manual l
The benchmark layout UICollectionView and UITableView cells in multiple pass, each pass contains more cells than the previous one.
-
+
See [Layout Framework Benchmark](https://github.com/layoutBox/LayoutFrameworkBenchmark) for complete details and benchmarks charts for iPhone X/8/7/6S/...
@@ -55,30 +56,29 @@ override func layoutSubviews() {
super.layoutSubviews()
let hMargin: CGFloat = 8
- let vMargin: CGFloat = 2
+ let vMargin: CGFloat = 4
optionsLabel.pin.topRight().margin(hMargin)
actionLabel.pin.topLeft().margin(hMargin)
posterImageView.pin.below(of: actionLabel, aligned: .left).marginTop(10)
- posterNameLabel.pin.right(of: posterImageView, aligned: .top).margin(-6, 6).right(hMargin).sizeToFit()
- posterHeadlineLabel.pin.below(of: posterNameLabel, aligned: .left).right(hMargin).marginTop(1).sizeToFit()
- posterTimeLabel.pin.below(of: posterHeadlineLabel, aligned: .left).right(hMargin).marginTop(1).sizeToFit()
- posterCommentLabel.pin.below(of: posterTimeLabel).left(hMargin).right().right(hMargin)
- .marginTop(vMargin).sizeToFit()
+ posterHeadlineLabel.pin.after(of: posterImageView, aligned: .center).marginLeft(4)
+ posterNameLabel.pin.above(of: posterHeadlineLabel, aligned: .left).marginBottom(vMargin)
+ posterTimeLabel.pin.below(of: posterHeadlineLabel, aligned: .left).marginTop(vMargin)
- contentImageView.pin.below(of: posterCommentLabel).hCenter().width(100%).sizeToFit()
- contentTitleLabel.pin.below(of: contentImageView).left().right().marginHorizontal(hMargin).sizeToFit()
- contentDomainLabel.pin.below(of: contentTitleLabel, aligned: .left).right().marginRight(hMargin)
- .sizeToFit()
+ posterCommentLabel.pin.below(of: posterTimeLabel).left(hMargin).marginTop(vMargin)
+
+ contentImageView.pin.below(of: posterCommentLabel, aligned: .left).right().marginTop(vMargin).marginRight(hMargin)
+ contentTitleLabel.pin.below(of: contentImageView).left().marginHorizontal(hMargin)
+ contentDomainLabel.pin.below(of: contentTitleLabel, aligned: .left)
likeLabel.pin.below(of: contentDomainLabel, aligned: .left).marginTop(vMargin)
- commentLabel.pin.top(to: likeLabel.edge.top).hCenter(50%)
+ commentLabel.pin.top(to: likeLabel.edge.top).hCenter()
shareLabel.pin.top(to: likeLabel.edge.top).right().marginRight(hMargin)
actorImageView.pin.below(of: likeLabel, aligned: .left).marginTop(vMargin)
- actorCommentLabel.pin.right(of: actorImageView, aligned: .center).marginLeft(4)
+ actorCommentLabel.pin.after(of: actorImageView, aligned: .center).marginLeft(4)
}
```
diff --git a/docs/Benchmark/benchmark_comparison_all.png b/docs/Benchmark/benchmark_comparison_all.png
deleted file mode 100644
index 7b6068e1..00000000
Binary files a/docs/Benchmark/benchmark_comparison_all.png and /dev/null differ
diff --git a/docs/Benchmark/benchmark_comparison_all_small.png b/docs/Benchmark/benchmark_comparison_all_small.png
index fbd2baf4..0e93d47e 100644
Binary files a/docs/Benchmark/benchmark_comparison_all_small.png and b/docs/Benchmark/benchmark_comparison_all_small.png differ
diff --git a/docs/Benchmark/benchmark_result_Autolayout.png b/docs/Benchmark/benchmark_result_Autolayout.png
deleted file mode 100644
index 016b9ce1..00000000
Binary files a/docs/Benchmark/benchmark_result_Autolayout.png and /dev/null differ
diff --git a/docs/Benchmark/benchmark_result_FlexLayout.png b/docs/Benchmark/benchmark_result_FlexLayout.png
deleted file mode 100644
index b22f4233..00000000
Binary files a/docs/Benchmark/benchmark_result_FlexLayout.png and /dev/null differ
diff --git a/docs/Benchmark/benchmark_result_LayoutKit.png b/docs/Benchmark/benchmark_result_LayoutKit.png
deleted file mode 100644
index 1e0e3ca1..00000000
Binary files a/docs/Benchmark/benchmark_result_LayoutKit.png and /dev/null differ
diff --git a/docs/Benchmark/benchmark_result_PinLayout.png b/docs/Benchmark/benchmark_result_PinLayout.png
deleted file mode 100644
index 6fe1fd09..00000000
Binary files a/docs/Benchmark/benchmark_result_PinLayout.png and /dev/null differ
diff --git a/docs/PinLayout_principles.md b/docs/PinLayout_principles.md
index 34664e37..3ee6b36b 100644
--- a/docs/PinLayout_principles.md
+++ b/docs/PinLayout_principles.md
@@ -6,7 +6,7 @@
* Manual layouting (doesn't rely on auto layout).
-* PinLayout exist to be simple and fast as possible! In fact, it is fast as manual layouting. See [performance results below.](#performance)
+* PinLayout exist to be simple and fast as possible! In fact, it is fast as manual layouting. See [performance results here.](https://github.com/layoutBox/PinLayout#pinlayouts-performance)
* Full control: You're in the middle of the layout process, no magic black box.
* You can add conditions (if/switch/guard/...) related to the device orientation, device type, traitCollection, animations, ...
@@ -31,4 +31,4 @@ Each view can use the layout system that better suit it (PinLayout, autolayout,
* Not too intrusive. PinLayout only adds three properties to existing iOS classes: `UIView.pin`, `UIView.anchor` and `UIView.edge`
* Minimize as much as possible calculations and constants when layouting views. But it is always possible to add advanced computation if required.
-* Method's name match as much as possible other layout frameworks, including [FlexLayout](https://github.com/layoutBox/FlexLayout)/flexbox, CSS, React Native, …
\ No newline at end of file
+* Method's name match as much as possible other layout frameworks, including [FlexLayout](https://github.com/layoutBox/FlexLayout)/flexbox, CSS, React Native, …
diff --git a/docs/animations.md b/docs/animations.md
new file mode 100644
index 00000000..dbb738b2
--- /dev/null
+++ b/docs/animations.md
@@ -0,0 +1,190 @@
+
+
+
+
+Animations using PinLayout
+
+## Basic Swift animations
+Before explaining how to use PinLayout to animate views, you can check these two nice tutorials to learn the basic of animations:
+
+* [iOS Animation Tutorial: Getting Started](https://www.raywenderlich.com/363-ios-animation-tutorial-getting-started)
+* [Basic UIView Animation Tutorial: Getting Started](https://www.raywenderlich.com/5255-basic-uiview-animation-tutorial-getting-started)
+
+
+## PinLayout is stateless
+It is important to remember that PinLayout is stateless, i.e. PinLayout always start from the view's current position and size (frame) when layouting a view. You don't need to reset anything to animate a view using PinLayout.
+
+This also means that you can modify only the property you want to animate, for example the following code will only animate the view's width:
+
+```
+ UIView.animate(withDuration: 0.3) {
+ view.pin.width(30)
+ }
+```
+
+
+
+## Layout strategies
+Multiple strategies can be used to animate layout using PinLayout. The choice is a question of preferences and the kind of animations you want to achieve.
+
+Some possible strategies will be shown below using a simple example. The example animates a view position from left to right when the user tap a button.
+
+
+
+Note that in the following source code the view's size was set to 150 px (`view.pin.size(150)`) in the initialization.
+
+
+### Basic strategy: Using `UIView.setNeedsLayout` and `UIView.layoutIfNeeded`
+In this strategy, to force a call to layoutSubviews(), we call `UIView.setNeedsLayout` and `UIView.layoutIfNeeded` from the animation block.
+
+```swift
+var isViewLeftDocked = true
+
+override func layoutSubviews() {
+ super.layoutSubviews()
+
+ if isViewLeftDocked {
+ view.pin.top().left()
+ } else {
+ view.pin.top().right()
+ }
+}
+
+func didTapTogglePosition() {
+ isViewLeftDocked = !isViewLeftDocked
+
+ UIView.animate(withDuration: 0.3) {
+ self.setNeedsLayout()
+ self.layoutIfNeeded()
+ }
+}
+```
+
+### Using a layout method
+This strategy use a private method to layout the animated view (`layoutAnimatedView()`). The advantage of this solution is that it is not required to call `UIView.setNeedsLayout` and `UIView.layoutIfNeeded` to relayout the view.
+
+```swift
+var isViewLeftDocked = true
+
+override func layoutSubviews() {
+ super.layoutSubviews()
+
+ layoutAnimatedView()
+}
+
+private func layoutAnimatedView() {
+ if isViewLeftDocked {
+ view.pin.top().left()
+ } else {
+ view.pin.top().right()
+ }
+}
+
+func didTapTogglePosition() {
+ isViewLeftDocked = !isViewLeftDocked
+
+ UIView.animate(withDuration: 0.3) {
+ self.layoutAnimatedView()
+ }
+}
+```
+
+### Using an animation state
+This strategy is similar to the previous one, but use an enumeration to keep the animation state.
+
+```swift
+enum AnimationState {
+ case leftDocked
+ case rightDocked
+}
+
+var animationState = AnimationState.leftDocked
+
+override func layoutSubviews() {
+ super.layoutSubviews()
+
+ layoutAnimatedView()
+}
+
+private func layoutAnimatedView() {
+ switch animationState {
+ case .leftDocked:
+ view.pin.top().left()
+ case .rightDocked:
+ view.pin.top().right()
+ }
+}
+
+func didTapTogglePosition() {
+ switch animationState {
+ case .leftDocked: animationState = .rightDocked
+ case .rightDocked: animationState = .leftDocked
+ }
+
+ UIView.animate(withDuration: 0.3) {
+ self.layoutAnimatedView()
+ }
+}
+```
+
+### Other strategies
+It's really up to you to think of animation's strategies that match your situation. With PinLayout you are always in control of everything, including animations.
+
+
+
+## Collision between animations and `layoutSubViews()`
+In some particular situation it is possible that `layoutSubViews()` may be called during the animation is in progress, this can occur particularly on long animation. To handle this kind of situation it is possible to use a boolean indicating if an animation is in progress, and to block temporarely the layout of animated views in `layoutSubViews()`.
+
+Here is an example:
+
+```swift
+enum AnimationState {
+ case leftDocked
+ case rightDocked
+}
+
+var animationState = AnimationState.leftDocked
+var isAnimating = false
+
+override func layoutSubviews() {
+ super.layoutSubviews()
+
+ // If an animation of the view is in progress, we don't update animated views position.
+ guard !isAnimating else { return }
+ layoutAnimatedView()
+}
+
+private func layoutAnimatedView() {
+ switch animationState {
+ case .leftDocked:
+ view.pin.top().left()
+ case .rightDocked:
+ view.pin.top().right()
+ }
+}
+
+func didTapTogglePosition() {
+ switch animationState {
+ case .leftDocked: animationState = .rightDocked
+ case .rightDocked: animationState = .leftDocked
+ }
+
+ UIView.animate(withDuration: 0.3, animations: {
+ self.isAnimating = true
+ self.layoutAnimatedView()
+ }, completion: { (_) in
+ self.isAnimating = false
+ })
+}
+```
+
+
+
+## Animation Example
+You can check the animation example available in the [PinLayout's Example App](https://github.com/layoutBox/PinLayout/blob/master/docs/examples.md):
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/Animations/AnimationsView.swift)
+
+
+
+
diff --git a/docs/examples.md b/docs/examples.md
new file mode 100644
index 00000000..894bff63
--- /dev/null
+++ b/docs/examples.md
@@ -0,0 +1,127 @@
+
+
+
+
+ Examples
+
+The PinLayout's Example exposes some usage example of PinLayout.
+
+The Example App is available in the [`Example`](https://github.com/layoutBox/PinLayout/tree/master/Example) folder.
+
+### Running the Example app
+1. Do a `pod install` from the PinLayout root directory.
+2. Open the newly generated `PinLayout.xcworkspace` Xcode workspace.
+3. Select the `PinLayoutSample` target.
+4. Run the app on your device or simulator.
+
+
+
+## Intro Example
+PinLayout introduction example presented in the README.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/Intro/IntroView.swift)
+
+
+
+## Relative Edges Layout Example
+Example showing how to layout views relative to other views.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/RelativeView/RelativeView.swift)
+
+
+
+## Between Example
+Example showing how to use [`horizontallyBetween()`](https://github.com/layoutBox/PinLayout#layout-between-other-views) to position a view between two other views.
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/BetweenView/BetweenView.swift)
+
+
+
+## UITableView Example
+Example using a UITableView with variable height cells.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/TableViewExample/TableViewExampleView.swift)
+
+
+
+
+## UITableView Example with cells using `pin.readableMargins`
+Similar to the UITableView Example, but in this one cells use `pin.readableMargins` to layout their content inside the zone defined by `UIView.readableContentGuide`.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/TableViewExample/TableViewExampleView.swift)
+
+
+
+
+## UICollectionView Example
+Example using a UICollectionView with variable height cells.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/CollectionViewExample/HouseCell.swift)
+
+
+
+## Animations Example
+Example showing how to animate views with PinLayout.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/Animations/AnimationsView.swift)
+
+
+
+## Right to left language support Example
+This example show how PinLayout can support simultaneously Left to right and right to left languages.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/IntroRTL/IntroRTLView.swift)
+
+
+
+
+## pin.safeArea example
+Example showing the usage of `UIView.pin.safeArea`] with UINavigationController and UITabViewController:
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/SafeArea/SafeAreaView.swift)
+
+
+
+Also display the usage of `pin.readableMargins` and `pin.layoutMargins`:
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/SafeArea/SafeAreaAndMarginsView.swift)
+
+
+
+
+## Adjust To Container Example
+Example showing how PinLayout can be used to adjust the layout depending of the space available.
+
+In this example the UISegmentedControl is shown below its label if the available width is smaller than 500 pixels, or on the same line as the label if the width is wider.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/AdjustToContainer/Subviews/ChoiceSelectorView.swift)
+
+
+
+
+## wrapContent Example
+This example show how to use the `wrapContent()` method. This method is particularly useful to wrap a group of views and center them.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/WrapContent/WrapContentView.swift)
+
+
+
+## Form Example
+This example is a basic form containing 4 fields.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/Form/FormView.swift)
+
+
+
+## Auto Adjusting Size Example
+This example show how fixed size views and expandable views can be layouted using PinLayout to fill the available space.
+
+[Source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/AutoAdjustingSize/AutoAdjustingSizeView.swift)
+
+
+
+
+## Automatic Sizing Example
+This example show how to use Automatic Sizing (`autoSizeThatFits()`) to compute views size.
+[Source code](https://github.com/layoutBox/PinLayout/tree/master/Example/PinLayoutSample/UI/Examples/AutoSizing)
+
+
diff --git a/docs/images/example-animations-large.gif b/docs/images/example-animations-large.gif
new file mode 100644
index 00000000..3451d365
Binary files /dev/null and b/docs/images/example-animations-large.gif differ
diff --git a/docs/images/example-animations.gif b/docs/images/example-animations.gif
new file mode 100644
index 00000000..beb2dbfb
Binary files /dev/null and b/docs/images/example-animations.gif differ
diff --git a/docs/images/pinlayout_animation_example1.gif b/docs/images/pinlayout_animation_example1.gif
new file mode 100644
index 00000000..2e920652
Binary files /dev/null and b/docs/images/pinlayout_animation_example1.gif differ
diff --git a/docs/images/pinlayout_example_anchor_center.png b/docs/images/pinlayout_example_anchor_center.png
new file mode 100644
index 00000000..73d24fbc
Binary files /dev/null and b/docs/images/pinlayout_example_anchor_center.png differ
diff --git a/docs/images/pinlayout_example_layout_margins_all.png b/docs/images/pinlayout_example_layout_margins_all.png
new file mode 100644
index 00000000..703eb4eb
Binary files /dev/null and b/docs/images/pinlayout_example_layout_margins_all.png differ
diff --git a/docs/images/pinlayout_example_layout_margins_landscape.png b/docs/images/pinlayout_example_layout_margins_landscape.png
new file mode 100644
index 00000000..4d29810c
Binary files /dev/null and b/docs/images/pinlayout_example_layout_margins_landscape.png differ
diff --git a/docs/images/pinlayout_example_layout_margins_portrain.png b/docs/images/pinlayout_example_layout_margins_portrain.png
new file mode 100644
index 00000000..11c533d3
Binary files /dev/null and b/docs/images/pinlayout_example_layout_margins_portrain.png differ
diff --git a/docs/images/pinlayout_example_tableview_readable_content_all.png b/docs/images/pinlayout_example_tableview_readable_content_all.png
new file mode 100644
index 00000000..805c74c2
Binary files /dev/null and b/docs/images/pinlayout_example_tableview_readable_content_all.png differ
diff --git a/docs/images/pinlayout_example_tableview_readable_content_landscape.png b/docs/images/pinlayout_example_tableview_readable_content_landscape.png
new file mode 100644
index 00000000..e4cc7be9
Binary files /dev/null and b/docs/images/pinlayout_example_tableview_readable_content_landscape.png differ
diff --git a/docs/images/pinlayout_example_tableview_readable_content_portrait.png b/docs/images/pinlayout_example_tableview_readable_content_portrait.png
new file mode 100644
index 00000000..71ff37aa
Binary files /dev/null and b/docs/images/pinlayout_example_tableview_readable_content_portrait.png differ
diff --git a/docs/images/pinlayout_example_topRight.png b/docs/images/pinlayout_example_topRight.png
new file mode 100644
index 00000000..e635927d
Binary files /dev/null and b/docs/images/pinlayout_example_topRight.png differ
diff --git a/docs/images/pinlayout_horizontallyBetween.png b/docs/images/pinlayout_horizontallyBetween.png
new file mode 100644
index 00000000..80eea2cd
Binary files /dev/null and b/docs/images/pinlayout_horizontallyBetween.png differ
diff --git a/docs/images/pinlayout_plus_layoutBox.png b/docs/images/pinlayout_plus_layoutBox.png
new file mode 100644
index 00000000..02684ef2
Binary files /dev/null and b/docs/images/pinlayout_plus_layoutBox.png differ
diff --git a/docs/images/pinlayout_right_to_left_example.png b/docs/images/pinlayout_right_to_left_example.png
new file mode 100644
index 00000000..d398a916
Binary files /dev/null and b/docs/images/pinlayout_right_to_left_example.png differ
diff --git a/docs/images/pinlayout_verticallyBetween.png b/docs/images/pinlayout_verticallyBetween.png
new file mode 100644
index 00000000..871d46fb
Binary files /dev/null and b/docs/images/pinlayout_verticallyBetween.png differ
diff --git a/docs/images/wrapContent_all.png b/docs/images/wrapContent_all.png
new file mode 100644
index 00000000..0f00ca0f
Binary files /dev/null and b/docs/images/wrapContent_all.png differ
diff --git a/docs/images/wrapContent_before.png b/docs/images/wrapContent_before.png
new file mode 100644
index 00000000..ad081829
Binary files /dev/null and b/docs/images/wrapContent_before.png differ
diff --git a/docs/images/wrapContent_example.png b/docs/images/wrapContent_example.png
new file mode 100644
index 00000000..c55fde13
Binary files /dev/null and b/docs/images/wrapContent_example.png differ
diff --git a/docs/images/wrapContent_horizontally.png b/docs/images/wrapContent_horizontally.png
new file mode 100644
index 00000000..d8079987
Binary files /dev/null and b/docs/images/wrapContent_horizontally.png differ
diff --git a/docs/images/wrapContent_padding.png b/docs/images/wrapContent_padding.png
new file mode 100644
index 00000000..b71b2303
Binary files /dev/null and b/docs/images/wrapContent_padding.png differ
diff --git a/docs/images/wrapContent_vertically.png b/docs/images/wrapContent_vertically.png
new file mode 100644
index 00000000..32b5af9b
Binary files /dev/null and b/docs/images/wrapContent_vertically.png differ
diff --git a/docs/objective_c.md b/docs/objective_c.md
index f1132fd0..6c17b258 100644
--- a/docs/objective_c.md
+++ b/docs/objective_c.md
@@ -9,21 +9,24 @@ PinLayout can also be used from Objective-C. The PinLayout interface is slightly
###### Example 1:
This example implement the PinLayout's Intro example using objective-c
-
+
```
- (void) layoutSubviews {
[super layoutSubviews];
-
- [[[[[[logo.pinObjc top] left] width:100] aspectRatio] marginWithTop:topLayoutGuide + 10 horizontal:10 bottom:10] layout];
- [[[[segmented.pinObjc rightOf:logo aligned:VerticalAlignTop] right] marginHorizontal:10] layout];
- [[[[[[textLabel.pinObjc belowOf:segmented aligned:HorizontalAlignLeft] widthOf:segmented] pinEdges] marginTop:10] fitSize] layout];
- [[[[[separatorView.pinObjc belowOfViews:@[logo, textLabel] aligned:HorizontalAlignLeft] rightTo:segmented.edge.right] height:1] marginTop:10] layout];
+
+ CGFloat margin = 10;
+ UIEdgeInsets safeArea = self.pinObjc.safeArea;
+
+ logo.pinObjc.topInsets(safeArea).leftInsets(safeArea).width(100).aspectRatio().margin(margin).layout();
+ segmented.pinObjc.rightOfAligned(logo, VerticalAlignTop).rightInsets(safeArea).marginHorizontal(margin).layout();
+ textLabel.pinObjc.belowOfAligned(segmented, HorizontalAlignLeft).widthOf(segmented).pinEdges().marginTop(margin).sizeToFitType(FitWidth).layout();
+ separatorView.pinObjc.belowOfViewsAligned(@[logo, textLabel], HorizontalAlignLeft).rightToEdge(segmented.edge.right).height(1).marginTop(margin).layout();
}
```
-:pushpin: This example is available in the Examples App. See example complete [source code](https://github.com/mirego/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/IntroObjectiveC/IntroObjectiveCView.m)
+:pushpin: This example is available in the Examples App. See example complete [source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/IntroObjectiveC/IntroObjectiveCView.m)
## Important notes about PinLayout's Objective-c interface
@@ -31,7 +34,7 @@ This example implement the PinLayout's Intro example using objective-c
The PinLayout's objective-c interface is available using the property `pinObjc` (instead of `pin` in Swift)
```
- [[view.pinObjc top] layout];
+ view.pinObjc.top().layout();
```
#### `layout()`
@@ -47,6 +50,6 @@ When using the Objective-c interface, the `layout` method must be called explici
view.pin.width(100)
// Objective-c
- [[view.pinObjc width:100] layout];
+ view.pinObjc.width(100).layout();
```
diff --git a/docs/pinlayout_example_adjust_to_container-landscape.png b/docs/pinlayout_example_adjust_to_container-landscape.png
index fb45561d..9e0693f4 100644
Binary files a/docs/pinlayout_example_adjust_to_container-landscape.png and b/docs/pinlayout_example_adjust_to_container-landscape.png differ
diff --git a/docs/pinlayout_example_wrapContent.png b/docs/pinlayout_example_wrapContent.png
new file mode 100644
index 00000000..372a06cb
Binary files /dev/null and b/docs/pinlayout_example_wrapContent.png differ
diff --git a/docs/pinlayout_exampleapp_automatic_sizing.png b/docs/pinlayout_exampleapp_automatic_sizing.png
new file mode 100644
index 00000000..77157fba
Binary files /dev/null and b/docs/pinlayout_exampleapp_automatic_sizing.png differ
diff --git a/docs/rtl_support.md b/docs/rtl_support.md
index 0db33396..8f86f9b0 100644
--- a/docs/rtl_support.md
+++ b/docs/rtl_support.md
@@ -37,4 +37,4 @@ override func layoutSubviews() {
}
```
-:pushpin: The complete RTL "Introduction example" [source code](https://github.com/mirego/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/IntroRTL/IntroRTLView.swift). This example is available in the [Examples App](#examples_app)
\ No newline at end of file
+:pushpin: The complete RTL "Introduction example" [source code](https://github.com/layoutBox/PinLayout/blob/master/Example/PinLayoutSample/UI/Examples/IntroRTL/IntroRTLView.swift). This example is available in the [Examples App](#examples_app)
\ No newline at end of file
diff --git a/docs/xcode_playground.md b/docs/xcode_playground.md
index 329f9680..37a92f4e 100644
--- a/docs/xcode_playground.md
+++ b/docs/xcode_playground.md
@@ -16,7 +16,7 @@ The method will execute PinLayout commands immediately. This method is **require
```swift
view.pin.top(20).bottom(20).width(100).layout()
- view2.pin.below(of: view).left().right().layout()
+ view2.pin.below(of: view).horizontally().layout()
```
**TIP**: If your codes needs to work in Xcode playgrounds, you may set to `true` the property `Pin.logMissingLayoutCalls`, this way any missing call to `layout()` will generate a warning in the Xcode console.
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
deleted file mode 100644
index 5622d104..00000000
--- a/fastlane/Fastfile
+++ /dev/null
@@ -1,126 +0,0 @@
-# Change the syntax highlighting to Ruby
-# All lines starting with a # are ignored when running `fastlane`
-
-# If you want to automatically update fastlane if a new version is available:
-# update_fastlane
-
-# This is the minimum version number required.
-# Update this, if you use features of a newer version
-fastlane_version "2.29.0"
-
-#default_platform :ios
-
-##### iOS platform
-##############################################
-platform :ios do
- before_all do
- end
-
- lane :install do
- bundle_install
- cocoapods(use_bundle_exec: true, try_repo_update_on_error: true)
- end
-
- lane :build do
- install
-
- swiftlint(
- mode: :lint,
- config_file: ".swiftlint.yml",
- executable: "Pods/SwiftLint/swiftlint"
- )
-
- xcodebuild(
- project: "PinLayout.xcodeproj",
- scheme: "PinLayout-iOS",
- destination: "name=iPhone 8 Plus,OS=11.2",
- #configuration: "Debug",
- build: true,
- clean: true
- )
-
- xcodebuild(
- project: "PinLayout.xcodeproj",
- scheme: "PinLayout-tvOS",
- destination: "name=Apple TV",
- build: true,
- clean: true
- )
-
- xcodebuild(
- workspace: "PinLayout.xcworkspace",
- scheme: "PinLayoutSample",
- build: true,
- clean: true,
- #destination: "name=iPhone 8 Plus,OS=11.2",
- destination: "generic/platform=iOS\" CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY=\""
- )
- end
-
- lane :tests do
- scan(
- scheme: "PinLayoutSample",
- workspace: "PinLayout.xcworkspace",
- devices: [
- "iPhone 7 (10.2)",
- "iPhone 7 (11.2)",
- "iPad Air (11.2)",
- "iPhone X (11.2)"
- ]
- )
- end
-
- lane :doc do
- jazzy
- end
-
- lane :travis do
- build
- tests
- pod_lib_lint(allow_warnings: true, verbose: false)
- end
-end
-
-
-##### MAC platform
-##############################################
-platform :mac do
- lane :install do
- bundle_install
- cocoapods(use_bundle_exec: true, try_repo_update_on_error: true)
- end
-
- lane :build do
- install
- xcodebuild(
- project: "PinLayout.xcodeproj",
- scheme: "PinLayout-macOS",
- #destination: "name=Apple TV",
- build: true
- #clean: true,
- #destination: "generic/platform=iOS\" CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY=\""
- )
-
- #xcodebuild(
- # workspace: "PinLayout.xcworkspace",
- # scheme: "PinLayoutSample",
- # build: true,
- # clean: true,
- # #destination: "name=iPhone 8 Plus,OS=11.2",
- # destination: "generic/platform=iOS\" CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY=\""
- #)
- end
-
- #lane :tests do
- # scan(
- # scheme: "PinLayout-macOS",
- # workspace: "PinLayout.xcworkspace",
- # destination: "platform=macOS,arch=x86_64"
- # )
- #end
-
- lane :travis do
- build
- # tests
- end
-end
diff --git a/index.md b/index.md
index 7095389e..eae3d345 100644
--- a/index.md
+++ b/index.md
@@ -1,17 +1,17 @@
-
+
PinLayout
-
-
+
+
-
+
-
+
@@ -22,4 +22,4 @@ Extremely Fast views layouting without auto layout. No magic, pure code, full co
-[See GitHub PinLayout' page for the complete documentation](https://github.com/mirego/PinLayout)
\ No newline at end of file
+[See GitHub PinLayout' page for the complete documentation](https://github.com/layoutBox/PinLayout)
\ No newline at end of file