Skip to content

Commit

Permalink
Develop (#45)
Browse files Browse the repository at this point in the history
* Separate ClockIndex and HourMark

* Remove useless resultbuilder

* Refactor

1. rename non mutate function with Swift API design guideline
2. make some foreground support gradient color

* support preview on different platform

* Support preview on different platform

* Add placeholder for tvOS preview

* update preview

* update reference to avoid redirect to insecurity website

* Add RingStack to layout any view circular

* publish RingStack

* public init

* bug fix

* Adjust argument order in init function

* Fix visibility issue

* Fix visibility issue

* Complete knob adjustable option

* update swift and platform version

* update preview

* Improve RingStack animation

* [Refactor]

Wrap RingStack to provide rotation ability on its subview

* Solve version issue

* Solve os version issue

* Apply direction setting on RingStack

* Implement ArcStack

Also fix RingStack visibility issue on preview

* Fix os compatible issue

* Fix os compatible issue

* Extract common function

1. Alignment/Anchor mapping
2. CGPoint offset

* Refactor

Simplify anchor calculation

* Adjust preview

* Refactor

Simplify direction enum

* Add preview gif

* Use RingStackDirection to instead of TextDirection and ArcStackDirection

* [Refactor] move Text Extension to Common

* Refactor

1. Rename RingStackDirection to RingLayoutDirection -- to make the naming more general
2. Extract RingLayoutDirection to independent file
3. Re-defining those directions to follow consistent rule.
4. Refine CGPoint offset function to support generic type

* Extract variadic related function to target Common

* Renaming and adjust comment

* update github action to specify swift version

* workaround to pass git hub action

* Remove github action

Reason: The GitHub host does not include the macOS 14.*

* Remove useless function and init argument

* refactor to provide clues of crashes

* Add trace code

* update arugment

* Fix potential crash issue

* Adjust documents structure

* Adjust dooc content

* Update documents structure

* Update document on github

* Update HandAiguille.md

Fix path

* Update resource path

* Update image resource

* Update framework icon

* update ReadMe.md

* Update resource path in readme

* Add deprecated flags

* Feature/gauge meter (#44)

* Add offset and radius to AngularLayer

To support more type of layers. add offset and radius to help implementation to design it's appeareance

* [Bug fix] Image Knob degrees not work

* [Refactor] Create CustomViewLayer to instead of ImageKnobLayer

* Add GaugeMeter

* solve macOS compatible issue on preview

* Fix gradient offset issue

* add convenience function to setup gradient

* Add SemiCircleGaugeMeter as a convenience gauge meter

* Separate mark size from arc width

* Adjust value mark appearance

* Add inset support

* To support new Gauge style after ios 16

* [Refactor]

1. Rename properties
2. Add some document

* update platform condition

* [Refactor]

Extract picker extension

* Documents Archimedean Spiral Text

* Document ArcStack

* Refactor and document

* Document ring gauge meter style

* Update documents

* Update readme

* Update docs
  • Loading branch information
chenhaiteng authored Feb 19, 2024
1 parent bfbaab9 commit bfea622
Show file tree
Hide file tree
Showing 33 changed files with 1,240 additions and 163 deletions.
3 changes: 2 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ let package = Package(
.package(url: "https://github.com/chenhaiteng/ArchimedeanSpiral.git", from: "1.0.12"),
.package(url: "https://github.com/chenhaiteng/GradientBuilder.git", from: "1.0.0"),
.package(url: "https://github.com/andtie/SequenceBuilder.git", from: "0.0.7"),
.package(url: "https://github.com/GeorgeElsham/ViewExtractor", from: "2.0.0")
.package(url: "https://github.com/GeorgeElsham/ViewExtractor", from: "2.0.0"),
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.1.0")
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
Expand Down
44 changes: 8 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ It includes following controls, click to see what it looks like:
* **[ArchimedeanSpiralText](#archimedeanspiraltext)**
* **[SphericText](#spherictext)**
* **[Knob](#knob)**
* **[GaugeMeter](#gaugemeter)**
* **[RingGaugeMeterStyle](#ringgaugemeterstyle)**

and following functions are in progress:

* Swing
For more detail please refer to the [documentation](https://chenhaiteng.github.io/Docs/Rings/documentation/rings/)

---
## Installation:
Expand Down Expand Up @@ -57,62 +57,34 @@ targets: [
---

## RingStack

### What it looks like
![Demo](Sources/Rings/Documentation.docc/Resources/RingStack.gif)

### [How to use it](Markdown/Rings/RingStack.md)

## ArcStack

### What it looks like
![Demo](Sources/Rings/Documentation.docc/Resources/ArcStack.gif)

### [How to use it](Markdown/Rings/ArcStack.md)

## RingText

### What it looks like
![RingDemo](Sources/Rings/Documentation.docc/Resources/RingTextDemo.gif)

### [How to use it](Markdown/Rings/RingText.md)

## ClockIndex

### What it looks like
![Demo](Sources/Rings/Documentation.docc/Resources/ClockIndex.gif)

![Demo](Sources/Rings/Documentation.docc/Resources/EarchlyClock.png)

### [How to use it](Markdown/Rings/ClockIndex.md)

## HandAiguille

### What it looks like:
![Demo](Sources/Rings/Documentation.docc/Resources/HandAiguille.gif)

### [How to use it](Markdown/Rings/HandAiguille.md)

## ArchimedeanSpiralText

### What it looks like:
![Demo](Sources/Rings/Documentation.docc/Resources/ArchimedeanSpiralText.gif)

### [How to use it](Markdown/Rings/ArchimedeanSpiralText.md)

## SphericText

### What it looks like:
![Demo](Sources/Rings/Documentation.docc/Resources/SphericText.gif)

### [How to use it](Markdown/Rings/SphericText.md)

## Knob

### What it looks like:
![Demo](Sources/Rings/Documentation.docc/Resources/Knob.gif)

### [How to use it](Markdown/Rings/Knob.md)
## GaugeMeter
![Demo](Sources/Rings/Documentation.docc/Resources/GaugeMeterDemo.gif)

## RingGaugeMeterStyle
![Demo](Sources/Rings/Documentation.docc/Resources/RingGaugeMeterStyle.png)

---
# License
Expand Down
43 changes: 43 additions & 0 deletions Sources/Common/PickerExt.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//
// PickerExt.swift
//
//
// Created by Chen Hai Teng on 2/13/24.
//

import SwiftUI

public struct SegmentedPicker: ViewModifier {
public func body(content: Content) -> some View {
#if os(watchOS)
content
#else
content.pickerStyle(SegmentedPickerStyle()).padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 7))
#endif
}
}

public struct ColoredPicker: ViewModifier {
@Binding var selection: Color
public func body(content: Content) -> some View {
#if os(macOS) || os(iOS)
if #available(macOS 11.0, iOS 14.0, macCatalyst 14.0, *) {
ColorPicker("", selection: _selection)
} else {
content.modifier(SegmentedPicker())
}
#else
content.modifier(SegmentedPicker())
#endif
}
}

public extension Picker {
func segmented() -> some View {
modifier(SegmentedPicker())
}

func colorPicker(_ selection: Binding<Color>) -> some View {
modifier(ColoredPicker(selection: selection))
}
}
54 changes: 46 additions & 8 deletions Sources/Rings/ArcStack.swift
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,11 @@ fileprivate struct ArcStackComponent<V: View>: View {
}

@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *)
public struct ArcStack<Content: View> : View {
let radius: Double
let anchor: UnitPoint
let range: ClosedRange<Double>
let direction: RingLayoutDirection
public struct ArcStack<Content: View> : View, Adjustable {
var radius: Double
var anchor: UnitPoint
var range: ClosedRange<Double>
var direction: RingLayoutDirection

let content: () -> Content
public var body: some View {
Expand Down Expand Up @@ -216,6 +216,44 @@ public struct ArcStack<Content: View> : View {
self.direction = direction
self.content = content
}

/// Sets the radius of the arc stack.
/// - Parameter radius: The radius.
/// - Returns: arc stack with the radius you specify.
public func radius<F: BinaryFloatingPoint>(_ radius: F) -> Self {
setProperty { adjustObject in
adjustObject.radius = Double(radius)
}
}

/// Sets the anchor of the arc stack.
/// - Parameter anchor: The unit point that defines where the center of arc stack is within its bounds.
/// - Returns: arc stack with the anchor you specify.
public func anchor(_ anchor: UnitPoint) -> Self {
setProperty { adjustObject in
adjustObject.anchor = anchor
}
}

/// Sets the range of the arc stack to place subviews.
/// - Parameter range: the range to specify where to place subviews.
/// The full range depends on the what the anchor defined. If the anchor is `.top`, `.bottom`, `.leading`, or `.trailing`, the full range maps to semi-circle. If the anchor is `.topLeading`, `.topTrailing`, `.bottomLeading`, or `bottomTrailing`, the full range maps to quarter-circle.
/// Otherwise, the arc stack place its subviews as ``RingStack``
/// - Returns: arc stack with the anchor you specify.
public func range(_ range: ClosedRange<Double>) -> Self {
setProperty { adjustObject in
adjustObject.range = range
}
}

/// Sets the layout direction of sub views in arc stack.
/// - Parameter direction: The layout direction to define how sub views placed. The direction shows where the top of each sub views is towarding.
/// - Returns: arc stack with the layout direction you specify.
public func direction(_ direction: RingLayoutDirection) -> Self {
setProperty { adjustObject in
adjustObject.direction = direction
}
}
}

@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *)
Expand Down Expand Up @@ -262,7 +300,7 @@ struct ArcStackPreview : View {
}.animation(.easeInOut(duration: 1.0), value: anchor).frame(width: Self.arcSize, height: Self.arcSize)
}
ZStack(alignment:.leading) {
ArcStack(radius: expandRadius, anchor: anchor, range: 0.0...1.0, direction: .none) {
ArcStack(anchor: anchor, range: 0.0...1.0, direction: .none) {
ForEach(0..<colors.count, id: \.self) { index in
Text("\(index + 1)").frame(width: 20.0, height: 20.0).rounded(color: .white).background {
RoundedRectangle(cornerRadius: 5.0).fill(colors[index])
Expand All @@ -283,7 +321,7 @@ struct ArcStackPreview : View {
} label: {
Image(systemName: arcStateImage).resizable().frame(width: 20.0, height: 20.0)
}.buttonStyle(.borderedProminent)
}.frame(width: Self.arcSize, height: Self.arcSize)
}.radius(expandRadius).frame(width: Self.arcSize, height: Self.arcSize)
}.border(.blue.opacity(0.5))
}
Divider()
Expand Down Expand Up @@ -318,7 +356,7 @@ struct ArcStackPreview : View {
}

#Preview {
VStack {
ZStack {
if #available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *) {
ArcStackPreview().frame(height: 450.0)
}
Expand Down
63 changes: 28 additions & 35 deletions Sources/Rings/ArchimedeanSpiralText.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ extension TextDirection {
}
}

/// A view that displays read-only text along archimedean spiral.
public struct ArchimedeanSpiralText: View, CompatibleForegroundProxy {
public typealias Content = Self

Expand All @@ -68,6 +69,12 @@ public struct ArchimedeanSpiralText: View, CompatibleForegroundProxy {

private var textPoints: [CGPolarPoint] = []

/// Creates a archimedean spiral text.
/// - Parameters:
/// - innerRadius: the distance between the center and the innerest char.
/// - radiusSpacing: the distance between each radius at the same phase.
/// - gap: specifies the distance between adjacent charcters.
/// - text: the text displayed.
public init(_ innerRadius: Double = 12.0, radiusSpacing: Double = 10.0, gap: Double = 5.0, text: String = "") {
self.radiusSpacing = radiusSpacing
self.innerRadius = innerRadius
Expand Down Expand Up @@ -103,20 +110,29 @@ public struct ArchimedeanSpiralText: View, CompatibleForegroundProxy {
}

extension ArchimedeanSpiralText: Adjustable {
/// Sets the space between adjacent points at the same phase.
/// - Parameter space: The distance between adjacent points at the same phase.
/// - Returns: Archimedean spiral text use the space you specify.
public func radiusSpacing<T: BinaryFloatingPoint>(_ space: T) -> Self {
setProperty { tmp in
tmp.radiusSpacing = Double(space)
tmp.updateTextPoints()
}
}

/// Sets the space between the first character and the center
/// - Parameter radius: The radius of the first character.
/// - Returns: Archimedean spiral text use the inner radius you specify.
public func innerRadius<T: BinaryFloatingPoint>(_ radius: T) -> Self {
setProperty { tmp in
tmp.innerRadius = Double(radius)
tmp.updateTextPoints()
}
}

/// Sets the gap between the
/// - Parameter gap: The gap between adjacent characters.
/// - Returns: Archimedean spiral text use the gap you specify.
public func gap<T: BinaryFloatingPoint>(_ gap: T) -> Self {
setProperty { tmp in
tmp.gap = Double(gap)
Expand All @@ -125,24 +141,36 @@ extension ArchimedeanSpiralText: Adjustable {
}

@available(*, deprecated, renamed: "textLayoutDirection", message: "deprectaed at version 0.4.0")
/// Sets how to layout each character along the archimedean spiral.
/// - Parameter direction: Text direction
/// - Returns: Archimedean spiral text use the text direction you specify.
public func textDirection(_ direction: TextDirection) -> Self {
setProperty { tmp in
tmp.textDirection = direction.ringLayoutDirection
}
}

/// Sets how to layout each character along the archimedean spiral.
/// - Parameter direction: The layout direction which depends on the top of each character.
/// - Returns: Archimedean spiral text use the layout direction you specify.
public func textLayoutDirection(_ direction: RingLayoutDirection) -> Self {
setProperty { tmp in
tmp.textDirection = direction
}
}

/// Sets the font for text in the view
/// - Parameter font: The font to use when displaying this text.
/// - Returns: Archimedean spiral text use the font you specify.
public func font(_ font: Font) -> Self {
setProperty { tmp in
tmp.font = font
}
}

/// Sets the color for text in the view
/// - Parameter font: The color to use when displaying this text.
/// - Returns: Archimedean spiral text use the color you specify.
public func textColor(_ color: Color) -> Self {
setProperty { tmp in
tmp.color = color
Expand All @@ -151,41 +179,6 @@ extension ArchimedeanSpiralText: Adjustable {
}
}

struct SegmentedPicker: ViewModifier {
func body(content: Content) -> some View {
#if os(watchOS)
content
#else
content.pickerStyle(SegmentedPickerStyle()).padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 7))
#endif
}
}

struct ColoredPicker: ViewModifier {
@Binding var selection: Color
func body(content: Content) -> some View {
#if os(macOS) || os(iOS)
if #available(macOS 11.0, iOS 14.0, macCatalyst 14.0, *) {
ColorPicker("", selection: _selection)
} else {
content.modifier(SegmentedPicker())
}
#else
content.modifier(SegmentedPicker())
#endif
}
}

extension Picker {
func segmented() -> some View {
modifier(SegmentedPicker())
}

func colorPicker(_ selection: Binding<Color>) -> some View {
modifier(ColoredPicker(selection: selection))
}
}

#if !os(tvOS)
struct ArchimedeanSpiralText_Preview_macOS : View {
private let demoText = "1234567890abcdefgABCDEFG♩♪♫♬"
Expand Down
4 changes: 4 additions & 0 deletions Sources/Rings/ClockHourMark.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import SwiftUI
import CoreGraphicsExtension
import ViewExtractor

@available(iOS, introduced: 14.0, deprecated: 16.0, message: "Use RingStack to instead of.")
@available(macOS, deprecated: 13.0, message: "Use RingStack to instead of.")
@available(watchOS, deprecated: 9.0, message: "Use RingStack to instead of.")
@available(tvOS, deprecated: 16.0, message: "Use RingStack to instead of.")
public struct ClockHourMark<Mark: View>: View, Adjustable {

private let markers: Mark
Expand Down
Loading

0 comments on commit bfea622

Please sign in to comment.