diff --git a/Charts.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Charts.xcworkspace/xcshareddata/swiftpm/Package.resolved deleted file mode 100644 index dcfd1f25b9..0000000000 --- a/Charts.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ /dev/null @@ -1,15 +0,0 @@ -{ - "originHash" : "09b08963887ce6eac26952e8acb25256a8ec102f2b5528ae68a97fa296723712", - "pins" : [ - { - "identity" : "swift-snapshot-testing", - "kind" : "remoteSourceControl", - "location" : "https://github.com/pointfreeco/swift-snapshot-testing", - "state" : { - "revision" : "cef5b3f6f11781dd4591bdd1dd0a3d22bd609334", - "version" : "1.11.0" - } - } - ], - "version" : 3 -} diff --git a/ChartsDemo-iOS/Objective-C/DemoBaseViewController.m b/ChartsDemo-iOS/Objective-C/DemoBaseViewController.m index a264f2a712..a2a6086230 100644 --- a/ChartsDemo-iOS/Objective-C/DemoBaseViewController.m +++ b/ChartsDemo-iOS/Objective-C/DemoBaseViewController.m @@ -153,6 +153,55 @@ - (void)handleOption:(NSString *)key forChartView:(ChartViewBase *)chartView [chartView setNeedsDisplay]; } + + if ([key isEqualToString:@"toggleValuesPosition"]) + { + BarChartView *barChart = (BarChartView *)chartView; + barChart.drawValueAboveBarEnabled = !barChart.drawValueAboveBarEnabled; + + [chartView notifyDataSetChanged]; + } + + if ([key isEqualToString:@"toggleValuesSideFlexible"]) + { + BarChartView *barChart = (BarChartView *)chartView; + barChart.isDrawValueSideFlexible = !barChart.isDrawValueSideFlexible; + + [chartView notifyDataSetChanged]; + } + + if ([key isEqualToString:@"toggleValueColorsAdjustment"]) + { + for (id set in chartView.data.dataSets) + { + if ([set conformsToProtocol:@protocol(BarChartDataSetProtocol)]) + { + set.valueColorsAdjustment = !set.valueColorsAdjustment; + } + } + + [chartView setNeedsDisplay]; + } + + if ([key isEqualToString:@"toggleValueColorsSecondary"]) + { + for (id set in chartView.data.dataSets) + { + if ([set conformsToProtocol:@protocol(BarChartDataSetProtocol)]) + { + if (set.valueColorsSecondary.count == 0) + { + set.valueTextColorSecondary = [UIColor blackColor]; + } + else + { + [set resetValueSecondaryColors]; + } + } + } + + [chartView setNeedsDisplay]; + } } #pragma mark - Actions diff --git a/ChartsDemo-iOS/Objective-C/Demos/BarChartViewController.m b/ChartsDemo-iOS/Objective-C/Demos/BarChartViewController.m index 5e1567c088..63a9b6408b 100644 --- a/ChartsDemo-iOS/Objective-C/Demos/BarChartViewController.m +++ b/ChartsDemo-iOS/Objective-C/Demos/BarChartViewController.m @@ -33,6 +33,10 @@ - (void)viewDidLoad self.options = @[ @{@"key": @"toggleValues", @"label": @"Toggle Values"}, + @{@"key": @"toggleValuesPosition", @"label": @"Toggle Values Position"}, + @{@"key": @"toggleValuesSideFlexible", @"label": @"Toggle Y-Values Flexible Side"}, + @{@"key": @"toggleValueColorsAdjustment", @"label": @"Toggle Y-Values Color Adjustment"}, + @{@"key": @"toggleValueColorsSecondary", @"label": @"Toggle Y-Values Secondary Color"}, @{@"key": @"toggleIcons", @"label": @"Toggle Icons"}, @{@"key": @"toggleHighlight", @"label": @"Toggle Highlight"}, @{@"key": @"animateX", @"label": @"Animate X"}, diff --git a/ChartsDemo-iOS/Objective-C/Demos/PositiveNegativeBarChartViewController.m b/ChartsDemo-iOS/Objective-C/Demos/PositiveNegativeBarChartViewController.m index fe6e9be935..dff61c04c0 100644 --- a/ChartsDemo-iOS/Objective-C/Demos/PositiveNegativeBarChartViewController.m +++ b/ChartsDemo-iOS/Objective-C/Demos/PositiveNegativeBarChartViewController.m @@ -31,6 +31,10 @@ - (void)viewDidLoad self.options = @[ @{@"key": @"toggleValues", @"label": @"Toggle Values"}, + @{@"key": @"toggleValuesPosition", @"label": @"Toggle Values Position"}, + @{@"key": @"toggleValuesSideFlexible", @"label": @"Toggle Y-Values Flexible Side"}, + @{@"key": @"toggleValueColorsAdjustment", @"label": @"Toggle Y-Values Color Adjustment"}, + @{@"key": @"toggleValueColorsSecondary", @"label": @"Toggle Y-Values Secondary Color"}, @{@"key": @"toggleHighlight", @"label": @"Toggle Highlight"}, @{@"key": @"animateX", @"label": @"Animate X"}, @{@"key": @"animateY", @"label": @"Animate Y"}, diff --git a/ChartsDemo-iOS/Swift/DemoBaseViewController.swift b/ChartsDemo-iOS/Swift/DemoBaseViewController.swift index da2afe2d4e..0aceee694c 100644 --- a/ChartsDemo-iOS/Swift/DemoBaseViewController.swift +++ b/ChartsDemo-iOS/Swift/DemoBaseViewController.swift @@ -50,6 +50,11 @@ enum Option { case toggleYLabels case toggleRotate case toggleHighlightCircle + // Bar Chart + case toggleValuesPosition + case toggleValuesSideFlexible + case toggleValueColorsAdjustment + case toggleValueColorsSecondary var label: String { switch self { @@ -91,6 +96,11 @@ enum Option { case .toggleYLabels: return "Toggle Y-Labels" case .toggleRotate: return "Toggle Rotate" case .toggleHighlightCircle: return "Toggle highlight circle" + //Bar Chart + case .toggleValuesPosition: return "Toggle Y-Values Position" + case .toggleValuesSideFlexible: return "Toggle Y-Values Flexible Side" + case .toggleValueColorsAdjustment: return "Toggle Y-Values Color Adjustment" + case .toggleValueColorsSecondary: return "Toggle Y-Values Secondary Color" } } } @@ -175,6 +185,33 @@ class DemoBaseViewController: UIViewController, ChartViewDelegate { } } chartView.setNeedsDisplay() + + case .toggleValuesPosition: + let barChart = chartView as! BarChartView + barChart.drawValueAboveBarEnabled = !barChart.drawValueAboveBarEnabled + chartView.notifyDataSetChanged() + + case .toggleValuesSideFlexible: + let barChart = chartView as! BarChartView + barChart.isDrawValueSideFlexible = !barChart.isDrawValueSideFlexible + chartView.notifyDataSetChanged() + + case .toggleValueColorsAdjustment: + for set in chartView.data!.dataSets { + set.valueColorsAdjustment = !set.valueColorsAdjustment + } + chartView.setNeedsDisplay() + + case .toggleValueColorsSecondary: + for set in chartView.data!.dataSets { + if set.valueColorsSecondary.isEmpty { + set.valueTextColorSecondary = .black + } else { + set.resetValueSecondaryColors() + } + } + chartView.setNeedsDisplay() + default: break } diff --git a/ChartsDemo-iOS/Swift/Demos/BarChartViewController.swift b/ChartsDemo-iOS/Swift/Demos/BarChartViewController.swift index 16b3837601..2e9a61cc35 100644 --- a/ChartsDemo-iOS/Swift/Demos/BarChartViewController.swift +++ b/ChartsDemo-iOS/Swift/Demos/BarChartViewController.swift @@ -29,6 +29,10 @@ class BarChartViewController: DemoBaseViewController { self.title = "Bar Chart" self.options = [.toggleValues, + .toggleValuesPosition, + .toggleValuesSideFlexible, + .toggleValueColorsAdjustment, + .toggleValueColorsSecondary, .toggleHighlight, .animateX, .animateY, @@ -134,6 +138,7 @@ class BarChartViewController: DemoBaseViewController { set1.colors = ChartColorTemplates.material() set1.drawValuesEnabled = false + set1.valueColorsAdjustment = chartView.valueColorsAdjustment let data = BarChartData(dataSet: set1) data.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 10)!) data.barWidth = 0.9 diff --git a/ChartsDemo-iOS/Swift/Demos/PositiveNegativeBarChartViewController.swift b/ChartsDemo-iOS/Swift/Demos/PositiveNegativeBarChartViewController.swift index 9526751457..5b4539f9bb 100644 --- a/ChartsDemo-iOS/Swift/Demos/PositiveNegativeBarChartViewController.swift +++ b/ChartsDemo-iOS/Swift/Demos/PositiveNegativeBarChartViewController.swift @@ -27,6 +27,10 @@ class PositiveNegativeBarChartViewController: DemoBaseViewController { // Do any additional setup after loading the view. self.title = "Positive/Negative Bar Chart" self.options = [.toggleValues, + .toggleValuesPosition, + .toggleValuesSideFlexible, + .toggleValueColorsAdjustment, + .toggleValueColorsSecondary, .toggleHighlight, .animateX, .animateY, @@ -98,6 +102,7 @@ class PositiveNegativeBarChartViewController: DemoBaseViewController { let set = BarChartDataSet(entries: yVals, label: "Values") set.colors = colors set.valueColors = colors + set.valueColorsAdjustment = chartView.valueColorsAdjustment let data = BarChartData(dataSet: set) data.setValueFont(.systemFont(ofSize: 13)) diff --git a/ChartsDemo-iOS/Swift/Demos/StackedBarChartViewController.swift b/ChartsDemo-iOS/Swift/Demos/StackedBarChartViewController.swift index fd704b596a..f72f7370b1 100644 --- a/ChartsDemo-iOS/Swift/Demos/StackedBarChartViewController.swift +++ b/ChartsDemo-iOS/Swift/Demos/StackedBarChartViewController.swift @@ -34,6 +34,10 @@ class StackedBarChartViewController: DemoBaseViewController { // Do any additional setup after loading the view. self.title = "Stacked Bar Chart" self.options = [.toggleValues, + .toggleValuesPosition, + .toggleValuesSideFlexible, + .toggleValueColorsAdjustment, + .toggleValueColorsSecondary, .toggleIcons, .toggleHighlight, .animateX, diff --git a/Source/Charts/Charts/BarChartView.swift b/Source/Charts/Charts/BarChartView.swift index ccd8d81c46..49e712b1d0 100644 --- a/Source/Charts/Charts/BarChartView.swift +++ b/Source/Charts/Charts/BarChartView.swift @@ -18,11 +18,15 @@ open class BarChartView: BarLineChartViewBase, BarChartDataProvider /// if set to true, all values are drawn above their bars, instead of below their top private var _drawValueAboveBarEnabled = true - /// if set to true and _drawValueAboveBarEnabled is false, values those do not fit into the value bar are drawn above their bars, instead of below their top - private var _drawValueInsideBarSoft = false + /// if set to true values those do not fit into the value bar/placed outside of visible area are drawn above/inside their bars + /// side effect - vertical bars offset (top/bottom) are set to 0 to prevent chart placement adjustment for low/big values + private var _drawValueSideFlexible = false /// Distance fo the values from the bars top private var _valuesOffset: CGFloat = 4.5 + + private var _valueColorsAdjustment = false + /// if set to true, a grey area is drawn behind each bar that indicates the maximum value private var _drawBarShadowEnabled = false @@ -157,14 +161,14 @@ open class BarChartView: BarLineChartViewBase, BarChartDataProvider } } - @objc open var isDrawValueInsideBarSoft: Bool + @objc open var isDrawValueSideFlexible: Bool { - get { return _drawValueInsideBarSoft } + get { return _drawValueSideFlexible } set { - _drawValueInsideBarSoft = newValue - if _drawValueInsideBarSoft { - //these offsets are not needed as the value labels do not "cross" zero edge + _drawValueSideFlexible = newValue + if _drawValueSideFlexible { + //these offsets are not needed as the value labels do not "cross" zero or chart min/max edges //default values (0.1) provide gap if min/max value are close to the edges, no need the gap to fit in content leftAxis.spaceTop = 0 leftAxis.spaceBottom = 0 @@ -185,6 +189,16 @@ open class BarChartView: BarLineChartViewBase, BarChartDataProvider } } + @objc open var valueColorsAdjustment: Bool + { + get { return _valueColorsAdjustment } + set + { + _valueColorsAdjustment = newValue + notifyDataSetChanged() + } + } + /// if set to true, a grey area is drawn behind each bar that indicates the maximum value @objc open var drawBarShadowEnabled: Bool { diff --git a/Source/Charts/Charts/CombinedChartView.swift b/Source/Charts/Charts/CombinedChartView.swift index 4836cbaca5..77330240c9 100644 --- a/Source/Charts/Charts/CombinedChartView.swift +++ b/Source/Charts/Charts/CombinedChartView.swift @@ -169,10 +169,10 @@ open class CombinedChartView: BarLineChartViewBase, CombinedChartDataProvider set { (renderer as! CombinedChartRenderer).drawValueAboveBarEnabled = newValue } } - @objc open var isDrawValueInsideBarSoft: Bool + @objc open var isDrawValueSideFlexible: Bool { - get { return (renderer as! CombinedChartRenderer).isDrawValueInsideBarSoft } - set { (renderer as! CombinedChartRenderer).isDrawValueInsideBarSoft = newValue } + get { return (renderer as! CombinedChartRenderer).isDrawValueSideFlexible } + set { (renderer as! CombinedChartRenderer).isDrawValueSideFlexible = newValue } } @objc open var valuesOffset: CGFloat diff --git a/Source/Charts/Data/Implementations/ChartBaseDataSet.swift b/Source/Charts/Data/Implementations/ChartBaseDataSet.swift index c2915abb84..10847acdfd 100644 --- a/Source/Charts/Data/Implementations/ChartBaseDataSet.swift +++ b/Source/Charts/Data/Implementations/ChartBaseDataSet.swift @@ -192,6 +192,12 @@ open class ChartBaseDataSet: NSObject, ChartDataSetProtocol, NSCopying /// List representing all colors that are used for drawing the actual values for this DataSet open var valueColors = [NSUIColor]() + /// valueColors in case of soft positions in effect (BarCharView:isDrawValueSideFlexible) + open var valueColorsSecondary = [NSUIColor]() + + /// Check if colors for the values for the DataSet are distinct from the background/bar color and apply inverted color if opposite + open var valueColorsAdjustment: Bool = false + /// The label string that describes the DataSet. open var label: String? = "DataSet" @@ -302,6 +308,39 @@ open class ChartBaseDataSet: NSObject, ChartDataSetProtocol, NSCopying return valueColors[index % valueColors.count] } + open var valueTextColorSecondary: NSUIColor + { + get + { + return valueTextColorSecondaryAt(0) + } + set + { + valueColorsSecondary.removeAll(keepingCapacity: false) + valueColorsSecondary.append(newValue) + } + } + + open func resetValueSecondaryColors() + { + valueColorsSecondary.removeAll(keepingCapacity: false) + } + + /// - Returns: The secondary color at the specified index that is used for drawing the values inside the chart. Uses modulus internally. + open func valueTextColorSecondaryAt(_ index: Int) -> NSUIColor + { + var index = index + if index < 0 + { + index = 0 + } + if valueColorsSecondary.isEmpty + { + return valueTextColorAt(index) + } + return valueColorsSecondary[index % valueColorsSecondary.count] + } + /// the font for the value-text labels open var valueFont: NSUIFont = NSUIFont.systemFont(ofSize: 7.0) @@ -393,6 +432,8 @@ open class ChartBaseDataSet: NSObject, ChartDataSetProtocol, NSCopying copy.colors = colors copy.valueColors = valueColors + copy.valueColorsAdjustment = valueColorsAdjustment + copy.valueColorsSecondary = valueColorsSecondary copy.label = label copy.axisDependency = axisDependency copy.highlightEnabled = highlightEnabled diff --git a/Source/Charts/Data/Interfaces/ChartDataSetProtocol.swift b/Source/Charts/Data/Interfaces/ChartDataSetProtocol.swift index 9cf80d3368..8d5984a1a5 100644 --- a/Source/Charts/Data/Interfaces/ChartDataSetProtocol.swift +++ b/Source/Charts/Data/Interfaces/ChartDataSetProtocol.swift @@ -175,6 +175,12 @@ public protocol ChartDataSetProtocol /// List representing all colors that are used for drawing the actual values for this DataSet var valueColors: [NSUIColor] { get } + /// valueColors in case of soft positions in effect (BarCharView:isDrawValueSideFlexible) + var valueColorsSecondary: [NSUIColor] { get } + + /// Check if colors for the values for the DataSet are distinct from the background/bar color and apply inverted color if opposite + var valueColorsAdjustment: Bool { get set } + /// All the colors that are used for this DataSet. /// Colors are reused as soon as the number of Entries the DataSet represents is higher than the size of the colors array. var colors: [NSUIColor] { get } @@ -205,6 +211,17 @@ public protocol ChartDataSetProtocol /// - Returns: The color at the specified index that is used for drawing the values inside the chart. Uses modulus internally. func valueTextColorAt(_ index: Int) -> NSUIColor + + /// Sets/get a single secondary color for value text. + /// Setting the color clears the valueColorsSecondary array and adds a single color. + /// Getting will return the first color in the valueColorsSecondary array. + /// If the array is empty - return value of valueTextColor + var valueTextColorSecondary: NSUIColor { get set } + + /// - Returns: The secondary color at the specified index that is used for drawing the values inside the chart. Uses modulus internally. If empty - return values from the valueTextColorAt + func valueTextColorSecondaryAt(_ index: Int) -> NSUIColor + + func resetValueSecondaryColors() /// the font for the value-text labels var valueFont: NSUIFont { get set } diff --git a/Source/Charts/Interfaces/BarChartDataProvider.swift b/Source/Charts/Interfaces/BarChartDataProvider.swift index a0c614bde6..e276b9041f 100644 --- a/Source/Charts/Interfaces/BarChartDataProvider.swift +++ b/Source/Charts/Interfaces/BarChartDataProvider.swift @@ -19,9 +19,11 @@ public protocol BarChartDataProvider: BarLineScatterCandleBubbleChartDataProvide var isDrawBarShadowEnabled: Bool { get } var isDrawValueAboveBarEnabled: Bool { get } - /// if set to true and isDrawValueAboveBarEnabled is false, values those do not fit into the value bar are drawn above their bars, instead of below their top - var isDrawValueInsideBarSoft: Bool { get } + /// if set to true values those + /// 1.do not fit into the value bar are drawn above them (below for negative), instead of partially inside and/or below (above if negative) + /// 2.do not fit into the visible area above/below their bars are drawn inside + var isDrawValueSideFlexible: Bool { get } /// distance from top (bottom in negative) for values drawn outside/inside the bar var valuesOffset: CGFloat { get } var isHighlightFullBarEnabled: Bool { get } -} \ No newline at end of file +} diff --git a/Source/Charts/Renderers/BarChartRenderer.swift b/Source/Charts/Renderers/BarChartRenderer.swift index 2a051f9bec..7da6c700fb 100644 --- a/Source/Charts/Renderers/BarChartRenderer.swift +++ b/Source/Charts/Renderers/BarChartRenderer.swift @@ -436,13 +436,14 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer let dataProvider = dataProvider, let barData = dataProvider.barData else { return } - + let valueOffsetPlus: CGFloat = dataProvider.valuesOffset var posOffset: CGFloat var negOffset: CGFloat - var posOffsetSoftFallback: CGFloat - var negOffsetSoftFallback: CGFloat + var posOffsetSideFallback: CGFloat + var negOffsetSideFallback: CGFloat let drawValueAboveBar = dataProvider.isDrawValueAboveBarEnabled + let chartBackgroundColor = NSUIColor.white //TODO: get the actual chart background color for dataSetIndex in barData.indices { @@ -459,33 +460,142 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer let valueFont = dataSet.valueFont let valueTextHeight = valueFont.lineHeight posOffset = (drawValueAboveBar ? -(valueTextHeight + valueOffsetPlus) : valueOffsetPlus) - posOffsetSoftFallback = (!drawValueAboveBar ? -(valueTextHeight + valueOffsetPlus) : valueOffsetPlus) + posOffsetSideFallback = (!drawValueAboveBar ? -(valueTextHeight + valueOffsetPlus) : valueOffsetPlus) negOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextHeight + valueOffsetPlus)) - negOffsetSoftFallback = (!drawValueAboveBar ? valueOffsetPlus : -(valueTextHeight + valueOffsetPlus)) + negOffsetSideFallback = (!drawValueAboveBar ? valueOffsetPlus : -(valueTextHeight + valueOffsetPlus)) if isInverted { posOffset = -posOffset - valueTextHeight - posOffsetSoftFallback = -posOffsetSoftFallback - valueTextHeight + posOffsetSideFallback = -posOffsetSideFallback - valueTextHeight negOffset = -negOffset - valueTextHeight - negOffsetSoftFallback = -negOffsetSoftFallback - valueTextHeight + negOffsetSideFallback = -negOffsetSideFallback - valueTextHeight } let buffer = _buffers[dataSetIndex] let formatter = dataSet.valueFormatter - let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) - let phaseY = animator.phaseY - + let iconsOffset = dataSet.iconsOffset + + func drawValueAndIconAndContinue(for e:BarChartDataEntry, in rect: CGRect, index j: Int, drawAbove: Bool, value: Double, anchor: CGPoint, angleRadians: CGFloat, backgroundColor outerColor: NSUIColor, ignoreAnimator: Bool = true) -> Bool + { + let x = rect.origin.x + rect.size.width / 2.0 + + if !viewPortHandler.isInBoundsRight(x) + { + return false + } + + if !viewPortHandler.isInBoundsLeft(x) + { + return true + } + + let animatorTransform = (CGFloat)(ignoreAnimator ? 1.0 : phaseY) + let y = rect.origin.y * animatorTransform + //allow to draw a value even is bar is slightly out of bounds but value should be inside bar + if !(viewPortHandler.isInBoundsY(y) || ((dataProvider.isDrawValueSideFlexible || !drawValueAboveBar) && ( + viewPortHandler.isInBoundsY(y - dataProvider.valuesOffset) || + viewPortHandler.isInBoundsY(y + dataProvider.valuesOffset) + ) + )) + { + return true + } + + if dataSet.isDrawValuesEnabled + { + var color = dataSet.valueTextColorAt(j) + var backgroundColor = outerColor + var yPos = y + (drawAbove + ? posOffset + : rect.height + negOffset) + + if drawValueAboveBar + { + if dataProvider.isDrawValueSideFlexible && (!viewPortHandler.isInBoundsY(yPos) || !viewPortHandler.isInBoundsY(yPos + valueTextHeight)) + { + yPos = y + (drawAbove + ? posOffsetSideFallback + : rect.height + negOffsetSideFallback) + + color = dataSet.valueTextColorSecondaryAt(j) + backgroundColor = dataSet.color(atIndex: j) + } + else + { + if dataProvider.isDrawBarShadowEnabled + { + backgroundColor = dataSet.barShadowColor + } + } + } + else + { + if dataProvider.isDrawValueSideFlexible && (yPos + valueTextHeight > rect.maxY || yPos < rect.minY) + { + yPos = y + (drawAbove + ? posOffsetSideFallback + : rect.height + negOffsetSideFallback) + + color = dataSet.valueTextColorSecondaryAt(j) + if dataProvider.isDrawBarShadowEnabled + { + backgroundColor = dataSet.barShadowColor + } + } + else + { + backgroundColor = dataSet.color(atIndex: j) + } + } + if dataSet.valueColorsAdjustment + { + if color.distance(from: backgroundColor) < 0.2 + { + color = backgroundColor.inverseColor() + } + } + drawValue( + context: context, + value: formatter.stringForValue( + value, + entry: e, + dataSetIndex: dataSetIndex, + viewPortHandler: viewPortHandler), + xPos: x, + yPos: yPos * animatorTransform, + font: valueFont, + align: .center, + color: color, + anchor: anchor, + angleRadians: angleRadians) + } + + if let icon = e.icon, dataSet.isDrawIconsEnabled + { + var px = x + var py = rect.minY + (drawAbove + ? posOffset + : rect.height + negOffset) + + px += iconsOffset.x + py += iconsOffset.y + + context.drawImage(icon, + atCenter: CGPoint(x: px, y: py * animatorTransform), + size: icon.size) + } + return true + } // if only single values are drawn (sum) if !dataSet.isStacked { - let range = 0 ..< Int(ceil(Double(dataSet.entryCount) * animator.phaseX)) - for j in range + for j in 0 ..< Int(ceil(Double(dataSet.entryCount) * animator.phaseX)) { guard let e = dataSet.entryForIndex(j) as? BarChartDataEntry else { continue } @@ -499,59 +609,31 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer viewPortHandler.isInBoundsLeft(x) else { continue } - let val = e.y - - if dataSet.isDrawValuesEnabled + let backgroundColor: NSUIColor + if dataProvider.isDrawBarShadowEnabled { - var color = dataSet.valueTextColorAt(j) - var yPos = val >= 0.0 - ? (rect.origin.y + posOffset) - : (rect.origin.y + rect.size.height + negOffset) - - if (yPos + valueTextHeight > rect.maxY || yPos < rect.minY) && !drawValueAboveBar && dataProvider.isDrawValueInsideBarSoft { - yPos = val >= 0.0 - ? (rect.origin.y + posOffsetSoftFallback) - : (rect.origin.y + rect.size.height + negOffsetSoftFallback) - color = dataSet.color(atIndex: j) //change color as value color is usually not visible on the chart background - } - drawValue( - context: context, - value: formatter.stringForValue( - val, - entry: e, - dataSetIndex: dataSetIndex, - viewPortHandler: viewPortHandler), - xPos: x, - yPos: yPos, - font: valueFont, - align: .center, - color: color, - anchor: CGPoint(x: 0.5, y: 0.5), - angleRadians: angleRadians) + backgroundColor = dataSet.barShadowColor } - - if let icon = e.icon, dataSet.isDrawIconsEnabled + else { - var px = x - var py = val >= 0.0 - ? (rect.origin.y + posOffset) - : (rect.origin.y + rect.size.height + negOffset) - - px += iconsOffset.x - py += iconsOffset.y - - context.drawImage(icon, - atCenter: CGPoint(x: px, y: py), - size: icon.size) + backgroundColor = chartBackgroundColor + } + if !drawValueAndIconAndContinue(for: e, in: rect, index: j, drawAbove: e.y >= 0.0, value: e.y, + anchor: CGPoint(x: 0.5, y: 0.5), + angleRadians: angleRadians, + backgroundColor: backgroundColor) + { + break } - } } else { // if we have stacks - + var bufferIndex = 0 +//index for the colors to count each bar even when move across stacks + let lastIndex = ceil(Double(dataSet.entryCount) * animator.phaseX) for index in 0 ..< Int(lastIndex) @@ -559,123 +641,87 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer guard let e = dataSet.entryForIndex(index) as? BarChartDataEntry else { continue } let vals = e.yValues - - let rect = buffer[bufferIndex] - - let x = rect.origin.x + rect.size.width / 2.0 - + // we still draw stacked bars, but there is one non-stacked in between - if let values = vals + if let vals = vals { - // draw stack values - var transformed = [CGPoint]() - var posY = 0.0 var negY = -e.negativeSum - - for value in values + for k in vals.indices { - let y: Double - + let value = vals[k] + if value == 0.0 && (posY == 0.0 || negY == 0.0) { // Take care of the situation of a 0.0 value, which overlaps a non-zero bar - y = value + //https://github.com/danielgindi/Charts/issues/1191 + //https://github.com/danielgindi/Charts/pull/1195 +// y = value } else if value >= 0.0 { posY += value - y = posY } else { - y = negY negY -= value } - transformed.append(CGPoint(x: 0.0, y: CGFloat(y * phaseY))) - } - - trans.pointValuesToPixel(&transformed) - - for (value, transformed) in zip(values, transformed) - { - let drawBelow = (value == 0.0 && negY == 0.0 && posY > 0.0) || value < 0.0 - let y = transformed.y + (drawBelow ? negOffset : posOffset) - - guard viewPortHandler.isInBoundsRight(x) else { break } - guard viewPortHandler.isInBoundsY(y), - viewPortHandler.isInBoundsLeft(x) - else { continue } + let val = value + let rect = buffer[bufferIndex] + let drawBelow = (val == 0.0 && negY == 0.0 && posY > 0.0) || val < 0.0 - if dataSet.isDrawValuesEnabled + let backgroundColor: NSUIColor + if k == 0 && val < 0 || k == vals.count - 1 && val >= 0 { - drawValue( - context: context, - value: formatter.stringForValue( - value, - entry: e, - dataSetIndex: dataSetIndex, - viewPortHandler: viewPortHandler), - xPos: x, - yPos: y, - font: valueFont, - align: .center, - color: dataSet.valueTextColorAt(index), - anchor: CGPoint(x: 0.5, y: 0.5), - angleRadians: angleRadians) + if dataProvider.isDrawBarShadowEnabled + { + backgroundColor = dataSet.barShadowColor + } + else + { + backgroundColor = chartBackgroundColor + } + } + else + { + backgroundColor = dataSet.color(atIndex: k + (val >= 0 ? 1 : -1)) } - if let icon = e.icon, dataSet.isDrawIconsEnabled + if !drawValueAndIconAndContinue(for: e, in: rect, index: bufferIndex, drawAbove: !drawBelow, value: val, + anchor: CGPoint(x: 0.5, y: 0.5), + angleRadians: angleRadians, + backgroundColor: backgroundColor, + ignoreAnimator: false) { - context.drawImage(icon, - atCenter: CGPoint(x: x + iconsOffset.x, - y: y + iconsOffset.y), - size: icon.size) + break } + + bufferIndex += 1 } } - else + else // we still draw stacked bars, but there is one non-stacked in between { - guard viewPortHandler.isInBoundsRight(x) else { break } - guard viewPortHandler.isInBoundsY(rect.origin.y), - viewPortHandler.isInBoundsLeft(x) else { continue } - - if dataSet.isDrawValuesEnabled + let backgroundColor: NSUIColor + if dataProvider.isDrawBarShadowEnabled { - drawValue( - context: context, - value: formatter.stringForValue( - e.y, - entry: e, - dataSetIndex: dataSetIndex, - viewPortHandler: viewPortHandler), - xPos: x, - yPos: rect.origin.y + - (e.y >= 0 ? posOffset : negOffset), - font: valueFont, - align: .center, - color: dataSet.valueTextColorAt(index), - anchor: CGPoint(x: 0.5, y: 0.5), - angleRadians: angleRadians) + backgroundColor = dataSet.barShadowColor } - - if let icon = e.icon, dataSet.isDrawIconsEnabled + else { - var px = x - var py = rect.origin.y + - (e.y >= 0 ? posOffset : negOffset) - - px += iconsOffset.x - py += iconsOffset.y - - context.drawImage(icon, - atCenter: CGPoint(x: px, y: py), - size: icon.size) + backgroundColor = chartBackgroundColor } - } + let rect = buffer[bufferIndex] - bufferIndex += vals?.count ?? 1 + if !drawValueAndIconAndContinue(for: e, in: rect, index: bufferIndex, drawAbove: e.y >= 0, value: e.y, + anchor: CGPoint(x: 0.5, y: 0.5), + angleRadians: angleRadians, + backgroundColor: backgroundColor) + { + break + } + bufferIndex += 1 + } } } } diff --git a/Source/Charts/Renderers/CombinedChartRenderer.swift b/Source/Charts/Renderers/CombinedChartRenderer.swift index c34fda7362..2ddab643cf 100644 --- a/Source/Charts/Renderers/CombinedChartRenderer.swift +++ b/Source/Charts/Renderers/CombinedChartRenderer.swift @@ -26,7 +26,7 @@ open class CombinedChartRenderer: NSObject, DataRenderer @objc open var drawValueAboveBarEnabled = true /// if set to true and drawValueAboveBarEnabled is false, values those do not fit into the value bar are drawn above their bars, instead of below their top - @objc open var isDrawValueInsideBarSoft = false + @objc open var isDrawValueSideFlexible = false /// distance from top (bottom in negative) for values drawn outside/inside the bar @objc open var valuesOffset: CGFloat = 4.5 diff --git a/Source/Charts/Utils/Platform+Color.swift b/Source/Charts/Utils/Platform+Color.swift index 02bff08ed4..21a820a0aa 100644 --- a/Source/Charts/Utils/Platform+Color.swift +++ b/Source/Charts/Utils/Platform+Color.swift @@ -29,6 +29,81 @@ private let labelColor: UIColor = fetchLabelColor() extension UIColor { static var labelOrBlack: UIColor { labelColor } + + func distance(from secondColor: UIColor) -> CGFloat //ignoring the alpha component + { + //color components https://stackoverflow.com/a/48610603 + var alpha = CGFloat(0) + var red = CGFloat(0); var green = CGFloat(0); var blue = CGFloat(0) + var red2 = CGFloat(0); var green2 = CGFloat(0); var blue2 = CGFloat(0) + //distance https://stackoverflow.com/a/11550492 + if self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) && + secondColor.getRed(&red2, green: &green2, blue: &blue2, alpha: &alpha) + { + return CGFloat(sqrtf(pow(Float(red - red2), 2) + + pow(Float(green - green2), 2) + + pow(Float(blue - blue2), 2))) + } + + var hue = CGFloat(0), saturation = CGFloat(0), brightness = CGFloat(0) + var hue2 = CGFloat(0), saturation2 = CGFloat(0), brightness2 = CGFloat(0) + if self.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) && + secondColor.getHue(&hue2, saturation: &saturation2, brightness: &brightness2, alpha: &alpha) + { + return CGFloat(sqrtf(pow(Float(hue - hue2), 2) + + pow(Float(saturation - saturation2), 2) + + pow(Float(brightness - brightness2), 2))) + } + + var white = CGFloat(0); var white2 = CGFloat(0) + if self.getWhite(&white, alpha: &alpha) && secondColor.getWhite(&white2, alpha: &alpha) + { + return CGFloat(sqrtf(pow(Float(white - white2), 2))) + } + + return -1 + } + + func inverseColor() -> UIColor //returns same alpha component + { + //https://stackoverflow.com/a/5901586 + var alpha = CGFloat(0) + + var red = CGFloat(0); var green = CGFloat(0); var blue = CGFloat(0) + if self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) + { + return UIColor(red: 1 - red, green: 1 - green, blue: 1 - blue, alpha: alpha) + } + + var hue = CGFloat(0), saturation = CGFloat(0), brightness = CGFloat(0) + if self.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) + { + return UIColor(hue: 1 - hue, saturation: 1 - saturation, brightness: 1 - brightness, alpha: alpha) + } + + var white = CGFloat(0) + if self.getWhite(&white, alpha: &alpha) + { + if white == 0.5 + { + return labelColor + } + if white > 0.33 && white < 0.67 //adjust gray as here https://stackoverflow.com/a/19767334 + { + if white > 0.5 + { + return .darkGray + } + else + { + return .lightGray + } + } + return UIColor(white: 1 - white, alpha: alpha) + } + + return self + } } #endif @@ -53,5 +128,29 @@ private let labelColor: NSColor = fetchLabelColor() extension NSColor { static var labelOrBlack: NSColor { labelColor } + func distance(from secondColor: NSColor) -> CGFloat //ignoring the alpha component + { + //color components https://stackoverflow.com/a/48610603 + var alpha = CGFloat(0) + var red = CGFloat(0); var green = CGFloat(0); var blue = CGFloat(0) + var red2 = CGFloat(0); var green2 = CGFloat(0); var blue2 = CGFloat(0) + //distance https://stackoverflow.com/a/11550492 + self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) + secondColor.getRed(&red2, green: &green2, blue: &blue2, alpha: &alpha) + + return CGFloat(sqrtf(pow(Float(red - red2), 2) + + pow(Float(green - green2), 2) + + pow(Float(blue - blue2), 2))) + } + + func inverseColor() -> NSColor //returns same alpha component + { + //https://stackoverflow.com/a/5901586 + var alpha = CGFloat(0) + + var red = CGFloat(0); var green = CGFloat(0); var blue = CGFloat(0) + self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) + return NSColor(red: 1 - red, green: 1 - green, blue: 1 - blue, alpha: alpha) + } } #endif diff --git a/Tests/ChartsTests/BarChartTests.swift b/Tests/ChartsTests/BarChartTests.swift index 460a9a6663..ea7954af3b 100644 --- a/Tests/ChartsTests/BarChartTests.swift +++ b/Tests/ChartsTests/BarChartTests.swift @@ -63,6 +63,18 @@ class BarChartTests: XCTestCase { return entries } + func setupStackedValuesWithSinglesDataEntries() -> [ChartDataEntry] { + var entries: [ChartDataEntry] = Array() + entries.append(BarChartDataEntry(x: 0, yValues: [28, 50, 60, 30, 42], icon: UIImage(named: "icon"))) + entries.append(BarChartDataEntry(x: 1, yValues: [-20, -36, -52, -40, -15], icon: UIImage(named: "icon"))) + entries.append(BarChartDataEntry(x: 2, yValues: [10, 30, 40, 90, 72], icon: UIImage(named: "icon"))) + entries.append(BarChartDataEntry(x: 3, yValues: [-40, -50, -30, -60, -20], icon: UIImage(named: "icon"))) + entries.append(BarChartDataEntry(x: 4, yValues: [10, 40, 60, 45, 62], icon: UIImage(named: "icon"))) + entries.append(BarChartDataEntry(x: 5, yValues: [10.0], icon: UIImage(named: "icon"))) + entries.append(BarChartDataEntry(x: 6, yValues: [-30.0], icon: UIImage(named: "icon"))) + return entries + } + func setupDefaultStackedDataSet(chartDataEntries: [ChartDataEntry]) -> BarChartDataSet { let dataSet = BarChartDataSet(entries: chartDataEntries, label: "Stacked bar chart unit test data") dataSet.drawIconsEnabled = false @@ -170,6 +182,14 @@ class BarChartTests: XCTestCase { assertChartSnapshot(matching: chart) } + func testPositiveValuesCustomOffset() { + let dataEntries = setupPositiveValuesDataEntries() + let dataSet = setupDefaultDataSet(chartDataEntries: dataEntries) + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.valuesOffset = 20 + assertChartSnapshot(matching: chart) + } + func testNegativeValues() { let dataEntries = setupNegativeValuesDataEntries() let dataSet = setupDefaultDataSet(chartDataEntries: dataEntries) @@ -224,6 +244,40 @@ class BarChartTests: XCTestCase { assertChartSnapshot(matching: chart) } + func testNegativeValuesCustomOffset() { + let dataEntries = setupNegativeValuesDataEntries() + let dataSet = setupDefaultDataSet(chartDataEntries: dataEntries) + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.valuesOffset = 20 + assertChartSnapshot(matching: chart) + } + + func testNegativeValuesFlexibleSecondaryColor() + { + let dataEntries = setupNegativeValuesDataEntries() + let dataSet = setupDefaultDataSet(chartDataEntries: dataEntries) + dataSet.valueTextColorSecondary = .red + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.drawValueAboveBarEnabled = true + chart.isDrawValueSideFlexible = true + chart.valuesOffset = 20 + chart.notifyDataSetChanged() + assertChartSnapshot(matching: chart) + } + + func testNotDrawValueAboveBarsNegativeValuesFlexibleSecondaryColor() + { + let dataEntries = setupNegativeValuesDataEntries() + let dataSet = setupDefaultDataSet(chartDataEntries: dataEntries) + dataSet.valueTextColorSecondary = .red + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.drawValueAboveBarEnabled = false + chart.isDrawValueSideFlexible = true + chart.valuesOffset = 20 + chart.notifyDataSetChanged() + assertChartSnapshot(matching: chart) + } + func testHidesValues() { let dataEntries = setupDefaultValuesDataEntries() let dataSet = setupDefaultDataSet(chartDataEntries: dataEntries) @@ -242,6 +296,53 @@ class BarChartTests: XCTestCase { assertChartSnapshot(matching: chart) } + func testDefaultNotDrawValueAboveBarsFlexible() { + let dataEntries = setupDefaultValuesDataEntries() + let dataSet = setupDefaultDataSet(chartDataEntries: dataEntries) + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.drawValueAboveBarEnabled = false + chart.isDrawValueSideFlexible = true + chart.valuesOffset = 20 + chart.notifyDataSetChanged() + assertChartSnapshot(matching: chart) + } + + func testDefaultNotDrawValueAboveBarsFlexibleInvertColor() { + let dataEntries = setupDefaultValuesDataEntries() + let dataSet = setupDefaultDataSet(chartDataEntries: dataEntries) + dataSet.valueTextColor = dataSet.color(atIndex: 0) + dataSet.valueColorsAdjustment = true + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.drawValueAboveBarEnabled = false + chart.isDrawValueSideFlexible = true + chart.valuesOffset = 20 + chart.notifyDataSetChanged() + assertChartSnapshot(matching: chart) + } + + func testDefaultValuesFlexibleSecondaryColor() { + let dataEntries = setupDefaultValuesDataEntries() + let dataSet = setupDefaultDataSet(chartDataEntries: dataEntries) + dataSet.valueTextColorSecondary = .red + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.isDrawValueSideFlexible = true + chart.valuesOffset = 20 + chart.notifyDataSetChanged() + assertChartSnapshot(matching: chart) + } + + func testDefaultNotDrawValueAboveBarsFlexibleSecondaryColor() { + let dataEntries = setupDefaultValuesDataEntries() + let dataSet = setupDefaultDataSet(chartDataEntries: dataEntries) + dataSet.valueTextColorSecondary = .red + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.drawValueAboveBarEnabled = false + chart.isDrawValueSideFlexible = true + chart.valuesOffset = 20 + chart.notifyDataSetChanged() + assertChartSnapshot(matching: chart) + } + func testStackedDrawValues() { let dataEntries = setupStackedValuesDataEntries() let dataSet = setupDefaultStackedDataSet(chartDataEntries: dataEntries) @@ -250,6 +351,27 @@ class BarChartTests: XCTestCase { assertChartSnapshot(matching: chart) } + func testStackedDrawValuesInvertColors() { + let dataEntries = setupStackedValuesDataEntries() + let dataSet = setupDefaultStackedDataSet(chartDataEntries: dataEntries) + dataSet.valueColors = dataSet.colors + dataSet.valueColorsAdjustment = true + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.notifyDataSetChanged() + assertChartSnapshot(matching: chart) + } + + func testStackedDrawValuesFlexibleInvertColors() { + let dataEntries = setupStackedValuesDataEntries() + let dataSet = setupDefaultStackedDataSet(chartDataEntries: dataEntries) + dataSet.valueColors = dataSet.colors + dataSet.valueColorsAdjustment = true + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.isDrawValueSideFlexible = true + chart.notifyDataSetChanged() + assertChartSnapshot(matching: chart) + } + func testStackedNotDrawValues() { let dataEntries = setupStackedValuesDataEntries() let dataSet = setupDefaultStackedDataSet(chartDataEntries: dataEntries) @@ -268,6 +390,102 @@ class BarChartTests: XCTestCase { assertChartSnapshot(matching: chart) } + func testStackedAndRegularPositiveDrawValues() { + var dataEntries = setupStackedValuesDataEntries() + dataEntries.append(BarChartDataEntry(x: 5, y: 10, icon: UIImage(named: "icon"))) + let dataSet = setupDefaultStackedDataSet(chartDataEntries: dataEntries) + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.notifyDataSetChanged() + assertChartSnapshot(matching: chart) + } + + func testStackedAndRegularNegativeDrawValues() { + var dataEntries = setupStackedValuesDataEntries() + dataEntries.append(BarChartDataEntry(x: 5, y: -10, icon: UIImage(named: "icon"))) + let dataSet = setupDefaultStackedDataSet(chartDataEntries: dataEntries) + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.notifyDataSetChanged() + assertChartSnapshot(matching: chart) + } + + func testStackedAndStackSinglePositiveDrawValues() { + var dataEntries = setupStackedValuesDataEntries() + dataEntries.append(BarChartDataEntry(x: 5, yValues: [10.0], icon: UIImage(named: "icon"))) + let dataSet = setupDefaultStackedDataSet(chartDataEntries: dataEntries) + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.notifyDataSetChanged() + assertChartSnapshot(matching: chart) + } + + func testStackedAndStackSingleNegativeDrawValues() { + var dataEntries = setupStackedValuesDataEntries() + dataEntries.append(BarChartDataEntry(x: 5, yValues: [-10.0], icon: UIImage(named: "icon"))) + let dataSet = setupDefaultStackedDataSet(chartDataEntries: dataEntries) + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.notifyDataSetChanged() + assertChartSnapshot(matching: chart) + } + + func testStackedAndStackSinglesDrawValuesFlexible() { + let dataEntries = setupStackedValuesWithSinglesDataEntries() + let dataSet = setupDefaultStackedDataSet(chartDataEntries: dataEntries) + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.isDrawValueSideFlexible = true + chart.notifyDataSetChanged() + assertChartSnapshot(matching: chart) + } + + func testStackedAndRegularsDrawValuesFlexible() { + let dataEntries = setupStackedValuesWithSinglesDataEntries() + let dataSet = setupDefaultStackedDataSet(chartDataEntries: dataEntries) + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.isDrawValueSideFlexible = true + chart.notifyDataSetChanged() + assertChartSnapshot(matching: chart) + } + + func testStackedAndRegularsNotDrawValueAboveBarsFlexible() { + let dataEntries = setupStackedValuesWithSinglesDataEntries() + let dataSet = setupDefaultStackedDataSet(chartDataEntries: dataEntries) + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.isDrawValueSideFlexible = true + chart.drawValueAboveBarEnabled = false + chart.notifyDataSetChanged() + assertChartSnapshot(matching: chart) + } + + func testStackedAndStackSinglesNotDrawValueAboveBarsFlexible() { + let dataEntries = setupStackedValuesWithSinglesDataEntries() + let dataSet = setupDefaultStackedDataSet(chartDataEntries: dataEntries) + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.isDrawValueSideFlexible = true + chart.drawValueAboveBarEnabled = false + chart.notifyDataSetChanged() + assertChartSnapshot(matching: chart) + } + + func testStackedAndStackSinglesDrawValueInvertColors() { + let dataEntries = setupStackedValuesWithSinglesDataEntries() + let dataSet = setupDefaultStackedDataSet(chartDataEntries: dataEntries) + dataSet.valueColors = dataSet.colors + dataSet.valueColorsAdjustment = true + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.notifyDataSetChanged() + assertChartSnapshot(matching: chart) + } + + func testStackedAndStackSinglesNotDrawValueAboveBarsFlexibleInvertColors() { + let dataEntries = setupStackedValuesWithSinglesDataEntries() + let dataSet = setupDefaultStackedDataSet(chartDataEntries: dataEntries) + dataSet.valueColors = dataSet.colors + dataSet.valueColorsAdjustment = true + let chart = setupDefaultChart(dataSets: [dataSet]) + chart.isDrawValueSideFlexible = true + chart.drawValueAboveBarEnabled = false + chart.notifyDataSetChanged() + assertChartSnapshot(matching: chart) + } + func testHideLeftAxis() { let dataEntries = setupDefaultValuesDataEntries() let dataSet = setupDefaultDataSet(chartDataEntries: dataEntries) diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testDefaultNotDrawValueAboveBarsFlexible-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testDefaultNotDrawValueAboveBarsFlexible-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..15fa9a3d10 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testDefaultNotDrawValueAboveBarsFlexible-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testDefaultNotDrawValueAboveBarsFlexibleInvertColor-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testDefaultNotDrawValueAboveBarsFlexibleInvertColor-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..b4d6afaad8 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testDefaultNotDrawValueAboveBarsFlexibleInvertColor-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testDefaultNotDrawValueAboveBarsFlexibleSecondaryColor-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testDefaultNotDrawValueAboveBarsFlexibleSecondaryColor-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..a5cc7ca86e Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testDefaultNotDrawValueAboveBarsFlexibleSecondaryColor-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testDefaultValuesFlexibleSecondaryColor-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testDefaultValuesFlexibleSecondaryColor-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..14556693e5 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testDefaultValuesFlexibleSecondaryColor-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testNegativeValuesCustomOffset-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testNegativeValuesCustomOffset-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..369af30589 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testNegativeValuesCustomOffset-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testNegativeValuesFlexibleSecondaryColor-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testNegativeValuesFlexibleSecondaryColor-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..4852ab3edc Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testNegativeValuesFlexibleSecondaryColor-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testNotDrawValueAboveBarsNegativeValuesFlexibleSecondaryColor-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testNotDrawValueAboveBarsNegativeValuesFlexibleSecondaryColor-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..d5e0bf9029 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testNotDrawValueAboveBarsNegativeValuesFlexibleSecondaryColor-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testPositiveValuesCustomOffset-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testPositiveValuesCustomOffset-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..841ce987b0 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testPositiveValuesCustomOffset-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndRegularNegativeDrawValues-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndRegularNegativeDrawValues-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..6b4724a787 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndRegularNegativeDrawValues-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndRegularPositiveDrawValues-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndRegularPositiveDrawValues-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..0e6b6ef6d0 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndRegularPositiveDrawValues-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndRegularsDrawValuesFlexible-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndRegularsDrawValuesFlexible-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..4ce9c2f903 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndRegularsDrawValuesFlexible-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndRegularsNotDrawValueAboveBarsFlexible-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndRegularsNotDrawValueAboveBarsFlexible-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..260ccae2d3 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndRegularsNotDrawValueAboveBarsFlexible-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndStackSingleNegativeDrawValues-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndStackSingleNegativeDrawValues-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..6b4724a787 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndStackSingleNegativeDrawValues-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndStackSinglePositiveDrawValues-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndStackSinglePositiveDrawValues-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..0e6b6ef6d0 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndStackSinglePositiveDrawValues-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndStackSinglesDrawValueInvertColors-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndStackSinglesDrawValueInvertColors-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..7a3975f4d0 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndStackSinglesDrawValueInvertColors-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndStackSinglesDrawValuesFlexible-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndStackSinglesDrawValuesFlexible-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..4ce9c2f903 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndStackSinglesDrawValuesFlexible-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndStackSinglesNotDrawValueAboveBarsFlexible-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndStackSinglesNotDrawValueAboveBarsFlexible-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..260ccae2d3 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndStackSinglesNotDrawValueAboveBarsFlexible-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndStackSinglesNotDrawValueAboveBarsFlexibleInvertColors-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndStackSinglesNotDrawValueAboveBarsFlexibleInvertColors-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..7047202953 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedAndStackSinglesNotDrawValueAboveBarsFlexibleInvertColors-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedDrawValuesFlexibleInvertColors-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedDrawValuesFlexibleInvertColors-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..69b0ade430 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedDrawValuesFlexibleInvertColors-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedDrawValuesInvertColors-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedDrawValuesInvertColors-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..e28827f3c8 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__AppleSilicon__/BarChartTests/testStackedDrawValuesInvertColors-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testDefaultNotDrawValueAboveBarsFlexible-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testDefaultNotDrawValueAboveBarsFlexible-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..ce9ca1be8f Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testDefaultNotDrawValueAboveBarsFlexible-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testDefaultNotDrawValueAboveBarsFlexibleInvertColor-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testDefaultNotDrawValueAboveBarsFlexibleInvertColor-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..f6b1e438e2 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testDefaultNotDrawValueAboveBarsFlexibleInvertColor-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testDefaultNotDrawValueAboveBarsFlexibleSecondaryColor-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testDefaultNotDrawValueAboveBarsFlexibleSecondaryColor-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..5f3ef439c3 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testDefaultNotDrawValueAboveBarsFlexibleSecondaryColor-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testDefaultValuesFlexibleSecondaryColor-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testDefaultValuesFlexibleSecondaryColor-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..3a6da2562e Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testDefaultValuesFlexibleSecondaryColor-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testNegativeValuesCustomOffset-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testNegativeValuesCustomOffset-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..2208784785 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testNegativeValuesCustomOffset-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testNegativeValuesFlexibleSecondaryColor-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testNegativeValuesFlexibleSecondaryColor-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..aee5d684b5 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testNegativeValuesFlexibleSecondaryColor-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testNotDrawValueAboveBarsNegativeValuesFlexibleSecondaryColor-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testNotDrawValueAboveBarsNegativeValuesFlexibleSecondaryColor-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..8142c1420b Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testNotDrawValueAboveBarsNegativeValuesFlexibleSecondaryColor-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testPositiveValuesCustomOffset-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testPositiveValuesCustomOffset-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..d4867ef772 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testPositiveValuesCustomOffset-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndRegularNegativeDrawValues-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndRegularNegativeDrawValues-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..2b4a7458cf Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndRegularNegativeDrawValues-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndRegularPositiveDrawValues-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndRegularPositiveDrawValues-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..ed7d1dee42 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndRegularPositiveDrawValues-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndRegularsDrawValuesFlexible-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndRegularsDrawValuesFlexible-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..6bffa503cd Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndRegularsDrawValuesFlexible-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndRegularsNotDrawValueAboveBarsFlexible-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndRegularsNotDrawValueAboveBarsFlexible-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..3f6015d215 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndRegularsNotDrawValueAboveBarsFlexible-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndStackSingleNegativeDrawValues-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndStackSingleNegativeDrawValues-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..2b4a7458cf Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndStackSingleNegativeDrawValues-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndStackSinglePositiveDrawValues-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndStackSinglePositiveDrawValues-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..ed7d1dee42 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndStackSinglePositiveDrawValues-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndStackSinglesDrawValueInvertColors-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndStackSinglesDrawValueInvertColors-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..2b008980be Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndStackSinglesDrawValueInvertColors-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndStackSinglesDrawValuesFlexible-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndStackSinglesDrawValuesFlexible-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..6bffa503cd Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndStackSinglesDrawValuesFlexible-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndStackSinglesNotDrawValueAboveBarsFlexible-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndStackSinglesNotDrawValueAboveBarsFlexible-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..3f6015d215 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndStackSinglesNotDrawValueAboveBarsFlexible-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndStackSinglesNotDrawValueAboveBarsFlexibleInvertColors-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndStackSinglesNotDrawValueAboveBarsFlexibleInvertColors-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..7e1638afe2 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedAndStackSinglesNotDrawValueAboveBarsFlexibleInvertColors-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedDrawValuesFlexibleInvertColors-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedDrawValuesFlexibleInvertColors-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..97f9bb7cf7 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedDrawValuesFlexibleInvertColors-iOS_390-0_844-0.1.png differ diff --git a/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedDrawValuesInvertColors-iOS_390-0_844-0.1.png b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedDrawValuesInvertColors-iOS_390-0_844-0.1.png new file mode 100644 index 0000000000..ce8e36a166 Binary files /dev/null and b/Tests/ChartsTests/__Snapshots__x86__/BarChartTests/testStackedDrawValuesInvertColors-iOS_390-0_844-0.1.png differ