Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some improvements to HorizontalBarChartView #8

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

55 changes: 33 additions & 22 deletions Sources/SwiftUICharts/HorizontalBarChartView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,61 +9,72 @@ 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.

- 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 {
VStack(alignment: .leading, spacing: 8) {
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
}
Expand Down
17 changes: 13 additions & 4 deletions Sources/SwiftUICharts/Model/DataPoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -102,7 +106,6 @@ public struct DataPoint {
self.legend = legend
self.visible = visible
}

}

extension DataPoint: Hashable {
Expand All @@ -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 {
Expand Down