From ee5027c5fa89bb58a14c1694ee82f3c7b3e7d8b7 Mon Sep 17 00:00:00 2001 From: Bohdan Hernandez Navia Date: Tue, 19 Jan 2021 20:09:34 +0000 Subject: [PATCH 1/4] Allows supplying custom text in HorizontalBarChartView. Uses ScaledMetric for bar height and circle size. Replaces RoundedRectangle by Capsule. Removes Spacer. --- .../HorizontalBarChartView.swift | 45 ++++++++++++------- Sources/SwiftUICharts/Model/DataPoint.swift | 6 +-- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/Sources/SwiftUICharts/HorizontalBarChartView.swift b/Sources/SwiftUICharts/HorizontalBarChartView.swift index 41cf79d..2814c63 100644 --- a/Sources/SwiftUICharts/HorizontalBarChartView.swift +++ b/Sources/SwiftUICharts/HorizontalBarChartView.swift @@ -9,8 +9,13 @@ import SwiftUI /// SwiftUI view that draws bars by placing them into a vertical container. public struct HorizontalBarChartView: View { + let dataPoints: [DataPoint] let barMaxWidth: CGFloat + let text: ((_ bar: DataPoint) -> Text)? + + @ScaledMetric private var barHeight: CGFloat = 17 + @ScaledMetric private var circleSize: CGFloat = 8 /** Creates new horizontal bar chart with the following parameters. @@ -18,10 +23,12 @@ public struct HorizontalBarChartView: View { - Parameters: - dataPoints: The array of data points that will be used to draw the bar chart. - barMaxWidth: The maximal width for the bar that presents the biggest value. Default is 100. + - text: The text to be shown next to the bar. Default is: bar.legend.label + ", " + bar.label */ - public init(dataPoints: [DataPoint], barMaxWidth: CGFloat = 100) { + public init(dataPoints: [DataPoint], barMaxWidth: CGFloat = 100, text: ((_ bar: DataPoint) -> Text)? = nil) { self.dataPoints = dataPoints self.barMaxWidth = barMaxWidth + self.text = text } private var max: Double { @@ -36,34 +43,42 @@ public struct HorizontalBarChartView: View { ForEach(dataPoints, id: \.self) { bar in #if os(watchOS) VStack(alignment: .leading) { - RoundedRectangle(cornerRadius: 8, style: .continuous) + Capsule() .foregroundColor(bar.legend.color) - .frame(width: CGFloat(bar.value / self.max) * barMaxWidth, height: 16) + .frame(width: CGFloat(bar.value / self.max) * barMaxWidth, height: barHeight) HStack { Circle() .foregroundColor(bar.legend.color) - .frame(width: 8, height: 8) + .frame(width: legendCircleSize, height: circleSize) - Text(bar.legend.label) + Text(", ") + Text(bar.label) - - // TODO: temp fix - Spacer() + Group { + if let text = text?(bar) { + text + } else { + Text(bar.legend.label) + Text(", ") + Text(bar.label) + } + } + .frame(maxWidth: .infinity, alignment: .leading) } } #else HStack { - RoundedRectangle(cornerRadius: 8, style: .continuous) + Capsule() .foregroundColor(bar.legend.color) - .frame(width: CGFloat(bar.value / self.max) * barMaxWidth, height: 16) + .frame(width: CGFloat(bar.value / self.max) * barMaxWidth, height: barHeight) Circle() .foregroundColor(bar.legend.color) - .frame(width: 8, height: 8) - - Text(bar.legend.label) + Text(", ") + Text(bar.label) + .frame(width: circleSize, height: circleSize) - // TODO: temp fix - Spacer() + Group { + if let text = text?(bar) { + text + } else { + Text(bar.legend.label) + Text(", ") + Text(bar.label) + } + } + .frame(maxWidth: .infinity, alignment: .leading) } #endif } diff --git a/Sources/SwiftUICharts/Model/DataPoint.swift b/Sources/SwiftUICharts/Model/DataPoint.swift index 795d396..4b28df2 100644 --- a/Sources/SwiftUICharts/Model/DataPoint.swift +++ b/Sources/SwiftUICharts/Model/DataPoint.swift @@ -9,9 +9,9 @@ import SwiftUI /// The type that describes the group of data points in the chart. public struct Legend { - let color: Color - let label: LocalizedStringKey - let order: Int + public let color: Color + public let label: LocalizedStringKey + public let order: Int /** Creates new legend with the following parameters. From 044fea1d6eb08cc79744b5def87e0a923cdb81a4 Mon Sep 17 00:00:00 2001 From: Bohdan Hernandez Navia Date: Wed, 20 Jan 2021 12:21:57 +0000 Subject: [PATCH 2/4] Fixes typo in circleSize for watchOS. --- Sources/SwiftUICharts/HorizontalBarChartView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/SwiftUICharts/HorizontalBarChartView.swift b/Sources/SwiftUICharts/HorizontalBarChartView.swift index 2814c63..28514b8 100644 --- a/Sources/SwiftUICharts/HorizontalBarChartView.swift +++ b/Sources/SwiftUICharts/HorizontalBarChartView.swift @@ -49,7 +49,7 @@ public struct HorizontalBarChartView: View { HStack { Circle() .foregroundColor(bar.legend.color) - .frame(width: legendCircleSize, height: circleSize) + .frame(width: circleSize, height: circleSize) Group { if let text = text?(bar) { From 3740b443239d3abab3a35ce144555d755b9c8285 Mon Sep 17 00:00:00 2001 From: Bohdan Hernandez Navia Date: Fri, 22 Jan 2021 21:04:49 +0000 Subject: [PATCH 3/4] Allows setting the max value for calculating the bar width. --- .../SwiftUICharts/HorizontalBarChartView.swift | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/Sources/SwiftUICharts/HorizontalBarChartView.swift b/Sources/SwiftUICharts/HorizontalBarChartView.swift index 28514b8..a3ca8cf 100644 --- a/Sources/SwiftUICharts/HorizontalBarChartView.swift +++ b/Sources/SwiftUICharts/HorizontalBarChartView.swift @@ -13,6 +13,7 @@ public struct HorizontalBarChartView: View { let dataPoints: [DataPoint] let barMaxWidth: CGFloat let text: ((_ bar: DataPoint) -> Text)? + let maxValue: Double @ScaledMetric private var barHeight: CGFloat = 17 @ScaledMetric private var circleSize: CGFloat = 8 @@ -23,19 +24,14 @@ public struct HorizontalBarChartView: View { - Parameters: - dataPoints: The array of data points that will be used to draw the bar chart. - barMaxWidth: The maximal width for the bar that presents the biggest value. Default is 100. + - maxValue: The max value for calculating the bar width. Default is max value from the dataPoints. - text: The text to be shown next to the bar. Default is: bar.legend.label + ", " + bar.label */ - public init(dataPoints: [DataPoint], barMaxWidth: CGFloat = 100, text: ((_ bar: DataPoint) -> Text)? = nil) { + public init(dataPoints: [DataPoint], barMaxWidth: CGFloat = 100, maxValue: Double? = nil, text: ((_ bar: DataPoint) -> Text)? = nil) { self.dataPoints = dataPoints self.barMaxWidth = barMaxWidth self.text = text - } - - private var max: Double { - guard let max = dataPoints.max()?.value, max != 0 else { - return 1 - } - return max + self.maxValue = max(maxValue ?? 1, dataPoints.max()?.value ?? 1) } public var body: some View { @@ -45,7 +41,7 @@ public struct HorizontalBarChartView: View { VStack(alignment: .leading) { Capsule() .foregroundColor(bar.legend.color) - .frame(width: CGFloat(bar.value / self.max) * barMaxWidth, height: barHeight) + .frame(width: CGFloat(bar.value / maxValue) * barMaxWidth, height: barHeight) HStack { Circle() .foregroundColor(bar.legend.color) @@ -65,7 +61,7 @@ public struct HorizontalBarChartView: View { HStack { Capsule() .foregroundColor(bar.legend.color) - .frame(width: CGFloat(bar.value / self.max) * barMaxWidth, height: barHeight) + .frame(width: CGFloat(bar.value / maxValue) * barMaxWidth, height: barHeight) Circle() .foregroundColor(bar.legend.color) From 7df7e813db126c3678e38de6c886becdf04319ec Mon Sep 17 00:00:00 2001 From: Bohdan Hernandez Navia Date: Fri, 13 Aug 2021 17:48:07 +0100 Subject: [PATCH 4/4] Adds Equatable conformance for Legend and DataPoint. --- .../xcode/package.xcworkspace/contents.xcworkspacedata | 7 +++++++ Sources/SwiftUICharts/Model/DataPoint.swift | 8 ++++++++ 2 files changed, 15 insertions(+) create mode 100644 .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Sources/SwiftUICharts/Model/DataPoint.swift b/Sources/SwiftUICharts/Model/DataPoint.swift index 4b28df2..4218417 100644 --- a/Sources/SwiftUICharts/Model/DataPoint.swift +++ b/Sources/SwiftUICharts/Model/DataPoint.swift @@ -38,6 +38,10 @@ extension Legend: Hashable { public func hash(into hasher: inout Hasher) { hasher.combine(color) } + + public static func ==(lhs: Legend, rhs: Legend) -> Bool { + return lhs.color == rhs.color + } } /// The type that describes a data point in the chart. @@ -69,6 +73,10 @@ extension DataPoint: Hashable { hasher.combine(legend) hasher.combine(value) } + + public static func ==(lhs: DataPoint, rhs: DataPoint) -> Bool { + return lhs.legend == rhs.legend && lhs.value == rhs.value + } } extension DataPoint: Comparable {