From c14ed458edeb0a0042c56199eb1eb4f37d9cd085 Mon Sep 17 00:00:00 2001 From: Oleg <> Date: Thu, 28 Mar 2024 21:58:54 +0300 Subject: [PATCH 1/3] Add logic to make cornerRadius on BarChart --- .../Standard/BarChartDataSet.swift | 6 ++++++ .../Interfaces/BarChartDataSetProtocol.swift | 10 ++++++++++ Source/Charts/Renderers/BarChartRenderer.swift | 16 +++++++++++++--- .../Renderers/HorizontalBarChartRenderer.swift | 11 +++++++++-- 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift b/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift index 999e94e443..2dee2ab262 100644 --- a/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift +++ b/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift @@ -51,6 +51,12 @@ open class BarChartDataSet: BarLineScatterCandleBubbleChartDataSet, BarChartData /// the overall entry count, including counting each stack-value individually private var _entryCountStacks = 0 + /// the corner radius applied to each data set + public var cornerRadius: CGFloat = 0.0 + + /// array of corners to be rounded + open var roundedCorners: UIRectCorner = [] + /// Calculates the total number of entries this DataSet represents, including /// stacks. All values belonging to a stack are calculated separately. private func calcEntryCountIncludingStacks(entries: [BarChartDataEntry]) diff --git a/Source/Charts/Data/Interfaces/BarChartDataSetProtocol.swift b/Source/Charts/Data/Interfaces/BarChartDataSetProtocol.swift index 3ea0903cce..7d1ab45548 100644 --- a/Source/Charts/Data/Interfaces/BarChartDataSetProtocol.swift +++ b/Source/Charts/Data/Interfaces/BarChartDataSetProtocol.swift @@ -12,6 +12,10 @@ import Foundation import CoreGraphics +#if canImport(UIKit) +import UIKit +#endif + @objc public protocol BarChartDataSetProtocol: BarLineScatterCandleBubbleChartDataSetProtocol { @@ -39,4 +43,10 @@ public protocol BarChartDataSetProtocol: BarLineScatterCandleBubbleChartDataSetP /// array of labels used to describe the different values of the stacked bars var stackLabels: [String] { get set } + + /// the corner radius applied to each data set + var cornerRadius: CGFloat { get set } + + /// array of corners to be rounded + var roundedCorners: UIRectCorner { get set } } diff --git a/Source/Charts/Renderers/BarChartRenderer.swift b/Source/Charts/Renderers/BarChartRenderer.swift index 2aa69a828f..eb2eebe819 100644 --- a/Source/Charts/Renderers/BarChartRenderer.swift +++ b/Source/Charts/Renderers/BarChartRenderer.swift @@ -351,7 +351,11 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer guard viewPortHandler.isInBoundsRight(barRect.origin.x) else { break } context.setFillColor(dataSet.barShadowColor.cgColor) - context.fill(barRect) + + let bezierPath = UIBezierPath(roundedRect: barRect, byRoundingCorners: dataSet.roundedCorners, + cornerRadii: .init(width: dataSet.cornerRadius, height: dataSet.cornerRadius)) + context.addPath(bezierPath.cgPath) + context.drawPath(using: .fill) } } @@ -379,7 +383,10 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer context.setFillColor(dataSet.color(atIndex: j).cgColor) } - context.fill(barRect) + let bezierPath = UIBezierPath(roundedRect: barRect, byRoundingCorners: dataSet.roundedCorners, + cornerRadii: .init(width: dataSet.cornerRadius, height: dataSet.cornerRadius)) + context.addPath(bezierPath.cgPath) + context.drawPath(using: .fill) if drawBorder { @@ -744,7 +751,10 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer setHighlightDrawPos(highlight: high, barRect: barRect) - context.fill(barRect) + let bezierPath = UIBezierPath(roundedRect: barRect, byRoundingCorners: set.roundedCorners, + cornerRadii: .init(width: set.cornerRadius, height: set.cornerRadius)) + context.addPath(bezierPath.cgPath) + context.drawPath(using: .fill) } } } diff --git a/Source/Charts/Renderers/HorizontalBarChartRenderer.swift b/Source/Charts/Renderers/HorizontalBarChartRenderer.swift index d2fed814f3..588f45bc95 100644 --- a/Source/Charts/Renderers/HorizontalBarChartRenderer.swift +++ b/Source/Charts/Renderers/HorizontalBarChartRenderer.swift @@ -228,7 +228,11 @@ open class HorizontalBarChartRenderer: BarChartRenderer _barShadowRectBuffer.size.width = viewPortHandler.contentWidth context.setFillColor(dataSet.barShadowColor.cgColor) - context.fill(_barShadowRectBuffer) + + let bezierPath = UIBezierPath(roundedRect: _barShadowRectBuffer, byRoundingCorners: dataSet.roundedCorners, + cornerRadii: .init(width: dataSet.cornerRadius, height: dataSet.cornerRadius)) + context.addPath(bezierPath.cgPath) + context.drawPath(using: .fill) } } @@ -265,7 +269,10 @@ open class HorizontalBarChartRenderer: BarChartRenderer context.setFillColor(dataSet.color(atIndex: j).cgColor) } - context.fill(barRect) + let bezierPath = UIBezierPath(roundedRect: barRect, byRoundingCorners: dataSet.roundedCorners, + cornerRadii: .init(width: dataSet.cornerRadius, height: dataSet.cornerRadius)) + context.addPath(bezierPath.cgPath) + context.drawPath(using: .fill) if drawBorder { From 1b9bc5bf3517f24750a266aa8331478d9852c4bd Mon Sep 17 00:00:00 2001 From: Oleg <> Date: Wed, 27 Mar 2024 05:01:16 +0300 Subject: [PATCH 2/3] Add inverted corners for negative values --- .../Standard/BarChartDataSet.swift | 24 ++++++++++++++++++- .../Interfaces/BarChartDataSetProtocol.swift | 3 +++ .../Charts/Renderers/BarChartRenderer.swift | 21 +++++++++++++--- .../HorizontalBarChartRenderer.swift | 13 ++++++++-- 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift b/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift index 2dee2ab262..63894b55d3 100644 --- a/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift +++ b/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift @@ -55,7 +55,29 @@ open class BarChartDataSet: BarLineScatterCandleBubbleChartDataSet, BarChartData public var cornerRadius: CGFloat = 0.0 /// array of corners to be rounded - open var roundedCorners: UIRectCorner = [] + open var roundedCorners: UIRectCorner = [] { + didSet { + var invertedCorners: UIRectCorner = [] + if roundedCorners.contains(.topLeft) { + invertedCorners.insert(.bottomLeft) + } + if roundedCorners.contains(.topRight) { + invertedCorners.insert(.bottomRight) + } + if roundedCorners.contains(.bottomLeft) { + invertedCorners.insert(.topLeft) + } + if roundedCorners.contains(.bottomRight) { + invertedCorners.insert(.topRight) + } + if roundedCorners.contains(.allCorners) { + invertedCorners.insert(.allCorners) + } + roundedCornersInverted = invertedCorners + } + } + + open var roundedCornersInverted: UIRectCorner = [] /// Calculates the total number of entries this DataSet represents, including /// stacks. All values belonging to a stack are calculated separately. diff --git a/Source/Charts/Data/Interfaces/BarChartDataSetProtocol.swift b/Source/Charts/Data/Interfaces/BarChartDataSetProtocol.swift index 7d1ab45548..fcd9277f6a 100644 --- a/Source/Charts/Data/Interfaces/BarChartDataSetProtocol.swift +++ b/Source/Charts/Data/Interfaces/BarChartDataSetProtocol.swift @@ -49,4 +49,7 @@ public protocol BarChartDataSetProtocol: BarLineScatterCandleBubbleChartDataSetP /// array of corners to be rounded var roundedCorners: UIRectCorner { get set } + + /// array of corners to be rounded + var roundedCornersInverted: UIRectCorner { get } } diff --git a/Source/Charts/Renderers/BarChartRenderer.swift b/Source/Charts/Renderers/BarChartRenderer.swift index eb2eebe819..7d5e5bfd95 100644 --- a/Source/Charts/Renderers/BarChartRenderer.swift +++ b/Source/Charts/Renderers/BarChartRenderer.swift @@ -352,7 +352,13 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer context.setFillColor(dataSet.barShadowColor.cgColor) - let bezierPath = UIBezierPath(roundedRect: barRect, byRoundingCorners: dataSet.roundedCorners, + var roundedCorners = dataSet.roundedCorners + if let i = buffer.firstIndex(of: barRect), + let entry = dataSet.entryForIndex(i), + entry.y < 0 { + roundedCorners = dataSet.roundedCornersInverted + } + let bezierPath = UIBezierPath(roundedRect: barRect, byRoundingCorners: roundedCorners, cornerRadii: .init(width: dataSet.cornerRadius, height: dataSet.cornerRadius)) context.addPath(bezierPath.cgPath) context.drawPath(using: .fill) @@ -383,7 +389,12 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer context.setFillColor(dataSet.color(atIndex: j).cgColor) } - let bezierPath = UIBezierPath(roundedRect: barRect, byRoundingCorners: dataSet.roundedCorners, + var roundedCorners = dataSet.roundedCorners + if let entry = dataSet.entryForIndex(j), + entry.y < 0 { + roundedCorners = dataSet.roundedCornersInverted + } + let bezierPath = UIBezierPath(roundedRect: barRect, byRoundingCorners: roundedCorners, cornerRadii: .init(width: dataSet.cornerRadius, height: dataSet.cornerRadius)) context.addPath(bezierPath.cgPath) context.drawPath(using: .fill) @@ -751,7 +762,11 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer setHighlightDrawPos(highlight: high, barRect: barRect) - let bezierPath = UIBezierPath(roundedRect: barRect, byRoundingCorners: set.roundedCorners, + var roundedCorners = set.roundedCorners + if e.y < 0 { + roundedCorners = set.roundedCornersInverted + } + let bezierPath = UIBezierPath(roundedRect: barRect, byRoundingCorners: roundedCorners, cornerRadii: .init(width: set.cornerRadius, height: set.cornerRadius)) context.addPath(bezierPath.cgPath) context.drawPath(using: .fill) diff --git a/Source/Charts/Renderers/HorizontalBarChartRenderer.swift b/Source/Charts/Renderers/HorizontalBarChartRenderer.swift index 588f45bc95..32116acd6d 100644 --- a/Source/Charts/Renderers/HorizontalBarChartRenderer.swift +++ b/Source/Charts/Renderers/HorizontalBarChartRenderer.swift @@ -229,7 +229,11 @@ open class HorizontalBarChartRenderer: BarChartRenderer context.setFillColor(dataSet.barShadowColor.cgColor) - let bezierPath = UIBezierPath(roundedRect: _barShadowRectBuffer, byRoundingCorners: dataSet.roundedCorners, + var roundedCorners = dataSet.roundedCorners + if e.x < 0 { + roundedCorners = dataSet.roundedCornersInverted + } + let bezierPath = UIBezierPath(roundedRect: _barShadowRectBuffer, byRoundingCorners: roundedCorners, cornerRadii: .init(width: dataSet.cornerRadius, height: dataSet.cornerRadius)) context.addPath(bezierPath.cgPath) context.drawPath(using: .fill) @@ -269,7 +273,12 @@ open class HorizontalBarChartRenderer: BarChartRenderer context.setFillColor(dataSet.color(atIndex: j).cgColor) } - let bezierPath = UIBezierPath(roundedRect: barRect, byRoundingCorners: dataSet.roundedCorners, + var roundedCorners = dataSet.roundedCorners + if let entry = dataSet.entryForIndex(j), + entry.x < 0 { + roundedCorners = dataSet.roundedCornersInverted + } + let bezierPath = UIBezierPath(roundedRect: barRect, byRoundingCorners: roundedCorners, cornerRadii: .init(width: dataSet.cornerRadius, height: dataSet.cornerRadius)) context.addPath(bezierPath.cgPath) context.drawPath(using: .fill) From 1c925209baebb7b834223f9873e474a059bdb51b Mon Sep 17 00:00:00 2001 From: Oleg <> Date: Fri, 29 Mar 2024 05:50:11 +0300 Subject: [PATCH 3/3] Make roundedCornersInverted setter private for better protocol --- .../Charts/Data/Implementations/Standard/BarChartDataSet.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift b/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift index 63894b55d3..069c3a7ed0 100644 --- a/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift +++ b/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift @@ -77,7 +77,7 @@ open class BarChartDataSet: BarLineScatterCandleBubbleChartDataSet, BarChartData } } - open var roundedCornersInverted: UIRectCorner = [] + open private(set) var roundedCornersInverted: UIRectCorner = [] /// Calculates the total number of entries this DataSet represents, including /// stacks. All values belonging to a stack are calculated separately.