From 79e9e6742c18562f251bd71d69fce9e10fcf0059 Mon Sep 17 00:00:00 2001 From: David Walter Date: Wed, 23 Feb 2022 01:06:37 +0100 Subject: [PATCH 1/3] Add SwiftUI Support --- ...mage+Awesome.swift => Amazing+Image.swift} | 2 +- Classes/SwiftUI/Awesome+Image.swift | 106 ++++++++++++++++++ Classes/SwiftUI/SwiftUI+Extensions.swift | 62 ++++++++++ Package.swift | 2 +- README.md | 2 + 5 files changed, 172 insertions(+), 2 deletions(-) rename Classes/Extensions/{Image+Awesome.swift => Amazing+Image.swift} (99%) create mode 100644 Classes/SwiftUI/Awesome+Image.swift create mode 100644 Classes/SwiftUI/SwiftUI+Extensions.swift diff --git a/Classes/Extensions/Image+Awesome.swift b/Classes/Extensions/Amazing+Image.swift similarity index 99% rename from Classes/Extensions/Image+Awesome.swift rename to Classes/Extensions/Amazing+Image.swift index 425b3a3..ea8cf6e 100755 --- a/Classes/Extensions/Image+Awesome.swift +++ b/Classes/Extensions/Amazing+Image.swift @@ -1,5 +1,5 @@ // -// Image+Awesome.swift +// Amazing+Image.swift // Awesome // // Created by Ondrej Rafaj on 13/10/2017. diff --git a/Classes/SwiftUI/Awesome+Image.swift b/Classes/SwiftUI/Awesome+Image.swift new file mode 100644 index 0000000..ab87124 --- /dev/null +++ b/Classes/SwiftUI/Awesome+Image.swift @@ -0,0 +1,106 @@ +// +// Awesome+Image.swift +// Awesome +// +// Created by David Walter on 22.02.22. +// + +#if canImport(SwiftUI) +import SwiftUI + +extension Awesome { + @available(iOS 13, macOS 11, watchOS 6, tvOS 13, *) + /// A view wrapper around an Awesome.Icon + public struct Image: View where Icon: Amazing { + @Environment(\.imageScale) var imageScale + @Environment(\.font) var font + + var icon: Icon + + private var forcedSize: CGSize? + private var color: Amazing.Color + private var backgroundColor: Amazing.Color + + var size: CGSize { + if let size = forcedSize { + return size + } + + let textStyle = self.font?.textStyle ?? .body + let size = Amazing.Font.preferredFont(forTextStyle: textStyle).pointSize * imageScale.value + return CGSize(width: size * 1.28571429, height: size) + } + + public var body: some View { + #if os(iOS) || os(watchOS) || os(tvOS) + SwiftUI.Image(uiImage: icon.asImage(size: size, color: color, backgroundColor: backgroundColor)) + #elseif os(macOS) + SwiftUI.Image(nsImage: icon.asImage(size: size, color: color, backgroundColor: backgroundColor)) + #endif + } + + public init(icon: Icon) { + self.icon = icon + self.forcedSize = nil + self.color = .black + self.backgroundColor = .clear + } + + /// Changes the size of the underlying image + /// + /// - Parameter size: The size to change to + public func size(_ size: CGFloat) -> Self { + var view = self + view.forcedSize = CGSize(width: size, height: size) + return view + } + + /// Changes the size of the underlying image + /// + /// - Parameter size: The size to change to + public func size(_ size: CGSize) -> Self { + var view = self + view.forcedSize = size + return view + } + + /// Changes the foreground color of the underlying image + /// + /// - Parameter color: The color + public func foregroundColor(_ color: Amazing.Color) -> Self { + var view = self + view.color = color + return view + } + + /// Changes the background color of the underlying image + /// + /// - Parameter color: The background color + public func backgroundColor(_ color: Amazing.Color) -> Self { + var view = self + view.backgroundColor = backgroundColor + return view + } + + @available(iOS 14, macOS 11, watchOS 7, tvOS 14, *) + /// Changes the foreground color of the underlying image + /// + /// - Parameter color: The color + public func foregroundColor(_ color: Color) -> Self { + var view = self + view.color = Amazing.Color(color) + return view + } + + @available(iOS 14, macOS 11, watchOS 7, tvOS 14, *) + /// Changes the background color of the underlying image + /// + /// - Parameter color: The background color + public func backgroundColor(_ color: Color) -> Self { + var view = self + view.backgroundColor = Amazing.Color(color) + return view + } + } +} +#endif diff --git a/Classes/SwiftUI/SwiftUI+Extensions.swift b/Classes/SwiftUI/SwiftUI+Extensions.swift new file mode 100644 index 0000000..410d3d8 --- /dev/null +++ b/Classes/SwiftUI/SwiftUI+Extensions.swift @@ -0,0 +1,62 @@ +// +// SwiftUI+Extensions.swift +// Awesome +// +// Created by David Walter on 23.02.22. +// + +#if canImport(SwiftUI) +import SwiftUI + +@available(iOS 13, macOS 11, watchOS 6, tvOS 13, *) +extension SwiftUI.Font { + var textStyle: Amazing.Font.TextStyle? { + switch self { + case .largeTitle: + #if os(tvOS) + return nil + #else + return .largeTitle + #endif + case .title: + return .title1 + case .title: + return .title2 + case .title: + return .title3 + case .headline: + return .headline + case .subheadline: + return .subheadline + case .body: + return .body + case .callout: + return .callout + case .footnote: + return .footnote + case .caption: + return .caption1 + case .caption: + return .caption2 + default: + return nil + } + } +} + +@available(iOS 13, macOS 11, watchOS 6, tvOS 13, *) +extension Image.Scale { + var value: CGFloat { + switch self { + case .small: + return 1 / 1.28571429 + case .medium: + return 1 + case .large: + return 1.28571429 + @unknown default: + return 1 + } + } +} +#endif diff --git a/Package.swift b/Package.swift index 55ecdcb..091c374 100644 --- a/Package.swift +++ b/Package.swift @@ -4,7 +4,7 @@ import PackageDescription let package = Package( name: "Awesome", - platforms: [.iOS(.v9), .macOS(.v10_11), .watchOS(.v2), .tvOS(.v9)], + platforms: [.iOS(.v11), .macOS(.v10_11), .watchOS(.v2), .tvOS(.v9)], products: [ .library( name: "Awesome", diff --git a/README.md b/README.md index 8008bd0..37c04eb 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,8 @@ let image = Awesome.Solid.handScissors.asImage(size: 40.0) let image = Awesome.Brand.android.asImage(size: CGSize(width: 40, height: 40), color: .red, backgroundColor: .blue) // :trollface: // or let attributedText = Awesome.Regular.envelopeOpen.asAttributedText(fontSize: 17, color: .red, backgroundColor: .blue) +// SwiftUI +Awesome.Image(icon: Awesome.Brand.apple) ``` ### Font Awesome Pro From d1629803250d6c008c6cd44e9115b62873cccb5e Mon Sep 17 00:00:00 2001 From: David Walter Date: Wed, 23 Feb 2022 08:54:19 +0100 Subject: [PATCH 2/3] Add helper extension Cleanup --- Classes/SwiftUI/Awesome+Image.swift | 29 ++++++++--------------------- README.md | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/Classes/SwiftUI/Awesome+Image.swift b/Classes/SwiftUI/Awesome+Image.swift index ab87124..c2864b1 100644 --- a/Classes/SwiftUI/Awesome+Image.swift +++ b/Classes/SwiftUI/Awesome+Image.swift @@ -8,6 +8,13 @@ #if canImport(SwiftUI) import SwiftUI +public extension Amazing { + @available(iOS 13, macOS 11, watchOS 6, tvOS 13, *) + var image: Awesome.Image { + Awesome.Image(icon: self) + } +} + extension Awesome { @available(iOS 13, macOS 11, watchOS 6, tvOS 13, *) /// A view wrapper around an Awesome.Icon @@ -78,27 +85,7 @@ extension Awesome { /// - Parameter color: The background color public func backgroundColor(_ color: Amazing.Color) -> Self { var view = self - view.backgroundColor = backgroundColor - return view - } - - @available(iOS 14, macOS 11, watchOS 7, tvOS 14, *) - /// Changes the foreground color of the underlying image - /// - /// - Parameter color: The color - public func foregroundColor(_ color: Color) -> Self { - var view = self - view.color = Amazing.Color(color) - return view - } - - @available(iOS 14, macOS 11, watchOS 7, tvOS 14, *) - /// Changes the background color of the underlying image - /// - /// - Parameter color: The background color - public func backgroundColor(_ color: Color) -> Self { - var view = self - view.backgroundColor = Amazing.Color(color) + view.backgroundColor = color return view } } diff --git a/README.md b/README.md index 37c04eb..dc5ea21 100644 --- a/README.md +++ b/README.md @@ -64,12 +64,26 @@ import Awesome All icons are available through autogenerated enums like this: ```swift +// UKit and AppKit let image = Awesome.Solid.handScissors.asImage(size: 40.0) // or let image = Awesome.Brand.android.asImage(size: CGSize(width: 40, height: 40), color: .red, backgroundColor: .blue) // :trollface: // or let attributedText = Awesome.Regular.envelopeOpen.asAttributedText(fontSize: 17, color: .red, backgroundColor: .blue) + // SwiftUI +Awesome.Brand.apple.image +// Set some modifiers +Awesome.Brand.android.image + .size(40) + .foregroundColor(.red) + .backgroundColor(.blue) +// Scales automatically with font +Awesome.Brand.android.image + .foregroundColor(.red) + .backgroundColor(.blue) + .font(.largeTitle) +// or Awesome.Image(icon: Awesome.Brand.apple) ``` From 1134a0124e13481f6336e27627336785e2b4a47b Mon Sep 17 00:00:00 2001 From: David Walter Date: Sun, 27 Feb 2022 15:49:24 +0100 Subject: [PATCH 3/3] Add resizable + cleanup --- Classes/Extensions/Amazing+Tools.swift | 12 ++++ Classes/Libs/Crossplatform.swift | 4 +- Classes/SwiftUI/Awesome+Image.swift | 87 +++++++++++++++++------- Classes/SwiftUI/SwiftUI+Extensions.swift | 2 +- 4 files changed, 78 insertions(+), 27 deletions(-) diff --git a/Classes/Extensions/Amazing+Tools.swift b/Classes/Extensions/Amazing+Tools.swift index 84c1fc6..aadf008 100755 --- a/Classes/Extensions/Amazing+Tools.swift +++ b/Classes/Extensions/Amazing+Tools.swift @@ -45,6 +45,18 @@ public extension Amazing { } } +#if canImport(SwiftUI) +import SwiftUI + +@available(iOS 13, macOS 11, watchOS 6, tvOS 13, *) +public extension Amazing { + /// A SwiftUI Image of the icon + var image: Awesome.Image { + Awesome.Image(icon: self) + } +} +#endif + extension Amazing { /// Returns an unique identifier string that contains the font name, font style and icon name diff --git a/Classes/Libs/Crossplatform.swift b/Classes/Libs/Crossplatform.swift index d7b2426..412840b 100644 --- a/Classes/Libs/Crossplatform.swift +++ b/Classes/Libs/Crossplatform.swift @@ -9,7 +9,7 @@ import Foundation #if os(iOS) || os(watchOS) || os(tvOS) - import UIKit +import UIKit extension Amazing { public typealias Color = UIColor @@ -19,7 +19,7 @@ extension Amazing { #elseif os(OSX) - import Cocoa +import Cocoa extension Amazing { public typealias Color = NSColor diff --git a/Classes/SwiftUI/Awesome+Image.swift b/Classes/SwiftUI/Awesome+Image.swift index c2864b1..30a5da8 100644 --- a/Classes/SwiftUI/Awesome+Image.swift +++ b/Classes/SwiftUI/Awesome+Image.swift @@ -8,26 +8,23 @@ #if canImport(SwiftUI) import SwiftUI -public extension Amazing { - @available(iOS 13, macOS 11, watchOS 6, tvOS 13, *) - var image: Awesome.Image { - Awesome.Image(icon: self) - } -} - +@available(iOS 13, macOS 11, watchOS 6, tvOS 13, *) extension Awesome { - @available(iOS 13, macOS 11, watchOS 6, tvOS 13, *) - /// A view wrapper around an Awesome.Icon - public struct Image: View where Icon: Amazing { + /// A view wrapper around an Awesome.Image + public struct Image: View where AmazingType: Amazing { + var icon: AmazingType + @Environment(\.imageScale) var imageScale @Environment(\.font) var font - var icon: Icon - private var forcedSize: CGSize? - private var color: Amazing.Color + private var foregroundColor: Amazing.Color private var backgroundColor: Amazing.Color + private var isResizable: Bool + private var capInsets: EdgeInsets + private var resizingMode: SwiftUI.Image.ResizingMode + var size: CGSize { if let size = forcedSize { return size @@ -39,55 +36,97 @@ extension Awesome { } public var body: some View { + if isResizable { + image.resizable(capInsets: capInsets, resizingMode: resizingMode) + } else { + image + } + } + + var image: SwiftUI.Image { #if os(iOS) || os(watchOS) || os(tvOS) - SwiftUI.Image(uiImage: icon.asImage(size: size, color: color, backgroundColor: backgroundColor)) + SwiftUI.Image(uiImage: icon.asImage(size: size, color: foregroundColor, backgroundColor: backgroundColor)) #elseif os(macOS) - SwiftUI.Image(nsImage: icon.asImage(size: size, color: color, backgroundColor: backgroundColor)) + SwiftUI.Image(nsImage: icon.asImage(size: size, color: foregroundColor, backgroundColor: backgroundColor)) #endif } - public init(icon: Icon) { + /// Creates a Font Awesome icon image. + /// + /// This initializer creates an image using a Font Awesome icon. + /// + /// - Parameters: + /// - icon: The icon to use + public init(icon: AmazingType) { self.icon = icon + self.forcedSize = nil - self.color = .black + self.foregroundColor = .black self.backgroundColor = .clear + + self.isResizable = false + self.capInsets = EdgeInsets() + self.resizingMode = .stretch } - /// Changes the size of the underlying image + /// Changes the size of the underlying image. This will disable the automatic sizing based on the font /// /// - Parameter size: The size to change to + /// + /// - Returns: An image that uses the size you supply public func size(_ size: CGFloat) -> Self { var view = self view.forcedSize = CGSize(width: size, height: size) return view } - /// Changes the size of the underlying image + /// Changes the size of the underlying image. This will disable the automatic sizing based on the font /// /// - Parameter size: The size to change to + /// + /// - Returns: An image that uses the size you supply public func size(_ size: CGSize) -> Self { var view = self view.forcedSize = size return view } - /// Changes the foreground color of the underlying image + /// Sets the color of the icon. /// - /// - Parameter color: The color + /// - Parameter color: The foreground color to use when displaying this icon. + /// + /// - Returns: A view that uses the foreground color you supply. public func foregroundColor(_ color: Amazing.Color) -> Self { var view = self - view.color = color + view.foregroundColor = color return view } - /// Changes the background color of the underlying image + /// Sets the background color of the icon. + /// + /// - Parameter color: The background color to use when displaying this icon. /// - /// - Parameter color: The background color + /// - Returns: An image that uses the background color you supply public func backgroundColor(_ color: Amazing.Color) -> Self { var view = self view.backgroundColor = color return view } + + /// Sets the mode by which SwiftUI resizes an image to fit its space. + /// + /// - Parameters: + /// - capInsets: Inset values that indicate a portion of the image that SwiftUI doesn't resize. + /// - resizingMode: The mode by which SwiftUI resizes the image. + /// + /// - Returns: An image, with the new resizing behavior set. + public func resizable(capInsets: EdgeInsets = EdgeInsets(), resizingMode: SwiftUI.Image.ResizingMode = .stretch) -> Self { + var view = self + view.isResizable = true + view.capInsets = capInsets + view.resizingMode = resizingMode + return view + } } } #endif diff --git a/Classes/SwiftUI/SwiftUI+Extensions.swift b/Classes/SwiftUI/SwiftUI+Extensions.swift index 410d3d8..1fd3aad 100644 --- a/Classes/SwiftUI/SwiftUI+Extensions.swift +++ b/Classes/SwiftUI/SwiftUI+Extensions.swift @@ -9,7 +9,7 @@ import SwiftUI @available(iOS 13, macOS 11, watchOS 6, tvOS 13, *) -extension SwiftUI.Font { +extension Font { var textStyle: Amazing.Font.TextStyle? { switch self { case .largeTitle: