Skip to content

Instantly share code, notes, and snippets.

@hironytic
Created November 15, 2020 06:17
Show Gist options
  • Select an option

  • Save hironytic/6dd2eb62daf2bae68ca54e67187b2432 to your computer and use it in GitHub Desktop.

Select an option

Save hironytic/6dd2eb62daf2bae68ca54e67187b2432 to your computer and use it in GitHub Desktop.
NSLayoutAnchorと同じようなものを作ってみるも、NSLayoutAnchorでいいや、となって使わなかったもの
//
// LayoutConstraint.swift
//
// Copyright (c) 2020 Hironori Ichimiya <hiron@hironytic.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
import UIKit
struct LayoutItem {
let item: Any
init(_ item: Any) {
self.item = item
}
var left: AttributedLayoutItem { attributedLayoutItem(attribute: .left) }
var right: AttributedLayoutItem { attributedLayoutItem(attribute: .right) }
var top: AttributedLayoutItem { attributedLayoutItem(attribute: .top) }
var bottom: AttributedLayoutItem { attributedLayoutItem(attribute: .bottom) }
var leading: AttributedLayoutItem { attributedLayoutItem(attribute: .leading) }
var trailing: AttributedLayoutItem { attributedLayoutItem(attribute: .trailing) }
var width: AttributedLayoutItem { attributedLayoutItem(attribute: .width) }
var height: AttributedLayoutItem { attributedLayoutItem(attribute: .height) }
var centerX: AttributedLayoutItem { attributedLayoutItem(attribute: .centerX) }
var centerY: AttributedLayoutItem { attributedLayoutItem(attribute: .centerY) }
var lastBaseline: AttributedLayoutItem { attributedLayoutItem(attribute: .lastBaseline) }
@available(iOS 8.0, *) var firstBaseline: AttributedLayoutItem { attributedLayoutItem(attribute: .firstBaseline) }
@available(iOS 8.0, *) var leftMargin: AttributedLayoutItem { attributedLayoutItem(attribute: .leftMargin) }
@available(iOS 8.0, *) var rightMargin: AttributedLayoutItem { attributedLayoutItem(attribute: .rightMargin) }
@available(iOS 8.0, *) var topMargin: AttributedLayoutItem { attributedLayoutItem(attribute: .topMargin) }
@available(iOS 8.0, *) var bottomMargin: AttributedLayoutItem { attributedLayoutItem(attribute: .bottomMargin) }
@available(iOS 8.0, *) var leadingMargin: AttributedLayoutItem { attributedLayoutItem(attribute: .leadingMargin) }
@available(iOS 8.0, *) var trailingMargin: AttributedLayoutItem { attributedLayoutItem(attribute: .trailingMargin) }
@available(iOS 8.0, *) var centerXWithinMargins: AttributedLayoutItem { attributedLayoutItem(attribute: .centerXWithinMargins) }
@available(iOS 8.0, *) var centerYWithinMargins: AttributedLayoutItem { attributedLayoutItem(attribute: .centerYWithinMargins) }
var notAnAttribute: AttributedLayoutItem { attributedLayoutItem(attribute: .notAnAttribute) }
private func attributedLayoutItem(attribute: NSLayoutConstraint.Attribute) -> AttributedLayoutItem {
AttributedLayoutItem(item: item, attribute: attribute)
}
}
struct AttributedLayoutItem {
let item: Any
let attribute: NSLayoutConstraint.Attribute
func lessThanOrEqualTo(_ item2: Any) -> LayoutRelationLackingInAttribute {
layoutRelationLackingInAttribute(relation: .lessThanOrEqual, item2: item2)
}
func equalTo(_ item2: Any) -> LayoutRelationLackingInAttribute {
layoutRelationLackingInAttribute(relation: .equal, item2: item2)
}
func greaterThanOrEqualTo(_ item2: Any) -> LayoutRelationLackingInAttribute {
layoutRelationLackingInAttribute(relation: .greaterThanOrEqual, item2: item2)
}
private func layoutRelationLackingInAttribute(relation: NSLayoutConstraint.Relation, item2: Any) -> LayoutRelationLackingInAttribute {
LayoutRelationLackingInAttribute(item1: item, attribute1: attribute, relation: relation, item2: item2)
}
func lessThanOrEqualTo(_ constant: CGFloat) -> LinearLayoutRelation {
linearLayoutRelation(relation: .lessThanOrEqual, constant: constant)
}
func equalTo(_ constant: CGFloat) -> LinearLayoutRelation {
linearLayoutRelation(relation: .equal, constant: constant)
}
func greaterThanOrEqualTo(_ constant: CGFloat) -> LinearLayoutRelation {
linearLayoutRelation(relation: .greaterThanOrEqual, constant: constant)
}
private func linearLayoutRelation(relation: NSLayoutConstraint.Relation, constant: CGFloat) -> LinearLayoutRelation {
LinearLayoutRelation(item1: item, attribute1: attribute, relation: relation, item2: nil, attribute2: .notAnAttribute, multiplier: 1.0, constant: constant)
}
}
struct LayoutRelationLackingInAttribute {
let item1: Any
let attribute1: NSLayoutConstraint.Attribute
let relation: NSLayoutConstraint.Relation
let item2: Any?
var left: LayoutRelation { layoutRelation(attribute2: .left) }
var right: LayoutRelation { layoutRelation(attribute2: .right) }
var top: LayoutRelation { layoutRelation(attribute2: .top) }
var bottom: LayoutRelation { layoutRelation(attribute2: .bottom) }
var leading: LayoutRelation { layoutRelation(attribute2: .leading) }
var trailing: LayoutRelation { layoutRelation(attribute2: .trailing) }
var width: LayoutRelation { layoutRelation(attribute2: .width) }
var height: LayoutRelation { layoutRelation(attribute2: .height) }
var centerX: LayoutRelation { layoutRelation(attribute2: .centerX) }
var centerY: LayoutRelation { layoutRelation(attribute2: .centerY) }
var lastBaseline: LayoutRelation { layoutRelation(attribute2: .lastBaseline) }
@available(iOS 8.0, *) var firstBaseline: LayoutRelation { layoutRelation(attribute2: .firstBaseline) }
@available(iOS 8.0, *) var leftMargin: LayoutRelation { layoutRelation(attribute2: .leftMargin) }
@available(iOS 8.0, *) var rightMargin: LayoutRelation { layoutRelation(attribute2: .rightMargin) }
@available(iOS 8.0, *) var topMargin: LayoutRelation { layoutRelation(attribute2: .topMargin) }
@available(iOS 8.0, *) var bottomMargin: LayoutRelation { layoutRelation(attribute2: .bottomMargin) }
@available(iOS 8.0, *) var leadingMargin: LayoutRelation { layoutRelation(attribute2: .leadingMargin) }
@available(iOS 8.0, *) var trailingMargin: LayoutRelation { layoutRelation(attribute2: .trailingMargin) }
@available(iOS 8.0, *) var centerXWithinMargins: LayoutRelation { layoutRelation(attribute2: .centerXWithinMargins) }
@available(iOS 8.0, *) var centerYWithinMargins: LayoutRelation { layoutRelation(attribute2: .centerYWithinMargins) }
var notAnAttribute: LayoutRelation { layoutRelation(attribute2: .notAnAttribute) }
private func layoutRelation(attribute2: NSLayoutConstraint.Attribute) -> LayoutRelation {
LayoutRelation(item1: item1, attribute1: attribute1, relation: relation, item2: item2, attribute2: attribute2)
}
}
struct LayoutRelation {
let item1: Any
let attribute1: NSLayoutConstraint.Attribute
let relation: NSLayoutConstraint.Relation
let item2: Any?
let attribute2: NSLayoutConstraint.Attribute
func times(_ multiplier: CGFloat) -> MultipliedLayoutRelation {
MultipliedLayoutRelation(item1: item1, attribute1: attribute1, relation: relation, item2: item2, attribute2: attribute2, multiplier: multiplier)
}
func plus(_ constant: CGFloat) -> LinearLayoutRelation {
LinearLayoutRelation(item1: item1, attribute1: attribute1, relation: relation, item2: item2, attribute2: attribute2, multiplier: 1.0, constant: constant)
}
func minus(_ constant: CGFloat) -> LinearLayoutRelation {
LinearLayoutRelation(item1: item1, attribute1: attribute1, relation: relation, item2: item2, attribute2: attribute2, multiplier: 1.0, constant: -constant)
}
}
struct MultipliedLayoutRelation {
let item1: Any
let attribute1: NSLayoutConstraint.Attribute
let relation: NSLayoutConstraint.Relation
let item2: Any?
let attribute2: NSLayoutConstraint.Attribute
let multiplier: CGFloat
func plus(_ constant: CGFloat) -> LinearLayoutRelation {
LinearLayoutRelation(item1: item1, attribute1: attribute1, relation: relation, item2: item2, attribute2: attribute2, multiplier: multiplier, constant: constant)
}
func minus(_ constant: CGFloat) -> LinearLayoutRelation {
LinearLayoutRelation(item1: item1, attribute1: attribute1, relation: relation, item2: item2, attribute2: attribute2, multiplier: multiplier, constant: -constant)
}
}
struct LinearLayoutRelation {
let item1: Any
let attribute1: NSLayoutConstraint.Attribute
let relation: NSLayoutConstraint.Relation
let item2: Any?
let attribute2: NSLayoutConstraint.Attribute
let multiplier: CGFloat
let constant: CGFloat
}
extension NSLayoutConstraint {
convenience init(_ r: LinearLayoutRelation) {
self.init(item: r.item1, attribute: r.attribute1, relatedBy: r.relation, toItem: r.item2, attribute: r.attribute2, multiplier: r.multiplier, constant: r.constant)
}
convenience init(_ r: MultipliedLayoutRelation) {
self.init(item: r.item1, attribute: r.attribute1, relatedBy: r.relation, toItem: r.item2, attribute: r.attribute2, multiplier: r.multiplier, constant: 0.0)
}
convenience init(_ r: LayoutRelation) {
self.init(item: r.item1, attribute: r.attribute1, relatedBy: r.relation, toItem: r.item2, attribute: r.attribute2, multiplier: 1.0, constant: 0.0)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment