diff --git a/Source/Charts/Animation/ChartAnimationEasing.swift b/Source/Charts/Animation/ChartAnimationEasing.swift index a6453d9e0c..1744111ee2 100644 --- a/Source/Charts/Animation/ChartAnimationEasing.swift +++ b/Source/Charts/Animation/ChartAnimationEasing.swift @@ -211,25 +211,25 @@ internal struct EasingFunctions internal static let EaseInSine = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in var position: TimeInterval = elapsed / duration - return Double( -cos(position * Double.pi / 2) + 1.0 ) + return -cos(position * Double.pi / 2) + 1.0 } internal static let EaseOutSine = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in var position: TimeInterval = elapsed / duration - return Double( sin(position * Double.pi / 2) ) + return sin(position * Double.pi / 2) } internal static let EaseInOutSine = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in var position: TimeInterval = elapsed / duration - return Double( -0.5 * (cos(Double.pi * position) - 1.0) ) + return -0.5 * (cos(Double.pi * position) - 1.0) } internal static let EaseInExpo = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in - return (elapsed == 0) ? 0.0 : Double(pow(2.0, 10.0 * (elapsed / duration - 1.0))) + return (elapsed == 0) ? 0.0 : pow(2.0, 10.0 * (elapsed / duration - 1.0)) } internal static let EaseOutExpo = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in - return (elapsed == duration) ? 1.0 : (-Double(pow(2.0, -10.0 * elapsed / duration)) + 1.0) + return (elapsed == duration) ? 1.0 : -(pow(2.0, -10.0 * elapsed / duration)) + 1.0 } internal static let EaseInOutExpo = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in @@ -245,32 +245,32 @@ internal struct EasingFunctions var position: TimeInterval = elapsed / (duration / 2.0) if position < 1.0 { - return Double( 0.5 * pow(2.0, 10.0 * (position - 1.0)) ) + return 0.5 * pow(2.0, 10.0 * (position - 1.0)) } position = position - 1.0 - return Double( 0.5 * (-pow(2.0, -10.0 * position) + 2.0) ) + return 0.5 * (-pow(2.0, -10.0 * position) + 2.0) } internal static let EaseInCirc = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in var position = Double(elapsed / duration) - return -(Double(sqrt(1.0 - position * position)) - 1.0) + return -((sqrt(1.0 - position * position)) - 1.0) } internal static let EaseOutCirc = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in var position = Double(elapsed / duration) position -= 1.0 - return Double( sqrt(1 - position * position) ) + return sqrt(1 - position * position) } internal static let EaseInOutCirc = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in var position: TimeInterval = elapsed / (duration / 2.0) if position < 1.0 { - return Double( -0.5 * (sqrt(1.0 - position * position) - 1.0) ) + return -0.5 * (sqrt(1.0 - (position * position)) - 1.0) } position -= 2.0 - return Double( 0.5 * (sqrt(1.0 - position * position) + 1.0) ) + return 0.5 * (sqrt(1.0 - (position * position)) + 1.0) } internal static let EaseInElastic = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in @@ -288,7 +288,7 @@ internal struct EasingFunctions var p = duration * 0.3 var s = p / (2.0 * Double.pi) * asin(1.0) position -= 1.0 - return Double( -(pow(2.0, 10.0 * position) * sin((position * duration - s) * (2.0 * Double.pi) / p)) ) + return -(pow(2.0, 10.0 * position) * sin((position * duration - s) * (2.0 * Double.pi) / p)) } internal static let EaseOutElastic = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in @@ -305,7 +305,7 @@ internal struct EasingFunctions var p = duration * 0.3 var s = p / (2.0 * Double.pi) * asin(1.0) - return Double( pow(2.0, -10.0 * position) * sin((position * duration - s) * (2.0 * Double.pi) / p) + 1.0 ) + return pow(2.0, -10.0 * position) * sin((position * duration - s) * (2.0 * Double.pi) / p) + 1.0 } internal static let EaseInOutElastic = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in @@ -325,23 +325,23 @@ internal struct EasingFunctions if position < 1.0 { position -= 1.0 - return Double( -0.5 * (pow(2.0, 10.0 * position) * sin((position * duration - s) * (2.0 * Double.pi) / p)) ) + return -0.5 * (pow(2.0, 10.0 * position) * sin((position * duration - s) * (2.0 * Double.pi) / p)) } position -= 1.0 - return Double( pow(2.0, -10.0 * position) * sin((position * duration - s) * (2.0 * Double.pi) / p) * 0.5 + 1.0 ) + return pow(2.0, -10.0 * position) * sin((position * duration - s) * (2.0 * Double.pi) / p) * 0.5 + 1.0 } internal static let EaseInBack = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in let s: TimeInterval = 1.70158 var position: TimeInterval = elapsed / duration - return Double( position * position * ((s + 1.0) * position - s) ) + return position * position * ((s + 1.0) * position - s) } internal static let EaseOutBack = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in let s: TimeInterval = 1.70158 var position: TimeInterval = elapsed / duration position -= 1.0 - return Double( position * position * ((s + Double(1.0)) * position + s) + Double(1.0) ) + return position * position * ((s + 1.0) * position + s) + 1.0 } internal static let EaseInOutBack = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in @@ -350,11 +350,11 @@ internal struct EasingFunctions if position < 1.0 { s *= 1.525 - return Double( 0.5 * (position * position * ((s + 1.0) * position - s)) ) + return 0.5 * (position * position * ((s + 1.0) * position - s)) } s *= 1.525 position -= 2.0 - return Double( 0.5 * (position * position * ((s + 1.0) * position + s) + 2.0) ) + return 0.5 * (position * position * ((s + 1.0) * position + s) + 2.0) } internal static let EaseInBounce = { (elapsed: TimeInterval, duration: TimeInterval) -> Double in @@ -365,22 +365,22 @@ internal struct EasingFunctions var position: TimeInterval = elapsed / duration if position < (1.0 / 2.75) { - return Double( 7.5625 * position * position ) + return 7.5625 * position * position } else if position < (2.0 / 2.75) { position -= (1.5 / 2.75) - return Double( 7.5625 * position * position + 0.75 ) + return 7.5625 * position * position + 0.75 } else if position < (2.5 / 2.75) { position -= (2.25 / 2.75) - return Double( 7.5625 * position * position + 0.9375 ) + return 7.5625 * position * position + 0.9375 } else { position -= (2.625 / 2.75) - return Double( 7.5625 * position * position + 0.984375 ) + return 7.5625 * position * position + 0.984375 } } diff --git a/Source/Charts/Charts/PieChartView.swift b/Source/Charts/Charts/PieChartView.swift index 704c066bdf..ac85c897b6 100644 --- a/Source/Charts/Charts/PieChartView.swift +++ b/Source/Charts/Charts/PieChartView.swift @@ -205,7 +205,7 @@ open class PieChartView: PieRadarChartViewBase @objc open override func distanceToCenter(x: CGFloat, y: CGFloat) -> CGFloat { let c = adjustedCenterOffsets() - var dist = CGFloat(0.0) + var dist = CGFloat.zero let xDist = x > c.x ? x - c.x : c.x - x let yDist = y > c.y ? y - c.y : c.y - y diff --git a/Source/Charts/Components/AxisBase.swift b/Source/Charts/Components/AxisBase.swift index 8e5ed766ce..d3d6d4c7f8 100644 --- a/Source/Charts/Components/AxisBase.swift +++ b/Source/Charts/Components/AxisBase.swift @@ -106,7 +106,7 @@ open class AxisBase: ComponentBase /// If using granularity this could be avoided by having fewer axis values visible. @objc open var granularityEnabled = false - private var _granularity = Double(1.0) + private var _granularity: Double = 1.0 /// The minimum interval between axis values. /// This can be used to avoid label duplicating when zooming in. @@ -210,15 +210,15 @@ open class AxisBase: ComponentBase /// Do not touch this directly, instead, use axisMinimum. /// This is automatically calculated to represent the real min value, /// and is used when calculating the effective minimum. - internal var _axisMinimum = Double(0) + internal var _axisMinimum: Double = 0 /// Do not touch this directly, instead, use axisMaximum. /// This is automatically calculated to represent the real max value, /// and is used when calculating the effective maximum. - internal var _axisMaximum = Double(0) + internal var _axisMaximum: Double = 0 /// the total range of values this axis covers - @objc open var axisRange = Double(0) + @objc open var axisRange: Double = 0 /// The minumum number of labels on the axis @objc open var axisMinLabels = Int(2) { diff --git a/Source/Charts/Components/ChartLimitLine.swift b/Source/Charts/Components/ChartLimitLine.swift index 26ad7bc6a5..8200bb720d 100644 --- a/Source/Charts/Components/ChartLimitLine.swift +++ b/Source/Charts/Components/ChartLimitLine.swift @@ -34,11 +34,11 @@ open class ChartLimitLine: ComponentBase } /// limit / maximum (the y-value or xIndex) - @objc open var limit = Double(0.0) + @objc open var limit: Double = 0.0 - private var _lineWidth = CGFloat(2.0) + private var _lineWidth: CGFloat = 2.0 @objc open var lineColor = NSUIColor(red: 237.0/255.0, green: 91.0/255.0, blue: 91.0/255.0, alpha: 1.0) - @objc open var lineDashPhase = CGFloat(0.0) + @objc open var lineDashPhase: CGFloat = 0.0 @objc open var lineDashLengths: [CGFloat]? @objc open var valueTextColor = NSUIColor.labelOrBlack diff --git a/Source/Charts/Components/Legend.swift b/Source/Charts/Components/Legend.swift index a9cd40a489..ffa8727836 100644 --- a/Source/Charts/Components/Legend.swift +++ b/Source/Charts/Components/Legend.swift @@ -155,8 +155,8 @@ open class Legend: ComponentBase @objc open func getMaximumEntrySize(withFont font: NSUIFont) -> CGSize { - var maxW = CGFloat(0.0) - var maxH = CGFloat(0.0) + var maxW: CGFloat = 0.0 + var maxH: CGFloat = 0.0 var maxFormSize: CGFloat = 0.0 @@ -189,10 +189,10 @@ open class Legend: ComponentBase ) } - @objc open var neededWidth = CGFloat(0.0) - @objc open var neededHeight = CGFloat(0.0) - @objc open var textWidthMax = CGFloat(0.0) - @objc open var textHeightMax = CGFloat(0.0) + @objc open var neededWidth: CGFloat = 0.0 + @objc open var neededHeight: CGFloat = 0.0 + @objc open var textWidthMax: CGFloat = 0.0 + @objc open var textHeightMax: CGFloat = 0.0 /// flag that indicates if word wrapping is enabled /// this is currently supported only for `orientation == Horizontal`. @@ -230,9 +230,9 @@ open class Legend: ComponentBase { case .vertical: - var maxWidth = CGFloat(0.0) - var width = CGFloat(0.0) - var maxHeight = CGFloat(0.0) + var maxWidth: CGFloat = 0.0 + var width: CGFloat = 0.0 + var maxHeight: CGFloat = 0.0 let labelLineHeight = labelFont.lineHeight var wasStacked = false diff --git a/Source/Charts/Data/Implementations/Standard/BarChartData.swift b/Source/Charts/Data/Implementations/Standard/BarChartData.swift index 0403c76b71..618d03f4bc 100644 --- a/Source/Charts/Data/Implementations/Standard/BarChartData.swift +++ b/Source/Charts/Data/Implementations/Standard/BarChartData.swift @@ -32,7 +32,7 @@ open class BarChartData: BarLineScatterCandleBubbleChartData /// The width of the bars on the x-axis, in values (not pixels) /// /// **default**: 0.85 - @objc open var barWidth = Double(0.85) + @objc open var barWidth: Double = 0.85 /// Groups all BarDataSet objects this data object holds together by modifying the x-value of their entries. /// Previously set x-values of entries will be overwritten. Leaves space between bars and groups as specified by the parameters. diff --git a/Source/Charts/Data/Implementations/Standard/CandleChartDataEntry.swift b/Source/Charts/Data/Implementations/Standard/CandleChartDataEntry.swift index 467bc168d1..fbf9dca216 100644 --- a/Source/Charts/Data/Implementations/Standard/CandleChartDataEntry.swift +++ b/Source/Charts/Data/Implementations/Standard/CandleChartDataEntry.swift @@ -14,16 +14,16 @@ import Foundation open class CandleChartDataEntry: ChartDataEntry { /// shadow-high value - @objc open var high = Double(0.0) + @objc open var high: Double = 0.0 /// shadow-low value - @objc open var low = Double(0.0) + @objc open var low: Double = 0.0 /// close value - @objc open var close = Double(0.0) + @objc open var close: Double = 0.0 /// open value - @objc open var open = Double(0.0) + @objc open var open: Double = 0.0 public required init() { diff --git a/Source/Charts/Renderers/BarChartRenderer.swift b/Source/Charts/Renderers/BarChartRenderer.swift index 2aa69a828f..046e6c6dd2 100644 --- a/Source/Charts/Renderers/BarChartRenderer.swift +++ b/Source/Charts/Renderers/BarChartRenderer.swift @@ -429,215 +429,179 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer open override func drawValues(context: CGContext) { - // if values are drawn - if isDrawingValuesAllowed(dataProvider: dataProvider) + guard + isDrawingValuesAllowed(dataProvider: dataProvider), + let dataProvider = dataProvider, + let barData = dataProvider.barData + else { return } + + let valueOffsetPlus: CGFloat = 4.5 + var posOffset: CGFloat + var negOffset: CGFloat + let drawValueAboveBar = dataProvider.isDrawValueAboveBarEnabled + + for dataSetIndex in barData.indices { guard - let dataProvider = dataProvider, - let barData = dataProvider.barData - else { return } - - let valueOffsetPlus: CGFloat = 4.5 - var posOffset: CGFloat - var negOffset: CGFloat - let drawValueAboveBar = dataProvider.isDrawValueAboveBarEnabled + let dataSet = barData[dataSetIndex] as? BarChartDataSetProtocol, + shouldDrawValues(forDataSet: dataSet) + else { continue } - for dataSetIndex in barData.indices + let angleRadians = dataSet.valueLabelAngle.DEG2RAD + + let isInverted = dataProvider.isInverted(axis: dataSet.axisDependency) + + // calculate the correct offset depending on the draw position of the value + let valueFont = dataSet.valueFont + let valueTextHeight = valueFont.lineHeight + posOffset = (drawValueAboveBar ? -(valueTextHeight + valueOffsetPlus) : valueOffsetPlus) + negOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextHeight + valueOffsetPlus)) + + if isInverted { - guard - let dataSet = barData[dataSetIndex] as? BarChartDataSetProtocol, - shouldDrawValues(forDataSet: dataSet) - else { continue } - - let angleRadians = dataSet.valueLabelAngle.DEG2RAD - - let isInverted = dataProvider.isInverted(axis: dataSet.axisDependency) - - // calculate the correct offset depending on the draw position of the value - let valueFont = dataSet.valueFont - let valueTextHeight = valueFont.lineHeight - posOffset = (drawValueAboveBar ? -(valueTextHeight + valueOffsetPlus) : valueOffsetPlus) - negOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextHeight + valueOffsetPlus)) - - if isInverted - { - posOffset = -posOffset - valueTextHeight - negOffset = -negOffset - valueTextHeight - } - - let buffer = _buffers[dataSetIndex] - - let formatter = dataSet.valueFormatter - - let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) - - let phaseY = animator.phaseY - - let iconsOffset = dataSet.iconsOffset - - // if only single values are drawn (sum) - if !dataSet.isStacked + posOffset = -posOffset - valueTextHeight + negOffset = -negOffset - valueTextHeight + } + + let buffer = _buffers[dataSetIndex] + + let formatter = dataSet.valueFormatter + + let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) + + let phaseY = animator.phaseY + + let iconsOffset = dataSet.iconsOffset + + // if only single values are drawn (sum) + if !dataSet.isStacked + { + let range = 0 ..< Int(ceil(Double(dataSet.entryCount) * animator.phaseX)) + for j in range { - let range = 0 ..< Int(ceil(Double(dataSet.entryCount) * animator.phaseX)) - for j in range + guard let e = dataSet.entryForIndex(j) as? BarChartDataEntry else { continue } + + let rect = buffer[j] + + let x = rect.origin.x + rect.size.width / 2.0 + + guard viewPortHandler.isInBoundsRight(x) else { break } + + guard viewPortHandler.isInBoundsY(rect.origin.y), + viewPortHandler.isInBoundsLeft(x) + else { continue } + + let val = e.y + + if dataSet.isDrawValuesEnabled { - guard let e = dataSet.entryForIndex(j) as? BarChartDataEntry else { continue } - - let rect = buffer[j] - - let x = rect.origin.x + rect.size.width / 2.0 - - guard viewPortHandler.isInBoundsRight(x) else { break } - - guard viewPortHandler.isInBoundsY(rect.origin.y), - viewPortHandler.isInBoundsLeft(x) - else { continue } - - let val = e.y - - if dataSet.isDrawValuesEnabled - { - drawValue( - context: context, - value: formatter.stringForValue( - val, - entry: e, - dataSetIndex: dataSetIndex, - viewPortHandler: viewPortHandler), - xPos: x, - yPos: val >= 0.0 - ? (rect.origin.y + posOffset) - : (rect.origin.y + rect.size.height + negOffset), - font: valueFont, - align: .center, - color: dataSet.valueTextColorAt(j), - anchor: CGPoint(x: 0.5, y: 0.5), - angleRadians: angleRadians) - } + drawValue( + context: context, + value: formatter.stringForValue( + val, + entry: e, + dataSetIndex: dataSetIndex, + viewPortHandler: viewPortHandler), + xPos: x, + yPos: val >= 0.0 + ? (rect.origin.y + posOffset) + : (rect.origin.y + rect.size.height + negOffset), + font: valueFont, + align: .center, + color: dataSet.valueTextColorAt(j), + anchor: CGPoint(x: 0.5, y: 0.5), + angleRadians: angleRadians) + } + + if let icon = e.icon, dataSet.isDrawIconsEnabled + { + var px = x + var py = val >= 0.0 + ? (rect.origin.y + posOffset) + : (rect.origin.y + rect.size.height + negOffset) - if let icon = e.icon, dataSet.isDrawIconsEnabled - { - var px = x - var py = val >= 0.0 - ? (rect.origin.y + posOffset) - : (rect.origin.y + rect.size.height + negOffset) - - px += iconsOffset.x - py += iconsOffset.y - - context.drawImage(icon, - atCenter: CGPoint(x: px, y: py), - size: icon.size) - } + px += iconsOffset.x + py += iconsOffset.y + context.drawImage(icon, + atCenter: CGPoint(x: px, y: py), + size: icon.size) } + } - else + } + else + { + // if we have stacks + + var bufferIndex = 0 + let lastIndex = ceil(Double(dataSet.entryCount) * animator.phaseX) + + for index in 0 ..< Int(lastIndex) { - // if we have stacks + guard let e = dataSet.entryForIndex(index) as? BarChartDataEntry else { continue } - var bufferIndex = 0 - let lastIndex = ceil(Double(dataSet.entryCount) * animator.phaseX) - - for index in 0 ..< Int(lastIndex) + let vals = e.yValues + + let rect = buffer[bufferIndex] + + let x = rect.origin.x + rect.size.width / 2.0 + + // we still draw stacked bars, but there is one non-stacked in between + if let values = vals { - guard let e = dataSet.entryForIndex(index) as? BarChartDataEntry else { continue } + // draw stack values + var transformed = [CGPoint]() - let vals = e.yValues + var posY = 0.0 + var negY = -e.negativeSum - let rect = buffer[bufferIndex] - - let x = rect.origin.x + rect.size.width / 2.0 - - // we still draw stacked bars, but there is one non-stacked in between - if let values = vals + for value in values { - // draw stack values - var transformed = [CGPoint]() - - var posY = 0.0 - var negY = -e.negativeSum - - for value in values + let y: Double + + if value == 0.0 && (posY == 0.0 || negY == 0.0) { - let y: Double - - if value == 0.0 && (posY == 0.0 || negY == 0.0) - { - // Take care of the situation of a 0.0 value, which overlaps a non-zero bar - y = value - } - else if value >= 0.0 - { - posY += value - y = posY - } - else - { - y = negY - negY -= value - } - - transformed.append(CGPoint(x: 0.0, y: CGFloat(y * phaseY))) + // Take care of the situation of a 0.0 value, which overlaps a non-zero bar + y = value } - - trans.pointValuesToPixel(&transformed) - - for (value, transformed) in zip(values, transformed) + else if value >= 0.0 + { + posY += value + y = posY + } + else { - let drawBelow = (value == 0.0 && negY == 0.0 && posY > 0.0) || value < 0.0 - let y = transformed.y + (drawBelow ? negOffset : posOffset) - - guard viewPortHandler.isInBoundsRight(x) else { break } - guard viewPortHandler.isInBoundsY(y), - viewPortHandler.isInBoundsLeft(x) - else { continue } - - if dataSet.isDrawValuesEnabled - { - drawValue( - context: context, - value: formatter.stringForValue( - value, - entry: e, - dataSetIndex: dataSetIndex, - viewPortHandler: viewPortHandler), - xPos: x, - yPos: y, - font: valueFont, - align: .center, - color: dataSet.valueTextColorAt(index), - anchor: CGPoint(x: 0.5, y: 0.5), - angleRadians: angleRadians) - } - - if let icon = e.icon, dataSet.isDrawIconsEnabled - { - context.drawImage(icon, - atCenter: CGPoint(x: x + iconsOffset.x, - y: y + iconsOffset.y), - size: icon.size) - } + y = negY + negY -= value } + + transformed.append(CGPoint(x: 0.0, y: CGFloat(y * phaseY))) } - else + + trans.pointValuesToPixel(&transformed) + + for (value, transformed) in zip(values, transformed) { + let drawBelow = (value == 0.0 && negY == 0.0 && posY > 0.0) || value < 0.0 + let y = transformed.y + (drawBelow ? negOffset : posOffset) + guard viewPortHandler.isInBoundsRight(x) else { break } - guard viewPortHandler.isInBoundsY(rect.origin.y), - viewPortHandler.isInBoundsLeft(x) else { continue } - + guard viewPortHandler.isInBoundsY(y), + viewPortHandler.isInBoundsLeft(x) + else { continue } + if dataSet.isDrawValuesEnabled { drawValue( context: context, value: formatter.stringForValue( - e.y, + value, entry: e, dataSetIndex: dataSetIndex, viewPortHandler: viewPortHandler), xPos: x, - yPos: rect.origin.y + - (e.y >= 0 ? posOffset : negOffset), + yPos: y, font: valueFont, align: .center, color: dataSet.valueTextColorAt(index), @@ -647,21 +611,54 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer if let icon = e.icon, dataSet.isDrawIconsEnabled { - var px = x - var py = rect.origin.y + - (e.y >= 0 ? posOffset : negOffset) - - px += iconsOffset.x - py += iconsOffset.y - context.drawImage(icon, - atCenter: CGPoint(x: px, y: py), + atCenter: CGPoint(x: x + iconsOffset.x, + y: y + iconsOffset.y), size: icon.size) } } - - bufferIndex += vals?.count ?? 1 } + else + { + guard viewPortHandler.isInBoundsRight(x) else { break } + guard viewPortHandler.isInBoundsY(rect.origin.y), + viewPortHandler.isInBoundsLeft(x) else { continue } + + if dataSet.isDrawValuesEnabled + { + drawValue( + context: context, + value: formatter.stringForValue( + e.y, + entry: e, + dataSetIndex: dataSetIndex, + viewPortHandler: viewPortHandler), + xPos: x, + yPos: rect.origin.y + + (e.y >= 0 ? posOffset : negOffset), + font: valueFont, + align: .center, + color: dataSet.valueTextColorAt(index), + anchor: CGPoint(x: 0.5, y: 0.5), + angleRadians: angleRadians) + } + + if let icon = e.icon, dataSet.isDrawIconsEnabled + { + var px = x + var py = rect.origin.y + + (e.y >= 0 ? posOffset : negOffset) + + px += iconsOffset.x + py += iconsOffset.y + + context.drawImage(icon, + atCenter: CGPoint(x: px, y: py), + size: icon.size) + } + } + + bufferIndex += vals?.count ?? 1 } } } diff --git a/Source/Charts/Renderers/HorizontalBarChartRenderer.swift b/Source/Charts/Renderers/HorizontalBarChartRenderer.swift index d2fed814f3..b70c3c8ae8 100644 --- a/Source/Charts/Renderers/HorizontalBarChartRenderer.swift +++ b/Source/Charts/Renderers/HorizontalBarChartRenderer.swift @@ -316,56 +316,134 @@ open class HorizontalBarChartRenderer: BarChartRenderer open override func drawValues(context: CGContext) { - // if values are drawn - if isDrawingValuesAllowed(dataProvider: dataProvider) + guard + isDrawingValuesAllowed(dataProvider: dataProvider), + let dataProvider = dataProvider, + let barData = dataProvider.barData + else { return } + + let textAlign = TextAlignment.left + + let valueOffsetPlus: CGFloat = 5.0 + var posOffset: CGFloat + var negOffset: CGFloat + let drawValueAboveBar = dataProvider.isDrawValueAboveBarEnabled + + for dataSetIndex in barData.indices { - guard - let dataProvider = dataProvider, - let barData = dataProvider.barData - else { return } - - let textAlign = TextAlignment.left + guard let + dataSet = barData[dataSetIndex] as? BarChartDataSetProtocol, + shouldDrawValues(forDataSet: dataSet) + else { continue } + + let angleRadians = dataSet.valueLabelAngle.DEG2RAD + + let isInverted = dataProvider.isInverted(axis: dataSet.axisDependency) + + let valueFont = dataSet.valueFont + let yOffset = -valueFont.lineHeight / 2.0 + + let formatter = dataSet.valueFormatter + + let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) + + let phaseY = animator.phaseY - let valueOffsetPlus: CGFloat = 5.0 - var posOffset: CGFloat - var negOffset: CGFloat - let drawValueAboveBar = dataProvider.isDrawValueAboveBarEnabled + let iconsOffset = dataSet.iconsOffset - for dataSetIndex in barData.indices + let buffer = _buffers[dataSetIndex] + + // if only single values are drawn (sum) + if !dataSet.isStacked { - guard let - dataSet = barData[dataSetIndex] as? BarChartDataSetProtocol, - shouldDrawValues(forDataSet: dataSet) - else { continue } - - let angleRadians = dataSet.valueLabelAngle.DEG2RAD - - let isInverted = dataProvider.isInverted(axis: dataSet.axisDependency) - - let valueFont = dataSet.valueFont - let yOffset = -valueFont.lineHeight / 2.0 - - let formatter = dataSet.valueFormatter - - let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency) - - let phaseY = animator.phaseY - - let iconsOffset = dataSet.iconsOffset - - let buffer = _buffers[dataSetIndex] - - // if only single values are drawn (sum) - if !dataSet.isStacked + for j in 0 ..< Int(ceil(Double(dataSet.entryCount) * animator.phaseX)) { - for j in 0 ..< Int(ceil(Double(dataSet.entryCount) * animator.phaseX)) + guard let e = dataSet.entryForIndex(j) as? BarChartDataEntry else { continue } + + let rect = buffer.rects[j] + + let y = rect.origin.y + rect.size.height / 2.0 + + if !viewPortHandler.isInBoundsTop(rect.origin.y) { - guard let e = dataSet.entryForIndex(j) as? BarChartDataEntry else { continue } - - let rect = buffer.rects[j] + break + } + + if !viewPortHandler.isInBoundsX(rect.origin.x) + { + continue + } + + if !viewPortHandler.isInBoundsBottom(rect.origin.y) + { + continue + } + + let val = e.y + let valueText = formatter.stringForValue( + val, + entry: e, + dataSetIndex: dataSetIndex, + viewPortHandler: viewPortHandler) + + // calculate the correct offset depending on the draw position of the value + let valueTextWidth = valueText.size(withAttributes: [.font: valueFont]).width + posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)) + negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus) - rect.size.width + + if isInverted + { + posOffset = -posOffset - valueTextWidth + negOffset = -negOffset - valueTextWidth + } + + if dataSet.isDrawValuesEnabled + { + drawValue( + context: context, + value: valueText, + xPos: (rect.origin.x + rect.size.width) + + (val >= 0.0 ? posOffset : negOffset), + yPos: y + yOffset, + font: valueFont, + align: textAlign, + color: dataSet.valueTextColorAt(j), + anchor: CGPoint.zero, + angleRadians: angleRadians) + } + + if let icon = e.icon, dataSet.isDrawIconsEnabled + { + var px = (rect.origin.x + rect.size.width) + + (val >= 0.0 ? posOffset : negOffset) + var py = y - let y = rect.origin.y + rect.size.height / 2.0 + px += iconsOffset.x + py += iconsOffset.y + context.drawImage(icon, + atCenter: CGPoint(x: px, y: py), + size: icon.size) + } + } + } + else + { + // if each value of a potential stack should be drawn + + var bufferIndex = 0 + + for index in 0 ..< Int(ceil(Double(dataSet.entryCount) * animator.phaseX)) + { + guard let e = dataSet.entryForIndex(index) as? BarChartDataEntry else { continue } + + let rect = buffer.rects[bufferIndex] + + let vals = e.yValues + + // we still draw stacked bars, but there is one non-stacked in between + if vals == nil + { if !viewPortHandler.isInBoundsTop(rect.origin.y) { break @@ -389,9 +467,9 @@ open class HorizontalBarChartRenderer: BarChartRenderer viewPortHandler: viewPortHandler) // calculate the correct offset depending on the draw position of the value - let valueTextWidth = valueText.size(withAttributes: [.font: valueFont]).width + let valueTextWidth = valueText.size(withAttributes: [NSAttributedString.Key.font: valueFont]).width posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)) - negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus) - rect.size.width + negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus) if isInverted { @@ -405,11 +483,11 @@ open class HorizontalBarChartRenderer: BarChartRenderer context: context, value: valueText, xPos: (rect.origin.x + rect.size.width) - + (val >= 0.0 ? posOffset : negOffset), - yPos: y + yOffset, + + (val >= 0.0 ? posOffset : negOffset), + yPos: rect.origin.y + yOffset, font: valueFont, align: textAlign, - color: dataSet.valueTextColorAt(j), + color: dataSet.valueTextColorAt(index), anchor: CGPoint.zero, angleRadians: angleRadians) } @@ -417,8 +495,8 @@ open class HorizontalBarChartRenderer: BarChartRenderer if let icon = e.icon, dataSet.isDrawIconsEnabled { var px = (rect.origin.x + rect.size.width) - + (val >= 0.0 ? posOffset : negOffset) - var py = y + + (val >= 0.0 ? posOffset : negOffset) + var py = rect.origin.y px += iconsOffset.x py += iconsOffset.y @@ -428,40 +506,43 @@ open class HorizontalBarChartRenderer: BarChartRenderer size: icon.size) } } - } - else - { - // if each value of a potential stack should be drawn - - var bufferIndex = 0 - - for index in 0 ..< Int(ceil(Double(dataSet.entryCount) * animator.phaseX)) + else { - guard let e = dataSet.entryForIndex(index) as? BarChartDataEntry else { continue } + let vals = vals! + var transformed = [CGPoint]() - let rect = buffer.rects[bufferIndex] + var posY = 0.0 + var negY = -e.negativeSum - let vals = e.yValues - - // we still draw stacked bars, but there is one non-stacked in between - if vals == nil + for k in vals.indices { - if !viewPortHandler.isInBoundsTop(rect.origin.y) + let value = vals[k] + var y: Double + + if value == 0.0 && (posY == 0.0 || negY == 0.0) { - break + // Take care of the situation of a 0.0 value, which overlaps a non-zero bar + y = value } - - if !viewPortHandler.isInBoundsX(rect.origin.x) + else if value >= 0.0 { - continue + posY += value + y = posY } - - if !viewPortHandler.isInBoundsBottom(rect.origin.y) + else { - continue + y = negY + negY -= value } - let val = e.y + transformed.append(CGPoint(x: CGFloat(y * phaseY), y: 0.0)) + } + + trans.pointValuesToPixel(&transformed) + + for k in transformed.indices + { + let val = vals[k] let valueText = formatter.stringForValue( val, entry: e, @@ -469,7 +550,7 @@ open class HorizontalBarChartRenderer: BarChartRenderer viewPortHandler: viewPortHandler) // calculate the correct offset depending on the draw position of the value - let valueTextWidth = valueText.size(withAttributes: [NSAttributedString.Key.font: valueFont]).width + let valueTextWidth = valueText.size(withAttributes: [.font: valueFont]).width posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)) negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus) @@ -479,134 +560,50 @@ open class HorizontalBarChartRenderer: BarChartRenderer negOffset = -negOffset - valueTextWidth } - if dataSet.isDrawValuesEnabled + let drawBelow = (val == 0.0 && negY == 0.0 && posY > 0.0) || val < 0.0 + + let x = transformed[k].x + (drawBelow ? negOffset : posOffset) + let y = rect.origin.y + rect.size.height / 2.0 + + if (!viewPortHandler.isInBoundsTop(y)) { - drawValue( - context: context, - value: valueText, - xPos: (rect.origin.x + rect.size.width) - + (val >= 0.0 ? posOffset : negOffset), - yPos: rect.origin.y + yOffset, - font: valueFont, - align: textAlign, - color: dataSet.valueTextColorAt(index), - anchor: CGPoint.zero, - angleRadians: angleRadians) + break } - if let icon = e.icon, dataSet.isDrawIconsEnabled + if (!viewPortHandler.isInBoundsX(x)) { - var px = (rect.origin.x + rect.size.width) - + (val >= 0.0 ? posOffset : negOffset) - var py = rect.origin.y - - px += iconsOffset.x - py += iconsOffset.y - - context.drawImage(icon, - atCenter: CGPoint(x: px, y: py), - size: icon.size) + continue } - } - else - { - let vals = vals! - var transformed = [CGPoint]() - var posY = 0.0 - var negY = -e.negativeSum - - for k in vals.indices + if (!viewPortHandler.isInBoundsBottom(y)) { - let value = vals[k] - var y: Double - - if value == 0.0 && (posY == 0.0 || negY == 0.0) - { - // Take care of the situation of a 0.0 value, which overlaps a non-zero bar - y = value - } - else if value >= 0.0 - { - posY += value - y = posY - } - else - { - y = negY - negY -= value - } - - transformed.append(CGPoint(x: CGFloat(y * phaseY), y: 0.0)) + continue } - trans.pointValuesToPixel(&transformed) + if dataSet.isDrawValuesEnabled + { + drawValue(context: context, + value: valueText, + xPos: x, + yPos: y + yOffset, + font: valueFont, + align: textAlign, + color: dataSet.valueTextColorAt(index), + anchor: CGPoint.zero, + angleRadians: angleRadians) + } - for k in transformed.indices + if let icon = e.icon, dataSet.isDrawIconsEnabled { - let val = vals[k] - let valueText = formatter.stringForValue( - val, - entry: e, - dataSetIndex: dataSetIndex, - viewPortHandler: viewPortHandler) - - // calculate the correct offset depending on the draw position of the value - let valueTextWidth = valueText.size(withAttributes: [.font: valueFont]).width - posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)) - negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus) - - if isInverted - { - posOffset = -posOffset - valueTextWidth - negOffset = -negOffset - valueTextWidth - } - - let drawBelow = (val == 0.0 && negY == 0.0 && posY > 0.0) || val < 0.0 - - let x = transformed[k].x + (drawBelow ? negOffset : posOffset) - let y = rect.origin.y + rect.size.height / 2.0 - - if (!viewPortHandler.isInBoundsTop(y)) - { - break - } - - if (!viewPortHandler.isInBoundsX(x)) - { - continue - } - - if (!viewPortHandler.isInBoundsBottom(y)) - { - continue - } - - if dataSet.isDrawValuesEnabled - { - drawValue(context: context, - value: valueText, - xPos: x, - yPos: y + yOffset, - font: valueFont, - align: textAlign, - color: dataSet.valueTextColorAt(index), - anchor: CGPoint.zero, - angleRadians: angleRadians) - } - - if let icon = e.icon, dataSet.isDrawIconsEnabled - { - context.drawImage(icon, - atCenter: CGPoint(x: x + iconsOffset.x, - y: y + iconsOffset.y), - size: icon.size) - } + context.drawImage(icon, + atCenter: CGPoint(x: x + iconsOffset.x, + y: y + iconsOffset.y), + size: icon.size) } } - - bufferIndex += vals?.count ?? 1 } + + bufferIndex += vals?.count ?? 1 } } } diff --git a/Source/Charts/Renderers/LegendRenderer.swift b/Source/Charts/Renderers/LegendRenderer.swift index 41fd499dbe..b31bf27370 100755 --- a/Source/Charts/Renderers/LegendRenderer.swift +++ b/Source/Charts/Renderers/LegendRenderer.swift @@ -174,10 +174,10 @@ open class LegendRenderer: NSObject, Renderer @objc open func renderLegend(context: CGContext) { - guard let legend = legend else { return } - - if !legend.enabled - { + guard + let legend = legend, + legend.enabled + else { return } @@ -376,7 +376,7 @@ open class LegendRenderer: NSObject, Renderer case .vertical: // contains the stacked legend size in pixels - var stack = CGFloat(0.0) + var stack: CGFloat = 0.0 var wasStacked = false var posY: CGFloat = 0.0 @@ -432,7 +432,7 @@ open class LegendRenderer: NSObject, Renderer } } - if e.label != nil + if let label = e.label { if drawingForm && !wasStacked { @@ -445,17 +445,17 @@ open class LegendRenderer: NSObject, Renderer if direction == .rightToLeft { - posX -= (e.label! as NSString).size(withAttributes: [.font: labelFont]).width + posX -= (label as NSString).size(withAttributes: [.font: labelFont]).width } if !wasStacked { - drawLabel(context: context, x: posX, y: posY, label: e.label!, font: labelFont, textColor: e.labelColor ?? labelTextColor) + drawLabel(context: context, x: posX, y: posY, label: label, font: labelFont, textColor: e.labelColor ?? labelTextColor) } else { posY += labelLineHeight + yEntrySpace - drawLabel(context: context, x: posX, y: posY, label: e.label!, font: labelFont, textColor: e.labelColor ?? labelTextColor) + drawLabel(context: context, x: posX, y: posY, label: label, font: labelFont, textColor: e.labelColor ?? labelTextColor) } // make a step down