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/HorizontalBarChartView.swift b/Sources/SwiftUICharts/HorizontalBarChartView.swift index deb2dfb..67f5582 100644 --- a/Sources/SwiftUICharts/HorizontalBarChartView.swift +++ b/Sources/SwiftUICharts/HorizontalBarChartView.swift @@ -9,8 +9,14 @@ 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)? + let maxValue: Double + + @ScaledMetric private var barHeight: CGFloat = 17 + @ScaledMetric private var circleSize: CGFloat = 8 /** Creates new horizontal bar chart with the following parameters. @@ -18,17 +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) { + public init(dataPoints: [DataPoint], barMaxWidth: CGFloat = 100, maxValue: Double? = nil, text: ((_ bar: DataPoint) -> Text)? = nil) { self.dataPoints = dataPoints self.barMaxWidth = barMaxWidth - } - - private var max: Double { - guard let max = dataPoints.max()?.endValue, max != 0 else { - return 1 - } - return max + self.text = text + self.maxValue = max(maxValue ?? 1, dataPoints.max()?.endValue ?? 1) } public var body: some View { @@ -36,34 +39,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.endValue / self.max) * barMaxWidth, height: 16) + .frame(width: CGFloat(bar.endValue / maxValue) * barMaxWidth, height: barHeight) HStack { Circle() .foregroundColor(bar.legend.color) - .frame(width: 8, height: 8) + .frame(width: circleSize, 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.endValue / self.max) * barMaxWidth, height: 16) + .frame(width: CGFloat(bar.endValue / maxValue) * 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 0d9c237..87aa13c 100644 --- a/Sources/SwiftUICharts/Model/DataPoint.swift +++ b/Sources/SwiftUICharts/Model/DataPoint.swift @@ -10,13 +10,13 @@ import SwiftUI /// The type that describes the group of data points in the chart. public struct Legend { /// Color representing the legend - let color: Color + public let color: Color /// Localized string key representing the legend - let label: LocalizedStringKey + public let label: LocalizedStringKey /// Integer representing the value to sort the array of legends - let order: Int + public let order: Int /** Creates new legend with the following parameters. @@ -43,6 +43,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. @@ -102,7 +106,6 @@ public struct DataPoint { self.legend = legend self.visible = visible } - } extension DataPoint: Hashable { @@ -111,6 +114,12 @@ extension DataPoint: Hashable { hasher.combine(startValue) hasher.combine(endValue) } + + public static func ==(lhs: DataPoint, rhs: DataPoint) -> Bool { + return lhs.legend == rhs.legend && + lhs.startValue == rhs.startValue && + lhs.endValue == rhs.endValue + } } extension DataPoint: Comparable {