From e6f82b3081ffb9bf9660091b8275510bfaac866f Mon Sep 17 00:00:00 2001 From: Ilya Laryionau Date: Wed, 8 Jul 2020 10:45:17 +0300 Subject: [PATCH 1/7] Add gradient bars for BarChart --- .../Swift/DemoBaseViewController.swift | 3 + .../Swift/Demos/BarChartViewController.swift | 42 +++++-- .../Demos/LineChart1ViewController.swift | 6 + .../Standard/BarChartDataSet.swift | 4 + .../Data/Interfaces/IBarChartDataSet.swift | 4 + .../Charts/Renderers/BarChartRenderer.swift | 113 ++++++++++++++++-- Source/Charts/Utils/ChartUtils.swift | 8 ++ Source/Charts/Utils/Platform.swift | 36 ++++++ 8 files changed, 196 insertions(+), 20 deletions(-) diff --git a/ChartsDemo-iOS/Swift/DemoBaseViewController.swift b/ChartsDemo-iOS/Swift/DemoBaseViewController.swift index 444d1f4729..c5f00c7c3e 100644 --- a/ChartsDemo-iOS/Swift/DemoBaseViewController.swift +++ b/ChartsDemo-iOS/Swift/DemoBaseViewController.swift @@ -23,6 +23,7 @@ enum Option { case toggleAutoScaleMinMax case toggleData case toggleBarBorders + case toggleGradient // CandleChart case toggleShadowColorSameAsCandle case toggleShowCandleBar @@ -61,6 +62,8 @@ enum Option { case .toggleAutoScaleMinMax: return "Toggle auto scale min/max" case .toggleData: return "Toggle Data" case .toggleBarBorders: return "Toggle Bar Borders" + // LineChart + case .toggleGradient: return "Toggle Gradient" // CandleChart case .toggleShadowColorSameAsCandle: return "Toggle shadow same color" case .toggleShowCandleBar: return "Toggle show candle bar" diff --git a/ChartsDemo-iOS/Swift/Demos/BarChartViewController.swift b/ChartsDemo-iOS/Swift/Demos/BarChartViewController.swift index 5400646822..330c115d2e 100644 --- a/ChartsDemo-iOS/Swift/Demos/BarChartViewController.swift +++ b/ChartsDemo-iOS/Swift/Demos/BarChartViewController.swift @@ -30,6 +30,7 @@ class BarChartViewController: DemoBaseViewController { self.options = [.toggleValues, .toggleHighlight, + .toggleGradient, .animateX, .animateY, .animateXY, @@ -123,18 +124,19 @@ class BarChartViewController: DemoBaseViewController { } } - var set1: BarChartDataSet! = nil if let set = chartView.data?.dataSets.first as? BarChartDataSet { - set1 = set - set1.replaceEntries(yVals) + setup(set) + set.replaceEntries(yVals) chartView.data?.notifyDataChanged() chartView.notifyDataSetChanged() } else { - set1 = BarChartDataSet(entries: yVals, label: "The year 2017") - set1.colors = ChartColorTemplates.material() - set1.drawValuesEnabled = false - - let data = BarChartData(dataSet: set1) + let set = BarChartDataSet(entries: yVals, label: "The year 2017") + set.colors = ChartColorTemplates.material() + set.drawValuesEnabled = false + + setup(set) + + let data = BarChartData(dataSet: set) data.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 10)!) data.barWidth = 0.9 chartView.data = data @@ -142,9 +144,31 @@ class BarChartViewController: DemoBaseViewController { // chartView.setNeedsDisplay() } + + private func setup(_ dataSet: BarChartDataSet) { + if dataSet.drawBarGradientEnabled { + dataSet.colors = [.black, .red, .white] + dataSet.gradientPositions = [0, 40, 100] + } else { + dataSet.colors = ChartColorTemplates.material() + dataSet.gradientPositions = nil + } + } override func optionTapped(_ option: Option) { - super.handleOption(option, forChartView: chartView) + switch option { + case .toggleGradient: + + chartView.data?.dataSets + .compactMap { $0 as? BarChartDataSet } + .forEach { (set) in + set.drawBarGradientEnabled = !set.drawBarGradientEnabled + setup(set) + } + chartView.setNeedsDisplay() + default: + super.handleOption(option, forChartView: chartView) + } } // MARK: - Actions diff --git a/ChartsDemo-iOS/Swift/Demos/LineChart1ViewController.swift b/ChartsDemo-iOS/Swift/Demos/LineChart1ViewController.swift index 43e5ff4f78..82ff509d97 100644 --- a/ChartsDemo-iOS/Swift/Demos/LineChart1ViewController.swift +++ b/ChartsDemo-iOS/Swift/Demos/LineChart1ViewController.swift @@ -32,6 +32,7 @@ class LineChart1ViewController: DemoBaseViewController { .toggleIcons, .toggleStepped, .toggleHighlight, + .toggleGradient, .animateX, .animateY, .animateXY, @@ -174,6 +175,11 @@ class LineChart1ViewController: DemoBaseViewController { set.mode = (set.mode == .cubicBezier) ? .horizontalBezier : .cubicBezier } chartView.setNeedsDisplay() + case .toggleGradient: + for set in chartView.data!.dataSets as! [LineChartDataSet] { + set.mode = (set.mode == .cubicBezier) ? .horizontalBezier : .cubicBezier + } + chartView.setNeedsDisplay() default: super.handleOption(option, forChartView: chartView) diff --git a/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift b/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift index 2478aeccf8..1cf0fb66e6 100644 --- a/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift +++ b/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift @@ -136,6 +136,10 @@ open class BarChartDataSet: BarLineScatterCandleBubbleChartDataSet, IBarChartDat open var stackLabels: [String] = [] // MARK: - Styling functions and accessors + + open var drawBarGradientEnabled = false + + open var gradientPositions: [CGFloat]? /// the color used for drawing the bar-shadows. The bar shadows is a surface behind the bar that indicates the maximum value open var barShadowColor = NSUIColor(red: 215.0/255.0, green: 215.0/255.0, blue: 215.0/255.0, alpha: 1.0) diff --git a/Source/Charts/Data/Interfaces/IBarChartDataSet.swift b/Source/Charts/Data/Interfaces/IBarChartDataSet.swift index b90b4dc0c2..dd7b21d296 100644 --- a/Source/Charts/Data/Interfaces/IBarChartDataSet.swift +++ b/Source/Charts/Data/Interfaces/IBarChartDataSet.swift @@ -39,4 +39,8 @@ public protocol IBarChartDataSet: IBarLineScatterCandleBubbleChartDataSet /// array of labels used to describe the different values of the stacked bars var stackLabels: [String] { get set } + + var drawBarGradientEnabled: Bool { get set } + + var gradientPositions: [CGFloat]? { get set } } diff --git a/Source/Charts/Renderers/BarChartRenderer.swift b/Source/Charts/Renderers/BarChartRenderer.swift index c2ff0b108b..d4cd7340d2 100644 --- a/Source/Charts/Renderers/BarChartRenderer.swift +++ b/Source/Charts/Renderers/BarChartRenderer.swift @@ -328,14 +328,11 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer guard let dataProvider = dataProvider else { return } let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) - + let valueToPixelMatrix = trans.valueToPixelMatrix + prepareBuffer(dataSet: dataSet, index: index) trans.rectValuesToPixel(&_buffers[index].rects) - let borderWidth = dataSet.barBorderWidth - let borderColor = dataSet.barBorderColor - let drawBorder = borderWidth > 0.0 - context.saveGState() // draw the bar shadow before the values @@ -399,9 +396,103 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer context.fill(barRect) } } - + + if dataSet.drawBarGradientEnabled { + drawGradientBars(context: context, dataSet: dataSet, buffer: buffer, matrix: valueToPixelMatrix) + } else { + drawDefaultBars(context: context, dataSet: dataSet, dateSetIndex: index, buffer: buffer) + } + } + + private func drawGradientBars( + context: CGContext, + dataSet: IBarChartDataSet, + buffer: BarChartRenderer.Buffer, + matrix: CGAffineTransform) { + + guard let gradientPositions = dataSet.gradientPositions else + { + assertionFailure("Must set `gradientPositions if `dataSet.drawBarGradientEnabled` is true") + return + } + + guard let boundingBox = buffer.rects.union() else { return } + guard !boundingBox.isNull, !boundingBox.isInfinite, !boundingBox.isEmpty else { + return + } + + let drawBorder = dataSet.barBorderWidth > 0 + + let gradientStart = CGPoint(x: boundingBox.minX, y: boundingBox.minY) + let gradientEnd = CGPoint(x: boundingBox.minX, y: boundingBox.maxY) + var gradientColorComponents: [CGFloat] = [] + var gradientLocations: [CGFloat] = [] + + for position in gradientPositions.reversed() + { + let location = CGPoint(x: boundingBox.minX, y: position) + .applying(matrix) + let normalizedLocation = + (location.y - boundingBox.minY) / (boundingBox.maxY - boundingBox.minY) + switch normalizedLocation { + case ..<0: + gradientLocations.append(0) + case 0..<1: + gradientLocations.append(normalizedLocation) + case 1...: + gradientLocations.append(1) + default: + assertionFailure() + } + } + + for color in dataSet.colors.reversed() + { + guard let (r, g, b, a) = color.nsuirgba else { + continue + } + gradientColorComponents += [r, g, b, a] + } + + let baseColorSpace = CGColorSpaceCreateDeviceRGB() + guard let gradient = CGGradient( + colorSpace: baseColorSpace, + colorComponents: &gradientColorComponents, + locations: &gradientLocations, + count: gradientLocations.count) else { + return + } + + for barRect in buffer.rects + { + context.saveGState() + defer { context.restoreGState() } + + guard viewPortHandler.isInBoundsLeft(barRect.maxX) else { continue } + guard viewPortHandler.isInBoundsRight(barRect.minX) else { break } + + context.beginPath() + context.addRect(barRect) + context.clip() + context.drawLinearGradient(gradient, start: gradientStart, end: gradientEnd, options: []) + + if drawBorder + { + context.setStrokeColor(dataSet.barBorderColor.cgColor) + context.setLineWidth(dataSet.barBorderWidth) + context.stroke(barRect) + } + } + } + + private func drawDefaultBars( + context: CGContext, + dataSet: IBarChartDataSet, + dateSetIndex index: Int, + buffer: BarChartRenderer.Buffer) { + let drawBorder = dataSet.barBorderWidth > 0 let isSingleColor = dataSet.colors.count == 1 - + if isSingleColor { context.setFillColor(dataSet.color(atIndex: 0).cgColor) @@ -430,13 +521,13 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer // Set the color for the currently drawn value. If the index is out of bounds, reuse colors. context.setFillColor(dataSet.color(atIndex: j).cgColor) } - + context.fill(barRect) - + if drawBorder { - context.setStrokeColor(borderColor.cgColor) - context.setLineWidth(borderWidth) + context.setStrokeColor(dataSet.barBorderColor.cgColor) + context.setLineWidth(dataSet.barBorderWidth) context.stroke(barRect) } diff --git a/Source/Charts/Utils/ChartUtils.swift b/Source/Charts/Utils/ChartUtils.swift index 5e90873b51..a455f754da 100644 --- a/Source/Charts/Utils/ChartUtils.swift +++ b/Source/Charts/Utils/ChartUtils.swift @@ -20,6 +20,14 @@ import CoreGraphics import Cocoa #endif +extension Array where Element == CGRect { + func union() -> Element? + { + guard !isEmpty else { return nil } + return reduce(nil, { $0?.union($1) ?? $1 }) + } +} + extension Comparable { func clamped(to range: ClosedRange) -> Self diff --git a/Source/Charts/Utils/Platform.swift b/Source/Charts/Utils/Platform.swift index 3722647d3d..c40866e0f7 100644 --- a/Source/Charts/Utils/Platform.swift +++ b/Source/Charts/Utils/Platform.swift @@ -14,6 +14,22 @@ public typealias NSUIScrollView = UIScrollView public typealias NSUIScreen = UIScreen public typealias NSUIDisplayLink = CADisplayLink +extension NSUIColor +{ + var nsuirgba: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)? { + var red: CGFloat = 0 + var green: CGFloat = 0 + var blue: CGFloat = 0 + var alpha: CGFloat = 0 + + guard getRed(&red, green: &green, blue: &blue, alpha: &alpha) else { + return nil + } + + return (red: red, green: green, blue: blue, alpha: alpha) + } +} + open class NSUIView: UIView { @objc var nsuiLayer: CALayer? @@ -124,6 +140,26 @@ public class NSUIDisplayLink } } +extension NSUIColor +{ + var nsuirgba: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)? { + var red: CGFloat = 0 + var green: CGFloat = 0 + var blue: CGFloat = 0 + var alpha: CGFloat = 0 + + guard let colorSpaceModel = cgColor.colorSpace?.model else { + return nil + } + guard colorSpaceModel == .rgb else { + return nil + } + + getRed(&red, green: &green, blue: &blue, alpha: &alpha) + return (red: red, green: green, blue: blue, alpha: alpha) + } +} + extension NSView { final var nsuiGestureRecognizers: [NSGestureRecognizer]? From 842b0d8fc74eaa4e589d834b3948e576a20cd3a4 Mon Sep 17 00:00:00 2001 From: Ilya Laryionau Date: Wed, 8 Jul 2020 10:49:45 +0300 Subject: [PATCH 2/7] Add gradient start and gradient end to bar chart renderer --- .../Implementations/Standard/BarChartDataSet.swift | 6 +++++- Source/Charts/Data/Interfaces/IBarChartDataSet.swift | 4 ++++ Source/Charts/Renderers/BarChartRenderer.swift | 10 ++++++++-- Source/Charts/Renderers/LineChartRenderer.swift | 2 +- Source/Charts/Utils/ChartUtils.swift | 8 ++++++++ 5 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift b/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift index 1cf0fb66e6..7a9f450b75 100644 --- a/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift +++ b/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift @@ -140,7 +140,11 @@ open class BarChartDataSet: BarLineScatterCandleBubbleChartDataSet, IBarChartDat open var drawBarGradientEnabled = false open var gradientPositions: [CGFloat]? - + + open var gradientStart: CGPoint = .infinite + + open var gradientEnd: CGPoint = .infinite + /// the color used for drawing the bar-shadows. The bar shadows is a surface behind the bar that indicates the maximum value open var barShadowColor = NSUIColor(red: 215.0/255.0, green: 215.0/255.0, blue: 215.0/255.0, alpha: 1.0) diff --git a/Source/Charts/Data/Interfaces/IBarChartDataSet.swift b/Source/Charts/Data/Interfaces/IBarChartDataSet.swift index dd7b21d296..468a904ebd 100644 --- a/Source/Charts/Data/Interfaces/IBarChartDataSet.swift +++ b/Source/Charts/Data/Interfaces/IBarChartDataSet.swift @@ -43,4 +43,8 @@ public protocol IBarChartDataSet: IBarLineScatterCandleBubbleChartDataSet var drawBarGradientEnabled: Bool { get set } var gradientPositions: [CGFloat]? { get set } + + var gradientStart: CGPoint { get set } + + var gradientEnd: CGPoint { get set } } diff --git a/Source/Charts/Renderers/BarChartRenderer.swift b/Source/Charts/Renderers/BarChartRenderer.swift index d4cd7340d2..76df8b7df7 100644 --- a/Source/Charts/Renderers/BarChartRenderer.swift +++ b/Source/Charts/Renderers/BarChartRenderer.swift @@ -423,8 +423,14 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer let drawBorder = dataSet.barBorderWidth > 0 - let gradientStart = CGPoint(x: boundingBox.minX, y: boundingBox.minY) - let gradientEnd = CGPoint(x: boundingBox.minX, y: boundingBox.maxY) + let gradientStart = dataSet.gradientEnd.isInfinite ? + CGPoint(x: boundingBox.minX, y: boundingBox.minY) : + dataSet.gradientEnd.applying(matrix) + + let gradientEnd = dataSet.gradientStart.isInfinite ? + CGPoint(x: boundingBox.minX, y: boundingBox.maxY) : + dataSet.gradientStart.applying(matrix) + var gradientColorComponents: [CGFloat] = [] var gradientLocations: [CGFloat] = [] diff --git a/Source/Charts/Renderers/LineChartRenderer.swift b/Source/Charts/Renderers/LineChartRenderer.swift index ce3a25915e..91e1289cd6 100644 --- a/Source/Charts/Renderers/LineChartRenderer.swift +++ b/Source/Charts/Renderers/LineChartRenderer.swift @@ -443,7 +443,7 @@ open class LineChartRenderer: LineRadarRenderer return filled } - + open override func drawValues(context: CGContext) { guard diff --git a/Source/Charts/Utils/ChartUtils.swift b/Source/Charts/Utils/ChartUtils.swift index a455f754da..96e1d61e6c 100644 --- a/Source/Charts/Utils/ChartUtils.swift +++ b/Source/Charts/Utils/ChartUtils.swift @@ -124,6 +124,14 @@ extension Double extension CGPoint { + static var infinite: CGPoint { + return CGPoint(x: CGFloat.infinity, y: CGFloat.infinity) + } + + var isInfinite: Bool { + return x.isInfinite || y.isInfinite + } + /// Calculates the position around a center point, depending on the distance from the center, and the angle of the position around the center. func moving(distance: CGFloat, atAngle angle: CGFloat) -> CGPoint { From b7af4db2df7dabf8e47c5db582dee649e8a169af Mon Sep 17 00:00:00 2001 From: Xuan Date: Mon, 13 Jul 2020 09:26:11 +0800 Subject: [PATCH 3/7] update code style --- .../Charts/Renderers/BarChartRenderer.swift | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/Source/Charts/Renderers/BarChartRenderer.swift b/Source/Charts/Renderers/BarChartRenderer.swift index 76df8b7df7..1b39700067 100644 --- a/Source/Charts/Renderers/BarChartRenderer.swift +++ b/Source/Charts/Renderers/BarChartRenderer.swift @@ -397,18 +397,18 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer } } - if dataSet.drawBarGradientEnabled { + if dataSet.drawBarGradientEnabled + { drawGradientBars(context: context, dataSet: dataSet, buffer: buffer, matrix: valueToPixelMatrix) - } else { + } + else + { drawDefaultBars(context: context, dataSet: dataSet, dateSetIndex: index, buffer: buffer) } } - private func drawGradientBars( - context: CGContext, - dataSet: IBarChartDataSet, - buffer: BarChartRenderer.Buffer, - matrix: CGAffineTransform) { + private func drawGradientBars(context: CGContext, dataSet: IBarChartDataSet, buffer: BarChartRenderer.Buffer, matrix: CGAffineTransform) + { guard let gradientPositions = dataSet.gradientPositions else { @@ -417,9 +417,7 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer } guard let boundingBox = buffer.rects.union() else { return } - guard !boundingBox.isNull, !boundingBox.isInfinite, !boundingBox.isEmpty else { - return - } + guard !boundingBox.isNull, !boundingBox.isInfinite, !boundingBox.isEmpty else { return } let drawBorder = dataSet.barBorderWidth > 0 @@ -491,11 +489,8 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer } } - private func drawDefaultBars( - context: CGContext, - dataSet: IBarChartDataSet, - dateSetIndex index: Int, - buffer: BarChartRenderer.Buffer) { + private func drawDefaultBars(context: CGContext, dataSet: IBarChartDataSet, dateSetIndex index: Int, buffer: BarChartRenderer.Buffer) + { let drawBorder = dataSet.barBorderWidth > 0 let isSingleColor = dataSet.colors.count == 1 From 30c8b210dd7eeed012bd9077ed40c8b00677a293 Mon Sep 17 00:00:00 2001 From: Xuan Date: Mon, 13 Jul 2020 09:29:34 +0800 Subject: [PATCH 4/7] update code style --- Source/Charts/Utils/ChartUtils.swift | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Source/Charts/Utils/ChartUtils.swift b/Source/Charts/Utils/ChartUtils.swift index 96e1d61e6c..ad888232da 100644 --- a/Source/Charts/Utils/ChartUtils.swift +++ b/Source/Charts/Utils/ChartUtils.swift @@ -20,7 +20,8 @@ import CoreGraphics import Cocoa #endif -extension Array where Element == CGRect { +extension Array where Element == CGRect +{ func union() -> Element? { guard !isEmpty else { return nil } @@ -124,11 +125,13 @@ extension Double extension CGPoint { - static var infinite: CGPoint { + static var infinite: CGPoint + { return CGPoint(x: CGFloat.infinity, y: CGFloat.infinity) } - var isInfinite: Bool { + var isInfinite: Bool + { return x.isInfinite || y.isInfinite } From be3ddb351e8ccd7ecf11e29deeda18b99f90e65f Mon Sep 17 00:00:00 2001 From: Xuan Date: Mon, 27 Jul 2020 10:07:32 +0800 Subject: [PATCH 5/7] Update BarChartViewController.swift rename `setup(_ dataSet: BarChartDataSet)` to `setupBarGradient(_ dataSet: BarChartDataSet)` --- ChartsDemo-iOS/Swift/Demos/BarChartViewController.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ChartsDemo-iOS/Swift/Demos/BarChartViewController.swift b/ChartsDemo-iOS/Swift/Demos/BarChartViewController.swift index 330c115d2e..9edf9477ea 100644 --- a/ChartsDemo-iOS/Swift/Demos/BarChartViewController.swift +++ b/ChartsDemo-iOS/Swift/Demos/BarChartViewController.swift @@ -125,7 +125,7 @@ class BarChartViewController: DemoBaseViewController { } if let set = chartView.data?.dataSets.first as? BarChartDataSet { - setup(set) + setupBarGradient(set) set.replaceEntries(yVals) chartView.data?.notifyDataChanged() chartView.notifyDataSetChanged() @@ -134,7 +134,7 @@ class BarChartViewController: DemoBaseViewController { set.colors = ChartColorTemplates.material() set.drawValuesEnabled = false - setup(set) + setupBarGradient(set) let data = BarChartData(dataSet: set) data.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 10)!) @@ -145,7 +145,7 @@ class BarChartViewController: DemoBaseViewController { // chartView.setNeedsDisplay() } - private func setup(_ dataSet: BarChartDataSet) { + private func setupBarGradient(_ dataSet: BarChartDataSet) { if dataSet.drawBarGradientEnabled { dataSet.colors = [.black, .red, .white] dataSet.gradientPositions = [0, 40, 100] @@ -163,7 +163,7 @@ class BarChartViewController: DemoBaseViewController { .compactMap { $0 as? BarChartDataSet } .forEach { (set) in set.drawBarGradientEnabled = !set.drawBarGradientEnabled - setup(set) + setupBarGradient(set) } chartView.setNeedsDisplay() default: From 204f66e7a125fdb9b28069195b0bd9d1575b6b45 Mon Sep 17 00:00:00 2001 From: Xuan Date: Mon, 27 Jul 2020 10:09:04 +0800 Subject: [PATCH 6/7] Update BarChartRenderer.swift rename `drawDefaultBars` to `drawNormalBars` --- Source/Charts/Renderers/BarChartRenderer.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Charts/Renderers/BarChartRenderer.swift b/Source/Charts/Renderers/BarChartRenderer.swift index 1b39700067..21a717957f 100644 --- a/Source/Charts/Renderers/BarChartRenderer.swift +++ b/Source/Charts/Renderers/BarChartRenderer.swift @@ -403,7 +403,7 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer } else { - drawDefaultBars(context: context, dataSet: dataSet, dateSetIndex: index, buffer: buffer) + drawNormalBars(context: context, dataSet: dataSet, dateSetIndex: index, buffer: buffer) } } @@ -489,7 +489,7 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer } } - private func drawDefaultBars(context: CGContext, dataSet: IBarChartDataSet, dateSetIndex index: Int, buffer: BarChartRenderer.Buffer) + private func drawNormalBars(context: CGContext, dataSet: IBarChartDataSet, dateSetIndex index: Int, buffer: BarChartRenderer.Buffer) { let drawBorder = dataSet.barBorderWidth > 0 let isSingleColor = dataSet.colors.count == 1 From e59ade133c3976ec19e3ebba7bd3c986bee4003e Mon Sep 17 00:00:00 2001 From: Ilya Laryionau Date: Mon, 27 Jul 2020 11:20:48 +0300 Subject: [PATCH 7/7] Add accessibilityOrderedElements support --- .../Charts/Renderers/BarChartRenderer.swift | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/Source/Charts/Renderers/BarChartRenderer.swift b/Source/Charts/Renderers/BarChartRenderer.swift index 21a717957f..39333f1c57 100644 --- a/Source/Charts/Renderers/BarChartRenderer.swift +++ b/Source/Charts/Renderers/BarChartRenderer.swift @@ -399,7 +399,7 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer if dataSet.drawBarGradientEnabled { - drawGradientBars(context: context, dataSet: dataSet, buffer: buffer, matrix: valueToPixelMatrix) + drawGradientBars(context: context, dataSet: dataSet, dateSetIndex: index, buffer: buffer, matrix: valueToPixelMatrix) } else { @@ -407,7 +407,7 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer } } - private func drawGradientBars(context: CGContext, dataSet: IBarChartDataSet, buffer: BarChartRenderer.Buffer, matrix: CGAffineTransform) + private func drawGradientBars(context: CGContext, dataSet: IBarChartDataSet, dateSetIndex index: Int, buffer: BarChartRenderer.Buffer, matrix: CGAffineTransform) { guard let gradientPositions = dataSet.gradientPositions else @@ -467,7 +467,11 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer return } - for barRect in buffer.rects + // In case the chart is stacked, we need to accomodate individual bars within accessibilityOrdereredElements + let isStacked = dataSet.isStacked + let stackSize = isStacked ? dataSet.stackSize : 1 + + for (barIndex, barRect) in buffer.rects.enumerated() { context.saveGState() defer { context.restoreGState() } @@ -486,6 +490,21 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer context.setLineWidth(dataSet.barBorderWidth) context.stroke(barRect) } + + // Create and append the corresponding accessibility element to accessibilityOrderedElements + if let chart = dataProvider as? BarChartView + { + let element = createAccessibleElement(withIndex: barIndex, + container: chart, + dataSet: dataSet, + dataSetIndex: index, + stackSize: stackSize) + { (element) in + element.accessibilityFrame = barRect + } + + accessibilityOrderedElements[barIndex/stackSize].append(element) + } } }