Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions GF/DeviceSwiftShims/Util/AdditiveArithmetic.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//
// AdditiveArithmetic.swift
// Gestures
//
// Audited for 9126.1.5
// Status: Complete

import CoreGraphics

// MARK: - _AdditiveArithmetic

package protocol _AdditiveArithmetic: Equatable {
static var zero: Self { get }

static func + (lhs: Self, rhs: Self) -> Self
static func += (lhs: inout Self, rhs: Self)
static func - (lhs: Self, rhs: Self) -> Self
static func -= (lhs: inout Self, rhs: Self)
}

extension _AdditiveArithmetic {
package static func += (lhs: inout Self, rhs: Self) {
lhs = lhs + rhs
}

package static func -= (lhs: inout Self, rhs: Self) {
lhs = lhs - rhs
}
}

// MARK: - Double + _AdditiveArithmetic

extension Double: _AdditiveArithmetic {}

// MARK: - CGPoint + _AdditiveArithmetic

extension CGPoint: _AdditiveArithmetic {
package static func + (lhs: CGPoint, rhs: CGPoint) -> CGPoint {
CGPoint(x: lhs.x + rhs.x, y: lhs.y + rhs.y)
}

package static func - (lhs: CGPoint, rhs: CGPoint) -> CGPoint {
CGPoint(x: lhs.x - rhs.x, y: lhs.y - rhs.y)
}
}

// MARK: - CGVector + _AdditiveArithmetic

extension CGVector: _AdditiveArithmetic {
package static func + (lhs: CGVector, rhs: CGVector) -> CGVector {
CGVector(dx: lhs.dx + rhs.dx, dy: lhs.dy + rhs.dy)
}

package static func - (lhs: CGVector, rhs: CGVector) -> CGVector {
CGVector(dx: lhs.dx - rhs.dx, dy: lhs.dy - rhs.dy)
}
}

// MARK: - CGSize + _AdditiveArithmetic

extension CGSize: _AdditiveArithmetic {
package static func + (lhs: CGSize, rhs: CGSize) -> CGSize {
CGSize(width: lhs.width + rhs.width, height: lhs.height + rhs.height)
}

package static func - (lhs: CGSize, rhs: CGSize) -> CGSize {
CGSize(width: lhs.width - rhs.width, height: lhs.height - rhs.height)
}
}
21 changes: 19 additions & 2 deletions GF/DeviceSwiftShims/Util/LocationContaining.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,26 @@ extension Never: LocationContaining {
}
}

// MARK: - IdentifiableLocation [WIP]
// MARK: - IdentifiableLocation

package struct IdentifiableLocation<ID> where ID: Hashable {
package struct IdentifiableLocation<ID>: Identifiable where ID: Hashable {
package var id: ID
package var location: CGPoint
}

extension IdentifiableLocation: LocationContaining {}

extension IdentifiableLocation: NestedCustomStringConvertible {}

extension IdentifiableLocation: VectorContaining {
package typealias VectorType = CGPoint

package var vector: CGPoint {
get { location }
set { location = newValue }
}
}

extension IdentifiableLocation: ThresholdAdjustable {
package typealias Threshold = Double
}
52 changes: 52 additions & 0 deletions GF/DeviceSwiftShims/Util/ThresholdAdjustable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// ThresholdAdjustable.swift
// Gestures
//
// Audited for 9126.1.5
// Status: Complete

import CoreGraphics

// MARK: - ThresholdAdjustable

/// A value whose backing vector can consume a threshold-sized movement.
package protocol ThresholdAdjustable: VectorContaining {
/// The scalar threshold type used to gate movement.
associatedtype Threshold

/// Consumes up to `threshold` units from `movement`.
///
/// When `movement` reaches the threshold, this subtracts the threshold-sized
/// portion of `movement` from `vector` and returns that consumed movement.
/// Returns `nil` without mutation when `threshold` is not positive or
/// `movement` is below threshold.
mutating func consume(_ threshold: Threshold, from movement: VectorType) -> VectorType?
}

extension ThresholdAdjustable where Threshold == Double {
package mutating func consume(_ threshold: Double, from movement: VectorType) -> VectorType? {
guard threshold > 0 else { return nil }

let movementMagnitude = movement.magnitude
guard movementMagnitude >= threshold else { return nil }

let scale = threshold / movementMagnitude
let consumedMovement = movement.scaled(by: scale)
vector -= consumedMovement
return consumedMovement
}
}

// MARK: - ThresholdAdjustable Conformance

extension Double: ThresholdAdjustable {
package typealias Threshold = Double
}

extension CGPoint: ThresholdAdjustable {
package typealias Threshold = Double
}

extension CGVector: ThresholdAdjustable {
package typealias Threshold = Double
}
85 changes: 85 additions & 0 deletions GF/DeviceSwiftShims/Util/VectorArithmetic.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//
// VectorArithmetic.swift
// Gestures
//
// Audited for 9126.1.5
// Status: Complete

import CoreGraphics

// MARK: - VectorArithmetic

package protocol VectorArithmetic: _AdditiveArithmetic {
var magnitude: Double { get }

func scaled(by rhs: Double) -> Self
}

// MARK: - VectorArithmetic Conformance

extension Double: VectorArithmetic {
package var magnitude: Double {
abs(self)
}

package func scaled(by rhs: Double) -> Double {
self * rhs
}
}

extension CGPoint: VectorArithmetic {
package var magnitude: Double {
hypot(abs(x), abs(y))
}

package func scaled(by rhs: Double) -> CGPoint {
CGPoint(x: x * rhs, y: y * rhs)
}
}

extension CGVector: VectorArithmetic {
package var magnitude: Double {
hypot(abs(dx), abs(dy))
}

package func scaled(by rhs: Double) -> CGVector {
CGVector(dx: dx * rhs, dy: dy * rhs)
}
}

// MARK: - VectorContaining

package protocol VectorContaining {
associatedtype VectorType: VectorArithmetic

var vector: VectorType { get set }
}

// MARK: - VectorContaining Conformance

extension Double: VectorContaining {
package typealias VectorType = Double

package var vector: Double {
get { self }
set { self = newValue }
}
}

extension CGPoint: VectorContaining {
package typealias VectorType = CGPoint

package var vector: CGPoint {
get { self }
set { self = newValue }
}
}

extension CGVector: VectorContaining {
package typealias VectorType = CGVector

package var vector: CGVector {
get { self }
set { self = newValue }
}
}
Loading