Skip to content

Commit

Permalink
Merge pull request #60 from willdale/v2.5.0
Browse files Browse the repository at this point in the history
V2.5.0
  • Loading branch information
willdale authored Apr 26, 2021
2 parents 83e4785 + 813cf92 commit e6412e7
Show file tree
Hide file tree
Showing 116 changed files with 3,049 additions and 3,228 deletions.
Binary file modified Resources/images/PieCharts/DoughnutChart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Resources/images/PieCharts/PieChart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions Sources/SwiftUICharts/BarChart/Extras/BarChartEnums.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import SwiftUI
```
*/
public enum ColourFrom {
/// From BarStyle data model
case barStyle
/// From each data point
case dataPoints
}

Expand Down
96 changes: 48 additions & 48 deletions Sources/SwiftUICharts/BarChart/Models/ChartData/BarChartData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,20 @@ import SwiftUI
*/
public final class BarChartData: CTBarChartDataProtocol {
// MARK: Properties
public let id : UUID = UUID()

@Published public final var dataSets : BarDataSet
@Published public final var metadata : ChartMetadata
@Published public final var xAxisLabels : [String]?
@Published public final var yAxisLabels : [String]?
@Published public final var barStyle : BarStyle
@Published public final var chartStyle : BarChartStyle
@Published public final var legends : [LegendData]
@Published public final var viewData : ChartViewData
@Published public final var infoView : InfoViewData<BarChartDataPoint> = InfoViewData()
public final var noDataText : Text
public final let chartType : (chartType: ChartType, dataSetType: DataSetType)
public let id: UUID = UUID()
@Published public final var dataSets: BarDataSet
@Published public final var metadata: ChartMetadata
@Published public final var xAxisLabels: [String]?
@Published public final var yAxisLabels: [String]?
@Published public final var barStyle: BarStyle
@Published public final var chartStyle: BarChartStyle
@Published public final var legends: [LegendData]
@Published public final var viewData: ChartViewData
@Published public final var infoView: InfoViewData<BarChartDataPoint> = InfoViewData()

public final var noDataText: Text
public final let chartType: (chartType: ChartType, dataSetType: DataSetType)

// MARK: Initializer
/// Initialises a standard Bar Chart.
Expand All @@ -38,34 +38,35 @@ public final class BarChartData: CTBarChartDataProtocol {
/// - barStyle: Control for the aesthetic of the bar chart.
/// - chartStyle: The style data for the aesthetic of the chart.
/// - noDataText: Customisable Text to display when where is not enough data to draw the chart.
public init(dataSets : BarDataSet,
metadata : ChartMetadata = ChartMetadata(),
xAxisLabels : [String]? = nil,
yAxisLabels : [String]? = nil,
barStyle : BarStyle = BarStyle(),
chartStyle : BarChartStyle = BarChartStyle(),
noDataText : Text = Text("No Data")
public init(
dataSets: BarDataSet,
metadata: ChartMetadata = ChartMetadata(),
xAxisLabels: [String]? = nil,
yAxisLabels: [String]? = nil,
barStyle: BarStyle = BarStyle(),
chartStyle: BarChartStyle = BarChartStyle(),
noDataText: Text = Text("No Data")
) {
self.dataSets = dataSets
self.metadata = metadata
self.xAxisLabels = xAxisLabels
self.yAxisLabels = yAxisLabels
self.barStyle = barStyle
self.chartStyle = chartStyle
self.noDataText = noDataText
self.dataSets = dataSets
self.metadata = metadata
self.xAxisLabels = xAxisLabels
self.yAxisLabels = yAxisLabels
self.barStyle = barStyle
self.chartStyle = chartStyle
self.noDataText = noDataText

self.legends = [LegendData]()
self.viewData = ChartViewData()
self.chartType = (.bar, .single)
self.legends = [LegendData]()
self.viewData = ChartViewData()
self.chartType = (.bar, .single)
self.setupLegends()
}

// MARK: Labels
public final func getXAxisLabels() -> some View {
Group {
switch self.chartStyle.xAxisLabelsFrom {
case .dataPoint(let angle):

HStack(alignment: .top, spacing: 0) {
ForEach(dataSets.dataPoints) { data in
Spacer()
Expand All @@ -78,15 +79,15 @@ public final class BarChartData: CTBarChartDataProtocol {
.frame(minWidth: 0, maxWidth: 500)
}
}

case .chartData(let angle):

if let labelArray = self.xAxisLabels {
HStack(spacing: 0) {
ForEach(labelArray, id: \.self) { data in
Spacer()
.frame(minWidth: 0, maxWidth: 500)
XAxisDataPointCell(chartData: self, label: data, rotationAngle: angle)
XAxisChartDataCell(chartData: self, label: data, rotationAngle: angle)
.foregroundColor(self.chartStyle.xAxisLabelColour)
.accessibilityLabel(Text("X Axis Label"))
.accessibilityValue(Text("\(data)"))
Expand All @@ -103,29 +104,28 @@ public final class BarChartData: CTBarChartDataProtocol {
public final func getTouchInteraction(touchLocation: CGPoint, chartSize: CGRect) -> some View {
self.markerSubView()
}

public final func getDataPoint(touchLocation: CGPoint, chartSize: CGRect) {
var points : [BarChartDataPoint] = []
let xSection : CGFloat = chartSize.width / CGFloat(dataSets.dataPoints.count)
let index : Int = Int((touchLocation.x) / xSection)
let xSection: CGFloat = chartSize.width / CGFloat(dataSets.dataPoints.count)
let index: Int = Int((touchLocation.x) / xSection)
if index >= 0 && index < dataSets.dataPoints.count {
var dataPoint = dataSets.dataPoints[index]
dataPoint.legendTag = dataSets.legendTitle
points.append(dataPoint)
dataSets.dataPoints[index].legendTag = dataSets.legendTitle
self.infoView.touchOverlayInfo = [dataSets.dataPoints[index]]
}
self.infoView.touchOverlayInfo = points
}

public final func getPointLocation(dataSet: BarDataSet, touchLocation: CGPoint, chartSize: CGRect) -> CGPoint? {
let xSection : CGFloat = chartSize.width / CGFloat(dataSet.dataPoints.count)
let ySection : CGFloat = chartSize.height / CGFloat(self.maxValue)
let index : Int = Int((touchLocation.x) / xSection)
let xSection: CGFloat = chartSize.width / CGFloat(dataSet.dataPoints.count)
let ySection: CGFloat = chartSize.height / CGFloat(self.maxValue)
let index: Int = Int((touchLocation.x) / xSection)
if index >= 0 && index < dataSet.dataPoints.count {
return CGPoint(x: (CGFloat(index) * xSection) + (xSection / 2),
y: (chartSize.size.height - CGFloat(dataSet.dataPoints[index].value) * ySection))
}
return nil
}

public typealias Set = BarDataSet
public typealias Set = BarDataSet
public typealias DataPoint = BarChartDataPoint
public typealias CTStyle = BarChartStyle
public typealias CTStyle = BarChartStyle
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,31 @@ import SwiftUI

/**
Data model for drawing and styling a Grouped Bar Chart.

The grouping data informs the model as to how the datapoints are linked.
```
*/
public final class GroupedBarChartData: CTMultiBarChartDataProtocol {

// MARK: Properties
public let id : UUID = UUID()

@Published public final var dataSets : GroupedBarDataSets
@Published public final var metadata : ChartMetadata
@Published public final var xAxisLabels : [String]?
@Published public final var yAxisLabels : [String]?
@Published public final var barStyle : BarStyle
@Published public final var chartStyle : BarChartStyle
@Published public final var legends : [LegendData]
@Published public final var viewData : ChartViewData
@Published public final var infoView : InfoViewData<GroupedBarDataPoint> = InfoViewData()
@Published public final var groups : [GroupingData]
public let id: UUID = UUID()

public final var noDataText : Text
public final var chartType : (chartType: ChartType, dataSetType: DataSetType)
@Published public final var dataSets: GroupedBarDataSets
@Published public final var metadata: ChartMetadata
@Published public final var xAxisLabels: [String]?
@Published public final var yAxisLabels: [String]?
@Published public final var barStyle: BarStyle
@Published public final var chartStyle: BarChartStyle
@Published public final var legends: [LegendData]
@Published public final var viewData: ChartViewData
@Published public final var infoView: InfoViewData<GroupedBarDataPoint> = InfoViewData()
@Published public final var groups: [GroupingData]

public final var noDataText: Text
public final var chartType: (chartType: ChartType, dataSetType: DataSetType)

final var groupSpacing: CGFloat = 0

final var groupSpacing : CGFloat = 0

// MARK: Initializer
/// Initialises a Grouped Bar Chart.
///
Expand All @@ -46,26 +46,27 @@ public final class GroupedBarChartData: CTMultiBarChartDataProtocol {
/// - barStyle: Control for the aesthetic of the bar chart.
/// - chartStyle: The style data for the aesthetic of the chart.
/// - noDataText: Customisable Text to display when where is not enough data to draw the chart.
public init(dataSets : GroupedBarDataSets,
groups : [GroupingData],
metadata : ChartMetadata = ChartMetadata(),
xAxisLabels : [String]? = nil,
yAxisLabels : [String]? = nil,
barStyle : BarStyle = BarStyle(),
chartStyle : BarChartStyle = BarChartStyle(),
noDataText : Text = Text("No Data")
public init(
dataSets: GroupedBarDataSets,
groups: [GroupingData],
metadata: ChartMetadata = ChartMetadata(),
xAxisLabels: [String]? = nil,
yAxisLabels: [String]? = nil,
barStyle: BarStyle = BarStyle(),
chartStyle: BarChartStyle = BarChartStyle(),
noDataText: Text = Text("No Data")
) {
self.dataSets = dataSets
self.groups = groups
self.metadata = metadata
self.xAxisLabels = xAxisLabels
self.yAxisLabels = yAxisLabels
self.barStyle = barStyle
self.chartStyle = chartStyle
self.noDataText = noDataText
self.legends = [LegendData]()
self.viewData = ChartViewData()
self.chartType = (chartType: .bar, dataSetType: .multi)
self.dataSets = dataSets
self.groups = groups
self.metadata = metadata
self.xAxisLabels = xAxisLabels
self.yAxisLabels = yAxisLabels
self.barStyle = barStyle
self.chartStyle = chartStyle
self.noDataText = noDataText
self.legends = [LegendData]()
self.viewData = ChartViewData()
self.chartType = (chartType: .bar, dataSetType: .multi)
self.setupLegends()
}

Expand Down Expand Up @@ -114,7 +115,7 @@ public final class GroupedBarChartData: CTMultiBarChartDataProtocol {
HStack(spacing: 0) {
Spacer()
.frame(minWidth: 0, maxWidth: 500)
XAxisDataPointCell(chartData: self, label: dataSet.setTitle, rotationAngle: .degrees(0))
XAxisChartDataCell(chartData: self, label: dataSet.setTitle, rotationAngle: .degrees(0))
.foregroundColor(self.chartStyle.xAxisLabelColour)
.accessibilityLabel(Text("X Axis Label"))
.accessibilityValue(Text("\(dataSet.setTitle)"))
Expand All @@ -131,66 +132,59 @@ public final class GroupedBarChartData: CTMultiBarChartDataProtocol {
public final func getTouchInteraction(touchLocation: CGPoint, chartSize: CGRect) -> some View {
self.markerSubView()
}

public final func getDataPoint(touchLocation: CGPoint, chartSize: CGRect) {

var points : [GroupedBarDataPoint] = []

// Divide the chart into equal sections.
let superXSection : CGFloat = (chartSize.width / CGFloat(dataSets.dataSets.count))
let superIndex : Int = Int((touchLocation.x) / superXSection)
let superXSection: CGFloat = (chartSize.width / CGFloat(dataSets.dataSets.count))
let superIndex: Int = Int((touchLocation.x) / superXSection)

// Work out how much to remove from xSection due to groupSpacing.
let compensation : CGFloat = ((groupSpacing * CGFloat(dataSets.dataSets.count - 1)) / CGFloat(dataSets.dataSets.count))
let compensation: CGFloat = ((groupSpacing * CGFloat(dataSets.dataSets.count - 1)) / CGFloat(dataSets.dataSets.count))

// Make those sections take account of spacing between groups.
let xSection : CGFloat = (chartSize.width / CGFloat(dataSets.dataSets.count)) - compensation
let index : Int = Int((touchLocation.x - CGFloat((groupSpacing * CGFloat(superIndex)))) / xSection)

let xSection: CGFloat = superXSection - compensation
let index: Int = Int((touchLocation.x - CGFloat((groupSpacing * CGFloat(superIndex)))) / xSection)
if index >= 0 && index < dataSets.dataSets.count && superIndex == index {
let dataSet = dataSets.dataSets[index]
let xSubSection : CGFloat = (xSection / CGFloat(dataSet.dataPoints.count))
let subIndex : Int = Int((touchLocation.x - CGFloat((groupSpacing * CGFloat(superIndex)))) / xSubSection) - (dataSet.dataPoints.count * index)
if subIndex >= 0 && subIndex < dataSet.dataPoints.count {
var dataPoint = dataSet.dataPoints[subIndex]
dataPoint.legendTag = dataSet.setTitle
points.append(dataPoint)
let xSubSection: CGFloat = (xSection / CGFloat(dataSets.dataSets[index].dataPoints.count))
let subIndex: Int = Int((touchLocation.x - CGFloat((groupSpacing * CGFloat(superIndex)))) / xSubSection) - (dataSets.dataSets[index].dataPoints.count * index)
if subIndex >= 0 && subIndex < dataSets.dataSets[index].dataPoints.count {
dataSets.dataSets[index].dataPoints[subIndex].legendTag = dataSets.dataSets[index].setTitle
self.infoView.touchOverlayInfo = [dataSets.dataSets[index].dataPoints[subIndex]]
}
}
self.infoView.touchOverlayInfo = points
}

public final func getPointLocation(dataSet: GroupedBarDataSets, touchLocation: CGPoint, chartSize: CGRect) -> CGPoint? {

// Divide the chart into equal sections.
let superXSection : CGFloat = (chartSize.width / CGFloat(dataSet.dataSets.count))
let superIndex : Int = Int((touchLocation.x) / superXSection)

let superXSection: CGFloat = (chartSize.width / CGFloat(dataSet.dataSets.count))
let superIndex: Int = Int((touchLocation.x) / superXSection)
// Work out how much to remove from xSection due to groupSpacing.
let compensation : CGFloat = ((groupSpacing * CGFloat(dataSet.dataSets.count - 1)) / CGFloat(dataSet.dataSets.count))

let compensation: CGFloat = ((groupSpacing * CGFloat(dataSet.dataSets.count - 1)) / CGFloat(dataSet.dataSets.count))
// Make those sections take account of spacing between groups.
let xSection : CGFloat = (chartSize.width / CGFloat(dataSet.dataSets.count)) - compensation
let ySection : CGFloat = chartSize.height / CGFloat(self.maxValue)

let index : Int = Int((touchLocation.x - CGFloat(groupSpacing * CGFloat(superIndex))) / xSection)

let xSection: CGFloat = superXSection - compensation
let ySection: CGFloat = chartSize.height / CGFloat(self.maxValue)
let index: Int = Int((touchLocation.x - CGFloat(groupSpacing * CGFloat(superIndex))) / xSection)
if index >= 0 && index < dataSet.dataSets.count && superIndex == index {

let subDataSet = dataSet.dataSets[index]
let xSubSection : CGFloat = (xSection / CGFloat(subDataSet.dataPoints.count))
let subIndex : Int = Int((touchLocation.x - CGFloat(groupSpacing * CGFloat(index))) / xSubSection) - (subDataSet.dataPoints.count * index)

let xSubSection: CGFloat = (xSection / CGFloat(subDataSet.dataPoints.count))
let subIndex: Int = Int((touchLocation.x - CGFloat(groupSpacing * CGFloat(index))) / xSubSection) - (subDataSet.dataPoints.count * index)
if subIndex >= 0 && subIndex < subDataSet.dataPoints.count {
let element : CGFloat = (CGFloat(subIndex) * xSubSection) + (xSubSection / 2)
let section : CGFloat = (superXSection * CGFloat(superIndex))
let spacing : CGFloat = ((groupSpacing / CGFloat(dataSets.dataSets.count)) * CGFloat(superIndex))
let element: CGFloat = (CGFloat(subIndex) * xSubSection) + (xSubSection / 2)
let section: CGFloat = (superXSection * CGFloat(superIndex))
let spacing: CGFloat = ((groupSpacing / CGFloat(dataSets.dataSets.count)) * CGFloat(superIndex))
return CGPoint(x: element + section + spacing,
y: (chartSize.height - CGFloat(subDataSet.dataPoints[subIndex].value) * ySection))
}
}
return nil
}

public typealias Set = GroupedBarDataSets
public typealias DataPoint = GroupedBarDataPoint
public typealias CTStyle = BarChartStyle
public typealias Set = GroupedBarDataSets
public typealias DataPoint = GroupedBarDataPoint
public typealias CTStyle = BarChartStyle
}
Loading

0 comments on commit e6412e7

Please sign in to comment.