Skip to content

Commit 0f4a4ea

Browse files
author
Reed Es
committed
Support Decimal Type #2
1 parent c6140c3 commit 0f4a4ea

File tree

3 files changed

+417
-18
lines changed

3 files changed

+417
-18
lines changed

README.md

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ _SwiftNumberPad_ is part of the [OpenAlloc](https://github.com/openalloc) family
1010

1111
## Features
1212

13-
* Support for both integer and floating point types
13+
* Support for integer, floating point, and Decimal types
1414
* Presently targeting .macOS(.v13), .iOS(.v16), .watchOS(.v9)
1515
* No external dependencies!
1616

@@ -67,27 +67,13 @@ Please submit pull requests if you'd like to tackle any of these. Thanks!
6767
* SwiftUI Preview not reliably working on macOS
6868
* See if earlier versions of platforms can be supported
6969
* Support for negative values
70-
* Support for Decimal input
7170

7271
## See Also
7372

74-
* [SwiftSideways](https://github.com/openalloc/SwiftSideways) - multi-platform SwiftUI component for the horizontal scrolling of tabular data in compact areas
75-
* [SwiftDetailer](https://github.com/openalloc/SwiftDetailer) - multi-platform SwiftUI component for editing fielded data
76-
* [SwiftDetailerMenu](https://github.com/openalloc/SwiftDetailerMenu) - optional menu support for _SwiftDetailer_
77-
* [SwiftCompactor](https://github.com/openalloc/SwiftCompactor) - formatters for the concise display of Numbers, Currency, and Time Intervals
78-
* [SwiftModifiedDietz](https://github.com/openalloc/SwiftModifiedDietz) - A tool for calculating portfolio performance using the Modified Dietz method
79-
* [SwiftNiceScale](https://github.com/openalloc/SwiftNiceScale) - generate 'nice' numbers for label ticks over a range, such as for y-axis on a chart
80-
* [SwiftRegressor](https://github.com/openalloc/SwiftRegressor) - a linear regression tool that’s flexible and easy to use
81-
* [SwiftSeriesResampler](https://github.com/openalloc/SwiftSeriesResampler) - transform a series of coordinate values into a new series with uniform intervals
82-
* [SwiftSimpleTree](https://github.com/openalloc/SwiftSimpleTree) - a nested data structure that’s flexible and easy to use
73+
This library is a member of the _OpenAlloc Project_.
8374

84-
And open source apps using this library (by the same author):
85-
86-
* [Gym Routine Tracker](https://open-trackers.github.io/grt/) - minimalist workout tracker, for the Apple Watch, iPhone, and iPad
87-
* [Daily Calorie Tracker](https://open-trackers.github.io/dct/) - minimalist calorie tracker, for the Apple Watch, iPhone, and iPad
88-
89-
* [FlowAllocator](https://openalloc.github.io/FlowAllocator/index.html) - portfolio rebalancing tool for macOS
90-
* [FlowWorth](https://openalloc.github.io/FlowWorth/index.html) - a new portfolio performance and valuation tracking tool for macOS
75+
* [_OpenAlloc_](https://openalloc.github.io) - product website for all the _OpenAlloc_ apps and libraries
76+
* [_OpenAlloc Project_](https://github.com/openalloc) - Github site for the development project, including full source code
9177

9278
## License
9379

Sources/NPDecimalConfig.swift

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//
2+
// NPDecimalConfig.swift
3+
//
4+
// Copyright 2023 OpenAlloc LLC
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
19+
import Foundation
20+
21+
22+
public final class NPDecimalConfig: NPBaseConfig<Decimal>
23+
{
24+
// MARK: - Parameters
25+
26+
public let precision: Int
27+
28+
public init(_ val: Decimal,
29+
precision: Int = NumberPadEnum.defaultPrecision,
30+
upperBound: Decimal = Decimal.greatestFiniteMagnitude)
31+
{
32+
self.precision = precision
33+
34+
let formatter = {
35+
let nf = NumberFormatter()
36+
nf.locale = Locale.current
37+
nf.numberStyle = .decimal
38+
nf.usesGroupingSeparator = false
39+
nf.isLenient = true
40+
nf.minimumFractionDigits = 0
41+
nf.maximumFractionDigits = precision
42+
nf.generatesDecimalNumbers = true
43+
return nf
44+
}()
45+
46+
let sVal = Self.toString(val, upperBound: upperBound, formatter: formatter)
47+
48+
super.init(sValue: sVal, upperBound: upperBound, formatter: formatter)
49+
}
50+
51+
// MARK: - Type-specific Actions
52+
53+
override public var showDecimalPoint: Bool { precision > 0 }
54+
55+
override public func decimalPointAction() -> Bool {
56+
guard decimalPointIndex == nil else { return false }
57+
sValue.append(".")
58+
59+
return true
60+
}
61+
62+
// MARK: - Internal
63+
64+
internal static func toString(_ val: Decimal, upperBound: Decimal, formatter: NumberFormatter) -> String {
65+
let clampedValue = max(0, min(val, upperBound))
66+
return formatter.string(from: clampedValue as NSDecimalNumber) ?? "0"
67+
}
68+
69+
override internal func validateDigit(_: NumberPadEnum) -> Bool {
70+
let cp = currentPrecision
71+
if cp > 0, cp == precision { return false } // ignore additional input
72+
return true
73+
}
74+
75+
override internal func toValue(_ str: String) -> Decimal? {
76+
guard let val: NSNumber = formatter.number(from: str)
77+
else { return nil }
78+
return Decimal(val.doubleValue)
79+
}
80+
81+
internal var currentPrecision: Int {
82+
guard let di = decimalPointIndex else { return 0 }
83+
return sValue.distance(from: di, to: sValue.endIndex) - 1
84+
}
85+
86+
internal var decimalPointIndex: String.Index? {
87+
sValue.firstIndex(of: ".")
88+
}
89+
}

0 commit comments

Comments
 (0)