Skip to content

Commit

Permalink
feat: new protocol for chained functions, and added support for expli…
Browse files Browse the repository at this point in the history
…cit Y ranges. X coming as well
  • Loading branch information
AppPear committed Sep 29, 2022
1 parent d7e9802 commit b48b701
Show file tree
Hide file tree
Showing 33 changed files with 538 additions and 351 deletions.
40 changes: 40 additions & 0 deletions Sources/SwiftUICharts/Base/Axis/AxisLabels.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import SwiftUI

public struct AxisLabels<Content: View>: View {
var axisLabelsData = AxisLabelsData()
let content: () -> Content
// font
// foregroundColor

public init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}

public var body: some View {
HStack {
VStack {
ForEach(Array(axisLabelsData.axisYLabels.reversed().enumerated()), id: \.element) { index, axisYData in
Text(axisYData)
if index != axisLabelsData.axisYLabels.count - 1 {
Spacer()
}
}
}
.padding([.trailing], 8.0)
.padding([.bottom], axisLabelsData.axisXLabels.count > 0 ? 28.0 : 0)
.frame(maxHeight: .infinity)
VStack {
self.content()
HStack {
ForEach(Array(axisLabelsData.axisXLabels.enumerated()), id: \.element) { index, axisXData in
Text(axisXData)
if index != axisLabelsData.axisXLabels.count - 1 {
Spacer()
}
}
}
}
.padding([.top, .bottom], 10.0)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import SwiftUI

extension AxisLabels {
public func setAxisYLabels(_ labels: [String]) -> AxisLabels {
self.axisLabelsData.axisYLabels = labels
return self
}

public func setAxisXLabels(_ labels: [String]) -> AxisLabels {
self.axisLabelsData.axisXLabels = labels
return self
}
}
10 changes: 10 additions & 0 deletions Sources/SwiftUICharts/Base/Axis/Model/AxisLablesData.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import SwiftUI

public final class AxisLabelsData: ObservableObject {
@Published public var axisYLabels: [String] = []
@Published public var axisXLabels: [String] = []

public init() {
// no-op
}
}
2 changes: 1 addition & 1 deletion Sources/SwiftUICharts/Base/Chart/ChartBase.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import SwiftUI

/// Protocol for any type of chart, to get access to underlying data
public protocol ChartBase {
public protocol ChartBase: View {
var chartData: ChartData { get }
}
63 changes: 52 additions & 11 deletions Sources/SwiftUICharts/Base/Chart/ChartData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,78 @@ import SwiftUI

/// An observable wrapper for an array of data for use in any chart
public class ChartData: ObservableObject {
@Published public var data: [(String, Double)] = []
@Published public var data: [(Double, Double)] = []
public var rangeY: ClosedRange<Double>?
public var rangeX: ClosedRange<Double>?

var points: [Double] {
data.map { $0.1 }
data.filter { rangeX?.contains($0.0) ?? true }.map { $0.1 }
}

var values: [String] {
data.map { $0.0 }
var values: [Double] {
data.filter { rangeX?.contains($0.0) ?? true }.map { $0.0 }
}

var normalisedPoints: [Double] {
let absolutePoints = points.map { abs($0) }
return points.map { $0 / (absolutePoints.max() ?? 1.0) }
var maxPoint = absolutePoints.max()
if let rangeY = rangeY {
maxPoint = Double(rangeY.overreach)
return points.map { ($0 - rangeY.lowerBound) / (maxPoint ?? 1.0) }
}

return points.map { $0 / (maxPoint ?? 1.0) }
}

var normalisedValues: [Double] {
let absoluteValues = values.map { abs($0) }
var maxValue = absoluteValues.max()
if let rangeX = rangeX {
maxValue = Double(rangeX.overreach)
return values.map { ($0 - rangeX.lowerBound) / (maxValue ?? 1.0) }
}

return values.map { $0 / (maxValue ?? 1.0) }
}

var normalisedRange: Double {
(normalisedPoints.max() ?? 0.0) - (normalisedPoints.min() ?? 0.0)
var normalisedData: [(Double, Double)] {
Array(zip(normalisedValues, normalisedPoints))
}

var normalisedYRange: Double {
if let _ = rangeY {
return 1
}

return (normalisedPoints.max() ?? 0.0) - (normalisedPoints.min() ?? 0.0)
}

var normalisedXRange: Double {
if let _ = rangeX {
return 1
}

return (normalisedValues.max() ?? 0.0) - (normalisedValues.min() ?? 0.0)
}

var isInNegativeDomain: Bool {
(points.min() ?? 0.0) < 0
if let rangeY = rangeY {
return rangeY.lowerBound < 0
}

return (points.min() ?? 0.0) < 0
}

/// Initialize with data array
/// - Parameter data: Array of `Double`
public init(_ data: [Double]) {
self.data = data.map { ("", $0) }
public init(_ data: [Double], rangeY: ClosedRange<FloatLiteralType>? = nil) {
self.data = data.enumerated().map{ (index, value) in (Double(index), value) }
self.rangeY = rangeY
}

public init(_ data: [(String, Double)]) {
public init(_ data: [(Double, Double)], rangeY: ClosedRange<FloatLiteralType>? = nil) {
self.data = data
self.rangeY = rangeY
}

public init() {
Expand Down
26 changes: 14 additions & 12 deletions Sources/SwiftUICharts/Base/Extensions/ChartBase+Extension.swift
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import SwiftUI

extension View where Self: ChartBase {

/// Set data for a chart
/// - Parameter data: array of `Double`
/// - Returns: modified `View` with data attached
public func data(_ data: [Double]) -> some View {
chartData.data = data.map { ("", $0) }
extension ChartBase {
public func data(_ data: [Double]) -> some ChartBase {
chartData.data = data.enumerated().map{ (index, value) in (Double(index), value) }
return self
.environmentObject(chartData)
.environmentObject(ChartValue())
}

public func data(_ data: [(String, Double)]) -> some View {
public func data(_ data: [(Double, Double)]) -> some ChartBase {
chartData.data = data
return self
.environmentObject(chartData)
.environmentObject(ChartValue())
}

public func rangeY(_ range: ClosedRange<FloatLiteralType>) -> some ChartBase{
chartData.rangeY = range
return self
}

public func rangeX(_ range: ClosedRange<FloatLiteralType>) -> some ChartBase{
chartData.rangeX = range
return self
}
}

0 comments on commit b48b701

Please sign in to comment.