Last active
September 7, 2022 02:21
-
-
Save codyrobb/d56d4a8f81a3a6c5209b to your computer and use it in GitHub Desktop.
CGRect Alignment Extension
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// CGGeometry+Additions.swift | |
// TokenField | |
// | |
// Created by Cody Robertson on 2/4/16. | |
// Copyright © 2016 Notion AI, Inc. All rights reserved. | |
// | |
import Foundation | |
import UIKit | |
public extension CGRect { | |
public enum Edge { | |
case Bottom | |
case Left | |
case Right | |
case Top | |
func toCGRectEdge() -> CGRectEdge { | |
switch self { | |
case .Bottom: return .MaxYEdge | |
case .Left: return .MinXEdge | |
case .Right: return .MaxXEdge | |
case .Top: return .MinYEdge | |
} | |
} | |
} | |
/** | |
This method creates a new CGRect by strecting the specified `edge` to align with the `toEdge`. | |
The result can end up with a negative width/height. | |
- Note: This method DOES mutate the size of the rect. | |
- SeeAlso: `algin(edge:toEdge:ofRect:withOffset:)` | |
*/ | |
public func pin(edge: Edge, toEdge: Edge, ofRect rect: CGRect, withOffset offset: CGFloat = 0) -> CGRect { | |
switch (edge, toEdge) { | |
case (.Left, .Left): | |
return CGRect(x: rect.minX - offset, y: minY, width: width + (minX - rect.minX) + offset, height: height) | |
case (.Left, .Right): | |
return CGRect(x: rect.maxX + offset, y: minY, width: width + (minX - rect.maxX) - offset, height: height) | |
case (.Top, .Top): | |
return CGRect(x: minX, y: rect.minY - offset, width: width, height: height + (minY - rect.minY) + offset) | |
case (.Top, .Bottom): | |
return CGRect(x: minX, y: rect.maxY + offset, width: width, height: height + (minY - rect.maxY) - offset) | |
case (.Right, .Left): | |
return CGRect(x: rect.minX, y: minY, width: width - (maxX - rect.minX) + offset, height: height) | |
case (.Right, .Right): | |
return CGRect(x: minX, y: minY, width: width - (maxX - rect.maxX) - offset, height: height) | |
case (.Bottom, .Top): | |
return CGRect(x: minX, y: minY, width: width, height: height - (maxY - rect.minY) + offset) | |
case (.Bottom, .Bottom): | |
return CGRect(x: minX, y: minY, width: width, height: height - (maxY - rect.maxY) - offset) | |
default: | |
preconditionFailure("Cannot align to this combination of edges") | |
} | |
} | |
/** | |
This method creates a new CGRect by aligning the specified `edge` to the `toEdge`. | |
- SeeAlso: `pin(edge:toEdge:ofRect:withOffset:)` | |
*/ | |
public func align(edge: Edge, toEdge: Edge, ofRect rect: CGRect, withOffset offset: CGFloat = 0) -> CGRect { | |
return CGRect(origin: alignOrigin(edge, toEdge: toEdge, ofRect: rect, withOffset: offset), size: size) | |
} | |
private func alignOrigin(edge: Edge, toEdge: Edge, ofRect rect: CGRect, withOffset offset: CGFloat) -> CGPoint { | |
switch (edge, toEdge) { | |
case (.Left, .Left): | |
return CGPoint(x: rect.minX + offset, y: minY) | |
case (.Left, .Right): | |
return CGPoint(x: rect.maxX + offset, y: minY) | |
case (.Top, .Top): | |
return CGPoint(x: minX, y: rect.minY + offset) | |
case (.Top, .Bottom): | |
return CGPoint(x: minX, y: rect.maxY + offset) | |
case (.Right, .Left): | |
return CGPoint(x: rect.minX - width - offset, y: minY) | |
case (.Right, .Right): | |
return CGPoint(x: rect.maxX - width - offset, y: minY) | |
case (.Bottom, .Top): | |
return CGPoint(x: minX, y: rect.minY - height - offset) | |
case (.Bottom, .Bottom): | |
return CGPoint(x: minX, y: rect.maxY - height - offset) | |
default: | |
preconditionFailure("Cannot align to this combination of edges") | |
} | |
} | |
} | |
extension CGRect { | |
public enum Direction { | |
case Up | |
case Down | |
case Left | |
case Right | |
} | |
public func move(direction: Direction, amount: CGFloat) -> CGRect { | |
switch direction { | |
case .Up: return CGRectMake(minX, minY - amount, width, height) | |
case .Down: return CGRectMake(minX, minY + amount, width, height) | |
case .Left: return CGRectMake(minX - amount, minY, width, height) | |
case .Right: return CGRectMake(minX + amount, minY, width, height) | |
} | |
} | |
public func expand(direction: Direction, amount: CGFloat) -> CGRect { | |
switch direction { | |
case .Up: return CGRectMake(minX, minY - amount, width, height + amount) | |
case .Down: return CGRectMake(minX, minY, width, height + amount) | |
case .Left: return CGRectMake(minX - amount, minY, width + amount, height) | |
case .Right: return CGRectMake(minX, minY, width + amount, height) | |
} | |
} | |
} | |
extension CGRect { | |
public enum Dimension { | |
case Height | |
case Width | |
} | |
public func setDimension(dimension: Dimension, toSize size: CGFloat) -> CGRect { | |
switch dimension { | |
case .Height: return CGRectMake(minX, minY, width, size) | |
case .Width: return CGRectMake(minX, minY, size, height) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment