Skip to content

Commit

Permalink
Merge pull request ChartsOrg#1 from zmchristensen/barchart-icon
Browse files Browse the repository at this point in the history
Barchart Icons
  • Loading branch information
zmchristensen committed Dec 21, 2015
2 parents 3f88894 + 0b8e7d1 commit 3cf0e88
Show file tree
Hide file tree
Showing 10 changed files with 263 additions and 6 deletions.
16 changes: 16 additions & 0 deletions Charts/Classes/Charts/BarChartView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ public class BarChartView: BarLineChartViewBase, BarChartDataProvider
/// if set to true, all values are drawn above their bars, instead of below their top
private var _drawValueAboveBarEnabled = true

/// if set to true, all icons are drawn above their bars, instead of below their top
private var _drawIconAboveBarEnabled = true

/// if set to true, a grey area is darawn behind each bar that indicates the maximum value
private var _drawBarShadowEnabled = false

Expand Down Expand Up @@ -147,6 +150,17 @@ public class BarChartView: BarLineChartViewBase, BarChartDataProvider
}
}

/// if set to true, all icons are drawn above their bars, instead of below their top
public var drawIconAboveBarEnabled: Bool
{
get { return _drawIconAboveBarEnabled; }
set
{
_drawIconAboveBarEnabled = newValue
setNeedsDisplay()
}
}

/// if set to true, a grey area is drawn behind each bar that indicates the maximum value
public var drawBarShadowEnabled: Bool
{
Expand All @@ -168,6 +182,8 @@ public class BarChartView: BarLineChartViewBase, BarChartDataProvider
/// - returns: true if drawing values above bars is enabled, false if not
public var isDrawValueAboveBarEnabled: Bool { return drawValueAboveBarEnabled }

public var isDrawIconAboveBarEnabled: Bool { return drawIconAboveBarEnabled }

/// - returns: true if drawing shadows (maxvalue) for each bar is enabled, false if not
public var isDrawBarShadowEnabled: Bool { return drawBarShadowEnabled }
}
10 changes: 10 additions & 0 deletions Charts/Classes/Charts/CombinedChartView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,13 @@ public class CombinedChartView: BarLineChartViewBase, LineChartDataProvider, Bar
get { return (renderer as! CombinedChartRenderer!).drawValueAboveBarEnabled }
set { (renderer as! CombinedChartRenderer!).drawValueAboveBarEnabled = newValue }
}

/// if set to true, all icons are drawn above their bars, instead of below their top
public var drawIconAboveBarEnabled: Bool
{
get { return (renderer as! CombinedChartRenderer!).drawIconAboveBarEnabled }
set { (renderer as! CombinedChartRenderer!).drawIconAboveBarEnabled = newValue }
}

/// if set to true, a grey area is darawn behind each bar that indicates the maximum value
public var drawBarShadowEnabled: Bool
Expand All @@ -209,6 +216,9 @@ public class CombinedChartView: BarLineChartViewBase, LineChartDataProvider, Bar
/// - returns: true if drawing values above bars is enabled, false if not
public var isDrawValueAboveBarEnabled: Bool { return (renderer as! CombinedChartRenderer!).drawValueAboveBarEnabled; }

/// - returns: true if drawing icons above bars is enabled, false if not
public var isDrawIconAboveBarEnabled: Bool { return (renderer as! CombinedChartRenderer!).drawIconAboveBarEnabled; }

/// - returns: true if drawing shadows (maxvalue) for each bar is enabled, false if not
public var isDrawBarShadowEnabled: Bool { return (renderer as! CombinedChartRenderer!).drawBarShadowEnabled; }

Expand Down
6 changes: 6 additions & 0 deletions Charts/Classes/Data/ChartDataSet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class ChartDataSet: NSObject
public var label: String? = "DataSet"
public var visible = true
public var drawValuesEnabled = true
public var drawIconsEnabled = true

/// the color used for the value-text
public var valueTextColor: UIColor = UIColor.blackColor()
Expand Down Expand Up @@ -505,6 +506,11 @@ public class ChartDataSet: NSObject
return drawValuesEnabled
}

public var isDrawIconsEnabled: Bool
{
return drawIconsEnabled
}

/// Checks if this DataSet contains the specified Entry.
/// - returns: true if contains the entry, false if not.
public func contains(e: ChartDataEntry) -> Bool
Expand Down
1 change: 1 addition & 0 deletions Charts/Classes/Interfaces/BarChartDataProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ public protocol BarChartDataProvider: BarLineScatterCandleBubbleChartDataProvide

var isDrawBarShadowEnabled: Bool { get }
var isDrawValueAboveBarEnabled: Bool { get }
var isDrawIconAboveBarEnabled: Bool { get }
var isDrawHighlightArrowEnabled: Bool { get }
}
189 changes: 188 additions & 1 deletion Charts/Classes/Renderers/BarChartRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -425,9 +425,196 @@ public class BarChartRenderer: ChartDataRendererBase
ChartUtils.drawText(context: context, text: value, point: CGPoint(x: xPos, y: yPos), align: align, attributes: [NSFontAttributeName: font, NSForegroundColorAttributeName: color])
}

internal func drawImage(context context: CGContext, image: UIImage, point: CGPoint, expectedSize: CGSize)
{
ChartUtils.drawImage(context: context, image: image, point: point, expectedSize: expectedSize)
}

public override func drawExtras(context context: CGContext)
{

// if values are drawn
if (passesCheck())
{
guard let dataProvider = dataProvider, barData = dataProvider.barData else { return }

var dataSets = barData.dataSets

let drawValueAboveBar = dataProvider.isDrawIconAboveBarEnabled

var posOffset: CGFloat
var negOffset: CGFloat

let imageProportion: CGFloat = 0.8
let dataSetCountScalar: CGFloat = barData.dataSetCount > 1 ? CGFloat(barData.dataSetCount) + 1.0 : CGFloat(barData.dataSetCount)

for (var i = 0, count = barData.dataSetCount; i < count; i++)
{
let dataSet = dataSets[i] as! BarChartDataSet
let barSpace = dataSet.barSpace

if !dataSet.isDrawIconsEnabled || dataSet.entryCount == 0
{
continue
}


let trans = dataProvider.getTransformer(dataSet.axisDependency)

var entries = dataSet.yVals as! [BarChartDataEntry]

var valuePoints = getTransformedValues(trans: trans, entries: entries, dataSetIndex: i)

// calculate the image size
var imageDimension: CGFloat = 0
if valuePoints.count > 1 {
imageDimension = imageProportion * (1 - barSpace) * (valuePoints[1].x - valuePoints[0].x)
}
else if valuePoints.count == 1 {
imageDimension = imageProportion * (1 - barSpace) * (valuePoints[0].x)
}

imageDimension = imageDimension / dataSetCountScalar


// calculate the correct offset depending on the draw position of the value
let valueOffsetPlus: CGFloat = 2.5 + imageDimension / 2
posOffset = (drawValueAboveBar ? -(valueOffsetPlus) : valueOffsetPlus)
negOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueOffsetPlus))

// if only single values are drawn (sum)
if (!dataSet.isStacked)
{
for (var j = 0, count = Int(ceil(CGFloat(valuePoints.count) * _animator.phaseX)); j < count; j++)
{
if (!viewPortHandler.isInBoundsRight(valuePoints[j].x))
{
break
}

if (!viewPortHandler.isInBoundsY(valuePoints[j].y)
|| !viewPortHandler.isInBoundsLeft(valuePoints[j].x))
{
continue
}

if let imageName = entries[j].data as! String! {
if let image = UIImage(named: imageName) {
let expectedSize = CGSizeMake(imageDimension, imageDimension)

drawImage(context: context,
image: image,
point: CGPoint(
x: valuePoints[j].x,
y: valuePoints[j].y + (entries[j].value >= 0.0 ? posOffset : negOffset)
),
expectedSize: expectedSize)
}
}
}
}
else
{
// if we have stacks
for (var j = 0, count = Int(ceil(CGFloat(valuePoints.count) * _animator.phaseX)); j < count; j++)
{
let e = entries[j]

let values = e.values

// we still draw stacked bars, but there is one non-stacked in between
if (values == nil)
{
if (!viewPortHandler.isInBoundsRight(valuePoints[j].x))
{
break
}

if (!viewPortHandler.isInBoundsY(valuePoints[j].y)
|| !viewPortHandler.isInBoundsLeft(valuePoints[j].x))
{
continue
}

if let imageName = entries[j].data as! String! {
if let image = UIImage(named: imageName) {
let expectedSize = CGSizeMake(imageDimension, imageDimension)

drawImage(context: context,
image: image,
point: CGPoint(
x: valuePoints[j].x,
y: valuePoints[j].y
),
expectedSize: expectedSize)
}
}
}
else
{
// draw stack values
let vals = values!
var transformed = [CGPoint]()

var posY = 0.0
var negY = -e.negativeSum

for (var k = 0; k < vals.count; k++)
{
let value = vals[k]
var y: Double

if value >= 0.0
{
posY += value
y = posY
}
else
{
y = negY
negY -= value
}

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

trans.pointValuesToPixel(&transformed)

for (var k = 0; k < transformed.count; k++)
{
let x = valuePoints[j].x
let y = transformed[k].y + (vals[k] >= 0 ? posOffset : negOffset)

if (!viewPortHandler.isInBoundsRight(x))
{
break
}

if (!viewPortHandler.isInBoundsY(y) || !viewPortHandler.isInBoundsLeft(x))
{
continue
}

if let dataArray = entries[j].data as! [String]! {
if let imageName = dataArray[k] as String! {
if let image = UIImage(named: imageName) {
let expectedSize = CGSizeMake(imageDimension, imageDimension)

drawImage(context: context,
image: image,
point: CGPoint(
x: x,
y: y
),
expectedSize: expectedSize)
}
}
}
}
}
}
}
}
}
}

private var _highlightArrowPtsBuffer = [CGPoint](count: 3, repeatedValue: CGPoint())
Expand Down
3 changes: 3 additions & 0 deletions Charts/Classes/Renderers/CombinedChartRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ public class CombinedChartRenderer: ChartDataRendererBase
/// if set to true, all values are drawn above their bars, instead of below their top
public var drawValueAboveBarEnabled = true

/// if set to true, all icons are drawn above their bars, instead of below their top
public var drawIconAboveBarEnabled = true

/// if set to true, a grey area is darawn behind each bar that indicates the maximum value
public var drawBarShadowEnabled = true

Expand Down
24 changes: 24 additions & 0 deletions Charts/Classes/Utils/ChartUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,30 @@ public class ChartUtils
drawMultilineText(context: context, text: text, knownTextSize: rect.size, point: point, attributes: attributes, constrainedToSize: constrainedToSize, anchor: anchor, angleRadians: angleRadians)
}

public class func drawImage(context context: CGContext, image: UIImage, point: CGPoint, expectedSize: CGSize)
{
var drawOffset = CGPoint()
drawOffset.x += point.x
drawOffset.x -= expectedSize.width / 2
drawOffset.y += point.y
drawOffset.y -= expectedSize.height / 2

UIGraphicsPushContext(context)

if image.size.width != expectedSize.width && image.size.height != expectedSize.height {
UIGraphicsBeginImageContextWithOptions(expectedSize, false, 0.0)
image.drawInRect(CGRect(origin: CGPointZero, size: expectedSize))
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
scaledImage.drawAtPoint(drawOffset)
}
else {
image.drawAtPoint(drawOffset)
}

UIGraphicsPopContext()
}

/// - returns: an angle between 0.0 < 360.0 (not less than zero, less than 360)
internal class func normalizedAngleFromAngle(var angle: CGFloat) -> CGFloat
{
Expand Down
4 changes: 3 additions & 1 deletion ChartsDemo/Classes/Demos/BarChartViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@ - (void)setDataCount:(int)count range:(double)range
{
double mult = (range + 1);
double val = (double) (arc4random_uniform(mult));
[yVals addObject:[[BarChartDataEntry alloc] initWithValue:val xIndex:i]];
BarChartDataEntry *entry = [[BarChartDataEntry alloc] initWithValue:val xIndex:i];
entry.data = @"[email protected]";
[yVals addObject: entry];
}

BarChartDataSet *set1 = [[BarChartDataSet alloc] initWithYVals:yVals label:@"DataSet"];
Expand Down
12 changes: 9 additions & 3 deletions ChartsDemo/Classes/Demos/MultipleBarChartViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,19 @@ - (void)setDataCount:(int)count range:(double)range
for (int i = 0; i < count; i++)
{
double val = (double) (arc4random_uniform(mult) + 3.0);
[yVals1 addObject:[[BarChartDataEntry alloc] initWithValue:val xIndex:i]];
BarChartDataEntry *entry = [[BarChartDataEntry alloc] initWithValue:val xIndex:i];
entry.data = @"[email protected]";
[yVals1 addObject: entry];

val = (double) (arc4random_uniform(mult) + 3.0);
[yVals2 addObject:[[BarChartDataEntry alloc] initWithValue:val xIndex:i]];
BarChartDataEntry *entry2 = [[BarChartDataEntry alloc] initWithValue:val xIndex:i];
entry2.data = @"[email protected]";
[yVals2 addObject: entry2];

val = (double) (arc4random_uniform(mult) + 3.0);
[yVals3 addObject:[[BarChartDataEntry alloc] initWithValue:val xIndex:i]];
BarChartDataEntry *entry3 = [[BarChartDataEntry alloc] initWithValue:val xIndex:i];
entry3.data = @"[email protected]";
[yVals3 addObject: entry3];
}

BarChartDataSet *set1 = [[BarChartDataSet alloc] initWithYVals:yVals1 label:@"Company A"];
Expand Down
4 changes: 3 additions & 1 deletion ChartsDemo/Classes/Demos/StackedBarChartViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ - (void)setDataCount:(int)count range:(double)range
double val2 = (double) (arc4random_uniform(mult) + mult / 3);
double val3 = (double) (arc4random_uniform(mult) + mult / 3);

[yVals addObject:[[BarChartDataEntry alloc] initWithValues:@[@(val1), @(val2), @(val3)] xIndex:i]];
BarChartDataEntry *entry = [[BarChartDataEntry alloc] initWithValues:@[@(val1), @(val2), @(val3)] xIndex:i];
entry.data = [NSArray arrayWithObjects: @"[email protected]", @"[email protected]", @"[email protected]", nil];
[yVals addObject: entry];
}

BarChartDataSet *set1 = [[BarChartDataSet alloc] initWithYVals:yVals label:@"Statistics Vienna 2014"];
Expand Down

0 comments on commit 3cf0e88

Please sign in to comment.