Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/calayer set figma shadow tokens #165

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from
Draft
148 changes: 148 additions & 0 deletions Sources/CALayer+SetFigmaShadowTokens.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
//
// CALayer+setFigmaShadowTokens.swift
//
//
// Created by Paul Addy on 2/12/22.
//

import UIKit
#if os(iOS)
//ref: https://stackoverflow.com/questions/34269399/how-to-control-shadow-spread-and-blur
extension CALayer {
func setFigmaShadowTokens(value: Any?) {
print("RAS/SwiftTheme setFigmaShadowTokens value \(value)")
guard let figmaValues = value as? [String: Any] else {
fatalError("Could not cast figmaTokenValuesRaw to Dictionary")
}

var xOffset: CGFloat = 0
var yOffset: CGFloat = 0
var blur: CGFloat = 0
var spread: CGFloat = 0
var color: UIColor = .black
var opacity: Float = 0

for (key, value) in figmaValues {
switch key {
case "x":
xOffset = value as! CGFloat
case "y":
yOffset = value as! CGFloat
case "blur":
blur = value as! CGFloat
case "spread":
spread = value as! CGFloat
case "color":
color = getColor(hexadecimal: value)
opacity = getOpacity(hexadecimal: value)
case "type":
guard let type = value as? String,
type == "dropShadow" else {
assertionFailure("missingData")
return
}
default:
assertionFailure("missingData")
}
}

masksToBounds = false
shadowColor = color.cgColor
shadowOpacity = opacity
shadowOffset = CGSize(width: xOffset, height: yOffset)
shadowRadius = blur / 2.0
if spread == 0 {
shadowPath = nil
} else {
let dx = -spread
let rect = bounds.insetBy(dx: dx, dy: dx)
shadowPath = UIBezierPath(rect: rect).cgPath
}
}

func getColor(hexadecimal: Any?) -> UIColor {
guard let hex = hexadecimal as? String,
hex.hasPrefix("#"),
hex.count == 9 else {
assertionFailure("missingData")
return .black
}

var colorString = hex
colorString.removeLast(2)

guard let color = UIColor(hex: colorString) else {
assertionFailure("missingData")
return .black
}

return color
}

func getOpacity(hexadecimal: Any?) -> Float {
guard let hex = hexadecimal as? String,
hex.hasPrefix("#"),
hex.count == 9 else {
assertionFailure("missingData")
return 0.0
}

let alpha: Float
let start = hex.index(hex.startIndex, offsetBy: 1)
let hexColor = String(hex[start...])

guard hexColor.count == 8 else {
assertionFailure("missingData")
return 0.0
}

let scanner = Scanner(string: hexColor)
var hexNumber: UInt64 = 0

guard scanner.scanHexInt64(&hexNumber) else {
assertionFailure("missingData")
return 0.0
}

alpha = Float(hexNumber & 0x000000ff) / 255
return alpha
}
}


// ref: https://www.hackingwithswift.com/example-code/uicolor/how-to-convert-a-hex-color-to-a-uicolor
fileprivate extension UIColor {
convenience init?(hex: String) {
guard hex.hasPrefix("#") else {
assertionFailure("missingData")
return nil
}

let red: CGFloat
let green: CGFloat
let blue: CGFloat
let alpha: CGFloat

let start = hex.index(hex.startIndex, offsetBy: 1)
let hexColor = String(hex[start...]) + "ff"
guard hexColor.count == 8 else {
assertionFailure("missingData")
return nil
}

let scanner = Scanner(string: hexColor)
var hexNumber: UInt64 = 0

guard scanner.scanHexInt64(&hexNumber) else {
assertionFailure("missingData")
return nil
}
red = CGFloat((hexNumber & 0xff000000) >> 24) / 255
green = CGFloat((hexNumber & 0x00ff0000) >> 16) / 255
blue = CGFloat((hexNumber & 0x0000ff00) >> 8) / 255
alpha = CGFloat(hexNumber & 0x000000ff) / 255
self.init(red: red, green: green, blue: blue, alpha: alpha)
return
}
}
#endif
21 changes: 21 additions & 0 deletions Sources/NSLayoutConstraint+Theme.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// NSLayoutConstraint+Theme.swift
//
// Setters used by ThemePickers operating on NSLayoutConstraint.
//
// Created by Ryan Tan on 29/11/22.
//

import UIKit

#if os(iOS)
extension NSLayoutConstraint {

/// Sets constant for the constraint.
///
/// Triggered by SwiftTheme when theme_constraintConstant is used.
@objc func setConstraintConstant(_ value: CGFloat) {
constant = value
}
}
#endif
30 changes: 30 additions & 0 deletions Sources/UIKit+Theme.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ import UIKit
get { return getThemePicker(self, "setTintColor:") as? ThemeColorPicker }
set { setThemePicker(self, "setTintColor:", newValue) }
}
var theme_backgroundColorOrGradient: ThemeAnyPicker? {
get { return getThemePicker(self, "setBackgroundColorOrGradient:") as? ThemeAnyPicker }
set { setThemePicker(self, "setBackgroundColorOrGradient:", newValue) }
}
var theme_widthConstant: ThemeCGFloatPicker? {
get { return getThemePicker(self, "setWidthConstantConstraint:") as? ThemeCGFloatPicker }
set { setThemePicker(self, "setWidthConstantConstraint:", newValue) }
}
var theme_heightConstant: ThemeCGFloatPicker? {
get { return getThemePicker(self, "setHeightConstantConstraint:") as? ThemeCGFloatPicker }
set { setThemePicker(self, "setHeightConstantConstraint:", newValue) }
}
}
@objc public extension UIApplication
{
Expand Down Expand Up @@ -311,6 +323,10 @@ import UIKit
get { return getThemePicker(self, "setFillColor:") as? ThemeCGColorPicker }
set { setThemePicker(self, "setFillColor:", newValue) }
}
var theme_figmaShadow: ThemeAnyPicker? {
get { return getThemePicker(self, "setFigmaShadowTokens:") as? ThemeAnyPicker }
set { setThemePicker(self, "setFigmaShadowTokens:", newValue) }
}
}
@objc public extension CATextLayer
{
Expand Down Expand Up @@ -397,6 +413,20 @@ import UIKit
set { setThemePicker(self, "setEffect:", newValue) }
}
}
@objc public extension NSLayoutConstraint
{
var theme_constraintConstant: ThemeCGFloatPicker? {
get { return getThemePicker(self, "setConstraintConstant:") as? ThemeCGFloatPicker }
set { setThemePicker(self, "setConstraintConstant:", newValue) }
}
}
@objc public extension UIStackView
{
var theme_stackViewSpacing: ThemeCGFloatPicker? {
get { return getThemePicker(self, "setStackViewSpacing:") as? ThemeCGFloatPicker }
set { setThemePicker(self, "setStackViewSpacing:", newValue) }
}
}
@available(iOS 13.0, *)
@objc public extension UINavigationBarAppearance
{
Expand Down
21 changes: 21 additions & 0 deletions Sources/UIStackview+Theme.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// UIStackview+Theme.swift
//
// Setters used by ThemePickers operating on UIStackView.
//
// Created by Ryan Tan on 29/11/22.
//

import UIKit

#if os(iOS)
extension UIStackView {

/// Sets spacing on stack views..
///
/// Triggered by SwiftTheme when theme_stackViewSpacing is used.
@objc func setStackViewSpacing(_ value: CGFloat) {
spacing = value
}
}
#endif
6 changes: 6 additions & 0 deletions SwiftTheme.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@
A3D5F8191E3C56CD00F901C1 /* ThemeActivityIndicatorViewStylePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3D5F8181E3C56CD00F901C1 /* ThemeActivityIndicatorViewStylePicker.swift */; };
A3D5F81E1E3C5B1F00F901C1 /* ThemeFontPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3D5F81D1E3C5B1F00F901C1 /* ThemeFontPicker.swift */; };
C7C3CC1E21CF8D6300DDA4C1 /* ThemeScrollViewIndicatorStylePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7C3CC1D21CF8D6300DDA4C1 /* ThemeScrollViewIndicatorStylePicker.swift */; };
DC731C36293D801C0001DD16 /* CALayer+SetFigmaShadowTokens.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC731C35293D801C0001DD16 /* CALayer+SetFigmaShadowTokens.swift */; };
DC731C37293D801C0001DD16 /* CALayer+SetFigmaShadowTokens.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC731C35293D801C0001DD16 /* CALayer+SetFigmaShadowTokens.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -357,6 +359,7 @@
A3D5F81D1E3C5B1F00F901C1 /* ThemeFontPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThemeFontPicker.swift; sourceTree = "<group>"; };
A3EF94C91CEC29FD0068F86C /* PlistDemo-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PlistDemo-Bridging-Header.h"; sourceTree = "<group>"; };
C7C3CC1D21CF8D6300DDA4C1 /* ThemeScrollViewIndicatorStylePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeScrollViewIndicatorStylePicker.swift; sourceTree = "<group>"; };
DC731C35293D801C0001DD16 /* CALayer+SetFigmaShadowTokens.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CALayer+SetFigmaShadowTokens.swift"; sourceTree = "<group>"; };
ECEAC74D333D35C31C5B72FB /* Pods-PlistDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PlistDemo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PlistDemo/Pods-PlistDemo.debug.xcconfig"; sourceTree = "<group>"; };
F49FBCCD673D55E76D872AA5 /* libPods-PlistDemo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PlistDemo.a"; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -624,6 +627,7 @@
18D642DF1C53638200DADEC5 /* Sources */ = {
isa = PBXGroup;
children = (
DC731C35293D801C0001DD16 /* CALayer+SetFigmaShadowTokens.swift */,
1C6079BA231B7D2200BCE899 /* ThemeAttributes */,
A373E3A31E3C387D00ED2F2B /* ThemePickers */,
18D642E31C53638200DADEC5 /* NSObject+Theme.swift */,
Expand Down Expand Up @@ -1179,6 +1183,7 @@
A3A389991D8E2F2800797F17 /* ThemeManager+OC.swift in Sources */,
0AD183E6204F8B90005F5D85 /* UITextField+PlaceholderAttributes.swift in Sources */,
A373E3811E3C341200ED2F2B /* ThemeColorPicker.swift in Sources */,
DC731C36293D801C0001DD16 /* CALayer+SetFigmaShadowTokens.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -1242,6 +1247,7 @@
A37F8C891F8A43B300ABB5EC /* ThemeImagePicker.swift in Sources */,
A37F8C971F8A551E00ABB5EC /* ThemeStatusBarStylePicker.swift in Sources */,
A37F8C8A1F8A43B300ABB5EC /* ThemeStatePicker.swift in Sources */,
DC731C37293D801C0001DD16 /* CALayer+SetFigmaShadowTokens.swift in Sources */,
A37F8C8D1F8A43B300ABB5EC /* ThemeActivityIndicatorViewStylePicker.swift in Sources */,
A37F8C8E1F8A43B300ABB5EC /* ThemeKeyboardAppearancePicker.swift in Sources */,
A37F8C8F1F8A43B300ABB5EC /* ThemeManager.swift in Sources */,
Expand Down