Skip to content

Commit

Permalink
Made all renderers extensible, everything is public now (Closes #357)
Browse files Browse the repository at this point in the history
Along the way:
Safer access to nullable variables,
some loops converted for support for Swift 3.0
  • Loading branch information
danielgindi committed Jan 24, 2016
1 parent 646d9c3 commit 64ce56e
Show file tree
Hide file tree
Showing 20 changed files with 770 additions and 583 deletions.
2 changes: 1 addition & 1 deletion Charts/Charts.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,6 @@
5B759ED41A9F98A90039D97F /* Renderers */ = {
isa = PBXGroup;
children = (
5B6A54711AA5DCA8000F57C2 /* ChartAxisRendererBase.swift */,
5B6A54961AA66AD2000F57C2 /* BarChartRenderer.swift */,
55E3565A1ADC63EB00A57971 /* BubbleChartRenderer.swift */,
5B6A54941AA66AC0000F57C2 /* CandleStickChartRenderer.swift */,
Expand All @@ -550,6 +549,7 @@
5B6A54861AA669F4000F57C2 /* RadarChartRenderer.swift */,
5B6A546F1AA5DB34000F57C2 /* ChartRendererBase.swift */,
5B6A54841AA669C9000F57C2 /* ScatterChartRenderer.swift */,
5B6A54711AA5DCA8000F57C2 /* ChartAxisRendererBase.swift */,
5B6A54731AA5DEDC000F57C2 /* ChartXAxisRenderer.swift */,
5B6A54751AA5DEE3000F57C2 /* ChartXAxisRendererBarChart.swift */,
5B6A547B1AA5DF02000F57C2 /* ChartXAxisRendererHorizontalBarChart.swift */,
Expand Down
77 changes: 51 additions & 26 deletions Charts/Classes/Renderers/BarChartRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,27 @@ public class BarChartRenderer: ChartDataRendererBase

for (var i = 0; i < barData.dataSetCount; i++)
{
let set = barData.getDataSetByIndex(i)
guard let set = barData.getDataSetByIndex(i) else { continue }

if set !== nil && set!.isVisible && set.entryCount > 0
if set.isVisible && set.entryCount > 0
{
if !(set is IBarChartDataSet)
{
fatalError("Datasets for BarChartRenderer must conform to IBarChartDataset")
}

drawDataSet(context: context, dataSet: set as! IBarChartDataSet, index: i)
}
}
}

internal func drawDataSet(context context: CGContext, dataSet: IBarChartDataSet, index: Int)
public func drawDataSet(context context: CGContext, dataSet: IBarChartDataSet, index: Int)
{
guard let dataProvider = dataProvider, barData = dataProvider.barData else { return }
guard let
dataProvider = dataProvider,
barData = dataProvider.barData,
animator = animator
else { return }

CGContextSaveGState(context)

Expand All @@ -58,13 +67,13 @@ public class BarChartRenderer: ChartDataRendererBase
let containsStacks = dataSet.isStacked
let isInverted = dataProvider.isInverted(dataSet.axisDependency)
let barWidth: CGFloat = 0.5
let phaseY = _animator.phaseY
let phaseY = animator.phaseY
var barRect = CGRect()
var barShadow = CGRect()
var y: Double

// do the drawing
for (var j = 0, count = Int(ceil(CGFloat(dataSet.entryCount) * _animator.phaseX)); j < count; j++)
for (var j = 0, count = Int(ceil(CGFloat(dataSet.entryCount) * animator.phaseX)); j < count; j++)
{
guard let e = dataSet.entryForIndex(j) as? BarChartDataEntry else { continue }

Expand Down Expand Up @@ -233,7 +242,7 @@ public class BarChartRenderer: ChartDataRendererBase
}

/// Prepares a bar for being highlighted.
internal func prepareBarHighlight(x x: CGFloat, y1: Double, y2: Double, barspacehalf: CGFloat, trans: ChartTransformer, inout rect: CGRect)
public func prepareBarHighlight(x x: CGFloat, y1: Double, y2: Double, barspacehalf: CGFloat, trans: ChartTransformer, inout rect: CGRect)
{
let barWidth: CGFloat = 0.5

Expand All @@ -247,15 +256,19 @@ public class BarChartRenderer: ChartDataRendererBase
rect.size.width = right - left
rect.size.height = bottom - top

trans.rectValueToPixel(&rect, phaseY: _animator.phaseY)
trans.rectValueToPixel(&rect, phaseY: animator?.phaseY ?? 1.0)
}

public override func drawValues(context context: CGContext)
{
// if values are drawn
if (passesCheck())
{
guard let dataProvider = dataProvider, barData = dataProvider.barData else { return }
guard let
dataProvider = dataProvider,
barData = dataProvider.barData,
animator = animator
else { return }

var dataSets = barData.dataSets

Expand All @@ -266,7 +279,7 @@ public class BarChartRenderer: ChartDataRendererBase

for (var dataSetIndex = 0, count = barData.dataSetCount; dataSetIndex < count; dataSetIndex++)
{
let dataSet = dataSets[dataSetIndex] as! IBarChartDataSet
guard let dataSet = dataSets[dataSetIndex] as? IBarChartDataSet else { continue }

if !dataSet.isDrawValuesEnabled || dataSet.entryCount == 0
{
Expand All @@ -290,22 +303,29 @@ public class BarChartRenderer: ChartDataRendererBase

let valueTextColor = dataSet.valueTextColor

let formatter = dataSet.valueFormatter
guard let formatter = dataSet.valueFormatter else { continue }

let trans = dataProvider.getTransformer(dataSet.axisDependency)

let phaseY = _animator.phaseY
let phaseY = animator.phaseY
let dataSetCount = barData.dataSetCount
let groupSpace = barData.groupSpace

// if only single values are drawn (sum)
if (!dataSet.isStacked)
{
for (var j = 0, count = Int(ceil(CGFloat(dataSet.entryCount) * _animator.phaseX)); j < count; j++)
for (var j = 0, count = Int(ceil(CGFloat(dataSet.entryCount) * animator.phaseX)); j < count; j++)
{
guard let e = dataSet.entryForIndex(j) as? BarChartDataEntry else { continue }

let valuePoint = trans.getTransformedValueBarChart(entry: e, xIndex: e.xIndex, dataSetIndex: dataSetIndex, phaseY: phaseY, dataSetCount: dataSetCount, groupSpace: groupSpace)
let valuePoint = trans.getTransformedValueBarChart(
entry: e,
xIndex: e.xIndex,
dataSetIndex: dataSetIndex,
phaseY: phaseY,
dataSetCount: dataSetCount,
groupSpace: groupSpace
)

if (!viewPortHandler.isInBoundsRight(valuePoint.x))
{
Expand All @@ -321,7 +341,7 @@ public class BarChartRenderer: ChartDataRendererBase
let val = e.value

drawValue(context: context,
value: formatter!.stringFromNumber(val)!,
value: formatter.stringFromNumber(val)!,
xPos: valuePoint.x,
yPos: valuePoint.y + (val >= 0.0 ? posOffset : negOffset),
font: valueFont,
Expand All @@ -333,7 +353,7 @@ public class BarChartRenderer: ChartDataRendererBase
{
// if we have stacks

for (var j = 0, count = Int(ceil(CGFloat(dataSet.entryCount) * _animator.phaseX)); j < count; j++)
for (var j = 0, count = Int(ceil(CGFloat(dataSet.entryCount) * animator.phaseX)); j < count; j++)
{
guard let e = dataSet.entryForIndex(j) as? BarChartDataEntry else { continue }

Expand All @@ -356,7 +376,7 @@ public class BarChartRenderer: ChartDataRendererBase
}

drawValue(context: context,
value: formatter!.stringFromNumber(e.value)!,
value: formatter.stringFromNumber(e.value)!,
xPos: valuePoint.x,
yPos: valuePoint.y + (e.value >= 0.0 ? posOffset : negOffset),
font: valueFont,
Expand Down Expand Up @@ -389,7 +409,7 @@ public class BarChartRenderer: ChartDataRendererBase
negY -= value
}

transformed.append(CGPoint(x: 0.0, y: CGFloat(y) * _animator.phaseY))
transformed.append(CGPoint(x: 0.0, y: CGFloat(y) * animator.phaseY))
}

trans.pointValuesToPixel(&transformed)
Expand All @@ -410,7 +430,7 @@ public class BarChartRenderer: ChartDataRendererBase
}

drawValue(context: context,
value: formatter!.stringFromNumber(vals[k])!,
value: formatter.stringFromNumber(vals[k])!,
xPos: x,
yPos: y,
font: valueFont,
Expand All @@ -425,7 +445,7 @@ public class BarChartRenderer: ChartDataRendererBase
}

/// Draws a value at the specified x and y position.
internal func drawValue(context context: CGContext, value: String, xPos: CGFloat, yPos: CGFloat, font: UIFont, align: NSTextAlignment, color: UIColor)
public func drawValue(context context: CGContext, value: String, xPos: CGFloat, yPos: CGFloat, font: UIFont, align: NSTextAlignment, color: UIColor)
{
ChartUtils.drawText(context: context, text: value, point: CGPoint(x: xPos, y: yPos), align: align, attributes: [NSFontAttributeName: font, NSForegroundColorAttributeName: color])
}
Expand All @@ -439,7 +459,11 @@ public class BarChartRenderer: ChartDataRendererBase

public override func drawHighlighted(context context: CGContext, indices: [ChartHighlight])
{
guard let dataProvider = dataProvider, barData = dataProvider.barData else { return }
guard let
dataProvider = dataProvider,
barData = dataProvider.barData,
animator = animator
else { return }

CGContextSaveGState(context)

Expand All @@ -453,9 +477,10 @@ public class BarChartRenderer: ChartDataRendererBase
let index = h.xIndex

let dataSetIndex = h.dataSetIndex
let set = barData.getDataSetByIndex(dataSetIndex) as! IBarChartDataSet!

if (set === nil || !set.isHighlightEnabled)
guard let set = barData.getDataSetByIndex(dataSetIndex) as? IBarChartDataSet else { continue }

if (!set.isHighlightEnabled)
{
continue
}
Expand All @@ -468,7 +493,7 @@ public class BarChartRenderer: ChartDataRendererBase
CGContextSetAlpha(context, set.highlightAlpha)

// check outofbounds
if (CGFloat(index) < (CGFloat(dataProvider.chartXMax) * _animator.phaseX) / CGFloat(setCount))
if (CGFloat(index) < (CGFloat(dataProvider.chartXMax) * animator.phaseX) / CGFloat(setCount))
{
let e = set.entryForXIndex(index) as! BarChartDataEntry!

Expand Down Expand Up @@ -506,7 +531,7 @@ public class BarChartRenderer: ChartDataRendererBase
CGContextSetAlpha(context, 1.0)

// distance between highlight arrow and bar
let offsetY = _animator.phaseY * 0.07
let offsetY = animator.phaseY * 0.07

CGContextSaveGState(context)

Expand All @@ -516,7 +541,7 @@ public class BarChartRenderer: ChartDataRendererBase
let arrowWidth = set.barSpace / 2.0
let arrowHeight = arrowWidth * xToYRel

let yArrow = (y1 > -y2 ? y1 : y1) * Double(_animator.phaseY)
let yArrow = (y1 > -y2 ? y1 : y1) * Double(animator.phaseY)

_highlightArrowPtsBuffer[0].x = CGFloat(x) + 0.4
_highlightArrowPtsBuffer[0].y = CGFloat(yArrow) + offsetY
Expand Down
65 changes: 40 additions & 25 deletions Charts/Classes/Renderers/BubbleChartRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,26 +47,31 @@ public class BubbleChartRenderer: ChartDataRendererBase
private var _pointBuffer = CGPoint()
private var _sizeBuffer = [CGPoint](count: 2, repeatedValue: CGPoint())

internal func drawDataSet(context context: CGContext, dataSet: IBubbleChartDataSet)
public func drawDataSet(context context: CGContext, dataSet: IBubbleChartDataSet)
{
guard let dataProvider = dataProvider else { return }
guard let
dataProvider = dataProvider,
animator = animator
else { return }

let trans = dataProvider.getTransformer(dataSet.axisDependency)

let phaseX = _animator.phaseX
let phaseY = _animator.phaseY
let phaseX = animator.phaseX
let phaseY = animator.phaseY

let entryCount = dataSet.entryCount

let valueToPixelMatrix = trans.valueToPixelMatrix

CGContextSaveGState(context)

let entryFrom = dataSet.entryForXIndex(_minX)
let entryTo = dataSet.entryForXIndex(_maxX)
guard let
entryFrom = dataSet.entryForXIndex(self.minX),
entryTo = dataSet.entryForXIndex(self.maxX)
else { return }

let minx = max(dataSet.entryIndex(entry: entryFrom!), 0)
let maxx = min(dataSet.entryIndex(entry: entryTo!) + 1, entryCount)
let minx = max(dataSet.entryIndex(entry: entryFrom), 0)
let maxx = min(dataSet.entryIndex(entry: entryTo) + 1, entryCount)

_sizeBuffer[0].x = 0.0
_sizeBuffer[0].y = 0.0
Expand Down Expand Up @@ -125,15 +130,19 @@ public class BubbleChartRenderer: ChartDataRendererBase

public override func drawValues(context context: CGContext)
{
guard let dataProvider = dataProvider, bubbleData = dataProvider.bubbleData else { return }
guard let
dataProvider = dataProvider,
bubbleData = dataProvider.bubbleData,
animator = animator
else { return }

// if values are drawn
if (bubbleData.yValCount < Int(ceil(CGFloat(dataProvider.maxVisibleValueCount) * viewPortHandler.scaleX)))
{
let dataSets = bubbleData.dataSets as! [IBubbleChartDataSet]
guard let dataSets = bubbleData.dataSets as? [IBubbleChartDataSet] else { return }

let phaseX = _animator.phaseX
let phaseY = _animator.phaseY
let phaseX = animator.phaseX
let phaseY = animator.phaseY

var pt = CGPoint()

Expand All @@ -147,18 +156,20 @@ public class BubbleChartRenderer: ChartDataRendererBase
let alpha = phaseX == 1 ? phaseY : phaseX
let valueTextColor = dataSet.valueTextColor.colorWithAlphaComponent(alpha)

let formatter = dataSet.valueFormatter
guard let formatter = dataSet.valueFormatter else { continue }

let trans = dataProvider.getTransformer(dataSet.axisDependency)
let valueToPixelMatrix = trans.valueToPixelMatrix

let entryCount = dataSet.entryCount

let entryFrom = dataSet.entryForXIndex(_minX)
let entryTo = dataSet.entryForXIndex(_maxX)
guard let
entryFrom = dataSet.entryForXIndex(self.minX),
entryTo = dataSet.entryForXIndex(self.maxX)
else { continue }

let minx = max(dataSet.entryIndex(entry: entryFrom!), 0)
let maxx = min(dataSet.entryIndex(entry: entryTo!) + 1, entryCount)
let minx = max(dataSet.entryIndex(entry: entryFrom), 0)
let maxx = min(dataSet.entryIndex(entry: entryTo) + 1, entryCount)

for (var j = minx; j < maxx; j++)
{
Expand All @@ -178,7 +189,7 @@ public class BubbleChartRenderer: ChartDataRendererBase
continue
}

let text = formatter!.stringFromNumber(e.size)
let text = formatter.stringFromNumber(e.size)

// Larger font for larger bubbles?
let valueFont = dataSet.valueFont
Expand All @@ -204,24 +215,28 @@ public class BubbleChartRenderer: ChartDataRendererBase

public override func drawHighlighted(context context: CGContext, indices: [ChartHighlight])
{
guard let dataProvider = dataProvider, bubbleData = dataProvider.bubbleData else { return }
guard let
dataProvider = dataProvider,
bubbleData = dataProvider.bubbleData,
animator = animator
else { return }

CGContextSaveGState(context)

let phaseX = _animator.phaseX
let phaseY = _animator.phaseY
let phaseX = animator.phaseX
let phaseY = animator.phaseY

for indice in indices
{
let dataSet = bubbleData.getDataSetByIndex(indice.dataSetIndex) as! IBubbleChartDataSet!
guard let dataSet = bubbleData.getDataSetByIndex(indice.dataSetIndex) as? IBubbleChartDataSet else { continue }

if (dataSet === nil || !dataSet.isHighlightEnabled)
if (!dataSet.isHighlightEnabled)
{
continue
}

let entryFrom = dataSet.entryForXIndex(_minX)
let entryTo = dataSet.entryForXIndex(_maxX)
let entryFrom = dataSet.entryForXIndex(self.minX)
let entryTo = dataSet.entryForXIndex(self.maxX)

let minx = max(dataSet.entryIndex(entry: entryFrom!), 0)
let maxx = min(dataSet.entryIndex(entry: entryTo!) + 1, dataSet.entryCount)
Expand Down
Loading

0 comments on commit 64ce56e

Please sign in to comment.