diff --git a/ChartsDemo/Classes/DemoBaseViewController.m b/ChartsDemo/Classes/DemoBaseViewController.m index 3a142369fd..33a6fe60c8 100644 --- a/ChartsDemo/Classes/DemoBaseViewController.m +++ b/ChartsDemo/Classes/DemoBaseViewController.m @@ -143,6 +143,28 @@ - (void)handleOption:(NSString *)key forChartView:(ChartViewBase *)chartView [chartView setNeedsDisplay]; } + + if ([key isEqualToString:@"toggleRoundedBarsAllCorners"]) + { + ((BarChartView *)chartView).drawRoundedBarEnabled = YES; + + [chartView setNeedsDisplay]; + } + + if ([key isEqualToString:@"toggleRoundedBarsTopCorners"]) + { + ((BarChartView *)chartView).drawRoundedBarEnabled = YES; + + for (id set in chartView.data.dataSets) + { + if ([set conformsToProtocol:@protocol(IBarChartDataSet)]) + { + set.barRoundingCorners = UIRectCornerTopLeft | UIRectCornerTopRight; + } + } + + [chartView setNeedsDisplay]; + } } #pragma mark - Actions diff --git a/ChartsDemo/Classes/Demos/BarChartViewController.m b/ChartsDemo/Classes/Demos/BarChartViewController.m index cdf8583cec..b0dc8c0029 100644 --- a/ChartsDemo/Classes/Demos/BarChartViewController.m +++ b/ChartsDemo/Classes/Demos/BarChartViewController.m @@ -42,6 +42,8 @@ - (void)viewDidLoad @{@"key": @"toggleAutoScaleMinMax", @"label": @"Toggle auto scale min/max"}, @{@"key": @"toggleData", @"label": @"Toggle Data"}, @{@"key": @"toggleBarBorders", @"label": @"Show Bar Borders"}, + @{@"key": @"toggleRoundedBarsAllCorners", @"label": @"All Corners Rounded"}, + @{@"key": @"toggleRoundedBarsTopCorners", @"label": @"Top Corners Rounded"}, ]; [self setupBarLineChartView:_chartView]; diff --git a/Source/Charts/Charts/BarChartView.swift b/Source/Charts/Charts/BarChartView.swift index a9e060b48b..08bc347e10 100644 --- a/Source/Charts/Charts/BarChartView.swift +++ b/Source/Charts/Charts/BarChartView.swift @@ -21,6 +21,9 @@ open class BarChartView: BarLineChartViewBase, BarChartDataProvider /// if set to true, a grey area is drawn behind each bar that indicates the maximum value fileprivate var _drawBarShadowEnabled = false + /// if set to true, a rounded rectangle with the corners is drawn on each bar + fileprivate var _drawRoundedBarEnabled = false + internal override func initialize() { super.initialize() @@ -159,6 +162,17 @@ open class BarChartView: BarLineChartViewBase, BarChartDataProvider setNeedsDisplay() } } + + /// if set to true, a rounded rectangle with the corners is drawn on each bar + open var drawRoundedBarEnabled: Bool + { + get { return _drawRoundedBarEnabled } + set + { + _drawRoundedBarEnabled = newValue + setNeedsDisplay() + } + } /// Adds half of the bar width to each side of the x-axis range in order to allow the bars of the barchart to be fully displayed. /// **default**: false @@ -180,4 +194,7 @@ open class BarChartView: BarLineChartViewBase, BarChartDataProvider /// - returns: `true` if drawing shadows (maxvalue) for each bar is enabled, `false` ifnot open var isDrawBarShadowEnabled: Bool { return drawBarShadowEnabled } + + /// - returns: `true` if drawing rounded bars is enabled, `false` ifnot + open var isDrawRoundedBarEnabled: Bool { return drawRoundedBarEnabled } } diff --git a/Source/Charts/Charts/CombinedChartView.swift b/Source/Charts/Charts/CombinedChartView.swift index 0fce9e8d94..3ffe1767ce 100644 --- a/Source/Charts/Charts/CombinedChartView.swift +++ b/Source/Charts/Charts/CombinedChartView.swift @@ -195,6 +195,13 @@ open class CombinedChartView: BarLineChartViewBase, CombinedChartDataProvider get { return (renderer as! CombinedChartRenderer!).drawBarShadowEnabled } set { (renderer as! CombinedChartRenderer!).drawBarShadowEnabled = newValue } } + + /// if set to true, a rounded rectangle with the corners is drawn on each bar + open var drawRoundedBarEnabled: Bool + { + get { return (renderer as! CombinedChartRenderer!).drawRoundedBarEnabled } + set { (renderer as! CombinedChartRenderer!).drawRoundedBarEnabled = newValue } + } /// - returns: `true` if drawing values above bars is enabled, `false` ifnot open var isDrawValueAboveBarEnabled: Bool { return (renderer as! CombinedChartRenderer!).drawValueAboveBarEnabled } @@ -222,4 +229,7 @@ open class CombinedChartView: BarLineChartViewBase, CombinedChartDataProvider /// - returns: `true` the highlight is be full-bar oriented, `false` ifsingle-value open var isHighlightFullBarEnabled: Bool { return highlightFullBarEnabled } + + /// - returns: `true` if drawing rounded bars is enabled, `false` ifnot + open var isDrawRoundedBarEnabled: Bool { return drawRoundedBarEnabled } } diff --git a/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift b/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift index bba2cac4ad..49b165ffab 100644 --- a/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift +++ b/Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift @@ -146,6 +146,11 @@ open class BarChartDataSet: BarLineScatterCandleBubbleChartDataSet, IBarChartDat /// the color drawing borders around the bars. open var barBorderColor = NSUIColor.black + #if !os(OSX) + /// the option rounding bar corners + open var barRoundingCorners: UIRectCorner = .allCorners + #endif + /// the alpha value (transparency) that is used for drawing the highlight indicator bar. min = 0.0 (fully transparent), max = 1.0 (fully opaque) open var highlightAlpha = CGFloat(120.0 / 255.0) diff --git a/Source/Charts/Data/Interfaces/IBarChartDataSet.swift b/Source/Charts/Data/Interfaces/IBarChartDataSet.swift index 6f5cad081c..e2d2a863a6 100644 --- a/Source/Charts/Data/Interfaces/IBarChartDataSet.swift +++ b/Source/Charts/Data/Interfaces/IBarChartDataSet.swift @@ -34,6 +34,11 @@ public protocol IBarChartDataSet: IBarLineScatterCandleBubbleChartDataSet /// the color drawing borders around the bars. var barBorderColor: NSUIColor { get set } + #if !os(OSX) + /// the option rounding bar corners + var barRoundingCorners: UIRectCorner { get set } + #endif + /// the alpha value (transparency) that is used for drawing the highlight indicator bar. min = 0.0 (fully transparent), max = 1.0 (fully opaque) var highlightAlpha: CGFloat { get set } diff --git a/Source/Charts/Interfaces/BarChartDataProvider.swift b/Source/Charts/Interfaces/BarChartDataProvider.swift index e1d0a8d0b5..fb0eae961c 100644 --- a/Source/Charts/Interfaces/BarChartDataProvider.swift +++ b/Source/Charts/Interfaces/BarChartDataProvider.swift @@ -18,6 +18,7 @@ public protocol BarChartDataProvider: BarLineScatterCandleBubbleChartDataProvide var barData: BarChartData? { get } var isDrawBarShadowEnabled: Bool { get } + var isDrawRoundedBarEnabled: Bool { get } var isDrawValueAboveBarEnabled: Bool { 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 579810f844..b5a7c88a47 100644 --- a/Source/Charts/Renderers/BarChartRenderer.swift +++ b/Source/Charts/Renderers/BarChartRenderer.swift @@ -310,14 +310,36 @@ 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 + + if dataProvider.isDrawRoundedBarEnabled { - context.setStrokeColor(borderColor.cgColor) - context.setLineWidth(borderWidth) - context.stroke(barRect) + let cornerRadius = CGSize(width: barRect.width / 2.0, height: barRect.width / 2.0) + #if os(OSX) + let bezierPath = NSBezierPath(roundedRect: barRect, xRadius: cornerRadius.width, yRadius: cornerRadius.height) + context.addPath(bezierPath.cgPath) + #else + let bezierPath = UIBezierPath(roundedRect: barRect, byRoundingCorners: dataSet.barRoundingCorners, cornerRadii: cornerRadius) + context.addPath(bezierPath.cgPath) + #endif + context.fillPath() + + if drawBorder + { + bezierPath.lineWidth = borderWidth + borderColor.setStroke() + bezierPath.stroke() + } + } + else + { + context.fill(barRect) + + if drawBorder + { + context.setStrokeColor(borderColor.cgColor) + context.setLineWidth(borderWidth) + context.stroke(barRect) + } } } @@ -574,7 +596,7 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer let set = barData.getDataSetByIndex(high.dataSetIndex) as? IBarChartDataSet, set.isHighlightEnabled else { continue } - + if let e = set.entryForXValue(high.x, closestToY: high.y) as? BarChartDataEntry { if !isInBoundsX(entry: e, dataSet: set) @@ -617,7 +639,22 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer setHighlightDrawPos(highlight: high, barRect: barRect) - context.fill(barRect) + if dataProvider.isDrawRoundedBarEnabled + { + let cornerRadius = CGSize(width: barRect.width / 2.0, height: barRect.width / 2.0) + #if os(OSX) + let bezierPath = NSBezierPath(roundedRect: barRect, xRadius: cornerRadius.width, yRadius: cornerRadius.height) + context.addPath(bezierPath.cgPath) + #else + let bezierPath = UIBezierPath(roundedRect: barRect, byRoundingCorners: set.barRoundingCorners, cornerRadii: cornerRadius) + context.addPath(bezierPath.cgPath) + #endif + context.fillPath() + } + else + { + context.fill(barRect) + } } } diff --git a/Source/Charts/Renderers/CombinedChartRenderer.swift b/Source/Charts/Renderers/CombinedChartRenderer.swift index 7c24d1cdee..93da083527 100644 --- a/Source/Charts/Renderers/CombinedChartRenderer.swift +++ b/Source/Charts/Renderers/CombinedChartRenderer.swift @@ -22,6 +22,9 @@ open class CombinedChartRenderer: DataRenderer /// if set to true, a grey area is drawn behind each bar that indicates the maximum value open var drawBarShadowEnabled = false + /// if set to true, a rounded rectangle with the corners is drawn on each bar + open var drawRoundedBarEnabled = false + internal var _renderers = [DataRenderer]() internal var _drawOrder: [CombinedChartView.DrawOrder] = [.bar, .bubble, .line, .candle, .scatter] diff --git a/Source/Charts/Utils/Platform.swift b/Source/Charts/Utils/Platform.swift index 00baaec3ef..c85184cc77 100644 --- a/Source/Charts/Utils/Platform.swift +++ b/Source/Charts/Utils/Platform.swift @@ -515,6 +515,54 @@ types are aliased to either their UI* implementation (on iOS) or their NS* imple } } } + + extension NSBezierPath + { + var cgPath: CGPath + { + let mutablePath = CGMutablePath() + var points = [CGPoint](repeating: .zero, count: 3) + for i in 0 ..< elementCount + { + let type = element(at: i, associatedPoints: &points) + switch type + { + case .moveToBezierPathElement: + mutablePath.move( + to: CGPoint( + x: points[0].x, + y: points[0].y + ) + ) + case .lineToBezierPathElement: + mutablePath.addLine( + to: CGPoint( + x: points[0].x, + y: points[0].y + ) + ) + case .curveToBezierPathElement: + mutablePath.addCurve( + to: CGPoint( + x: points[2].x, + y: points[2].y + ), + control1: CGPoint( + x: points[0].x, + y: points[0].y + ), + control2: CGPoint( + x: points[1].x, + y: points[1].y + ) + ) + case .closePathBezierPathElement: + mutablePath.closeSubpath() + } + } + return mutablePath + } + } extension NSString { diff --git a/Source/ChartsRealm/Data/RealmBarDataSet.swift b/Source/ChartsRealm/Data/RealmBarDataSet.swift index 3d1b600ecc..9c2810170a 100644 --- a/Source/ChartsRealm/Data/RealmBarDataSet.swift +++ b/Source/ChartsRealm/Data/RealmBarDataSet.swift @@ -214,6 +214,11 @@ open class RealmBarDataSet: RealmBarLineScatterCandleBubbleDataSet, IBarChartDat /// the color drawing borders around the bars. open var barBorderColor = NSUIColor(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 1.0) + #if !os(OSX) + /// the option rounding bar corners + open var barRoundingCorners: UIRectCorner = .allCorners + #endif + /// the alpha value (transparency) that is used for drawing the highlight indicator bar. min = 0.0 (fully transparent), max = 1.0 (fully opaque) open var highlightAlpha = CGFloat(120.0 / 255.0)