Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update the renderers with dedicated atomic rendering methods in order to make rendering overrides easier to implement. #4297

Closed
wants to merge 10 commits into from
19 changes: 13 additions & 6 deletions ChartsDemo-iOS/Swift/Demos/CandleStickChartViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,22 @@ class CandleStickChartViewController: DemoBaseViewController {
override func optionTapped(_ option: Option) {
switch option {
case .toggleShadowColorSameAsCandle:
for case let set as CandleChartDataSet in chartView.data! {
set.shadowColorSameAsCandle = !set.shadowColorSameAsCandle
if let datasets = chartView.data?.dataSets as? [CandleChartDataSet] {
for set in datasets {
set.shadowColorSameAsCandle.toggle()
}

chartView.notifyDataSetChanged()
}
chartView.notifyDataSetChanged()

case .toggleShowCandleBar:
for set in chartView.data!.dataSets as! [CandleChartDataSet] {
set.showCandleBar = !set.showCandleBar
if let datasets = chartView.data?.dataSets as? [CandleChartDataSet] {
for set in datasets {
set.showCandleBar.toggle()
}

chartView.notifyDataSetChanged()
}
chartView.notifyDataSetChanged()
default:
super.handleOption(option, forChartView: chartView)
}
Expand Down
130 changes: 95 additions & 35 deletions Source/Charts/Renderers/BarChartRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer
for i in barData.indices
{
guard let set = barData[i] as? BarChartDataSetProtocol else {
fatalError("Datasets for BarChartRenderer must conform to IBarChartDataset")
fatalError("Datasets for BarChartRenderer must conform to BarChartDataSetProtocol")
}

guard set.isVisible else { continue }
Expand All @@ -303,7 +303,6 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer

let borderWidth = dataSet.barBorderWidth
let borderColor = dataSet.barBorderColor
let drawBorder = borderWidth > 0.0

context.saveGState()
defer { context.restoreGState() }
Expand Down Expand Up @@ -336,8 +335,7 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer
_barShadowRectBuffer.origin.y = viewPortHandler.contentTop
_barShadowRectBuffer.size.height = viewPortHandler.contentHeight

context.setFillColor(dataSet.barShadowColor.cgColor)
context.fill(_barShadowRectBuffer)
renderShadow(with: dataSet.barShadowColor, for: _barShadowRectBuffer, in: context, dataSet: dataSet, entry: e)
}
}

Expand All @@ -346,47 +344,43 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer
// draw the bar shadow before the values
if dataProvider.isDrawBarShadowEnabled
{
for barRect in buffer where viewPortHandler.isInBoundsLeft(barRect.origin.x + barRect.size.width)
for (index, barRect) in buffer.enumerated() where viewPortHandler.isInBoundsLeft(barRect.origin.x + barRect.size.width)
{
guard viewPortHandler.isInBoundsRight(barRect.origin.x) else { break }

context.setFillColor(dataSet.barShadowColor.cgColor)
context.fill(barRect)

renderShadow(with: dataSet.barShadowColor,
for: barRect,
in: context,
dataSet: dataSet,
entry: dataSet.entryForIndex(index) as? BarChartDataEntry)
}
}

let isSingleColor = dataSet.colors.count == 1

if isSingleColor
{
context.setFillColor(dataSet.color(atIndex: 0).cgColor)
}


// 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 j in buffer.indices
{
let barRect = buffer[j]

guard viewPortHandler.isInBoundsLeft(barRect.origin.x + barRect.size.width) else { continue }
guard viewPortHandler.isInBoundsRight(barRect.origin.x) else { break }

if !isSingleColor
{
// 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)
renderFill(with: dataSet.color(atIndex: isSingleColor ? 0 : j),
for: barRect,
in: context,
dataSet: dataSet,
entry: dataSet.entryForIndex(j) as? BarChartDataEntry)

if drawBorder
{
context.setStrokeColor(borderColor.cgColor)
context.setLineWidth(borderWidth)
context.stroke(barRect)
}
renderBorder(with: borderColor,
width: borderWidth,
for: barRect,
in: context,
dataSet: dataSet,
entry: dataSet.entryForIndex(j) as? BarChartDataEntry)

// Create and append the corresponding accessibility element to accessibilityOrderedElements
if let chart = dataProvider as? BarChartView
Expand Down Expand Up @@ -709,10 +703,6 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer
guard isInBoundsX(entry: e, dataSet: set) else { continue }

let trans = dataProvider.getTransformer(forAxis: set.axisDependency)

context.setFillColor(set.highlightColor.cgColor)
context.setAlpha(set.highlightAlpha)

let isStack = high.stackIndex >= 0 && e.isStacked

let y1: Double
Expand Down Expand Up @@ -740,10 +730,8 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer
}

prepareBarHighlight(x: e.x, y1: y1, y2: y2, barWidthHalf: barData.barWidth / 2.0, trans: trans, rect: &barRect)

setHighlightDrawPos(highlight: high, barRect: barRect)

context.fill(barRect)
render(highlight: high, with: barRect, in: context, dataSet: set, entry: e)
}
}
}
Expand Down Expand Up @@ -831,4 +819,76 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer

return element
}

// MARK: - Rendering override points -

/// Render the fill of a (stacked) bar.
///
/// - Parameters:
/// - color: the color to fill the bar with.
/// - rect: the rectangle of the (stacked) bar.
/// - context: the drawing context.
/// - dataset: the dataset that is being rendered.
/// - entry: the entry that is being rendered.
@objc open func renderFill(with color: NSUIColor, for rect: CGRect, in context: CGContext, dataSet: BarChartDataSetProtocol, entry: BarChartDataEntry?) {
context.saveGState()
context.setFillColor(color.cgColor)
context.fill(rect)
context.restoreGState()
}

/// Render the border of a (stacked) bar.
///
/// - Parameters:
/// - color: the border color.
/// - lineWidth: the line width width of the border.
/// - rect: the rectangle of the (stacked) bar.
/// - context: the drawing context.
/// - dataset: the dataset that is being rendered.
/// - entry: the entry that is being rendered.
@objc open func renderBorder(with color: NSUIColor,
width lineWidth: CGFloat,
for rect: CGRect,
in context: CGContext,
dataSet: BarChartDataSetProtocol,
entry: BarChartDataEntry?) {
guard lineWidth > 0 else { return }

context.saveGState()
context.setStrokeColor(color.cgColor)
context.setLineWidth(lineWidth)
context.stroke(rect)
context.restoreGState()
}

/// Render the (stacked) highlight.
///
/// - Parameters:
/// - highlight: the highlight to render.
/// - rect: the rectangle of the (stacked) bar.
/// - context: the drawing context.
/// - dataset: the dataset that is being rendered.
/// - entry: the entry that is being rendered.
@objc open func render(highlight: Highlight, with rect: CGRect, in context: CGContext, dataSet: BarChartDataSetProtocol, entry: BarChartDataEntry) {
context.saveGState()
context.setFillColor(dataSet.highlightColor.cgColor)
context.setAlpha(dataSet.highlightAlpha)
context.fill(rect)
context.restoreGState()
}

/// Render the (stacked) shadow.
///
/// - Parameters:
/// - color: the shadow color.
/// - rect: the rectangle of the (stacked) bar.
/// - context: the drawing context.
/// - dataset: the dataset that is being rendered.
/// - entry: the entry that is being rendered.
@objc open func renderShadow(with color: NSUIColor, for rect: CGRect, in context: CGContext, dataSet: BarChartDataSetProtocol, entry: BarChartDataEntry?) {
context.saveGState()
context.setFillColor(color.cgColor)
context.fill(rect)
context.restoreGState()
}
}
59 changes: 54 additions & 5 deletions Source/Charts/Renderers/BubbleChartRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,7 @@ open class BubbleChartRenderer: BarLineScatterCandleBubbleRenderer
height: shapeSize
)

context.setFillColor(color.cgColor)
context.fillEllipse(in: rect)
renderFill(with: color, for: rect, in: context, dataSet: dataSet, dataEntry: entry)

// Create and append the corresponding accessibility element to accessibilityOrderedElements
if let chart = dataProvider as? BubbleChartView
Expand Down Expand Up @@ -304,9 +303,13 @@ open class BubbleChartRenderer: BarLineScatterCandleBubbleRenderer
width: shapeSize,
height: shapeSize)

context.setLineWidth(dataSet.highlightCircleWidth)
context.setStrokeColor(color.cgColor)
context.strokeEllipse(in: rect)
render(highlight: high,
with: color,
for: rect,
lineWidth: dataSet.highlightCircleWidth,
in: context,
dataSet: dataSet,
entry: entry)

high.setDraw(x: _pointBuffer.x, y: _pointBuffer.y)
}
Expand Down Expand Up @@ -356,4 +359,50 @@ open class BubbleChartRenderer: BarLineScatterCandleBubbleRenderer

return element
}

// MARK: - Rendering override points -

/// Render bubble fill.
///
/// - Parameters:
/// - color: the fill color of the bubble.
/// - rect: the rectangle for which to render the bubble.
/// - context: the drawing context.
/// - dataSet: the dataset that is being rendered.
/// - dataEntry: the entry that is being rendered.
@objc open func renderFill(with color: NSUIColor,
for rect: CGRect,
in context: CGContext,
dataSet: BubbleChartDataSetProtocol,
dataEntry: BubbleChartDataEntry) {
context.saveGState()
context.setFillColor(color.cgColor)
context.fillEllipse(in: rect)
context.restoreGState()
}


/// Render a highlighted bubble.
///
/// - Parameters:
/// - highlight: the hightligh to render.
/// - color: the color of the highlighted bubble.
/// - rect: the rectangle for which to render the bubble.
/// - lineWidth: the width of the border.
/// - context: the drawing context.
/// - dataSet: the dataset dat is being rendered.
/// - entry: the entry that is being rendered.
@objc open func render(highlight: Highlight,
with color: NSUIColor,
for rect: CGRect,
lineWidth: CGFloat,
in context: CGContext,
dataSet: BubbleChartDataSetProtocol,
entry: BubbleChartDataEntry) {
context.saveGState()
context.setLineWidth(lineWidth)
context.setStrokeColor(color.cgColor)
context.strokeEllipse(in: rect)
context.restoreGState()
}
}
Loading