Skip to content

Commit

Permalink
Update DoubleTextField.swift
Browse files Browse the repository at this point in the history
  • Loading branch information
tekezo committed Nov 4, 2023
1 parent 89647c7 commit 89cad63
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 2 deletions.
67 changes: 65 additions & 2 deletions src/ShowyEdge/swift/Views/DoubleTextField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,43 @@ import SwiftUI

struct DoubleTextField: View {
@Binding var value: Double
// Specifying a formatter directly in a TextField makes it difficult to enter numbers less than 1.0.
// Specifically, if a user wants to enter "0.2" and enters a value of "0.", the value becomes "0.0".
// To avoid this, do not specify the formatter directly in the TextField, but use onChange to format the value.
@State private var text = ""
@State private var error = false

private let step: Double
private let range: ClosedRange<Double>
private let width: CGFloat
private let maximumFractionDigits: Int
private let formatter: NumberFormatter

init(
value: Binding<Double>,
range: ClosedRange<Double>,
step: Double,
maximumFractionDigits: Int,
width: CGFloat
) {
_value = value
text = String(value.wrappedValue)

self.step = step
self.range = range
self.width = width
self.maximumFractionDigits = maximumFractionDigits

formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.numberStyle = .decimal // Use .decimal number style for double values
formatter.minimum = NSNumber(value: range.lowerBound)
formatter.maximum = NSNumber(value: range.upperBound)
formatter.maximumFractionDigits = maximumFractionDigits
}

var body: some View {
HStack(spacing: 0) {
TextField("", value: $value, formatter: formatter).frame(width: width)
TextField("", text: $text).frame(width: width)

Stepper(
value: $value,
Expand All @@ -44,6 +55,58 @@ struct DoubleTextField: View {
}
}
}

if error {
Text(
String(
format: "must be between %.\(maximumFractionDigits)f and %.\(maximumFractionDigits)f",
range.lowerBound,
range.upperBound)
)
.foregroundColor(Color.errorForeground)
.background(Color.errorBackground)
}
}
.onChange(of: text) { newText in
update(byText: newText)
}
.onChange(of: value) { newValue in
update(byValue: newValue)
}
}

private func update(byValue newValue: Double) {
if let newText = formatter.string(for: newValue) {
error = false

Task { @MainActor in
if value != newValue {
value = newValue
}
if text != newText {
text = newText
}
}
} else {
error = true
}
}

private func update(byText newText: String) {
if let number = formatter.number(from: newText) {
error = false

let newValue = number.doubleValue
Task { @MainActor in
if value != newValue {
value = newValue
}
if text != newText {
text = newText
}
}
} else {
error = true
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct SettingsCustomFrameView: View {
value: $userSettings.customFrameWidth,
range: 0...10000,
step: 10,
maximumFractionDigits: 1,
width: 50)

CustomFrameUnitPicker(value: $userSettings.customFrameWidthUnit)
Expand All @@ -45,6 +46,7 @@ struct SettingsCustomFrameView: View {
value: $userSettings.customFrameHeight,
range: 0...10000,
step: 10,
maximumFractionDigits: 1,
width: 50)

CustomFrameUnitPicker(value: $userSettings.customFrameHeightUnit)
Expand All @@ -69,6 +71,7 @@ struct SettingsCustomFrameView: View {
value: $userSettings.customFrameLeft,
range: -10000...10000,
step: 100,
maximumFractionDigits: 1,
width: 50)

Text("pt")
Expand All @@ -79,6 +82,7 @@ struct SettingsCustomFrameView: View {
value: $userSettings.customFrameTop,
range: -10000...10000,
step: 100,
maximumFractionDigits: 1,
width: 50)

Text("pt")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ struct SettingsIndicatorView: View {
value: $userSettings.indicatorHeightPx,
range: 0...10000,
step: 5,
maximumFractionDigits: 1,
width: 50)

Text("pt")
Expand Down

0 comments on commit 89cad63

Please sign in to comment.