├── .github └── workflows │ └── github-actions-ci.yml ├── .gitignore ├── .ruby-version_old ├── .swiftlint.yml ├── .swiftpm └── xcode │ └── package.xcworkspace │ └── contents.xcworkspacedata ├── CHANGELOG.md ├── Example ├── .DS_Store ├── .gitignore ├── .ruby-version ├── .swiftlint.yml ├── PinLayoutSample.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── PinLayoutSample.xcscheme └── PinLayoutSample │ ├── AppDelegate.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── Supporting Files │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024.png │ │ │ ├── Icon-App-57x57@1x.png │ │ │ ├── Icon-App-57x57@2x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-72x72@1x.png │ │ │ ├── Icon-App-72x72@2x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ ├── Contents.json │ │ ├── PinLayout-logo.imageset │ │ │ ├── Contents.json │ │ │ └── PinLayout-logo.png │ │ ├── SafeArea │ │ │ ├── Arrow.imageset │ │ │ │ ├── Arrow.png │ │ │ │ └── Contents.json │ │ │ ├── ArrowCorner.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── arrow_corner_tl.png │ │ │ ├── Barcode.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon_scan barcode_white.png │ │ │ │ ├── icon_scan barcode_white@2x.png │ │ │ │ └── icon_scan barcode_white@3x.png │ │ │ ├── Center.imageset │ │ │ │ ├── Center.png │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ ├── IconOrder.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── IconPickupLarge.png │ │ │ │ ├── IconPickupLarge@2x.png │ │ │ │ └── IconPickupLarge@3x.png │ │ │ ├── Tab1.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon orders.png │ │ │ │ ├── icon orders@2x.png │ │ │ │ └── icon orders@3x.png │ │ │ └── Tab2.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── IconBin.png │ │ │ │ ├── IconBin@2x.png │ │ │ │ └── IconBin@3x.png │ │ └── method.imageset │ │ │ ├── Contents.json │ │ │ └── method.png │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ └── Info.plist │ └── UI │ ├── Common │ ├── BaseFormView.swift │ ├── BasicView.swift │ ├── ContentService.swift │ ├── ProxyWrapper.swift │ ├── Stylesheet.swift │ ├── UIEdgeInsets+PinLayout.swift │ ├── UIImageView+Download.swift │ ├── UINavigationController+Orientation.swift │ └── UITabBarController+Orientation.swift │ ├── Examples │ ├── AdjustToContainer │ │ ├── AdjustToContainerView.swift │ │ ├── AdjustToContainerViewController.swift │ │ └── Subviews │ │ │ └── ChoiceSelectorView.swift │ ├── Animations │ │ ├── AnimationsView.swift │ │ └── AnimationsViewController.swift │ ├── AutoAdjustingSize │ │ ├── AutoAdjustingSizeView.swift │ │ └── AutoAdjustingSizeViewController.swift │ ├── AutoSizing │ │ ├── AutoSizingContainerView.swift │ │ ├── AutoSizingView.swift │ │ └── AutoSizingViewController.swift │ ├── BetweenView │ │ ├── BetweenView.swift │ │ └── BetweenViewController.swift │ ├── CollectionViewExample │ │ ├── CollectionViewExampleView.swift │ │ ├── CollectionViewExampleViewController.swift │ │ └── HouseCell.swift │ ├── Form │ │ ├── FormView.swift │ │ └── FormViewController.swift │ ├── Intro │ │ ├── IntroView.swift │ │ └── IntroViewController.swift │ ├── IntroObjectiveC │ │ ├── IntroObjectiveCView.h │ │ ├── IntroObjectiveCView.m │ │ ├── IntroObjectiveCViewController.h │ │ └── IntroObjectiveCViewController.m │ ├── IntroRTL │ │ ├── IntroRTLView.swift │ │ └── IntroRTLViewController.swift │ ├── PinLayoutSample-Bridging-Header.h │ ├── RelativeView │ │ ├── RelativeView.swift │ │ └── RelativeViewController.swift │ ├── SafeArea │ │ ├── SafeAreaAndMarginsView.swift │ │ ├── SafeAreaAndMarginsViewController.swift │ │ ├── SafeAreaView.swift │ │ ├── SafeAreaViewController.swift │ │ └── Subviews │ │ │ ├── AreaView.swift │ │ │ └── RoundedButton.swift │ ├── TableViewExample │ │ ├── Cells │ │ │ ├── MethodCell.swift │ │ │ └── MethodGroupHeader.swift │ │ ├── TableViewExampleView.swift │ │ └── TableViewExampleViewController.swift │ ├── TableViewReadableContent │ │ ├── Cells │ │ │ ├── MethodReadableInsetsCell.swift │ │ │ └── MethodReadableInsetsGroupHeader.swift │ │ ├── TableViewReadableContentView.swift │ │ └── TableViewReadableContentViewController.swift │ └── WrapContent │ │ ├── WrapContentView.swift │ │ └── WrapContentViewController.swift │ └── Menu │ ├── MenuView.swift │ └── MenuViewController.swift ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── Package.swift ├── PinLayout.podspec ├── PinLayout.xcodeproj ├── PinLayoutTests_Info.plist ├── PinLayout_Info.plist ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ ├── PinLayout-iOS.xcscheme │ ├── PinLayout-macOS.xcscheme │ ├── PinLayout-tvOS.xcscheme │ └── xcschememanagement.plist ├── PinLayout.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── Podfile ├── Podfile.lock ├── README.md ├── Sources ├── AutoSizeCalculable.swift ├── Extensions │ ├── CALayer+PinLayout.swift │ ├── NSView+PinLayout.swift │ ├── PEdgeInsets+Operators.swift │ └── UIView+PinLayout.swift ├── Filters.swift ├── Impl │ ├── Coordinates.swift │ ├── Percent.swift │ ├── PinLayout+Coordinates.swift │ ├── PinLayout+Layouting.swift │ ├── PinLayout+Warning.swift │ ├── PinSafeArea.swift │ └── TypesImpl.swift ├── Layoutable+PinLayout.swift ├── Layoutable.swift ├── ObjectiveC │ ├── PinLayoutObjC.swift │ └── PinLayoutObjCImpl.swift ├── Pin.swift ├── PinLayout+Between.swift ├── PinLayout+Relative.swift ├── PinLayout+Size.swift ├── PinLayout+WrapContent.swift ├── PinLayout.swift ├── SizeCalculable.swift ├── SupportingFiles │ ├── Info.plist │ ├── PinLayout.h │ ├── PinLayoutMacOS.h │ └── PinLayoutTVOS.h ├── Types+Description.swift └── Types.swift ├── TestProjects ├── carthage │ └── ios │ │ ├── Cartfile │ │ ├── PinLayout-Carthage-iOS.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── PinLayout-Carthage-iOS │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── PinLayout-Carthage-iOS-Bridging-Header.h │ │ ├── TestObjectiveC.m │ │ └── ViewController.swift ├── cocoapods │ ├── ios │ │ ├── PinLayout-iOS.xcodeproj │ │ │ ├── project.pbxproj │ │ │ └── project.xcworkspace │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── PinLayout-iOS │ │ │ ├── AppDelegate.swift │ │ │ ├── Assets.xcassets │ │ │ │ ├── AppIcon.appiconset │ │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ │ ├── Base.lproj │ │ │ │ ├── LaunchScreen.storyboard │ │ │ │ └── Main.storyboard │ │ │ ├── Info.plist │ │ │ ├── PinLayout-iOS-Bridging-Header.h │ │ │ ├── TestObjectiveC.m │ │ │ └── ViewController.swift │ │ ├── Podfile │ │ └── Podfile.lock │ ├── macos │ │ ├── PinLayout-macOS.xcodeproj │ │ │ ├── project.pbxproj │ │ │ ├── project.xcworkspace │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ └── xcshareddata │ │ │ │ │ └── IDEWorkspaceChecks.plist │ │ │ └── xcshareddata │ │ │ │ └── xcschemes │ │ │ │ └── PinLayout-macOS.xcscheme │ │ ├── PinLayout-macOS │ │ │ ├── AppDelegate.swift │ │ │ ├── Assets.xcassets │ │ │ │ └── AppIcon.appiconset │ │ │ │ │ └── Contents.json │ │ │ ├── Info.plist │ │ │ ├── Main.storyboard │ │ │ ├── PinLayout-macOS-Bridging-Header.h │ │ │ └── TestObjectiveC.m │ │ ├── Podfile │ │ └── Podfile.lock │ └── tvos │ │ ├── PinLayout-tvOS.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── PinLayout-tvOS.xcscheme │ │ ├── PinLayout-tvOS │ │ ├── AppDelegate.swift │ │ ├── Info.plist │ │ ├── Main.storyboard │ │ ├── PinLayout-tvOS-Bridging-Header.h │ │ ├── TestObjectiveC.m │ │ └── ViewController.swift │ │ ├── Podfile │ │ └── Podfile.lock └── swift-package-manager │ └── ios │ ├── -destination │ ├── Logs │ │ ├── Package │ │ │ └── LogStoreManifest.plist │ │ └── Test │ │ │ └── LogStoreManifest.plist │ └── info.plist │ ├── Package.resolved │ ├── Package.swift │ ├── PinLayout-Carthage-iOS.xcodeproj │ └── project.xcworkspace │ │ └── xcshareddata │ │ └── swiftpm │ │ └── Package.resolved │ ├── PinLayout-SPM-iOS.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── swiftpm │ │ └── Package.resolved │ ├── PinLayout-SPM-iOS │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ └── ViewController.swift │ └── update_packages.sh ├── Tests ├── BasicView.swift ├── Common │ ├── AdjustSizeSpec.swift │ ├── AspectRatioTests.swift │ ├── BetweenSpec.swift │ ├── CALayerSpec.swift │ ├── Info.plist │ ├── JustifyAlignSpec.swift │ ├── LayoutMethodSpec.swift │ ├── MarginsSpec.swift │ ├── MinMaxWidthHeightSpec.swift │ ├── ObjectiveCSpec.m │ ├── PinEdgeCoordinateSpec.swift │ ├── PinEdgesSpec.swift │ ├── PinPointCoordinatesSpec.swift │ ├── RTLSpec.swift │ ├── RelativePositionMultipleViewsSpec.swift │ ├── RelativePositionSpec.swift │ ├── WarningSpec.swift │ └── WrapContentSpec.swift ├── Info.plist ├── RectNimbleMatcher.swift ├── UIImage+Color.swift ├── iOS │ ├── PinSafeAreaTests.swift │ ├── ReadableLayoutMarginsSpec.swift │ ├── TransformSpec.swift │ ├── Types+UIKit.swift │ └── UIScrollViewSpec.swift └── macOS │ ├── PinLayoutTestMacOS.swift │ └── Types+Appkit.swift ├── docs ├── 01-example-distance-superview-edge.png ├── 02-example-superview-edge.png ├── Benchmark.md ├── Benchmark │ └── benchmark_comparison_all_small.png ├── Keynote Layout presentation.key ├── PinLayout_principles.md ├── animations.md ├── example-anchors.png ├── example-edges.png ├── example-form.gif ├── example-multiple-anchors.png ├── example-superview-anchors.png ├── examples.md ├── images │ ├── example-animations-large.gif │ ├── example-animations.gif │ ├── pinlayout-sizeToFit.png │ ├── pinlayout_animation_example1.gif │ ├── pinlayout_example_anchor_center.png │ ├── pinlayout_example_layout_margins_all.png │ ├── pinlayout_example_layout_margins_landscape.png │ ├── pinlayout_example_layout_margins_portrain.png │ ├── pinlayout_example_tableview_readable_content_all.png │ ├── pinlayout_example_tableview_readable_content_landscape.png │ ├── pinlayout_example_tableview_readable_content_portrait.png │ ├── pinlayout_example_topRight.png │ ├── pinlayout_horizontallyBetween.png │ ├── pinlayout_intro_example_iphonex.png │ ├── pinlayout_plus_flexlayout_small.png │ ├── pinlayout_plus_layoutBox.png │ ├── pinlayout_relative_transform_scale_original.png │ ├── pinlayout_relative_transform_scale_pin.png │ ├── pinlayout_relative_transform_scale_pinFrame.png │ ├── pinlayout_right_to_left_example.png │ ├── pinlayout_safearea_2_example_iphonex.png │ ├── pinlayout_safearea_example_iphonex.png │ ├── pinlayout_transform_orig.png │ ├── pinlayout_transform_rotate_pin.png │ ├── pinlayout_transform_rotate_pinFrame.png │ ├── pinlayout_verticallyBetween.png │ ├── wrapContent_all.png │ ├── wrapContent_before.png │ ├── wrapContent_example.png │ ├── wrapContent_horizontally.png │ ├── wrapContent_padding.png │ └── wrapContent_vertically.png ├── objective_c.md ├── pinlayout-anchors.png ├── pinlayout-edges.png ├── pinlayout-example-cells.png ├── pinlayout-example-justify-center.png ├── pinlayout-example-justify-left.png ├── pinlayout-example-justify-remaining-space.png ├── pinlayout-example-justify-right.png ├── pinlayout-example-maxWidth.png ├── pinlayout-logo-small.png ├── pinlayout-logo-text.png ├── pinlayout-logo.png ├── pinlayout-margin-01.png ├── pinlayout-margin-02.png ├── pinlayout-margin-03.png ├── pinlayout-margin-04.png ├── pinlayout-margin-05.png ├── pinlayout-margin-pinEdges-01.png ├── pinlayout-margin-pinEdges-02.png ├── pinlayout-margin-pinEdges-03.png ├── pinlayout-relative-multi.png ├── pinlayout-relative-visible.png ├── pinlayout-relative-with-alignment.png ├── pinlayout-relative.png ├── pinlayout_example_adjust_to_container-landscape.png ├── pinlayout_example_adjust_to_container-portrait.png ├── pinlayout_example_adjust_to_container.png ├── pinlayout_example_adjust_to_container2.png ├── pinlayout_example_aspectratio.png ├── pinlayout_example_form.gif ├── pinlayout_example_hCenter_edge.png ├── pinlayout_example_wrapContent.png ├── pinlayout_exampleapp_auto_adjusting_size.png ├── pinlayout_exampleapp_automatic_sizing.png ├── pinlayout_exampleapp_collectionview.png ├── pinlayout_exampleapp_intro.png ├── pinlayout_exampleapp_multi_relative_position.png ├── pinlayout_exampleapp_relative_position.png ├── pinlayout_exampleapp_tableview.png ├── rtl_support.md └── xcode_playground.md └── index.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | 4 | .build/ 5 | build/ 6 | xcuserdata 7 | data/ 8 | 9 | Pods/ 10 | 11 | TestProjects/cocoapods/ios/PinLayout-iOS.xcworkspace/ 12 | TestProjects/cocoapods/macos/PinLayout-macOS.xcworkspace/ 13 | TestProjects/cocoapods/tvos/PinLayout-tvOS.xcworkspace/ 14 | 15 | TestProjects/carthage/ios/Cartfile.resolved 16 | TestProjects/carthage/ios/Carthage/ 17 | 18 | Example/PinLayoutExampleMacOS 19 | -------------------------------------------------------------------------------- /.ruby-version_old: -------------------------------------------------------------------------------- 1 | ruby-2.6.6 2 | -------------------------------------------------------------------------------- /.swiftlint.yml: -------------------------------------------------------------------------------- 1 | opt_in_rules: # some rules are only opt-in 2 | - closure_end_indentation 3 | - closure_spacing 4 | - explicit_init 5 | - nimble_operator 6 | - operator_usage_whitespace 7 | - overridden_super_call 8 | - private_outlet 9 | - prohibited_super_call 10 | - redundant_nil_coalescing 11 | 12 | disabled_rules: # rule identifiers to exclude from running 13 | - function_body_length 14 | - trailing_whitespace 15 | - force_cast 16 | - type_name 17 | - file_length 18 | - type_body_length 19 | - cyclomatic_complexity 20 | - nimble_operator 21 | - identifier_name 22 | - line_length 23 | - empty_count 24 | - todo 25 | - private_over_fileprivate 26 | 27 | excluded: # paths to ignore during linting. overridden by `included`. 28 | - Pods 29 | - Example/PinLayoutExampleMacOS 30 | - TestProjects 31 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/.DS_Store -------------------------------------------------------------------------------- /Example/.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | 4 | xcuserdata -------------------------------------------------------------------------------- /Example/.ruby-version: -------------------------------------------------------------------------------- 1 | 2.3.3 -------------------------------------------------------------------------------- /Example/.swiftlint.yml: -------------------------------------------------------------------------------- 1 | opt_in_rules: # some rules are only opt-in 2 | - closure_end_indentation 3 | - closure_spacing 4 | - explicit_init 5 | - nimble_operator 6 | - operator_usage_whitespace 7 | - overridden_super_call 8 | - private_outlet 9 | - prohibited_super_call 10 | - redundant_nil_coalescing 11 | 12 | disabled_rules: # rule identifiers to exclude from running 13 | - function_body_length 14 | - trailing_whitespace 15 | - force_cast 16 | - type_name 17 | - file_length 18 | - type_body_length 19 | - cyclomatic_complexity 20 | - nimble_operator 21 | - identifier_name 22 | - line_length 23 | - empty_count 24 | 25 | excluded: # paths to ignore during linting. overridden by `included`. 26 | - Pods 27 | - PinLayoutExampleMacOS -------------------------------------------------------------------------------- /Example/PinLayoutSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/PinLayoutSample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | import PinLayout 22 | 23 | @UIApplicationMain 24 | class AppDelegate: UIResponder, UIApplicationDelegate { 25 | var window: UIWindow? 26 | 27 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 28 | 29 | window = UIWindow(frame: UIScreen.main.bounds) 30 | window!.backgroundColor = UIColor.white 31 | window!.rootViewController = UINavigationController(rootViewController: MenuViewController()) 32 | window!.makeKeyAndVisible() 33 | 34 | return true 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /Example/PinLayoutSample/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-1024.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/PinLayout-logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "PinLayout-logo.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/PinLayout-logo.imageset/PinLayout-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/PinLayout-logo.imageset/PinLayout-logo.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Arrow.imageset/Arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Arrow.imageset/Arrow.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Arrow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "Arrow.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/ArrowCorner.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "arrow_corner_tl.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/ArrowCorner.imageset/arrow_corner_tl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/ArrowCorner.imageset/arrow_corner_tl.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Barcode.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_scan barcode_white.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "icon_scan barcode_white@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "icon_scan barcode_white@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Barcode.imageset/icon_scan barcode_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Barcode.imageset/icon_scan barcode_white.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Barcode.imageset/icon_scan barcode_white@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Barcode.imageset/icon_scan barcode_white@2x.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Barcode.imageset/icon_scan barcode_white@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Barcode.imageset/icon_scan barcode_white@3x.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Center.imageset/Center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Center.imageset/Center.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Center.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "Center.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/IconOrder.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "IconPickupLarge.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "IconPickupLarge@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "IconPickupLarge@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/IconOrder.imageset/IconPickupLarge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/IconOrder.imageset/IconPickupLarge.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/IconOrder.imageset/IconPickupLarge@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/IconOrder.imageset/IconPickupLarge@2x.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/IconOrder.imageset/IconPickupLarge@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/IconOrder.imageset/IconPickupLarge@3x.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Tab1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon orders.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "icon orders@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "icon orders@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Tab1.imageset/icon orders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Tab1.imageset/icon orders.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Tab1.imageset/icon orders@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Tab1.imageset/icon orders@2x.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Tab1.imageset/icon orders@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Tab1.imageset/icon orders@3x.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Tab2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "IconBin.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "IconBin@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "IconBin@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Tab2.imageset/IconBin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Tab2.imageset/IconBin.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Tab2.imageset/IconBin@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Tab2.imageset/IconBin@2x.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Tab2.imageset/IconBin@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/SafeArea/Tab2.imageset/IconBin@3x.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/method.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "method.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Assets.xcassets/method.imageset/method.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/Example/PinLayoutSample/Supporting Files/Assets.xcassets/method.imageset/method.png -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/Supporting Files/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Common/ContentService.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | class ContentService { 4 | static let shared = ContentService() 5 | 6 | private init() {} 7 | 8 | func fetchText(numberOfParagraph: Int = 1, completionHandler: ((Result<[String], Error>) -> Void)?) { 9 | URLSession.shared.dataTask(with: URL(string: "https://baconipsum.com/api/?type=all-meat¶s=\(numberOfParagraph)&start-with-lorem=1")!) { data, _, error in 10 | guard let data = data, error == nil, 11 | let paragraphs = try? JSONDecoder().decode([String].self, from: data) 12 | else { 13 | DispatchQueue.main.async { 14 | completionHandler?(Result<[String], Error>.failure(error!)) 15 | } 16 | return 17 | } 18 | 19 | DispatchQueue.main.async { 20 | completionHandler?(Result<[String], Error>.success(paragraphs)) 21 | } 22 | }.resume() 23 | } 24 | 25 | func fetchImage(width: Int, height: Int, completionHandler: ((Result) -> Void)?) { 26 | URLSession.shared.dataTask(with: URL(string: "https://baconmockup.com/\(width)/\(height)")!) { data, _, error in 27 | guard let data = data, error == nil, 28 | let image = UIImage(data: data) 29 | else { 30 | DispatchQueue.main.async { 31 | completionHandler?(Result.failure(error!)) 32 | } 33 | return 34 | } 35 | 36 | DispatchQueue.main.async { 37 | completionHandler?(Result.success(image)) 38 | } 39 | }.resume() 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Common/ProxyWrapper.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | @propertyWrapper 4 | public struct Proxy { 5 | private let keyPath: ReferenceWritableKeyPath 6 | 7 | public init(_ keyPath: ReferenceWritableKeyPath) { 8 | self.keyPath = keyPath 9 | } 10 | 11 | public var wrappedValue: Value { 12 | get { fatalError() } 13 | set { fatalError() } 14 | } 15 | 16 | public static subscript( 17 | _enclosingInstance observed: EnclosingSelf, 18 | wrapped wrappedKeyPath: ReferenceWritableKeyPath, 19 | storage storageKeyPath: ReferenceWritableKeyPath 20 | ) -> Value { 21 | get { 22 | let storageValue = observed[keyPath: storageKeyPath] 23 | let value = observed[keyPath: storageValue.keyPath] 24 | return value 25 | } 26 | set { 27 | let storageValue = observed[keyPath: storageKeyPath] 28 | observed[keyPath: storageValue.keyPath] = newValue 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Common/Stylesheet.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | 22 | extension UIColor { 23 | class var pinLayoutColor: UIColor { 24 | return UIColor(red: 90.0 / 255.0, green: 171.0 / 255.0, blue: 243.0 / 255.0, alpha: 1.0) 25 | } 26 | 27 | class var lightColor: UIColor { 28 | return UIColor(red: 230.0 / 255.0, green: 240.0 / 255.0, blue: 255.0 / 255.0, alpha: 1.0) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Common/UIEdgeInsets+PinLayout.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | 22 | extension UIEdgeInsets { 23 | func insetBy(dx: CGFloat, dy: CGFloat) -> UIEdgeInsets { 24 | return UIEdgeInsets(top: self.top + dy, left: self.left + dx, bottom: self.bottom + dy, right: self.right + dx) 25 | } 26 | 27 | func minInsets(_ insets: UIEdgeInsets) -> UIEdgeInsets { 28 | return UIEdgeInsets(top: minValue(self.top, minValue: insets.top), 29 | left: minValue(self.left, minValue: insets.left), 30 | bottom: minValue(self.bottom, minValue: insets.bottom), 31 | right: minValue(self.right, minValue: insets.right)) 32 | } 33 | 34 | func minInsets(dx: CGFloat, dy: CGFloat) -> UIEdgeInsets { 35 | return UIEdgeInsets(top: minValue(self.top, minValue: dy), 36 | left: minValue(self.left, minValue: dx), 37 | bottom: minValue(self.bottom, minValue: dy), 38 | right: minValue(self.right, minValue: dx)) 39 | } 40 | 41 | private func minValue(_ value: CGFloat, minValue: CGFloat) -> CGFloat { 42 | return value >= minValue ? value : minValue 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Common/UIImageView+Download.swift: -------------------------------------------------------------------------------- 1 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11 | // POSSIBILITY OF SUCH DAMAGE. 12 | // 13 | // Created by Luc Dion on 2017-10-31. 14 | 15 | import UIKit 16 | 17 | extension UIImageView { 18 | func download(url: URL) { 19 | URLSession.shared.dataTask(with: url) { data, response, error in 20 | guard 21 | let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200, 22 | let mimeType = response?.mimeType, mimeType.hasPrefix("image"), 23 | let data = data, error == nil, 24 | let image = UIImage(data: data) 25 | else { return } 26 | DispatchQueue.main.async { 27 | self.image = image 28 | } 29 | }.resume() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Common/UINavigationController+Orientation.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | import UIKit 20 | 21 | extension UINavigationController { 22 | open override var supportedInterfaceOrientations: UIInterfaceOrientationMask { 23 | if let visibleViewControllerOrientations = visibleViewController?.supportedInterfaceOrientations { 24 | return visibleViewControllerOrientations 25 | } else { 26 | return .all 27 | } 28 | } 29 | 30 | open override var shouldAutorotate: Bool { 31 | return visibleViewController?.shouldAutorotate ?? super.shouldAutorotate 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Common/UITabBarController+Orientation.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | import UIKit 20 | 21 | extension UITabBarController { 22 | open override var supportedInterfaceOrientations: UIInterfaceOrientationMask { 23 | if let selected = selectedViewController { 24 | return selected.supportedInterfaceOrientations 25 | } 26 | return super.supportedInterfaceOrientations 27 | } 28 | 29 | open override var shouldAutorotate: Bool { 30 | if let selected = selectedViewController { 31 | return selected.shouldAutorotate 32 | } 33 | return super.shouldAutorotate 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/AdjustToContainer/AdjustToContainerView.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | import PinLayout 22 | 23 | class AdjustToContainerView: UIView { 24 | private let languageSelectorView = ChoiceSelectorView(text: "What is your favorite language?", choices: ["Swift", "Objective-C", "C++"]) 25 | private let swiftOpinionSelector = ChoiceSelectorView(text: "Overall, are you satisfied with the Swift performance in your projects?", choices: ["Yes", "No"]) 26 | private let swiftUsageSelector = ChoiceSelectorView(text: "How often do you typically use Swift?", choices: ["Daily", "Weekly", "Montly", "Do not use"]) 27 | 28 | init() { 29 | super.init(frame: .zero) 30 | backgroundColor = .white 31 | 32 | addSubview(languageSelectorView) 33 | addSubview(swiftOpinionSelector) 34 | addSubview(swiftUsageSelector) 35 | } 36 | 37 | required init?(coder aDecoder: NSCoder) { 38 | super.init(coder: aDecoder) 39 | } 40 | 41 | override func layoutSubviews() { 42 | super.layoutSubviews() 43 | 44 | languageSelectorView.pin.top(pin.safeArea).horizontally(pin.safeArea).sizeToFit(.width) 45 | swiftOpinionSelector.pin.below(of: languageSelectorView).horizontally(pin.safeArea).marginTop(10).sizeToFit(.width) 46 | swiftUsageSelector.pin.below(of: swiftOpinionSelector).horizontally(pin.safeArea).marginTop(10).sizeToFit(.width) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/AdjustToContainer/AdjustToContainerViewController.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | 22 | class AdjustToContainerViewController: UIViewController { 23 | private var mainView: AdjustToContainerView { 24 | return self.view as! AdjustToContainerView 25 | } 26 | 27 | init(pageType: PageType) { 28 | super.init(nibName: nil, bundle: nil) 29 | 30 | title = pageType.title 31 | } 32 | 33 | required init?(coder aDecoder: NSCoder) { 34 | super.init(coder: aDecoder) 35 | } 36 | 37 | override func loadView() { 38 | view = AdjustToContainerView() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/Animations/AnimationsViewController.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | 22 | class AnimationsViewController: UIViewController { 23 | private var mainView: AnimationsView { 24 | return self.view as! AnimationsView 25 | } 26 | 27 | init(pageType: PageType) { 28 | super.init(nibName: nil, bundle: nil) 29 | 30 | title = pageType.title 31 | } 32 | 33 | required init?(coder aDecoder: NSCoder) { 34 | super.init(coder: aDecoder) 35 | } 36 | 37 | override func loadView() { 38 | view = AnimationsView() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/AutoAdjustingSize/AutoAdjustingSizeViewController.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | 22 | class AutoAdjustingSizeViewController: UIViewController { 23 | private var mainView: AutoAdjustingSizeView { 24 | return self.view as! AutoAdjustingSizeView 25 | } 26 | 27 | init(pageType: PageType) { 28 | super.init(nibName: nil, bundle: nil) 29 | 30 | title = pageType.title 31 | } 32 | 33 | required init?(coder aDecoder: NSCoder) { 34 | super.init(coder: aDecoder) 35 | } 36 | 37 | override func loadView() { 38 | view = AutoAdjustingSizeView() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/AutoSizing/AutoSizingContainerView.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | final class AutoSizingContainerView: UIView { 4 | private let imageView = UIImageView() 5 | private let firstTextLabel = UILabel() 6 | private let secondTextLabel = UILabel() 7 | 8 | private let margin: CGFloat = 10 9 | 10 | @Proxy(\AutoSizingContainerView.imageView.image) 11 | var image: UIImage? { 12 | didSet { 13 | setNeedsLayout() 14 | } 15 | } 16 | 17 | @Proxy(\AutoSizingContainerView.firstTextLabel.text) 18 | var firstText: String? { 19 | didSet { 20 | setNeedsLayout() 21 | } 22 | } 23 | 24 | @Proxy(\AutoSizingContainerView.secondTextLabel.text) 25 | var secondText: String? { 26 | didSet { 27 | setNeedsLayout() 28 | } 29 | } 30 | 31 | init() { 32 | super.init(frame: CGRect.zero) 33 | configureView() 34 | } 35 | 36 | required init?(coder: NSCoder) { 37 | fatalError("init(coder:) has not been implemented") 38 | } 39 | 40 | private func configureView() { 41 | imageView.clipsToBounds = true 42 | imageView.contentMode = .scaleAspectFill 43 | addSubview(imageView) 44 | 45 | firstTextLabel.numberOfLines = 0 46 | firstTextLabel.backgroundColor = UIColor.orange.withAlphaComponent(0.3) 47 | addSubview(firstTextLabel) 48 | 49 | secondTextLabel.numberOfLines = 0 50 | secondTextLabel.backgroundColor = UIColor.green.withAlphaComponent(0.3) 51 | addSubview(secondTextLabel) 52 | } 53 | 54 | override func layoutSubviews() { 55 | super.layoutSubviews() 56 | performLayout() 57 | } 58 | 59 | private func performLayout() { 60 | imageView.pin.top().horizontally().sizeToFit(.width).margin(margin) 61 | firstTextLabel.pin.below(of: imageView).horizontally().sizeToFit(.width).margin(margin) 62 | secondTextLabel.pin.below(of: firstTextLabel).horizontally().sizeToFit(.width).margin(margin) 63 | } 64 | 65 | override func sizeThatFits(_ size: CGSize) -> CGSize { 66 | autoSizeThatFits(size, layoutClosure: performLayout) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/AutoSizing/AutoSizingView.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import PinLayout 3 | 4 | final class AutoSizingView: UIView { 5 | private let scrollView = UIScrollView() 6 | private let containerView = AutoSizingContainerView() 7 | 8 | private let margin: CGFloat = 30 9 | 10 | init() { 11 | super.init(frame: CGRect.zero) 12 | configureView() 13 | } 14 | 15 | required init?(coder: NSCoder) { 16 | fatalError("init(coder:) has not been implemented") 17 | } 18 | 19 | private func configureView() { 20 | backgroundColor = .white 21 | 22 | scrollView.alwaysBounceVertical = true 23 | addSubview(scrollView) 24 | 25 | containerView.backgroundColor = UIColor.lightGray.withAlphaComponent(0.3) 26 | scrollView.addSubview(containerView) 27 | } 28 | 29 | func updateImage(_ image: UIImage?) { 30 | containerView.image = image 31 | setNeedsLayout() 32 | } 33 | 34 | func updateTexts(firstText: String?, secondText: String?) { 35 | containerView.firstText = firstText 36 | containerView.secondText = secondText 37 | setNeedsLayout() 38 | } 39 | 40 | override func layoutSubviews() { 41 | super.layoutSubviews() 42 | performLayout() 43 | didPerformLayout() 44 | } 45 | 46 | private func performLayout() { 47 | scrollView.pin.all() 48 | containerView.pin.top(margin).horizontally(margin).sizeToFit(.width) 49 | } 50 | 51 | private func didPerformLayout() { 52 | scrollView.contentSize = CGSize(width: bounds.width, height: containerView.frame.maxY + margin) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/AutoSizing/AutoSizingViewController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | class AutoSizingViewController: UIViewController { 4 | private var mainView: AutoSizingView { 5 | return self.view as! AutoSizingView 6 | } 7 | 8 | override func loadView() { 9 | self.view = AutoSizingView() 10 | } 11 | 12 | override func viewDidLoad() { 13 | super.viewDidLoad() 14 | configureNavigationBar() 15 | } 16 | 17 | override func viewWillAppear(_ animated: Bool) { 18 | super.viewWillAppear(animated) 19 | randomizeContent() 20 | } 21 | 22 | private func configureNavigationBar() { 23 | navigationItem.title = "AutoSizing" 24 | navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Randomize", style: .plain, target: self, action: #selector(randomizeContent)) 25 | } 26 | 27 | @objc 28 | private func randomizeContent() { 29 | ContentService.shared.fetchText(numberOfParagraph: 2) { [weak self] (result) in 30 | guard let strongSelf = self, case let .success(paragraphs) = result else { return } 31 | strongSelf.mainView.updateTexts(firstText: paragraphs[0], secondText: paragraphs[1]) 32 | } 33 | 34 | ContentService.shared.fetchImage(width: Int.random(in: 200..<500), height: Int.random(in: 200..<500)) { [weak self] (result) in 35 | guard let strongSelf = self, case let .success(image) = result else { return } 36 | strongSelf.mainView.updateImage(image) 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/BetweenView/BetweenView.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | import PinLayout 22 | 23 | class BetweenView: UIView { 24 | private let view1 = BasicView(text: "Relative view 1 (width: 20%, height: 50%)", color: .lightGray) 25 | private let view2 = BasicView(text: "Relative view 2 (width: 20%, height: 50%)", color: .lightGray) 26 | private let view = BasicView(text: "View layouted using method horizontallyBetween: \n - horizontallyBetween(view1, and: view2, aligned: .top)", 27 | color: .pinLayoutColor) 28 | 29 | init() { 30 | super.init(frame: .zero) 31 | backgroundColor = .white 32 | 33 | addSubview(view1) 34 | addSubview(view2) 35 | addSubview(view) 36 | } 37 | 38 | required init?(coder aDecoder: NSCoder) { 39 | super.init(coder: aDecoder) 40 | } 41 | 42 | override func layoutSubviews() { 43 | super.layoutSubviews() 44 | 45 | view1.pin.top(pin.safeArea).left(pin.safeArea).width(20%).height(50%) 46 | view2.pin.top(pin.safeArea).right(pin.safeArea).width(20%).height(50%) 47 | 48 | view.pin.horizontallyBetween(view1, and: view2, aligned: .top).height(of: view1).marginHorizontal(10) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/BetweenView/BetweenViewController.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | 22 | class BetweenViewController: UIViewController { 23 | private var mainView: BetweenView { 24 | return self.view as! BetweenView 25 | } 26 | 27 | init(pageType: PageType) { 28 | super.init(nibName: nil, bundle: nil) 29 | 30 | title = pageType.title 31 | } 32 | 33 | required init?(coder aDecoder: NSCoder) { 34 | fatalError("init(coder:) has not been implemented") 35 | } 36 | 37 | override func loadView() { 38 | view = BetweenView() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/Form/FormViewController.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | 22 | class FormViewController: UIViewController { 23 | private var mainView: FormView { 24 | return self.view as! FormView 25 | } 26 | 27 | init(pageType: PageType) { 28 | super.init(nibName: nil, bundle: nil) 29 | 30 | title = pageType.title 31 | } 32 | 33 | required init?(coder aDecoder: NSCoder) { 34 | super.init(coder: aDecoder) 35 | } 36 | 37 | override func loadView() { 38 | view = FormView() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/Intro/IntroViewController.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | 22 | class IntroViewController: UIViewController { 23 | private var mainView: IntroView { 24 | return self.view as! IntroView 25 | } 26 | 27 | init(pageType: PageType) { 28 | super.init(nibName: nil, bundle: nil) 29 | 30 | title = pageType.title 31 | } 32 | 33 | required init?(coder aDecoder: NSCoder) { 34 | super.init(coder: aDecoder) 35 | } 36 | 37 | override func loadView() { 38 | view = IntroView() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/IntroObjectiveC/IntroObjectiveCView.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | #ifndef IntroObjectiveCView_h 21 | #define IntroObjectiveCView_h 22 | 23 | @import UIKit; 24 | 25 | @interface IntroObjectiveCView: UIView { 26 | 27 | } 28 | 29 | - (void) setLayoutGuidesTop:(CGFloat)top; 30 | 31 | @end 32 | 33 | #endif /* IntroObjectiveCView_h */ 34 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/IntroObjectiveC/IntroObjectiveCViewController.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | #ifndef IntroObjectiveC_h 21 | #define IntroObjectiveC_h 22 | 23 | @import UIKit; 24 | 25 | @interface IntroObjectiveCViewController: UIViewController { 26 | } 27 | @end 28 | 29 | #endif /* IntroObjectiveC_h */ 30 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/IntroObjectiveC/IntroObjectiveCViewController.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | #import 21 | #import "IntroObjectiveCViewController.h" 22 | 23 | #import "IntroObjectiveCView.h" 24 | 25 | @implementation IntroObjectiveCViewController { 26 | } 27 | 28 | - (id) init { 29 | if (self = [super init]){ 30 | 31 | } 32 | return self; 33 | } 34 | 35 | - (void)loadView { 36 | self.view = [[IntroObjectiveCView alloc] initWithFrame: CGRectZero]; 37 | } 38 | 39 | - (void)viewWillLayoutSubviews { 40 | [super viewWillLayoutSubviews]; 41 | [((IntroObjectiveCView*)self.view) setLayoutGuidesTop:self.view.safeAreaInsets.top]; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/IntroRTL/IntroRTLViewController.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | 22 | class IntroRTLViewController: UIViewController { 23 | private var mainView: IntroRTLView { 24 | return self.view as! IntroRTLView 25 | } 26 | 27 | init(pageType: PageType) { 28 | super.init(nibName: nil, bundle: nil) 29 | 30 | title = pageType.title 31 | } 32 | 33 | required init?(coder aDecoder: NSCoder) { 34 | super.init(coder: aDecoder) 35 | } 36 | 37 | override func loadView() { 38 | view = IntroRTLView() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/PinLayoutSample-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | #import "IntroObjectiveCViewController.h" 21 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/RelativeView/RelativeViewController.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | 22 | class RelativeViewController: UIViewController { 23 | private var mainView: RelativeView { 24 | return self.view as! RelativeView 25 | } 26 | 27 | init(pageType: PageType) { 28 | super.init(nibName: nil, bundle: nil) 29 | 30 | title = pageType.title 31 | } 32 | 33 | required init?(coder aDecoder: NSCoder) { 34 | fatalError("init(coder:) has not been implemented") 35 | } 36 | 37 | override func loadView() { 38 | view = RelativeView() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/SafeArea/SafeAreaAndMarginsViewController.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | 22 | class SafeAreaAndMarginsViewController: UIViewController { 23 | private var mainView: SafeAreaAndMarginsView { 24 | return self.view as! SafeAreaAndMarginsView 25 | } 26 | 27 | init() { 28 | super.init(nibName: nil, bundle: nil) 29 | 30 | tabBarItem = UITabBarItem(title: "Layout areas", image: UIImage(named: "Tab2"), tag: 0) 31 | } 32 | 33 | required init?(coder aDecoder: NSCoder) { 34 | super.init(coder: aDecoder) 35 | } 36 | 37 | override func loadView() { 38 | view = SafeAreaAndMarginsView() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/SafeArea/SafeAreaViewController.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | 22 | class SafeAreaViewController: UIViewController { 23 | private var mainView: SafeAreaView { 24 | return self.view as! SafeAreaView 25 | } 26 | 27 | init() { 28 | super.init(nibName: nil, bundle: nil) 29 | 30 | tabBarItem = UITabBarItem(title: "SafeArea", image: UIImage(named: "Tab1"), tag: 0) 31 | } 32 | 33 | required init?(coder aDecoder: NSCoder) { 34 | super.init(coder: aDecoder) 35 | } 36 | 37 | override func loadView() { 38 | view = SafeAreaView() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/SafeArea/Subviews/AreaView.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | class AreaView: UIView { 4 | private let nameLabel = UILabel() 5 | 6 | init(name: String, color: UIColor) { 7 | super.init(frame: .zero) 8 | 9 | layer.borderColor = color.cgColor 10 | layer.borderWidth = 2 11 | 12 | nameLabel.text = name 13 | nameLabel.textColor = color 14 | nameLabel.font = .systemFont(ofSize: 18) 15 | nameLabel.layer.anchorPoint = CGPoint(x: 0, y: 1) 16 | nameLabel.transform = .init(rotationAngle: (CGFloat.pi / 2)) 17 | addSubview(nameLabel) 18 | } 19 | 20 | required init?(coder aDecoder: NSCoder) { 21 | fatalError("init(coder:) has not been implemented") 22 | } 23 | 24 | override func layoutSubviews() { 25 | super.layoutSubviews() 26 | 27 | nameLabel.pin.topLeft(1).sizeToFit() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/TableViewExample/Cells/MethodGroupHeader.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | 22 | class MethodGroupHeader: UITableViewHeaderFooterView { 23 | static let reuseIdentifier = "MethodGroupHeader" 24 | static let height: CGFloat = 50 25 | 26 | private let titleLabel = UILabel() 27 | 28 | override init(reuseIdentifier: String?) { 29 | super.init(reuseIdentifier: reuseIdentifier) 30 | 31 | titleLabel.font = UIFont.systemFont(ofSize: 20) 32 | contentView.addSubview(titleLabel) 33 | } 34 | 35 | required init?(coder aDecoder: NSCoder) { 36 | fatalError("init(coder:) has not been implemented") 37 | } 38 | 39 | func configure(title: String) { 40 | titleLabel.text = title 41 | } 42 | 43 | override func layoutSubviews() { 44 | super.layoutSubviews() 45 | 46 | titleLabel.pin.horizontally(10).vCenter().sizeToFit(.width) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/TableViewReadableContent/Cells/MethodReadableInsetsCell.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | class MethodReadableInsetsCell: UITableViewCell { 4 | static let reuseIdentifier = "MethodReadableInsetsCell" 5 | 6 | private let iconImageView = UIImageView(image: UIImage(named: "method")) 7 | private let nameLabel = UILabel() 8 | private let descriptionLabel = UILabel() 9 | private let margin: CGFloat = 10 10 | 11 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 12 | super.init(style: style, reuseIdentifier: reuseIdentifier) 13 | 14 | selectionStyle = .none 15 | separatorInset = .zero 16 | preservesSuperviewLayoutMargins = false 17 | 18 | contentView.addSubview(iconImageView) 19 | 20 | nameLabel.font = UIFont.boldSystemFont(ofSize: 14) 21 | nameLabel.lineBreakMode = .byTruncatingTail 22 | contentView.addSubview(nameLabel) 23 | 24 | descriptionLabel.font = UIFont.systemFont(ofSize: 12) 25 | descriptionLabel.numberOfLines = 0 26 | contentView.addSubview(descriptionLabel) 27 | } 28 | 29 | required init?(coder aDecoder: NSCoder) { 30 | super.init(coder: aDecoder) 31 | } 32 | 33 | func configure(method: Method) { 34 | nameLabel.text = method.name 35 | descriptionLabel.text = method.description 36 | } 37 | 38 | override func layoutSubviews() { 39 | super.layoutSubviews() 40 | layout() 41 | } 42 | 43 | private func layout() { 44 | // 1) Layout the contentView 45 | contentView.pin.top(margin).horizontally(pin.readableMargins) 46 | 47 | // 2) Layout contentView's childs 48 | iconImageView.pin.topLeft().size(30) 49 | nameLabel.pin.after(of: iconImageView, aligned: .center).right().marginHorizontal(margin).sizeToFit(.width) 50 | descriptionLabel.pin.below(of: [iconImageView, nameLabel]).horizontally().marginTop(margin).sizeToFit(.width) 51 | 52 | // 3) Adjust the contentView size to wrap its childs 53 | contentView.pin.wrapContent(.vertically) 54 | } 55 | 56 | override func sizeThatFits(_ size: CGSize) -> CGSize { 57 | // 1) Set the width to the specified size parameter 58 | pin.width(size.width) 59 | 60 | // 2) Layout the contentView's controls 61 | layout() 62 | 63 | // 3) Returns a size that contains all views 64 | return CGSize(width: size.width, height: contentView.frame.maxY + margin) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/TableViewReadableContent/Cells/MethodReadableInsetsGroupHeader.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | 22 | class MethodReadableInsetsGroupHeader: UITableViewHeaderFooterView { 23 | static let reuseIdentifier = "MethodReadableInsetsGroupHeader" 24 | static let height: CGFloat = 50 25 | 26 | fileprivate let titleLabel = UILabel() 27 | 28 | override init(reuseIdentifier: String?) { 29 | super.init(reuseIdentifier: reuseIdentifier) 30 | 31 | preservesSuperviewLayoutMargins = false 32 | 33 | titleLabel.font = .systemFont(ofSize: 20) 34 | contentView.addSubview(titleLabel) 35 | } 36 | 37 | required init?(coder aDecoder: NSCoder) { 38 | fatalError("init(coder:) has not been implemented") 39 | } 40 | 41 | func configure(title: String) { 42 | titleLabel.text = title 43 | } 44 | 45 | override func layoutSubviews() { 46 | super.layoutSubviews() 47 | 48 | contentView.pin.horizontally(pin.readableMargins) 49 | titleLabel.pin.horizontally().vCenter().sizeToFit(.width) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Example/PinLayoutSample/UI/Examples/WrapContent/WrapContentViewController.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | 22 | class WrapContentViewController: UIViewController { 23 | private var mainView: WrapContentView { 24 | return self.view as! WrapContentView 25 | } 26 | 27 | init(pageType: PageType) { 28 | super.init(nibName: nil, bundle: nil) 29 | 30 | title = pageType.title 31 | } 32 | 33 | required init?(coder aDecoder: NSCoder) { 34 | super.init(coder: aDecoder) 35 | } 36 | 37 | override func loadView() { 38 | view = WrapContentView() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gem 'cocoapods', '~> 1.7' 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2018 Luc Dion 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.4 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "PinLayout", 7 | products: [ 8 | .library(name: "PinLayout", targets: ["PinLayout"]) 9 | ], 10 | targets: [ 11 | .target( 12 | name: "PinLayout", 13 | path: "Sources", 14 | exclude: [ 15 | "SupportingFiles/Info.plist" 16 | ] 17 | ) 18 | ] 19 | ) 20 | -------------------------------------------------------------------------------- /PinLayout.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint Taylor.podspec' to ensure this is a 3 | # valid spec and to remove all comments including this before submitting the spec. 4 | # 5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html 6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ 7 | # 8 | 9 | Pod::Spec.new do |spec| 10 | spec.name = "PinLayout" 11 | spec.version = "1.10.5" 12 | spec.summary = "Fast Swift Views layouting without auto layout. No magic, pure code, full control and blazing fast." 13 | spec.description = "Fast Swift Views layouting without auto layout. No magic, pure code, full control and blazing fast. Concise syntax, intuitive, readable & chainable. [iOS/macOS/tvOS/CALayer]" 14 | spec.homepage = "https://github.com/layoutBox/PinLayout" 15 | spec.license = "MIT license" 16 | spec.author = { "Luc Dion" => "luc_dion@yahoo.com" } 17 | spec.source = { :git => "https://github.com/layoutBox/PinLayout.git", :tag => "#{spec.version}" } 18 | spec.source_files = "Sources/**/*.swift" 19 | spec.swift_versions = ['4.2', '5.7'] 20 | 21 | spec.ios.deployment_target = '12.0' 22 | spec.ios.frameworks = 'Foundation', 'CoreGraphics', 'UIKit' 23 | 24 | spec.tvos.deployment_target = '12.0' 25 | spec.tvos.frameworks = 'Foundation', 'CoreGraphics', 'UIKit' 26 | 27 | spec.osx.deployment_target = '10.13' 28 | spec.osx.frameworks = 'Foundation', 'CoreGraphics', 'AppKit' 29 | end 30 | -------------------------------------------------------------------------------- /PinLayout.xcodeproj/PinLayoutTests_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | BNDL 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /PinLayout.xcodeproj/PinLayout_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | FMWK 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /PinLayout.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PinLayout.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /PinLayout.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SchemeUserState 5 | 6 | PinLayout.xcscheme 7 | 8 | 9 | SuppressBuildableAutocreation 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /PinLayout.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /PinLayout.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | source 'https://cdn.cocoapods.org/' 2 | use_frameworks! 3 | 4 | workspace 'PinLayout.xcworkspace' 5 | 6 | target 'PinLayoutTests-iOS' do 7 | platform :ios, "12.0" 8 | project 'PinLayout.xcodeproj' 9 | 10 | pod 'Quick' 11 | pod 'Nimble', :inhibit_warnings => true 12 | end 13 | 14 | target 'PinLayoutTests-tvOS' do 15 | platform :tvos, "12.0" 16 | project 'PinLayout.xcodeproj' 17 | 18 | pod 'Quick' 19 | pod 'Nimble', :inhibit_warnings => true 20 | end 21 | 22 | target 'PinLayoutTests-macOS' do 23 | platform :osx, "10.13" 24 | project 'PinLayout.xcodeproj' 25 | 26 | pod 'Quick' 27 | pod 'Nimble', :inhibit_warnings => true 28 | end 29 | 30 | target 'PinLayoutSample' do 31 | platform :ios, "12.0" 32 | project 'Example/PinLayoutSample.xcodeproj' 33 | 34 | pod 'PinLayout', :path => './' 35 | pod 'SwiftLint' 36 | end 37 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Nimble (10.0.0) 3 | - PinLayout (1.10.4) 4 | - Quick (5.0.1) 5 | - SwiftLint (0.50.3) 6 | 7 | DEPENDENCIES: 8 | - Nimble 9 | - PinLayout (from `./`) 10 | - Quick 11 | - SwiftLint 12 | 13 | SPEC REPOS: 14 | trunk: 15 | - Nimble 16 | - Quick 17 | - SwiftLint 18 | 19 | EXTERNAL SOURCES: 20 | PinLayout: 21 | :path: "./" 22 | 23 | SPEC CHECKSUMS: 24 | Nimble: 5316ef81a170ce87baf72dd961f22f89a602ff84 25 | PinLayout: f8a677ce0cd1cfe96b58435d029b4ceb4ce9c04c 26 | Quick: 749aa754fd1e7d984f2000fe051e18a3a9809179 27 | SwiftLint: 77f7cb2b9bb81ab4a12fcc86448ba3f11afa50c6 28 | 29 | PODFILE CHECKSUM: 373beda8a5b3bfadeb1918c9d5c439ae90f949f1 30 | 31 | COCOAPODS: 1.12.0 32 | -------------------------------------------------------------------------------- /Sources/AutoSizeCalculable.swift: -------------------------------------------------------------------------------- 1 | #if os(iOS) || os(tvOS) 2 | import UIKit 3 | #else 4 | import AppKit 5 | #endif 6 | 7 | public protocol AutoSizeCalculable { 8 | func setAutoSizingRect(_ rect: CGRect, margins: PEdgeInsets) 9 | func autoSizeThatFits(_ size: CGSize, layoutClosure: () -> Void) -> CGSize 10 | } 11 | -------------------------------------------------------------------------------- /Sources/Extensions/PEdgeInsets+Operators.swift: -------------------------------------------------------------------------------- 1 | #if os(iOS) || os(tvOS) 2 | import UIKit 3 | #else 4 | import AppKit 5 | #endif 6 | 7 | public extension PEdgeInsets { 8 | func minInsets(_ insets: PEdgeInsets) -> PEdgeInsets { 9 | return PEdgeInsets(top: minValue(self.top, minValue: insets.top), 10 | left: minValue(self.left, minValue: insets.left), 11 | bottom: minValue(self.bottom, minValue: insets.bottom), 12 | right: minValue(self.right, minValue: insets.right)) 13 | } 14 | 15 | func minInsets(dx: CGFloat, dy: CGFloat) -> PEdgeInsets { 16 | return PEdgeInsets(top: minValue(self.top, minValue: dy), 17 | left: minValue(self.left, minValue: dx), 18 | bottom: minValue(self.bottom, minValue: dy), 19 | right: minValue(self.right, minValue: dx)) 20 | } 21 | 22 | private func minValue(_ value: CGFloat, minValue: CGFloat) -> CGFloat { 23 | return value >= minValue ? value : minValue 24 | } 25 | } 26 | 27 | public func + (lhs: PEdgeInsets, rhs: Int) -> PEdgeInsets { 28 | let rhsf = CGFloat(rhs) 29 | return PEdgeInsets(top: lhs.top + rhsf, 30 | left: lhs.left + rhsf, 31 | bottom: lhs.bottom + rhsf, 32 | right: lhs.right + rhsf) 33 | } 34 | 35 | public func + (lhs: PEdgeInsets, rhs: CGFloat) -> PEdgeInsets { 36 | return PEdgeInsets(top: lhs.top + rhs, 37 | left: lhs.left + rhs, 38 | bottom: lhs.bottom + rhs, 39 | right: lhs.right + rhs) 40 | } 41 | -------------------------------------------------------------------------------- /Sources/Filters.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | #if os(iOS) || os(tvOS) 21 | import UIKit 22 | 23 | // Filter out all hidden views (isHidden is true or alpha is 0) 24 | public func visible(_ views: [UIView]) -> [UIView] { 25 | return views.filter({ !$0.isHidden && $0.alpha > 0 }) 26 | } 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /Sources/Impl/Percent.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | #if os(iOS) || os(tvOS) 21 | import UIKit 22 | #else 23 | import AppKit 24 | #endif 25 | 26 | public struct Percent { 27 | let value: CGFloat 28 | 29 | public func of(_ value: CGFloat) -> CGFloat { 30 | return value * self.value / 100 31 | } 32 | 33 | public var description: String { 34 | if value.truncatingRemainder(dividingBy: 1) == 0.0 { 35 | return "\(Int(value))%" 36 | } else { 37 | return "\(value)%" 38 | } 39 | } 40 | } 41 | 42 | postfix operator % 43 | 44 | public postfix func % (v: CGFloat) -> Percent { 45 | return Percent(value: v) 46 | } 47 | 48 | public postfix func % (v: Float) -> Percent { 49 | return Percent(value: CGFloat(v)) 50 | } 51 | 52 | public postfix func % (v: Double) -> Percent { 53 | return Percent(value: CGFloat(v)) 54 | } 55 | 56 | public postfix func % (v: Int) -> Percent { 57 | return Percent(value: CGFloat(v)) 58 | } 59 | 60 | prefix operator - 61 | public prefix func - (p: Percent) -> Percent { 62 | return Percent(value: -p.value) 63 | } 64 | -------------------------------------------------------------------------------- /Sources/Layoutable+PinLayout.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import Foundation 21 | 22 | extension Layoutable { 23 | public var anchor: AnchorList { 24 | return AnchorListImpl(view: self as! PinView) 25 | } 26 | 27 | public var edge: EdgeList { 28 | return EdgeListImpl(view: self as! PinView) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Sources/Layoutable.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | #if os(iOS) || os(tvOS) 21 | import UIKit 22 | #else 23 | import AppKit 24 | #endif 25 | 26 | public protocol Layoutable: AnyObject, Equatable, CustomDebugStringConvertible { 27 | associatedtype PinView: Layoutable 28 | 29 | var superview: PinView? { get } 30 | var subviews: [PinView] { get } 31 | 32 | func getRect(keepTransform: Bool) -> CGRect 33 | func setRect(_ rect: CGRect, keepTransform: Bool) 34 | 35 | func convert(_ point: CGPoint, to view: PinView?) -> CGPoint 36 | 37 | func isLTR() -> Bool 38 | } 39 | -------------------------------------------------------------------------------- /Sources/SizeCalculable.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | #if os(iOS) || os(tvOS) 21 | import UIKit 22 | #else 23 | import AppKit 24 | #endif 25 | 26 | public protocol SizeCalculable { 27 | func sizeThatFits(_ size: CGSize) -> CGSize 28 | } 29 | -------------------------------------------------------------------------------- /Sources/SupportingFiles/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Sources/SupportingFiles/PinLayout.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | #import 21 | 22 | //! Project version number for PinLayout. 23 | FOUNDATION_EXPORT double PinLayoutVersionNumber; 24 | 25 | //! Project version string for PinLayout. 26 | FOUNDATION_EXPORT const unsigned char PinLayoutVersionString[]; 27 | 28 | // In this header, you should import all the public headers of your framework using statements like #import 29 | 30 | 31 | -------------------------------------------------------------------------------- /Sources/SupportingFiles/PinLayoutMacOS.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | #import 21 | 22 | //! Project version number for PinLayoutMacOS. 23 | FOUNDATION_EXPORT double PinLayoutMacOSVersionNumber; 24 | 25 | //! Project version string for PinLayoutMacOS. 26 | FOUNDATION_EXPORT const unsigned char PinLayoutMacOSVersionString[]; 27 | 28 | // In this header, you should import all the public headers of your framework using statements like #import 29 | 30 | 31 | -------------------------------------------------------------------------------- /Sources/SupportingFiles/PinLayoutTVOS.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | #import 21 | 22 | //! Project version number for PinLayoutTVOS. 23 | FOUNDATION_EXPORT double PinLayoutTVOSVersionNumber; 24 | 25 | //! Project version string for PinLayoutTVOS. 26 | FOUNDATION_EXPORT const unsigned char PinLayoutTVOSVersionString[]; 27 | 28 | // In this header, you should import all the public headers of your framework using statements like #import 29 | 30 | 31 | -------------------------------------------------------------------------------- /TestProjects/carthage/ios/Cartfile: -------------------------------------------------------------------------------- 1 | git "file:////Users/lucdion/dev_luc/PinLayout" 2 | -------------------------------------------------------------------------------- /TestProjects/carthage/ios/PinLayout-Carthage-iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TestProjects/carthage/ios/PinLayout-Carthage-iOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TestProjects/carthage/ios/PinLayout-Carthage-iOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit 3 | 4 | @UIApplicationMain 5 | class AppDelegate: UIResponder, UIApplicationDelegate { 6 | 7 | var window: UIWindow? 8 | 9 | 10 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 11 | // Override point for customization after application launch. 12 | return true 13 | } 14 | 15 | func applicationWillResignActive(_ application: UIApplication) { 16 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 17 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 18 | } 19 | 20 | func applicationDidEnterBackground(_ application: UIApplication) { 21 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 22 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 23 | } 24 | 25 | func applicationWillEnterForeground(_ application: UIApplication) { 26 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 27 | } 28 | 29 | func applicationDidBecomeActive(_ application: UIApplication) { 30 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 31 | } 32 | 33 | func applicationWillTerminate(_ application: UIApplication) { 34 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 35 | } 36 | 37 | 38 | } 39 | 40 | -------------------------------------------------------------------------------- /TestProjects/carthage/ios/PinLayout-Carthage-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /TestProjects/carthage/ios/PinLayout-Carthage-iOS/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /TestProjects/carthage/ios/PinLayout-Carthage-iOS/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /TestProjects/carthage/ios/PinLayout-Carthage-iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /TestProjects/carthage/ios/PinLayout-Carthage-iOS/PinLayout-Carthage-iOS-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | -------------------------------------------------------------------------------- /TestProjects/carthage/ios/PinLayout-Carthage-iOS/TestObjectiveC.m: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | @import UIKit; 5 | @import PinLayout; 6 | 7 | @interface IntroObjectiveCView: UIView { 8 | } 9 | @end 10 | 11 | @implementation IntroObjectiveCView { 12 | CGFloat topLayoutGuide; 13 | UIImageView* logo; 14 | UISegmentedControl* segmented; 15 | UILabel* textLabel; 16 | UIView* separatorView; 17 | } 18 | 19 | - (id)initWithFrame:(CGRect)frame { 20 | if ((self = [super initWithFrame:frame])) { 21 | topLayoutGuide = 0; 22 | self.backgroundColor = UIColor.whiteColor; 23 | 24 | logo = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"PinLayout-logo" inBundle:nil compatibleWithTraitCollection:nil]]; 25 | [self addSubview:logo]; 26 | 27 | segmented = [[UISegmentedControl alloc] initWithItems: @[@"Intro", @"1", @"2"]]; 28 | [self addSubview:segmented]; 29 | 30 | textLabel = [[UILabel alloc] init]; 31 | textLabel.text = @"Swift manual views layouting without auto layout, no magic, pure code, full control. Concise syntax, readable & chainable.\n\nSwift manual views layouting without auto layout, no magic, pure code, full control. Concise syntax, readable & chainable."; 32 | textLabel.font = [UIFont systemFontOfSize:14]; 33 | textLabel.numberOfLines = 0; 34 | textLabel.lineBreakMode = NSLineBreakByWordWrapping; 35 | [self addSubview:textLabel]; 36 | 37 | separatorView = [[UIView alloc] init]; 38 | separatorView.backgroundColor = UIColor.grayColor; 39 | 40 | [self addSubview:separatorView]; 41 | } 42 | return self; 43 | } 44 | 45 | - (void) layoutSubviews { 46 | [super layoutSubviews]; 47 | 48 | logo.pinObjc.top().left().width(100).aspectRatio().marginTHB(topLayoutGuide + 10, 10, 10).layout(); 49 | segmented.pinObjc.rightOfAligned(logo, VerticalAlignTop).right().marginHorizontal(10).layout(); 50 | textLabel.pinObjc.belowOfAligned(segmented, HorizontalAlignLeft).widthOf(segmented).pinEdges().marginTop(10).sizeToFitType(FitWidth).layout(); 51 | separatorView.pinObjc.belowOfViewsAligned(@[logo, textLabel], HorizontalAlignLeft).rightToEdge(segmented.edge.right).height(1).marginTop(10).layout(); 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /TestProjects/carthage/ios/PinLayout-Carthage-iOS/ViewController.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit 3 | import PinLayout 4 | 5 | class ViewController: UIViewController { 6 | fileprivate let subview = UIView() 7 | 8 | override func viewDidLoad() { 9 | super.viewDidLoad() 10 | 11 | subview.backgroundColor = .red 12 | view.addSubview(subview) 13 | } 14 | 15 | override func didReceiveMemoryWarning() { 16 | super.didReceiveMemoryWarning() 17 | // Dispose of any resources that can be recreated. 18 | } 19 | 20 | override func viewDidLayoutSubviews() { 21 | super.viewDidLayoutSubviews() 22 | 23 | subview.pin.horizontally(20%).vertically(30%) 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/ios/PinLayout-iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/ios/PinLayout-iOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/ios/PinLayout-iOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit 3 | 4 | @UIApplicationMain 5 | class AppDelegate: UIResponder, UIApplicationDelegate { 6 | 7 | var window: UIWindow? 8 | 9 | 10 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 11 | // Override point for customization after application launch. 12 | return true 13 | } 14 | 15 | func applicationWillResignActive(_ application: UIApplication) { 16 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 17 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 18 | } 19 | 20 | func applicationDidEnterBackground(_ application: UIApplication) { 21 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 22 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 23 | } 24 | 25 | func applicationWillEnterForeground(_ application: UIApplication) { 26 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 27 | } 28 | 29 | func applicationDidBecomeActive(_ application: UIApplication) { 30 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 31 | } 32 | 33 | func applicationWillTerminate(_ application: UIApplication) { 34 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 35 | } 36 | 37 | 38 | } 39 | 40 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/ios/PinLayout-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /TestProjects/cocoapods/ios/PinLayout-iOS/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /TestProjects/cocoapods/ios/PinLayout-iOS/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/ios/PinLayout-iOS/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/ios/PinLayout-iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/ios/PinLayout-iOS/PinLayout-iOS-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/ios/PinLayout-iOS/TestObjectiveC.m: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | @import UIKit; 5 | @import PinLayout; 6 | 7 | @interface IntroObjectiveCView: UIView { 8 | } 9 | @end 10 | 11 | @implementation IntroObjectiveCView { 12 | CGFloat topLayoutGuide; 13 | UIImageView* logo; 14 | UISegmentedControl* segmented; 15 | UILabel* textLabel; 16 | UIView* separatorView; 17 | } 18 | 19 | - (id)initWithFrame:(CGRect)frame { 20 | if ((self = [super initWithFrame:frame])) { 21 | topLayoutGuide = 0; 22 | self.backgroundColor = UIColor.whiteColor; 23 | 24 | logo = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"PinLayout-logo" inBundle:nil compatibleWithTraitCollection:nil]]; 25 | [self addSubview:logo]; 26 | 27 | segmented = [[UISegmentedControl alloc] initWithItems: @[@"Intro", @"1", @"2"]]; 28 | [self addSubview:segmented]; 29 | 30 | textLabel = [[UILabel alloc] init]; 31 | textLabel.text = @"Swift manual views layouting without auto layout, no magic, pure code, full control. Concise syntax, readable & chainable.\n\nSwift manual views layouting without auto layout, no magic, pure code, full control. Concise syntax, readable & chainable."; 32 | textLabel.font = [UIFont systemFontOfSize:14]; 33 | textLabel.numberOfLines = 0; 34 | textLabel.lineBreakMode = NSLineBreakByWordWrapping; 35 | [self addSubview:textLabel]; 36 | 37 | separatorView = [[UIView alloc] init]; 38 | separatorView.backgroundColor = UIColor.grayColor; 39 | 40 | [self addSubview:separatorView]; 41 | } 42 | return self; 43 | } 44 | 45 | - (void) layoutSubviews { 46 | [super layoutSubviews]; 47 | 48 | logo.pinObjc.top().left().width(100).aspectRatio().marginTHB(topLayoutGuide + 10, 10, 10).layout(); 49 | segmented.pinObjc.rightOfAligned(logo, VerticalAlignTop).right().marginHorizontal(10).layout(); 50 | textLabel.pinObjc.belowOfAligned(segmented, HorizontalAlignLeft).widthOf(segmented).pinEdges().marginTop(10).sizeToFitType(FitWidth).layout(); 51 | separatorView.pinObjc.belowOfViewsAligned(@[logo, textLabel], HorizontalAlignLeft).rightToEdge(segmented.edge.right).height(1).marginTop(10).layout(); 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/ios/PinLayout-iOS/ViewController.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit 3 | import PinLayout 4 | 5 | class ViewController: UIViewController { 6 | // PinLayout 7 | fileprivate let logo = UIImageView(image: UIImage(named: "PinLayout-logo")) 8 | fileprivate let label1 = UILabel() 9 | fileprivate let label2 = UILabel() 10 | fileprivate let label3 = UILabel() 11 | 12 | // FlexLayout 13 | fileprivate let flexContainer = UIView() 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | 18 | logo.layer.borderColor = UIColor.black.cgColor 19 | logo.layer.borderWidth = 1 20 | logo.contentMode = .scaleAspectFit 21 | view.addSubview(logo) 22 | 23 | label1.text = "PinLayout Label 1" 24 | label1.font = .systemFont(ofSize: 14) 25 | view.addSubview(label1) 26 | 27 | label2.text = "PinLayout Label 2" 28 | label2.font = .systemFont(ofSize: 14) 29 | view.addSubview(label2) 30 | 31 | label3.text = "PinLayout Label 3" 32 | label3.font = .systemFont(ofSize: 14) 33 | view.addSubview(label3) 34 | } 35 | 36 | override func viewDidLayoutSubviews() { 37 | super.viewDidLayoutSubviews() 38 | 39 | // PinLayout 40 | logo.pin.top().left().size(100).margin(view.safeAreaInsets.top + 10, 10, 10) 41 | label1.pin.after(of: logo, aligned: .top).right().marginHorizontal(10).sizeToFit(.width) 42 | label2.pin.after(of: logo, aligned: .center).right().marginHorizontal(10).sizeToFit(.width) 43 | label3.pin.after(of: logo, aligned: .bottom).right().marginHorizontal(10).sizeToFit(.width) 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/ios/Podfile: -------------------------------------------------------------------------------- 1 | source 'https://cdn.cocoapods.org/' 2 | platform :ios, '12.0' 3 | 4 | use_frameworks! 5 | 6 | target 'PinLayout-iOS' do 7 | #pod 'PinLayout' 8 | #pod 'PinLayout', :git => 'https://github.com/layoutBox/PinLayout.git', :commit => 'f29519b08890da144772fe9b082cd6499b5d82c1' 9 | pod 'PinLayout', :path => '../../..' 10 | 11 | 12 | # Include popular libraries that include UIKit classes extensions to check conflicts with PinLayout. 13 | pod 'SwifterSwift' 14 | end 15 | 16 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - PinLayout (1.10.4) 3 | - SwifterSwift (5.2.0): 4 | - SwifterSwift/AppKit (= 5.2.0) 5 | - SwifterSwift/CoreAnimation (= 5.2.0) 6 | - SwifterSwift/CoreGraphics (= 5.2.0) 7 | - SwifterSwift/CoreLocation (= 5.2.0) 8 | - SwifterSwift/Dispatch (= 5.2.0) 9 | - SwifterSwift/Foundation (= 5.2.0) 10 | - SwifterSwift/MapKit (= 5.2.0) 11 | - SwifterSwift/SceneKit (= 5.2.0) 12 | - SwifterSwift/SpriteKit (= 5.2.0) 13 | - SwifterSwift/StoreKit (= 5.2.0) 14 | - SwifterSwift/SwiftStdlib (= 5.2.0) 15 | - SwifterSwift/UIKit (= 5.2.0) 16 | - SwifterSwift/AppKit (5.2.0) 17 | - SwifterSwift/CoreAnimation (5.2.0) 18 | - SwifterSwift/CoreGraphics (5.2.0) 19 | - SwifterSwift/CoreLocation (5.2.0) 20 | - SwifterSwift/Dispatch (5.2.0) 21 | - SwifterSwift/Foundation (5.2.0) 22 | - SwifterSwift/MapKit (5.2.0) 23 | - SwifterSwift/SceneKit (5.2.0) 24 | - SwifterSwift/SpriteKit (5.2.0) 25 | - SwifterSwift/StoreKit (5.2.0) 26 | - SwifterSwift/SwiftStdlib (5.2.0) 27 | - SwifterSwift/UIKit (5.2.0) 28 | 29 | DEPENDENCIES: 30 | - PinLayout (from `../../..`) 31 | - SwifterSwift 32 | 33 | SPEC REPOS: 34 | trunk: 35 | - SwifterSwift 36 | 37 | EXTERNAL SOURCES: 38 | PinLayout: 39 | :path: "../../.." 40 | 41 | SPEC CHECKSUMS: 42 | PinLayout: f8a677ce0cd1cfe96b58435d029b4ceb4ce9c04c 43 | SwifterSwift: 334181863c416882d97b7a60c05054d9e4d799e2 44 | 45 | PODFILE CHECKSUM: f40959ab258f12059918e48f6019cb401a81723f 46 | 47 | COCOAPODS: 1.12.0 48 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/macos/PinLayout-macOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/macos/PinLayout-macOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/macos/PinLayout-macOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2017 LinkedIn Corp. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 3 | // You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 4 | // 5 | // Unless required by applicable law or agreed to in writing, 6 | // software distributed under the License is distributed on an "AS IS" BASIS, 7 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8 | 9 | import Cocoa 10 | import PinLayout 11 | 12 | @NSApplicationMain 13 | class AppDelegate: NSObject, NSApplicationDelegate { 14 | func applicationDidFinishLaunching(_ aNotification: Notification) { 15 | let view = NSView() 16 | view.pin.top().bottom().all() 17 | } 18 | 19 | func applicationWillTerminate(_ aNotification: Notification) { 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/macos/PinLayout-macOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /TestProjects/cocoapods/macos/PinLayout-macOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | Copyright © 2017 Linkedin. All rights reserved. 27 | NSMainStoryboardFile 28 | Main 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/macos/PinLayout-macOS/PinLayout-macOS-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/macos/PinLayout-macOS/TestObjectiveC.m: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | @import AppKit; 5 | @import PinLayout; 6 | 7 | @interface IntroObjectiveCView: NSView { 8 | } 9 | @end 10 | 11 | @implementation IntroObjectiveCView { 12 | CGFloat topLayoutGuide; 13 | NSImageView* logo; 14 | NSView* separatorView; 15 | } 16 | 17 | - (id)initWithFrame:(CGRect)frame { 18 | if ((self = [super initWithFrame:frame])) { 19 | topLayoutGuide = 0; 20 | 21 | logo = [[NSImageView alloc] init]; 22 | separatorView = [[NSView alloc] init]; 23 | } 24 | return self; 25 | } 26 | 27 | - (void)layout { 28 | [super layout]; 29 | 30 | logo.pinObjc.top().left().width(100).marginTHB(topLayoutGuide + 10, 10, 10).layout(); 31 | separatorView.pinObjc.belowOfAligned(logo, HorizontalAlignLeft).height(1).marginTop(10).layout(); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/macos/Podfile: -------------------------------------------------------------------------------- 1 | source 'https://cdn.cocoapods.org/' 2 | platform :osx, '10.13' 3 | 4 | use_frameworks! 5 | 6 | target 'PinLayout-macOS' do 7 | #pod 'PinLayout' 8 | #pod 'PinLayout', :git => 'https://github.com/layoutBox/PinLayout.git', :commit => 'f29519b08890da144772fe9b082cd6499b5d82c1' 9 | pod 'PinLayout', :path => '../../..' 10 | end 11 | 12 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/macos/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - PinLayout (1.10.4) 3 | 4 | DEPENDENCIES: 5 | - PinLayout (from `../../..`) 6 | 7 | EXTERNAL SOURCES: 8 | PinLayout: 9 | :path: "../../.." 10 | 11 | SPEC CHECKSUMS: 12 | PinLayout: 9b3aacc4a5a7c942a8ef6b42b254a448fbf422e5 13 | 14 | PODFILE CHECKSUM: 6f367e85dc6a99ba93382237d1ecc5f5475c5e70 15 | 16 | COCOAPODS: 1.12.0 17 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/tvos/PinLayout-tvOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/tvos/PinLayout-tvOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/tvos/PinLayout-tvOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIMainStoryboardFile 24 | Main 25 | UIRequiredDeviceCapabilities 26 | 27 | arm64 28 | 29 | UIUserInterfaceStyle 30 | Automatic 31 | 32 | 33 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/tvos/PinLayout-tvOS/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/tvos/PinLayout-tvOS/PinLayout-tvOS-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/tvos/PinLayout-tvOS/TestObjectiveC.m: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | @import UIKit; 5 | @import PinLayout; 6 | 7 | @interface IntroObjectiveCView: UIView { 8 | } 9 | @end 10 | 11 | @implementation IntroObjectiveCView { 12 | CGFloat topLayoutGuide; 13 | UIImageView* logo; 14 | UISegmentedControl* segmented; 15 | UILabel* textLabel; 16 | UIView* separatorView; 17 | } 18 | 19 | - (id)initWithFrame:(CGRect)frame { 20 | if ((self = [super initWithFrame:frame])) { 21 | topLayoutGuide = 0; 22 | self.backgroundColor = UIColor.whiteColor; 23 | 24 | logo = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"PinLayout-logo" inBundle:nil compatibleWithTraitCollection:nil]]; 25 | [self addSubview:logo]; 26 | 27 | segmented = [[UISegmentedControl alloc] initWithItems: @[@"Intro", @"1", @"2"]]; 28 | [self addSubview:segmented]; 29 | 30 | textLabel = [[UILabel alloc] init]; 31 | textLabel.text = @"Swift manual views layouting without auto layout, no magic, pure code, full control. Concise syntax, readable & chainable.\n\nSwift manual views layouting without auto layout, no magic, pure code, full control. Concise syntax, readable & chainable."; 32 | textLabel.font = [UIFont systemFontOfSize:14]; 33 | textLabel.numberOfLines = 0; 34 | textLabel.lineBreakMode = NSLineBreakByWordWrapping; 35 | [self addSubview:textLabel]; 36 | 37 | separatorView = [[UIView alloc] init]; 38 | separatorView.backgroundColor = UIColor.grayColor; 39 | 40 | [self addSubview:separatorView]; 41 | } 42 | return self; 43 | } 44 | 45 | - (void) layoutSubviews { 46 | [super layoutSubviews]; 47 | 48 | logo.pinObjc.top().left().width(100).aspectRatio().marginTHB(topLayoutGuide + 10, 10, 10).layout(); 49 | segmented.pinObjc.rightOfAligned(logo, VerticalAlignTop).right().marginHorizontal(10).layout(); 50 | textLabel.pinObjc.belowOfAligned(segmented, HorizontalAlignLeft).widthOf(segmented).pinEdges().marginTop(10).sizeToFitType(FitWidth).layout(); 51 | separatorView.pinObjc.belowOfViewsAligned(@[logo, textLabel], HorizontalAlignLeft).rightToEdge(segmented.edge.right).height(1).marginTop(10).layout(); 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/tvos/PinLayout-tvOS/ViewController.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit 3 | import PinLayout 4 | 5 | class ViewController: UIViewController { 6 | let temp = UIView() 7 | 8 | override func viewDidLoad() { 9 | super.viewDidLoad() 10 | // Do any additional setup after loading the view, typically from a nib. 11 | 12 | temp.backgroundColor = .red 13 | view.addSubview(temp) 14 | } 15 | 16 | override func didReceiveMemoryWarning() { 17 | super.didReceiveMemoryWarning() 18 | // Dispose of any resources that can be recreated. 19 | } 20 | 21 | override func viewWillLayoutSubviews() { 22 | super.viewWillLayoutSubviews() 23 | 24 | temp.pin.top().hCenter().size(50%) 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/tvos/Podfile: -------------------------------------------------------------------------------- 1 | source 'https://cdn.cocoapods.org/' 2 | platform :tvos, '12.0' 3 | 4 | target 'PinLayout-tvOS' do 5 | #pod 'PinLayout' 6 | #pod 'PinLayout', :git => 'https://github.com/layoutBox/PinLayout.git', :commit => 'f29519b08890da144772fe9b082cd6499b5d82c1' 7 | pod 'PinLayout', :path => '../../..' 8 | end 9 | 10 | -------------------------------------------------------------------------------- /TestProjects/cocoapods/tvos/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - PinLayout (1.10.4) 3 | 4 | DEPENDENCIES: 5 | - PinLayout (from `../../..`) 6 | 7 | EXTERNAL SOURCES: 8 | PinLayout: 9 | :path: "../../.." 10 | 11 | SPEC CHECKSUMS: 12 | PinLayout: 9b3aacc4a5a7c942a8ef6b42b254a448fbf422e5 13 | 14 | PODFILE CHECKSUM: f6f33c54b299d48dce16c8db06bb1624e146e6de 15 | 16 | COCOAPODS: 1.12.0 17 | -------------------------------------------------------------------------------- /TestProjects/swift-package-manager/ios/-destination/Logs/Package/LogStoreManifest.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | logFormatVersion 6 | 10 7 | logs 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestProjects/swift-package-manager/ios/-destination/Logs/Test/LogStoreManifest.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | logFormatVersion 6 | 10 7 | logs 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestProjects/swift-package-manager/ios/-destination/info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LastAccessedDate 6 | 2021-05-18T15:33:02Z 7 | WorkspacePath 8 | /Users/lucdion/dev_luc/PinLayout/TestProjects/swift-package-manager/ios/PinLayout-Carthage-iOS.xcodeproj 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestProjects/swift-package-manager/ios/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "PinLayout", 6 | "repositoryURL": "https://github.com/layoutBox/PinLayout.git", 7 | "state": { 8 | "branch": null, 9 | "revision": "eb3e2a3b14954c89f0a6c31f8f0a00dbe3208121", 10 | "version": "1.9.4" 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /TestProjects/swift-package-manager/ios/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.4 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "PinLayoutSwiftPackageManagerTest", 6 | defaultLocalization: "en", 7 | dependencies: [ 8 | .package(url: "https://github.com/layoutBox/PinLayout.git", from: "1.0.0") 9 | ], 10 | targets: [ 11 | .target(name: "PinLayout-SPM-iOS", dependencies: ["PinLayout"]), 12 | ] 13 | ) -------------------------------------------------------------------------------- /TestProjects/swift-package-manager/ios/PinLayout-Carthage-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "PinLayout", 6 | "repositoryURL": "https://github.com/layoutBox/PinLayout.git", 7 | "state": { 8 | "branch": "master", 9 | "revision": "c33d7aba9e4501886d35a9399bccf109a93ebde8", 10 | "version": null 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /TestProjects/swift-package-manager/ios/PinLayout-SPM-iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TestProjects/swift-package-manager/ios/PinLayout-SPM-iOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TestProjects/swift-package-manager/ios/PinLayout-SPM-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "PinLayout", 6 | "repositoryURL": "https://github.com/layoutBox/PinLayout.git", 7 | "state": { 8 | "branch": "master", 9 | "revision": "c33d7aba9e4501886d35a9399bccf109a93ebde8", 10 | "version": null 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /TestProjects/swift-package-manager/ios/PinLayout-SPM-iOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit 3 | 4 | @UIApplicationMain 5 | class AppDelegate: UIResponder, UIApplicationDelegate { 6 | 7 | var window: UIWindow? 8 | 9 | 10 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 11 | // Override point for customization after application launch. 12 | return true 13 | } 14 | 15 | func applicationWillResignActive(_ application: UIApplication) { 16 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 17 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 18 | } 19 | 20 | func applicationDidEnterBackground(_ application: UIApplication) { 21 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 22 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 23 | } 24 | 25 | func applicationWillEnterForeground(_ application: UIApplication) { 26 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 27 | } 28 | 29 | func applicationDidBecomeActive(_ application: UIApplication) { 30 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 31 | } 32 | 33 | func applicationWillTerminate(_ application: UIApplication) { 34 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 35 | } 36 | 37 | 38 | } 39 | 40 | -------------------------------------------------------------------------------- /TestProjects/swift-package-manager/ios/PinLayout-SPM-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /TestProjects/swift-package-manager/ios/PinLayout-SPM-iOS/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /TestProjects/swift-package-manager/ios/PinLayout-SPM-iOS/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /TestProjects/swift-package-manager/ios/PinLayout-SPM-iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /TestProjects/swift-package-manager/ios/PinLayout-SPM-iOS/ViewController.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit 3 | 4 | class ViewController: UIViewController { 5 | 6 | override func viewDidLoad() { 7 | super.viewDidLoad() 8 | // Do any additional setup after loading the view, typically from a nib. 9 | } 10 | 11 | override func didReceiveMemoryWarning() { 12 | super.didReceiveMemoryWarning() 13 | // Dispose of any resources that can be recreated. 14 | } 15 | 16 | 17 | } 18 | 19 | -------------------------------------------------------------------------------- /TestProjects/swift-package-manager/ios/update_packages.sh: -------------------------------------------------------------------------------- 1 | rm -rf .build/ && rm Package.pins; swift package show-dependencies --format json && swift package show-dependencies --format json 2 | -------------------------------------------------------------------------------- /Tests/Common/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Tests/RectNimbleMatcher.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import Nimble 21 | 22 | public func beCloseTo(_ expectedValue: CGRect, within delta: CGFloat = 0.00001) -> Predicate { 23 | let errorMessage = "be close to <\(stringify(expectedValue))> (each within \(stringify(delta)))" 24 | return Predicate.simple(errorMessage) { actualExpression in 25 | if let actual = try actualExpression.evaluate() { 26 | if abs(actual.origin.x - expectedValue.origin.x) > delta { 27 | return .doesNotMatch 28 | } 29 | 30 | if abs(actual.origin.y - expectedValue.origin.y) > delta { 31 | return .doesNotMatch 32 | } 33 | 34 | if abs(actual.size.width - expectedValue.size.width) > delta { 35 | return .doesNotMatch 36 | } 37 | 38 | if abs(actual.size.height - expectedValue.size.height) > delta { 39 | return .doesNotMatch 40 | } 41 | 42 | return .matches 43 | } 44 | return .doesNotMatch 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Tests/UIImage+Color.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | 22 | public extension UIImage { 23 | convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) { 24 | let rect = CGRect(origin: .zero, size: size) 25 | UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0) 26 | color.setFill() 27 | UIRectFill(rect) 28 | let image = UIGraphicsGetImageFromCurrentImageContext() 29 | UIGraphicsEndImageContext() 30 | 31 | guard let cgImage = image?.cgImage else { return nil } 32 | self.init(cgImage: cgImage) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Tests/iOS/Types+UIKit.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import UIKit 21 | 22 | typealias PView = UIView 23 | typealias PScrollView = UIScrollView 24 | typealias PEdgeInsets = UIEdgeInsets 25 | typealias PViewController = UIViewController 26 | typealias PColor = UIColor 27 | typealias PLabel = UILabel 28 | -------------------------------------------------------------------------------- /Tests/macOS/PinLayoutTestMacOS.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import XCTest 21 | 22 | class PinLayoutTestMacOS: XCTestCase { 23 | 24 | override func setUp() { 25 | super.setUp() 26 | // Put setup code here. This method is called before the invocation of each test method in the class. 27 | } 28 | 29 | override func tearDown() { 30 | // Put teardown code here. This method is called after the invocation of each test method in the class. 31 | super.tearDown() 32 | } 33 | 34 | func testExample() { 35 | // This is an example of a functional test case. 36 | // Use XCTAssert and related functions to verify your tests produce the correct results. 37 | } 38 | 39 | func testPerformanceExample() { 40 | // This is an example of a performance test case. 41 | self.measure { 42 | // Put the code you want to measure the time of here. 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /Tests/macOS/Types+Appkit.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Luc Dion 2 | // Permission is hereby granted, free of charge, to any person obtaining a copy 3 | // of this software and associated documentation files (the "Software"), to deal 4 | // in the Software without restriction, including without limitation the rights 5 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | // copies of the Software, and to permit persons to whom the Software is 7 | // furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in 10 | // all copies or substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | // THE SOFTWARE. 19 | 20 | import AppKit 21 | 22 | typealias PView = NSView 23 | typealias PScrollView = NSScrollView 24 | typealias PEdgeInsets = NSEdgeInsets 25 | typealias PViewController = NSViewController 26 | typealias PColor = NSColor 27 | -------------------------------------------------------------------------------- /docs/01-example-distance-superview-edge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/01-example-distance-superview-edge.png -------------------------------------------------------------------------------- /docs/02-example-superview-edge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/02-example-superview-edge.png -------------------------------------------------------------------------------- /docs/Benchmark/benchmark_comparison_all_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/Benchmark/benchmark_comparison_all_small.png -------------------------------------------------------------------------------- /docs/Keynote Layout presentation.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/Keynote Layout presentation.key -------------------------------------------------------------------------------- /docs/PinLayout_principles.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | ## PinLayout principles and philosophy 6 | 7 | * Manual layouting (doesn't rely on auto layout). 8 | 9 | * 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) 10 | 11 | * Full control: You're in the middle of the layout process, no magic black box. 12 | * You can add conditions (if/switch/guard/...) related to the device orientation, device type, traitCollection, animations, ... 13 | * You can add iterations and enumerations (for/while/forEach/...) 14 | 15 | * Layout one view at a time. Make it simple to code and debug. 16 | 17 | * Concise syntax. Layout most views using a single line. 18 | 19 | * Stateless 20 | * PinLayout doesn’t add any stored properties to UIView/NSView. It simply computes the view's frame property, one view at a time. 21 | * Since it is stateless, it can be used with any other layout framework without conflicts. 22 | Each view can use the layout system that better suit it (PinLayout, autolayout, flexbox, …) 23 | 24 | * No Auto layout and constraints 25 | * Constraints are verbose and quite hard for a human brains to understand when there are many views implicated, even with sugar-syntax frameworks. 26 | * PinLayout positions views as a designer would explain it (eg: “The TextField is below the Label, aligned left, and is its width matches the other view’s width“). 27 | * No priorities, simply layout views in the order that makes sense. No priorities required. 28 | 29 | * Before applying the new sets of attributes, PinLayout always start with the view’s current frame. So its possible to set the view’s size during the initialization (ex: view.pin.width(100).height(200)), and later only position the view (ex: view.pin.top(10).left(20)). This makes PinLayout really animation friendly. 30 | 31 | * Not too intrusive. PinLayout only adds three properties to existing iOS classes: `UIView.pin`, `UIView.anchor` and `UIView.edge` 32 | * Minimize as much as possible calculations and constants when layouting views. But it is always possible to add advanced computation if required. 33 | 34 | * Method's name match as much as possible other layout frameworks, including [FlexLayout](https://github.com/layoutBox/FlexLayout)/flexbox, CSS, React Native, … 35 | -------------------------------------------------------------------------------- /docs/example-anchors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/example-anchors.png -------------------------------------------------------------------------------- /docs/example-edges.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/example-edges.png -------------------------------------------------------------------------------- /docs/example-form.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/example-form.gif -------------------------------------------------------------------------------- /docs/example-multiple-anchors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/example-multiple-anchors.png -------------------------------------------------------------------------------- /docs/example-superview-anchors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/example-superview-anchors.png -------------------------------------------------------------------------------- /docs/images/example-animations-large.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/example-animations-large.gif -------------------------------------------------------------------------------- /docs/images/example-animations.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/example-animations.gif -------------------------------------------------------------------------------- /docs/images/pinlayout-sizeToFit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout-sizeToFit.png -------------------------------------------------------------------------------- /docs/images/pinlayout_animation_example1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_animation_example1.gif -------------------------------------------------------------------------------- /docs/images/pinlayout_example_anchor_center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_example_anchor_center.png -------------------------------------------------------------------------------- /docs/images/pinlayout_example_layout_margins_all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_example_layout_margins_all.png -------------------------------------------------------------------------------- /docs/images/pinlayout_example_layout_margins_landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_example_layout_margins_landscape.png -------------------------------------------------------------------------------- /docs/images/pinlayout_example_layout_margins_portrain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_example_layout_margins_portrain.png -------------------------------------------------------------------------------- /docs/images/pinlayout_example_tableview_readable_content_all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_example_tableview_readable_content_all.png -------------------------------------------------------------------------------- /docs/images/pinlayout_example_tableview_readable_content_landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_example_tableview_readable_content_landscape.png -------------------------------------------------------------------------------- /docs/images/pinlayout_example_tableview_readable_content_portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_example_tableview_readable_content_portrait.png -------------------------------------------------------------------------------- /docs/images/pinlayout_example_topRight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_example_topRight.png -------------------------------------------------------------------------------- /docs/images/pinlayout_horizontallyBetween.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_horizontallyBetween.png -------------------------------------------------------------------------------- /docs/images/pinlayout_intro_example_iphonex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_intro_example_iphonex.png -------------------------------------------------------------------------------- /docs/images/pinlayout_plus_flexlayout_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_plus_flexlayout_small.png -------------------------------------------------------------------------------- /docs/images/pinlayout_plus_layoutBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_plus_layoutBox.png -------------------------------------------------------------------------------- /docs/images/pinlayout_relative_transform_scale_original.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_relative_transform_scale_original.png -------------------------------------------------------------------------------- /docs/images/pinlayout_relative_transform_scale_pin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_relative_transform_scale_pin.png -------------------------------------------------------------------------------- /docs/images/pinlayout_relative_transform_scale_pinFrame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_relative_transform_scale_pinFrame.png -------------------------------------------------------------------------------- /docs/images/pinlayout_right_to_left_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_right_to_left_example.png -------------------------------------------------------------------------------- /docs/images/pinlayout_safearea_2_example_iphonex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_safearea_2_example_iphonex.png -------------------------------------------------------------------------------- /docs/images/pinlayout_safearea_example_iphonex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_safearea_example_iphonex.png -------------------------------------------------------------------------------- /docs/images/pinlayout_transform_orig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_transform_orig.png -------------------------------------------------------------------------------- /docs/images/pinlayout_transform_rotate_pin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_transform_rotate_pin.png -------------------------------------------------------------------------------- /docs/images/pinlayout_transform_rotate_pinFrame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_transform_rotate_pinFrame.png -------------------------------------------------------------------------------- /docs/images/pinlayout_verticallyBetween.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/pinlayout_verticallyBetween.png -------------------------------------------------------------------------------- /docs/images/wrapContent_all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/wrapContent_all.png -------------------------------------------------------------------------------- /docs/images/wrapContent_before.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/wrapContent_before.png -------------------------------------------------------------------------------- /docs/images/wrapContent_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/wrapContent_example.png -------------------------------------------------------------------------------- /docs/images/wrapContent_horizontally.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/wrapContent_horizontally.png -------------------------------------------------------------------------------- /docs/images/wrapContent_padding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/wrapContent_padding.png -------------------------------------------------------------------------------- /docs/images/wrapContent_vertically.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/images/wrapContent_vertically.png -------------------------------------------------------------------------------- /docs/objective_c.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 |

PinLayout using Objective-C

6 | 7 | PinLayout can also be used from Objective-C. The PinLayout interface is slightly different from the Swift interface due to more limited Objective-C parameters definitions. 8 | 9 | ###### Example 1: 10 | This example implement the PinLayout's Intro example using objective-c 11 | 12 | 13 | 14 | ``` 15 | - (void) layoutSubviews { 16 | [super layoutSubviews]; 17 | 18 | CGFloat margin = 10; 19 | UIEdgeInsets safeArea = self.pinObjc.safeArea; 20 | 21 | logo.pinObjc.topInsets(safeArea).leftInsets(safeArea).width(100).aspectRatio().margin(margin).layout(); 22 | segmented.pinObjc.rightOfAligned(logo, VerticalAlignTop).rightInsets(safeArea).marginHorizontal(margin).layout(); 23 | textLabel.pinObjc.belowOfAligned(segmented, HorizontalAlignLeft).widthOf(segmented).pinEdges().marginTop(margin).sizeToFitType(FitWidth).layout(); 24 | separatorView.pinObjc.belowOfViewsAligned(@[logo, textLabel], HorizontalAlignLeft).rightToEdge(segmented.edge.right).height(1).marginTop(margin).layout(); 25 | } 26 | 27 | ``` 28 | 29 | :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) 30 | 31 | ## Important notes about PinLayout's Objective-c interface 32 | 33 | #### `pinObjc` property 34 | The PinLayout's objective-c interface is available using the property `pinObjc` (instead of `pin` in Swift) 35 | 36 | ``` 37 | view.pinObjc.top().layout(); 38 | ``` 39 | 40 | #### `layout()` 41 | 42 | **Method:** 43 | 44 | * **`layout()`** 45 | When using the Objective-c interface, the `layout` method must be called explicitly to complete the view's layout. The method will execute PinLayout commands immediately. In Swift, PinLayout executes this method implicitly, it is not necessary to call it. 46 | 47 | 48 | ``` 49 | // Swift 50 | view.pin.width(100) 51 | 52 | // Objective-c 53 | view.pinObjc.width(100).layout(); 54 | ``` 55 | 56 | -------------------------------------------------------------------------------- /docs/pinlayout-anchors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-anchors.png -------------------------------------------------------------------------------- /docs/pinlayout-edges.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-edges.png -------------------------------------------------------------------------------- /docs/pinlayout-example-cells.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-example-cells.png -------------------------------------------------------------------------------- /docs/pinlayout-example-justify-center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-example-justify-center.png -------------------------------------------------------------------------------- /docs/pinlayout-example-justify-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-example-justify-left.png -------------------------------------------------------------------------------- /docs/pinlayout-example-justify-remaining-space.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-example-justify-remaining-space.png -------------------------------------------------------------------------------- /docs/pinlayout-example-justify-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-example-justify-right.png -------------------------------------------------------------------------------- /docs/pinlayout-example-maxWidth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-example-maxWidth.png -------------------------------------------------------------------------------- /docs/pinlayout-logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-logo-small.png -------------------------------------------------------------------------------- /docs/pinlayout-logo-text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-logo-text.png -------------------------------------------------------------------------------- /docs/pinlayout-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-logo.png -------------------------------------------------------------------------------- /docs/pinlayout-margin-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-margin-01.png -------------------------------------------------------------------------------- /docs/pinlayout-margin-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-margin-02.png -------------------------------------------------------------------------------- /docs/pinlayout-margin-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-margin-03.png -------------------------------------------------------------------------------- /docs/pinlayout-margin-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-margin-04.png -------------------------------------------------------------------------------- /docs/pinlayout-margin-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-margin-05.png -------------------------------------------------------------------------------- /docs/pinlayout-margin-pinEdges-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-margin-pinEdges-01.png -------------------------------------------------------------------------------- /docs/pinlayout-margin-pinEdges-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-margin-pinEdges-02.png -------------------------------------------------------------------------------- /docs/pinlayout-margin-pinEdges-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-margin-pinEdges-03.png -------------------------------------------------------------------------------- /docs/pinlayout-relative-multi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-relative-multi.png -------------------------------------------------------------------------------- /docs/pinlayout-relative-visible.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-relative-visible.png -------------------------------------------------------------------------------- /docs/pinlayout-relative-with-alignment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-relative-with-alignment.png -------------------------------------------------------------------------------- /docs/pinlayout-relative.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout-relative.png -------------------------------------------------------------------------------- /docs/pinlayout_example_adjust_to_container-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout_example_adjust_to_container-landscape.png -------------------------------------------------------------------------------- /docs/pinlayout_example_adjust_to_container-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout_example_adjust_to_container-portrait.png -------------------------------------------------------------------------------- /docs/pinlayout_example_adjust_to_container.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout_example_adjust_to_container.png -------------------------------------------------------------------------------- /docs/pinlayout_example_adjust_to_container2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout_example_adjust_to_container2.png -------------------------------------------------------------------------------- /docs/pinlayout_example_aspectratio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout_example_aspectratio.png -------------------------------------------------------------------------------- /docs/pinlayout_example_form.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout_example_form.gif -------------------------------------------------------------------------------- /docs/pinlayout_example_hCenter_edge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout_example_hCenter_edge.png -------------------------------------------------------------------------------- /docs/pinlayout_example_wrapContent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout_example_wrapContent.png -------------------------------------------------------------------------------- /docs/pinlayout_exampleapp_auto_adjusting_size.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout_exampleapp_auto_adjusting_size.png -------------------------------------------------------------------------------- /docs/pinlayout_exampleapp_automatic_sizing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout_exampleapp_automatic_sizing.png -------------------------------------------------------------------------------- /docs/pinlayout_exampleapp_collectionview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout_exampleapp_collectionview.png -------------------------------------------------------------------------------- /docs/pinlayout_exampleapp_intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout_exampleapp_intro.png -------------------------------------------------------------------------------- /docs/pinlayout_exampleapp_multi_relative_position.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout_exampleapp_multi_relative_position.png -------------------------------------------------------------------------------- /docs/pinlayout_exampleapp_relative_position.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout_exampleapp_relative_position.png -------------------------------------------------------------------------------- /docs/pinlayout_exampleapp_tableview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/layoutBox/PinLayout/babea9c8e821dfb0687e66c123fed2006e688929/docs/pinlayout_exampleapp_tableview.png -------------------------------------------------------------------------------- /docs/rtl_support.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | ## PinLayout Right to left languages (RTL) support 6 | 7 | Every method/properties with a name containing `left`/`right`, has RTL enabled equivalent methods with a name containing `start`/`end`. 8 | 9 | Using `start` or `end` methods, you can position views without having to think about whether your item will show up on the left or the right side of the screen (depending on the person’s language). 10 | 11 | :pushpin: In this documentation all methods that support RTL languages are marked using the following icon :left_right_arrow: 12 | 13 | **Method**: 14 | 15 | * **`Pin.layoutDirection(direction: LayoutDirection)`**:left_right_arrow:: 16 | Set the PinLayout layout direction. Note that this set PinLayout's layout direction globally. By default PinLayout use the left-to-right direction. 17 | 18 | Layout direction modes: 19 | * `.ltr`: Layout views from left to right. (Default) 20 | * `.rtl`: Layout views from right to left. 21 | * `.auto`: Layout views based on `UIView.userInterfaceLayoutDirection(for: semanticContentAttribute)` (>= iOS 9) or `UIApplication.shared.userInterfaceLayoutDirection` (< iOS 9). If you want to control the layout direction individually for each views, you should use this mode and control the view's layout direction using `UIView.userInterfaceLayoutDirection` property. 22 | 23 | ###### Usage examples: 24 | 25 | ```swift 26 | override func layoutSubviews() { 27 | super.layoutSubviews() 28 | 29 | // Layout the contentView using the view's safeArea 30 | contentView.pin.all(pin.safeArea) 31 | 32 | let padding: CGFloat = 10 33 | logo.pin.top().start(padding).width(100).aspectRatio().marginTop(10) 34 | segmented.pin.after(of: logo, aligned: .top).end(padding).marginStart(10) 35 | textLabel.pin.below(of: segmented, aligned: .start).width(of: segmented).pinEdges().marginTop(10).sizeToFit(.width) 36 | separatorView.pin.below(of: [logo, textLabel], aligned: .start).end(to: segmented.edge.end).marginTop(10) 37 | } 38 | ``` 39 | 40 | :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) -------------------------------------------------------------------------------- /docs/xcode_playground.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 |

PinLayout and Xcode Playgrounds

6 | 7 | ## Using PinLayout with Xcode Playgrounds 8 | PinLayout layouts views immediately after the line containing `.pin` has been fully executed, thanks to ARC (Automatic Reference Counting) this works perfectly on iOS/tvOS/macOS simulators and devices. But in Xcode Playgrounds, ARC doesn't work as expected, object references are kept much longer. This is a well documented issue. The impact of this problem is that PinLayout doesn't layout views at the time and in the order required. To handle this situation in playgrounds it is possible to call the `layout()` method to complete the layout. 9 | 10 | **Method:** 11 | 12 | * **`layout()`** 13 | The method will execute PinLayout commands immediately. This method is **required only if your source codes should also work in Xcode Playgrounds**. Outside of playgrounds, PinLayout executes this method implicitly, it is not necessary to call it. 14 | 15 | ###### Usage Examples: 16 | 17 | ```swift 18 | view.pin.top(20).bottom(20).width(100).layout() 19 | view2.pin.below(of: view).horizontally().layout() 20 | ``` 21 | 22 | **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. 23 | -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 |

2 | PinLayout 3 |

4 | 5 |

PinLayout

6 | 7 |

8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |

16 | 17 |
18 | 19 | Extremely Fast views layouting without auto layout. No magic, pure code, full control and blazing fast. Concise syntax, intuitive, readable & chainable. 20 | 21 | > "No auto-layout constraints attached" 22 | 23 |
24 | 25 | [See GitHub PinLayout' page for the complete documentation](https://github.com/layoutBox/PinLayout) --------------------------------------------------------------------------------