Skip to content

Commit

Permalink
⭐️ Impl: Add RNILayout
Browse files Browse the repository at this point in the history
  • Loading branch information
dominicstop committed May 19, 2023
1 parent 6596f25 commit 99cd472
Show file tree
Hide file tree
Showing 2 changed files with 268 additions and 0 deletions.
54 changes: 54 additions & 0 deletions ios/src_library/Extensions/CGRect+Helpers.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// CGSize+Helpers.swift
// swift-programmatic-modal
//
// Created by Dominic Go on 5/19/23.
//

import Foundation

extension CGRect {
mutating func setPoint(
minX: CGFloat? = nil,
minY: CGFloat? = nil
){
self.origin = CGPoint(
x: minX ?? self.minX,
y: minY ?? self.minY
);
};

mutating func setPoint(
midX: CGFloat? = nil,
midY: CGFloat? = nil
){
let newX: CGFloat = {
guard let midX = midX else { return self.minX };
return midX - (self.width / 2);
}();

let newY: CGFloat = {
guard let midY = midY else { return self.minY };
return midY - (self.height / 2);
}();

self.origin = CGPoint(x: newX, y: newY);
};

mutating func setPoint(
maxX: CGFloat? = nil,
maxY: CGFloat? = nil
){
let newX: CGFloat = {
guard let maxX = maxX else { return self.minX };
return maxX - self.width;
}();

let newY: CGFloat = {
guard let maxY = maxY else { return self.minY };
return maxY - self.height;
}();

self.origin = CGPoint(x: newX, y: newY);
};
};
214 changes: 214 additions & 0 deletions ios/src_library/React Native/RNILayout/RNILayout.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
//
// RNILayout.swift
// swift-programmatic-modal
//
// Created by Dominic Go on 5/19/23.
//

import Foundation

public struct RNILayout {

public enum HorizontalAlignment: String {
case left, right, center;
};

public enum VerticalAlignment: String {
case top, bottom, center;
};

// MARK: - Properties
// ------------------

public let horizontalAlignment: HorizontalAlignment;
public let verticalAlignment: VerticalAlignment;

public let width: RNIComputableValue;
public let height: RNIComputableValue;

public let marginLeft: CGFloat?;
public let marginRight: CGFloat?;
public let marginTop: CGFloat?;
public let marginBottom: CGFloat?;

// MARK: - Computed Properties
// ---------------------------

public var marginHorizontal: CGFloat {
(self.marginLeft ?? 0) + (self.marginRight ?? 0)
};

public var marginVertical: CGFloat {
(self.marginTop ?? 0) + (self.marginBottom ?? 0)
};

// MARK: - Init
// ------------

init(
horizontalAlignment: HorizontalAlignment,
verticalAlignment: VerticalAlignment,
width: RNIComputableValue,
height: RNIComputableValue,
marginLeft: CGFloat? = nil,
marginRight: CGFloat? = nil,
marginTop: CGFloat? = nil,
marginBottom: CGFloat? = nil
) {
self.horizontalAlignment = horizontalAlignment;
self.verticalAlignment = verticalAlignment;
self.width = width;
self.height = height;
self.marginLeft = marginLeft;
self.marginRight = marginRight;
self.marginTop = marginTop;
self.marginBottom = marginBottom;
};

// MARK: - Intermediate Functions
// ------------------------------

/// Compute Rect - Step 1
/// * Rect with the computed size based on `size` config.
///
public func computeRawRectSize(
withTargetRect targetRect: CGRect,
currentSize: CGSize
) -> CGRect {
let targetSize = targetRect.size;

let computedSize = CGSize(
width: self.width.compute(
withTargetValue: targetSize.width,
currentValue: currentSize.width
),
height: self.height.compute(
withTargetValue: targetSize.height,
currentValue: currentSize.height
)
);

return CGRect(origin: .zero, size: computedSize);
};

/// Compute Rect - Step 2
/// * Rect with the computed size based on `size` config.
///
/// * Rect with the origin based on `horizontalAlignment`, and
/// `verticalAlignment` config.
///
public func computeRawRectOrigin(
forRect rect: CGRect? = nil,
withTargetRect targetRect: CGRect,
currentSize: CGSize,
ignoreXAxis: Bool = false,
ignoreYAxis: Bool = false
) -> CGRect {

var rect = rect ?? self.computeRawRectSize(
withTargetRect: targetRect,
currentSize: currentSize
);

if !ignoreXAxis {
// Compute Origin - X
switch self.horizontalAlignment {
case .center:
rect.setPoint(midX: targetRect.midX);

case .left:
rect.setPoint(minX: targetRect.minX);

case .right:
rect.setPoint(maxX: targetRect.maxX);
};
};

if !ignoreYAxis {
// Compute Origin - Y
switch self.verticalAlignment {
case .center:
rect.setPoint(midY: targetRect.midY);

case .top:
rect.setPoint(minY: targetRect.minY);

case .bottom:
rect.setPoint(maxY: targetRect.maxY);
};
};

return rect;
};

// MARK: - Functions
// -----------------

/// Compute Rect - Step 3
/// * Rect with the computed size based on `size` config.
///
/// * Rect with the origin based on `horizontalAlignment`, and
/// `verticalAlignment` config.
///
/// * Rect with margins applied to it based on the margin-related properties
///
public func computeRect(
withTargetRect targetRect: CGRect,
currentSize: CGSize
) -> CGRect {
var rect = self.computeRawRectOrigin(
withTargetRect: targetRect,
currentSize: currentSize
);

// Margin - X-Axis
switch self.horizontalAlignment {
case .left:
guard let marginLeft = self.marginLeft else { break };
rect.origin.x = rect.origin.x + marginLeft;

case .right:
guard let marginRight = self.marginRight else { break };
rect.origin.x = rect.origin.x - marginRight;

case .center:
if case .stretch = self.width.mode {
rect.size.width = rect.size.width - self.marginHorizontal;

// re-compute origin
rect = self.computeRawRectOrigin(
forRect: rect,
withTargetRect: targetRect,
currentSize: currentSize,
ignoreYAxis: true
);
};
};

// Margin - Y-Axis
switch self.verticalAlignment {
case .top:
guard let marginTop = self.marginTop else { break };
rect.origin.y = rect.origin.y + marginTop;

case .bottom:
guard let marginBottom = self.marginBottom else { break };
rect.origin.y = rect.origin.y - marginBottom;

case .center:
if case .stretch = self.height.mode {
rect.size.height = rect.size.height - self.marginVertical;

// re-compute origin
rect = self.computeRawRectOrigin(
forRect: rect,
withTargetRect: targetRect,
currentSize: currentSize,
ignoreXAxis: true
);
};
};

return rect;
};
};

0 comments on commit 99cd472

Please sign in to comment.