From baca6dd52b9e841aa6a35e916a7843514344671b Mon Sep 17 00:00:00 2001 From: liuxuan30 Date: Thu, 16 Jul 2015 11:00:54 +0800 Subject: [PATCH 1/4] try to fix wrong position bug. use entry.xIndex instead of j of dataSet.entryCount to calculate the offset and position --- Charts/Classes/Charts/BarChartView.swift | 12 +----------- Charts/Classes/Renderers/BarChartRenderer.swift | 4 ++-- Charts/Classes/Utils/ChartTransformer.swift | 2 +- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/Charts/Classes/Charts/BarChartView.swift b/Charts/Classes/Charts/BarChartView.swift index 3d9d637829..d46575523f 100644 --- a/Charts/Classes/Charts/BarChartView.swift +++ b/Charts/Classes/Charts/BarChartView.swift @@ -56,17 +56,7 @@ public class BarChartView: BarLineChartViewBase, BarChartRendererDelegate // extend xDelta to make space for multiple datasets (if ther are one) _deltaX *= CGFloat(_data.dataSetCount) - var maxEntry = 0 - - for (var i = 0, count = barData.dataSetCount; i < count; i++) - { - var set = barData.getDataSetByIndex(i) - - if (maxEntry < set!.entryCount) - { - maxEntry = set!.entryCount - } - } + var maxEntry = barData.xValCount var groupSpace = barData.groupSpace _deltaX += CGFloat(maxEntry) * groupSpace diff --git a/Charts/Classes/Renderers/BarChartRenderer.swift b/Charts/Classes/Renderers/BarChartRenderer.swift index 83e4e5502a..181d91034a 100644 --- a/Charts/Classes/Renderers/BarChartRenderer.swift +++ b/Charts/Classes/Renderers/BarChartRenderer.swift @@ -93,8 +93,8 @@ public class BarChartRenderer: ChartDataRendererBase var e = entries[j] // calculate the x-position, depending on datasetcount - var x = CGFloat(e.xIndex + j * dataSetOffset) + CGFloat(index) - + groupSpace * CGFloat(j) + groupSpaceHalf + var x = CGFloat(e.xIndex + e.xIndex * dataSetOffset) + CGFloat(index) + + groupSpace * CGFloat(e.xIndex) + groupSpaceHalf var vals = e.values if (!containsStacks || vals == nil) diff --git a/Charts/Classes/Utils/ChartTransformer.swift b/Charts/Classes/Utils/ChartTransformer.swift index 815dce70db..3adff1903b 100644 --- a/Charts/Classes/Utils/ChartTransformer.swift +++ b/Charts/Classes/Utils/ChartTransformer.swift @@ -142,7 +142,7 @@ public class ChartTransformer: NSObject var e = entries[j] // calculate the x-position, depending on datasetcount - var x = CGFloat(e.xIndex + (j * (setCount - 1)) + dataSet) + space * CGFloat(j) + space / 2.0 + var x = CGFloat(e.xIndex + (e.xIndex * (setCount - 1)) + dataSet) + space * CGFloat(e.xIndex) + space / 2.0 var y = e.value valuePoints.append(CGPoint(x: x, y: CGFloat(y) * phaseY)) From 2f75778a7ed88384466fca748bd4c9c2e897b505 Mon Sep 17 00:00:00 2001 From: liuxuan30 Date: Thu, 16 Jul 2015 11:30:22 +0800 Subject: [PATCH 2/4] apply the same logic for getMarkerPosition --- Charts/Classes/Charts/BarLineChartViewBase.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Charts/Classes/Charts/BarLineChartViewBase.swift b/Charts/Classes/Charts/BarLineChartViewBase.swift index 6f100fc3ae..3768f5ec51 100644 --- a/Charts/Classes/Charts/BarLineChartViewBase.swift +++ b/Charts/Classes/Charts/BarLineChartViewBase.swift @@ -445,9 +445,8 @@ public class BarLineChartViewBase: ChartViewBase, UIGestureRecognizerDelegate { var bd = _data as! BarChartData var space = bd.groupSpace - var j = _data.getDataSetByIndex(dataSetIndex)!.entryIndex(entry: entry, isEqual: true) - var x = CGFloat(j * (_data.dataSetCount - 1) + dataSetIndex) + space * CGFloat(j) + space / 2.0 + var x = CGFloat(entry.xIndex * (_data.dataSetCount - 1) + dataSetIndex) + space * CGFloat(entry.xIndex) + space / 2.0 xPos += x } From c861feafded48c5843caa5d95f6e9518a797eccd Mon Sep 17 00:00:00 2001 From: liuxuan30 Date: Mon, 27 Jul 2015 18:32:34 +0800 Subject: [PATCH 3/4] add fix for horizontal bar chart --- Charts/Classes/Renderers/HorizontalBarChartRenderer.swift | 4 ++-- Charts/Classes/Utils/ChartTransformer.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Charts/Classes/Renderers/HorizontalBarChartRenderer.swift b/Charts/Classes/Renderers/HorizontalBarChartRenderer.swift index 10dd9b8e28..735970abf0 100644 --- a/Charts/Classes/Renderers/HorizontalBarChartRenderer.swift +++ b/Charts/Classes/Renderers/HorizontalBarChartRenderer.swift @@ -54,8 +54,8 @@ public class HorizontalBarChartRenderer: BarChartRenderer var e = entries[j] // calculate the x-position, depending on datasetcount - var x = CGFloat(e.xIndex + j * dataSetOffset) + CGFloat(index) - + groupSpace * CGFloat(j) + groupSpaceHalf + var x = CGFloat(e.xIndex + e.xIndex * dataSetOffset) + CGFloat(index) + + groupSpace * CGFloat(e.xIndex) + groupSpaceHalf var vals = e.values if (!containsStacks || vals == nil) diff --git a/Charts/Classes/Utils/ChartTransformer.swift b/Charts/Classes/Utils/ChartTransformer.swift index 3adff1903b..a50baac6bb 100644 --- a/Charts/Classes/Utils/ChartTransformer.swift +++ b/Charts/Classes/Utils/ChartTransformer.swift @@ -167,7 +167,7 @@ public class ChartTransformer: NSObject var e = entries[j] // calculate the x-position, depending on datasetcount - var x = CGFloat(e.xIndex + (j * (setCount - 1)) + dataSet) + space * CGFloat(j) + space / 2.0 + var x = CGFloat(e.xIndex + (e.xIndex * (setCount - 1)) + dataSet) + space * CGFloat(e.xIndex) + space / 2.0 var y = e.value valuePoints.append(CGPoint(x: CGFloat(y) * phaseY, y: x)) From 56fbc9f96bedde0e454cb392752251833dcc1a4f Mon Sep 17 00:00:00 2001 From: liuxuan30 Date: Mon, 27 Jul 2015 19:08:32 +0800 Subject: [PATCH 4/4] merge from upstream master --- Charts/Charts.xcodeproj/project.pbxproj | 32 +++- Charts/Classes/Charts/BarChartView.swift | 129 +---------------- .../Classes/Charts/BarLineChartViewBase.swift | 137 +++++------------- .../Classes/Renderers/BarChartRenderer.swift | 70 +++++---- .../HorizontalBarChartRenderer.swift | 89 ++++++------ Charts/Classes/Utils/ChartUtils.swift | 4 +- .../Demos/MultipleBarChartViewController.m | 2 +- 7 files changed, 158 insertions(+), 305 deletions(-) mode change 100755 => 100644 Charts/Classes/Utils/ChartUtils.swift diff --git a/Charts/Charts.xcodeproj/project.pbxproj b/Charts/Charts.xcodeproj/project.pbxproj index 263ddafe95..e9ecd2aa46 100644 --- a/Charts/Charts.xcodeproj/project.pbxproj +++ b/Charts/Charts.xcodeproj/project.pbxproj @@ -12,6 +12,11 @@ 55E356581ADC63CD00A57971 /* BubbleChartDataEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E356551ADC63CD00A57971 /* BubbleChartDataEntry.swift */; }; 55E356591ADC63CD00A57971 /* BubbleChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E356561ADC63CD00A57971 /* BubbleChartDataSet.swift */; }; 55E3565B1ADC63EB00A57971 /* BubbleChartRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E3565A1ADC63EB00A57971 /* BubbleChartRenderer.swift */; }; + 5B0032451B6524AD00B6A2FE /* ChartHighlight.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0032441B6524AD00B6A2FE /* ChartHighlight.swift */; }; + 5B0032471B6524D300B6A2FE /* ChartRange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0032461B6524D300B6A2FE /* ChartRange.swift */; }; + 5B0032491B6525FC00B6A2FE /* ChartHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0032481B6525FC00B6A2FE /* ChartHighlighter.swift */; }; + 5B00324B1B652BF900B6A2FE /* BarChartHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B00324A1B652BF900B6A2FE /* BarChartHighlighter.swift */; }; + 5B00324D1B65351C00B6A2FE /* HorizontalBarChartHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B00324C1B65351C00B6A2FE /* HorizontalBarChartHighlighter.swift */; }; 5B378F171AD500A4009414A4 /* ChartAnimationEasing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B378F161AD500A4009414A4 /* ChartAnimationEasing.swift */; }; 5B4BCD3E1AA9C0A60063F019 /* ChartFillFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B4BCD3D1AA9C0A60063F019 /* ChartFillFormatter.swift */; }; 5B4BCD401AA9C4930063F019 /* ChartTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B4BCD3F1AA9C4930063F019 /* ChartTransformer.swift */; }; @@ -23,7 +28,6 @@ 5B680D221A9D17C30026A057 /* ChartXAxis.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC6D1A9D151C00CE82E1 /* ChartXAxis.swift */; }; 5B680D231A9D17C30026A057 /* ChartYAxis.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC6E1A9D151C00CE82E1 /* ChartYAxis.swift */; }; 5B680D271A9D17C30026A057 /* ChartColorTemplates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC791A9D151C00CE82E1 /* ChartColorTemplates.swift */; }; - 5B680D281A9D17C30026A057 /* ChartHighlight.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC7A1A9D151C00CE82E1 /* ChartHighlight.swift */; }; 5B680D291A9D17C30026A057 /* ChartSelectionDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC7B1A9D151C00CE82E1 /* ChartSelectionDetail.swift */; }; 5B680D2A1A9D17C30026A057 /* ChartUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8EC7C1A9D151C00CE82E1 /* ChartUtils.swift */; }; 5B680D3D1A9D1AD90026A057 /* Charts.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B680D3C1A9D1AD90026A057 /* Charts.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -92,6 +96,11 @@ 55E356551ADC63CD00A57971 /* BubbleChartDataEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BubbleChartDataEntry.swift; sourceTree = ""; }; 55E356561ADC63CD00A57971 /* BubbleChartDataSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BubbleChartDataSet.swift; sourceTree = ""; }; 55E3565A1ADC63EB00A57971 /* BubbleChartRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BubbleChartRenderer.swift; sourceTree = ""; }; + 5B0032441B6524AD00B6A2FE /* ChartHighlight.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartHighlight.swift; sourceTree = ""; }; + 5B0032461B6524D300B6A2FE /* ChartRange.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartRange.swift; sourceTree = ""; }; + 5B0032481B6525FC00B6A2FE /* ChartHighlighter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartHighlighter.swift; sourceTree = ""; }; + 5B00324A1B652BF900B6A2FE /* BarChartHighlighter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarChartHighlighter.swift; sourceTree = ""; }; + 5B00324C1B65351C00B6A2FE /* HorizontalBarChartHighlighter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HorizontalBarChartHighlighter.swift; sourceTree = ""; }; 5B378F161AD500A4009414A4 /* ChartAnimationEasing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartAnimationEasing.swift; sourceTree = ""; }; 5B4BCD3D1AA9C0A60063F019 /* ChartFillFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartFillFormatter.swift; sourceTree = ""; }; 5B4BCD3F1AA9C4930063F019 /* ChartTransformer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartTransformer.swift; sourceTree = ""; }; @@ -161,7 +170,6 @@ 5BA8EC751A9D151C00CE82E1 /* ChartDataApproximatorFilter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartDataApproximatorFilter.swift; sourceTree = ""; }; 5BA8EC761A9D151C00CE82E1 /* ChartDataBaseFilter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartDataBaseFilter.swift; sourceTree = ""; }; 5BA8EC791A9D151C00CE82E1 /* ChartColorTemplates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartColorTemplates.swift; sourceTree = ""; }; - 5BA8EC7A1A9D151C00CE82E1 /* ChartHighlight.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartHighlight.swift; sourceTree = ""; }; 5BA8EC7B1A9D151C00CE82E1 /* ChartSelectionDetail.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartSelectionDetail.swift; sourceTree = ""; }; 5BA8EC7C1A9D151C00CE82E1 /* ChartUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartUtils.swift; sourceTree = ""; }; 5BB6EC1C1ACC28AB006E9C25 /* ChartTransformerHorizontalBarChart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartTransformerHorizontalBarChart.swift; sourceTree = ""; }; @@ -180,6 +188,18 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 5B0032431B65247600B6A2FE /* Highlight */ = { + isa = PBXGroup; + children = ( + 5B0032441B6524AD00B6A2FE /* ChartHighlight.swift */, + 5B0032461B6524D300B6A2FE /* ChartRange.swift */, + 5B0032481B6525FC00B6A2FE /* ChartHighlighter.swift */, + 5B00324A1B652BF900B6A2FE /* BarChartHighlighter.swift */, + 5B00324C1B65351C00B6A2FE /* HorizontalBarChartHighlighter.swift */, + ); + path = Highlight; + sourceTree = ""; + }; 5B680D1E1A9D170B0026A057 /* Frameworks */ = { isa = PBXGroup; children = ( @@ -259,6 +279,7 @@ 5BA8EC691A9D151C00CE82E1 /* Components */, 5BA8EC6F1A9D151C00CE82E1 /* Data */, 5BA8EC741A9D151C00CE82E1 /* Filters */, + 5B0032431B65247600B6A2FE /* Highlight */, 5B759ED41A9F98A90039D97F /* Renderers */, 5BA8EC781A9D151C00CE82E1 /* Utils */, ); @@ -343,7 +364,6 @@ children = ( 5BA8EC791A9D151C00CE82E1 /* ChartColorTemplates.swift */, 5B4BCD3D1AA9C0A60063F019 /* ChartFillFormatter.swift */, - 5BA8EC7A1A9D151C00CE82E1 /* ChartHighlight.swift */, 5BA8EC7B1A9D151C00CE82E1 /* ChartSelectionDetail.swift */, 5B4BCD3F1AA9C4930063F019 /* ChartTransformer.swift */, 5BB6EC1C1ACC28AB006E9C25 /* ChartTransformerHorizontalBarChart.swift */, @@ -432,7 +452,6 @@ buildActionMask = 2147483647; files = ( 5B680D1F1A9D17C30026A057 /* ChartAxisBase.swift in Sources */, - 5B680D281A9D17C30026A057 /* ChartHighlight.swift in Sources */, 5B4BCD3E1AA9C0A60063F019 /* ChartFillFormatter.swift in Sources */, 5B6A54DE1AA74516000F57C2 /* RadarChartDataSet.swift in Sources */, 5B680D211A9D17C30026A057 /* ChartLimitLine.swift in Sources */, @@ -463,6 +482,7 @@ 5B6A54801AA5DF28000F57C2 /* ChartYAxisRendererHorizontalBarChart.swift in Sources */, 5B6A54D21AA74516000F57C2 /* CandleChartDataEntry.swift in Sources */, 5B6A54CC1AA74516000F57C2 /* BarChartData.swift in Sources */, + 5B00324D1B65351C00B6A2FE /* HorizontalBarChartHighlighter.swift in Sources */, 5B6A54CE1AA74516000F57C2 /* BarChartDataSet.swift in Sources */, 5B6A54871AA669F4000F57C2 /* RadarChartRenderer.swift in Sources */, 5B6A548D1AA66A60000F57C2 /* ChartLegendRenderer.swift in Sources */, @@ -492,7 +512,9 @@ 55E356571ADC63CD00A57971 /* BubbleChartData.swift in Sources */, 5B6A54DF1AA74516000F57C2 /* ScatterChartData.swift in Sources */, 5B6A54D31AA74516000F57C2 /* CandleChartDataSet.swift in Sources */, + 5B0032491B6525FC00B6A2FE /* ChartHighlighter.swift in Sources */, 5B6A54D71AA74516000F57C2 /* ChartDataSet.swift in Sources */, + 5B00324B1B652BF900B6A2FE /* BarChartHighlighter.swift in Sources */, 5B6A54781AA5DEF0000F57C2 /* ChartXAxisRendererRadarChart.swift in Sources */, 5B6A54A71AA66BA7000F57C2 /* PieRadarChartViewBase.swift in Sources */, 5B6A546E1AA5D2DC000F57C2 /* ChartAnimator.swift in Sources */, @@ -504,7 +526,9 @@ 5B6A54CD1AA74516000F57C2 /* BarChartDataEntry.swift in Sources */, 5B6A54D41AA74516000F57C2 /* CombinedChartData.swift in Sources */, 5B680D2A1A9D17C30026A057 /* ChartUtils.swift in Sources */, + 5B0032451B6524AD00B6A2FE /* ChartHighlight.swift in Sources */, 5B680D201A9D17C30026A057 /* ChartLegend.swift in Sources */, + 5B0032471B6524D300B6A2FE /* ChartRange.swift in Sources */, 5BD8F06E1AB89AD800566E05 /* HorizontalBarChartView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Charts/Classes/Charts/BarChartView.swift b/Charts/Classes/Charts/BarChartView.swift index d46575523f..f5d19414a0 100644 --- a/Charts/Classes/Charts/BarChartView.swift +++ b/Charts/Classes/Charts/BarChartView.swift @@ -22,9 +22,6 @@ public class BarChartView: BarLineChartViewBase, BarChartRendererDelegate /// 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 values of a stack are drawn individually, and not just their sum - private var _drawValuesForWholeStackEnabled = true /// if set to true, a grey area is darawn behind each bar that indicates the maximum value private var _drawBarShadowEnabled = false @@ -36,6 +33,8 @@ public class BarChartView: BarLineChartViewBase, BarChartRendererDelegate renderer = BarChartRenderer(delegate: self, animator: _animator, viewPortHandler: _viewPortHandler) _xAxisRenderer = ChartXAxisRendererBarChart(viewPortHandler: _viewPortHandler, xAxis: _xAxis, transformer: _leftAxisTransformer, chart: self) + _highlighter = BarChartHighlighter(chart: self) + _chartXMin = -0.5 } @@ -64,7 +63,7 @@ public class BarChartView: BarLineChartViewBase, BarChartRendererDelegate } /// Returns the Highlight object (contains x-index and DataSet index) of the selected value at the given touch point inside the BarChart. - public override func getHighlightByTouchPoint(var pt: CGPoint) -> ChartHighlight! + public override func getHighlightByTouchPoint(pt: CGPoint) -> ChartHighlight? { if (_dataNotSet || _data === nil) { @@ -72,108 +71,7 @@ public class BarChartView: BarLineChartViewBase, BarChartRendererDelegate return nil } - _leftAxisTransformer.pixelToValue(&pt) - - if (pt.x < CGFloat(_chartXMin) || pt.x > CGFloat(_chartXMax)) - { - return nil - } - - return getHighlight(xPosition: pt.x, yPosition: pt.y) - } - - /// Returns the correct Highlight object (including xIndex and dataSet-index) for the specified touch position. - internal func getHighlight(#xPosition: CGFloat, yPosition: CGFloat) -> ChartHighlight! - { - if (_dataNotSet || _data === nil) - { - return nil - } - - var barData = _data as! BarChartData! - - var setCount = barData.dataSetCount - var valCount = barData.xValCount - var dataSetIndex = 0 - var xIndex = 0 - - if (!barData.isGrouped) - { // only one dataset exists - - xIndex = Int(round(xPosition)) - - // check bounds - if (xIndex < 0) - { - xIndex = 0 - } - else if (xIndex >= valCount) - { - xIndex = valCount - 1 - } - } - else - { // if this bardata is grouped into more datasets - - // calculate how often the group-space appears - var steps = Int(xPosition / (CGFloat(setCount) + CGFloat(barData.groupSpace))) - - var groupSpaceSum = barData.groupSpace * CGFloat(steps) - - var baseNoSpace = xPosition - groupSpaceSum - - dataSetIndex = Int(baseNoSpace) % setCount - xIndex = Int(baseNoSpace) / setCount - - // check bounds - if (xIndex < 0) - { - xIndex = 0 - dataSetIndex = 0 - } - else if (xIndex >= valCount) - { - xIndex = valCount - 1 - dataSetIndex = setCount - 1 - } - - // check bounds - if (dataSetIndex < 0) - { - dataSetIndex = 0 - } - else if (dataSetIndex >= setCount) - { - dataSetIndex = setCount - 1 - } - } - - var dataSet = barData.getDataSetByIndex(dataSetIndex) as! BarChartDataSet! - if (!dataSet.isStacked) - { - return ChartHighlight(xIndex: xIndex, dataSetIndex: dataSetIndex) - } - else - { - return getStackedHighlight(xIndex: xIndex, dataSetIndex: dataSetIndex, yValue: Double(yPosition)) - } - } - - /// This method creates the Highlight object that also indicates which value of a stacked BarEntry has been selected. - internal func getStackedHighlight(#xIndex: Int, dataSetIndex: Int, yValue: Double) -> ChartHighlight! - { - var dataSet = _data.getDataSetByIndex(dataSetIndex) - var entry = dataSet.entryForXIndex(xIndex) as! BarChartDataEntry! - - if (entry !== nil) - { - var stackIndex = entry.getClosestIndexAbove(yValue) - return ChartHighlight(xIndex: xIndex, dataSetIndex: dataSetIndex, stackIndex: stackIndex) - } - else - { - return nil - } + return _highlighter?.getHighlight(x: Double(pt.x), y: Double(pt.y)) } /// Returns the bounding box of the specified Entry in the specified DataSet. Returns null if the Entry could not be found in the charts data. @@ -251,17 +149,6 @@ public class BarChartView: BarLineChartViewBase, BarChartRendererDelegate } } - /// if set to true, all values of a stack are drawn individually, and not just their sum - public var drawValuesForWholeStackEnabled: Bool - { - get { return _drawValuesForWholeStackEnabled; } - set - { - _drawValuesForWholeStackEnabled = newValue - setNeedsDisplay() - } - } - /// if set to true, a grey area is drawn behind each bar that indicates the maximum value public var drawBarShadowEnabled: Bool { @@ -279,9 +166,6 @@ public class BarChartView: BarLineChartViewBase, BarChartRendererDelegate /// returns true if drawing values above bars is enabled, false if not public var isDrawValueAboveBarEnabled: Bool { return drawValueAboveBarEnabled; } - /// returns true if all values of a stack are drawn, and not just their sum - public var isDrawValuesForWholeStackEnabled: Bool { return drawValuesForWholeStackEnabled; } - /// returns true if drawing shadows (maxvalue) for each bar is enabled, false if not public var isDrawBarShadowEnabled: Bool { return drawBarShadowEnabled; } @@ -337,11 +221,6 @@ public class BarChartView: BarLineChartViewBase, BarChartRendererDelegate return drawValueAboveBarEnabled } - public func barChartIsDrawValuesForWholeStackEnabled(renderer: BarChartRenderer) -> Bool - { - return drawValuesForWholeStackEnabled - } - public func barChartIsDrawBarShadowEnabled(renderer: BarChartRenderer) -> Bool { return drawBarShadowEnabled diff --git a/Charts/Classes/Charts/BarLineChartViewBase.swift b/Charts/Classes/Charts/BarLineChartViewBase.swift index 3768f5ec51..82674f2515 100644 --- a/Charts/Classes/Charts/BarLineChartViewBase.swift +++ b/Charts/Classes/Charts/BarLineChartViewBase.swift @@ -101,6 +101,8 @@ public class BarLineChartViewBase: ChartViewBase, UIGestureRecognizerDelegate _xAxisRenderer = ChartXAxisRenderer(viewPortHandler: _viewPortHandler, xAxis: _xAxis, transformer: _leftAxisTransformer) + _highlighter = ChartHighlighter(chart: self) + _tapGestureRecognizer = UITapGestureRecognizer(target: self, action: Selector("tapGestureRecognized:")) _doubleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: Selector("doubleTapGestureRecognized:")) _doubleTapGestureRecognizer.numberOfTapsRequired = 2 @@ -325,12 +327,30 @@ public class BarLineChartViewBase: ChartViewBase, UIGestureRecognizerDelegate // consider starting at zero (0) if (_leftAxis.isStartAtZeroEnabled) { - _leftAxis.axisMinimum = 0.0 + if _leftAxis.axisMinimum < 0.0 && _leftAxis.axisMaximum < 0.0 + { + // If the values are all negative, let's stay in the negative zone + _leftAxis.axisMaximum = 0.0 + } + else + { + // We have positive values, stay in the positive zone + _leftAxis.axisMinimum = 0.0 + } } if (_rightAxis.isStartAtZeroEnabled) { - _rightAxis.axisMinimum = 0.0 + if _rightAxis.axisMinimum < 0.0 && _rightAxis.axisMaximum < 0.0 + { + // If the values are all negative, let's stay in the negative zone + _rightAxis.axisMaximum = 0.0 + } + else + { + // We have positive values, stay in the positive zone + _rightAxis.axisMinimum = 0.0 + } } _leftAxis.axisRange = abs(_leftAxis.axisMaximum - _leftAxis.axisMinimum) @@ -437,9 +457,11 @@ public class BarLineChartViewBase: ChartViewBase, UIGestureRecognizerDelegate } } - public override func getMarkerPosition(#entry: ChartDataEntry, dataSetIndex: Int) -> CGPoint + public override func getMarkerPosition(#entry: ChartDataEntry, highlight: ChartHighlight) -> CGPoint { + let dataSetIndex = highlight.dataSetIndex var xPos = CGFloat(entry.xIndex) + var yPos = entry.value if (self.isKindOfClass(BarChartView)) { @@ -449,10 +471,18 @@ public class BarLineChartViewBase: ChartViewBase, UIGestureRecognizerDelegate var x = CGFloat(entry.xIndex * (_data.dataSetCount - 1) + dataSetIndex) + space * CGFloat(entry.xIndex) + space / 2.0 xPos += x + + if let barEntry = entry as? BarChartDataEntry + { + if barEntry.values != nil && highlight.range !== nil + { + yPos = highlight.range!.to + } + } } // position of the marker depends on selected value index and value - var pt = CGPoint(x: xPos, y: CGFloat(entry.value) * _animator.phaseY) + var pt = CGPoint(x: xPos, y: CGFloat(yPos) * _animator.phaseY) getTransformer(_data.getDataSetByIndex(dataSetIndex)!.axisDependency).pointValueToPixel(&pt) @@ -1261,108 +1291,15 @@ public class BarLineChartViewBase: ChartViewBase, UIGestureRecognizerDelegate } /// Returns the Highlight object (contains x-index and DataSet index) of the selected value at the given touch point inside the Line-, Scatter-, or CandleStick-Chart. - public func getHighlightByTouchPoint(var pt: CGPoint) -> ChartHighlight! + public func getHighlightByTouchPoint(pt: CGPoint) -> ChartHighlight? { if (_dataNotSet || _data === nil) { println("Can't select by touch. No data set.") return nil } - - var valPt = CGPoint() - valPt.x = pt.x - valPt.y = 0.0 - - // take any transformer to determine the x-axis value - _leftAxisTransformer.pixelToValue(&valPt) - - var xTouchVal = valPt.x - var base = floor(xTouchVal) - - var touchOffset = _deltaX * 0.025 - - // touch out of chart - if (xTouchVal < -touchOffset || xTouchVal > _deltaX + touchOffset) - { - return nil - } - - if (base < 0.0) - { - base = 0.0 - } - if (base >= _deltaX) - { - base = _deltaX - 1.0 - } - - var xIndex = Int(base) - - // check if we are more than half of a x-value or not - if (xTouchVal - base > 0.5) - { - xIndex = Int(base + 1.0) - } - - var valsAtIndex = getSelectionDetailsAtIndex(xIndex) - - var leftdist = ChartUtils.getMinimumDistance(valsAtIndex, val: Double(pt.y), axis: .Left) - var rightdist = ChartUtils.getMinimumDistance(valsAtIndex, val: Double(pt.y), axis: .Right) - - if (_data!.getFirstRight() === nil) - { - rightdist = DBL_MAX - } - if (_data!.getFirstLeft() === nil) - { - leftdist = DBL_MAX - } - - var axis: ChartYAxis.AxisDependency = leftdist < rightdist ? .Left : .Right - - var dataSetIndex = ChartUtils.closestDataSetIndex(valsAtIndex, value: Double(pt.y), axis: axis) - - if (dataSetIndex == -1) - { - return nil - } - - return ChartHighlight(xIndex: xIndex, dataSetIndex: dataSetIndex) - } - - /// Returns an array of SelectionDetail objects for the given x-index. The SelectionDetail - /// objects give information about the value at the selected index and the - /// DataSet it belongs to. - public func getSelectionDetailsAtIndex(xIndex: Int) -> [ChartSelectionDetail] - { - var vals = [ChartSelectionDetail]() - - var pt = CGPoint() - - for (var i = 0, count = _data.dataSetCount; i < count; i++) - { - var dataSet = _data.getDataSetByIndex(i) - if (dataSet === nil || !dataSet.isHighlightEnabled) - { - continue - } - - // extract all y-values from all DataSets at the given x-index - let yVal = dataSet!.yValForXIndex(xIndex) - if (yVal.isNaN) - { - continue - } - - pt.y = CGFloat(yVal) - - getTransformer(dataSet!.axisDependency).pointValueToPixel(&pt) - - vals.append(ChartSelectionDetail(value: Double(pt.y), dataSetIndex: i, dataSet: dataSet!)) - } - - return vals + return _highlighter?.getHighlight(x: Double(pt.x), y: Double(pt.y)) } /// Returns the x and y values in the chart at the given touch point @@ -1411,7 +1348,7 @@ public class BarLineChartViewBase: ChartViewBase, UIGestureRecognizerDelegate var h = getHighlightByTouchPoint(pt) if (h !== nil) { - return _data.getDataSetByIndex(h.dataSetIndex) as! BarLineScatterCandleChartDataSet! + return _data.getDataSetByIndex(h!.dataSetIndex) as! BarLineScatterCandleChartDataSet! } return nil } diff --git a/Charts/Classes/Renderers/BarChartRenderer.swift b/Charts/Classes/Renderers/BarChartRenderer.swift index 181d91034a..cdac1ef88c 100644 --- a/Charts/Classes/Renderers/BarChartRenderer.swift +++ b/Charts/Classes/Renderers/BarChartRenderer.swift @@ -28,7 +28,6 @@ public protocol BarChartRendererDelegate func barChartRendererChartXMin(renderer: BarChartRenderer) -> Double func barChartIsDrawHighlightArrowEnabled(renderer: BarChartRenderer) -> Bool func barChartIsDrawValueAboveBarEnabled(renderer: BarChartRenderer) -> Bool - func barChartIsDrawValuesForWholeStackEnabled(renderer: BarChartRenderer) -> Bool func barChartIsDrawBarShadowEnabled(renderer: BarChartRenderer) -> Bool func barChartIsInverted(renderer: BarChartRenderer, axis: ChartYAxis.AxisDependency) -> Bool } @@ -151,8 +150,9 @@ public class BarChartRenderer: ChartDataRendererBase } else { - var allPos = e.positiveSum - var allNeg = e.negativeSum + var posY = 0.0 + var negY = -e.negativeSum + var yStart = 0.0 // if drawing the bar shadow is enabled if (drawBarShadowEnabled) @@ -191,36 +191,41 @@ public class BarChartRenderer: ChartDataRendererBase } // fill the stack - for (var k = 0; k < vals.count; k++) + for (var k = 0; k < vals!.count; k++) { - let value = vals[k] + let value = vals![k] if value >= 0.0 { - allPos -= value - y = value + allPos + y = posY + yStart = posY + value + posY = yStart } else { - allNeg -= abs(value) - y = value + allNeg + y = negY + yStart = negY + abs(value) + negY += abs(value) } var left = x - barWidth + barSpaceHalf var right = x + barWidth - barSpaceHalf - var top = y >= 0.0 ? CGFloat(y) : 0 - var bottom = y <= 0.0 ? CGFloat(y) : 0 - - // multiply the height of the rect with the phase - if (top > 0) + var top: CGFloat, bottom: CGFloat + if isInverted { - top *= phaseY + bottom = y >= yStart ? CGFloat(y) : CGFloat(yStart) + top = y <= yStart ? CGFloat(y) : CGFloat(yStart) } else { - bottom *= phaseY + top = y >= yStart ? CGFloat(y) : CGFloat(yStart) + bottom = y <= yStart ? CGFloat(y) : CGFloat(yStart) } + // multiply the height of the rect with the phase + top *= phaseY + bottom *= phaseY + barRect.origin.x = left barRect.size.width = right - left barRect.origin.y = top @@ -280,14 +285,13 @@ public class BarChartRenderer: ChartDataRendererBase var dataSets = barData.dataSets var drawValueAboveBar = delegate!.barChartIsDrawValueAboveBarEnabled(self) - var drawValuesForWholeStackEnabled = delegate!.barChartIsDrawValuesForWholeStackEnabled(self) var posOffset: CGFloat var negOffset: CGFloat for (var i = 0, count = barData.dataSetCount; i < count; i++) { - var dataSet = dataSets[i] + var dataSet = dataSets[i] as! BarChartDataSet if (!dataSet.isDrawValuesEnabled) { @@ -297,7 +301,7 @@ public class BarChartRenderer: ChartDataRendererBase var isInverted = delegate!.barChartIsInverted(self, axis: dataSet.axisDependency) // calculate the correct offset depending on the draw position of the value - let valueOffsetPlus: CGFloat = 5.0 + let valueOffsetPlus: CGFloat = 4.5 var valueFont = dataSet.valueFont var valueTextHeight = valueFont.lineHeight posOffset = (drawValueAboveBar ? -(valueTextHeight + valueOffsetPlus) : valueOffsetPlus) @@ -324,7 +328,7 @@ public class BarChartRenderer: ChartDataRendererBase var valuePoints = getTransformedValues(trans: trans, entries: entries, dataSetIndex: i) // if only single values are drawn (sum) - if (!drawValuesForWholeStackEnabled) + if (!dataSet.isStacked) { for (var j = 0, count = Int(ceil(CGFloat(valuePoints.count) * _animator.phaseX)); j < count; j++) { @@ -352,16 +356,16 @@ public class BarChartRenderer: ChartDataRendererBase } else { - // if each value of a potential stack should be drawn + // if we have stacks for (var j = 0, count = Int(ceil(CGFloat(valuePoints.count) * _animator.phaseX)); j < count; j++) { var e = entries[j] - var vals = e.values + let values = e.values // we still draw stacked bars, but there is one non-stacked in between - if (vals == nil) + if (values == nil) { if (!viewPortHandler.isInBoundsRight(valuePoints[j].x)) { @@ -384,9 +388,13 @@ public class BarChartRenderer: ChartDataRendererBase } else { + // draw stack values + + let vals = values! var transformed = [CGPoint]() - var allPos = e.positiveSum - var allNeg = e.negativeSum + + var posY = 0.0 + var negY = -e.negativeSum for (var k = 0; k < vals.count; k++) { @@ -395,13 +403,13 @@ public class BarChartRenderer: ChartDataRendererBase if value >= 0.0 { - allPos -= value - y = value + allPos + posY += value + y = posY } else { - allNeg -= abs(value) - y = value + allNeg + y = negY + negY -= value } transformed.append(CGPoint(x: 0.0, y: CGFloat(y) * _animator.phaseY)) @@ -507,8 +515,8 @@ public class BarChartRenderer: ChartDataRendererBase if (isStack) { - y1 = e.positiveSum - y2 = -e.negativeSum + y1 = h.range?.from ?? 0.0 + y2 = (h.range?.to ?? 0.0) * Double(_animator.phaseY) } else { diff --git a/Charts/Classes/Renderers/HorizontalBarChartRenderer.swift b/Charts/Classes/Renderers/HorizontalBarChartRenderer.swift index 735970abf0..6c6572a2b8 100644 --- a/Charts/Classes/Renderers/HorizontalBarChartRenderer.swift +++ b/Charts/Classes/Renderers/HorizontalBarChartRenderer.swift @@ -17,9 +17,6 @@ import UIKit public class HorizontalBarChartRenderer: BarChartRenderer { - private var xOffset: CGFloat = 0.0 - private var yOffset: CGFloat = 0.0 - public override init(delegate: BarChartRendererDelegate?, animator: ChartAnimator?, viewPortHandler: ChartViewPortHandler) { super.init(delegate: delegate, animator: animator, viewPortHandler: viewPortHandler) @@ -58,7 +55,7 @@ public class HorizontalBarChartRenderer: BarChartRenderer + groupSpace * CGFloat(e.xIndex) + groupSpaceHalf var vals = e.values - if (!containsStacks || vals == nil) + if (!containsStacks || values == nil) { y = e.value @@ -112,8 +109,10 @@ public class HorizontalBarChartRenderer: BarChartRenderer } else { - var allPos = e.positiveSum - var allNeg = e.negativeSum + let vals = values! + var posY = 0.0 + var negY = -e.negativeSum + var yStart = 0.0 // if drawing the bar shadow is enabled if (drawBarShadowEnabled) @@ -158,30 +157,35 @@ public class HorizontalBarChartRenderer: BarChartRenderer if value >= 0.0 { - allPos -= value - y = value + allPos + y = posY + yStart = posY + value + posY = yStart } else { - allNeg -= abs(value) - y = value + allNeg + y = negY + yStart = negY + abs(value) + negY += abs(value) } var bottom = x - barWidth + barSpaceHalf var top = x + barWidth - barSpaceHalf - var right = y >= 0.0 ? CGFloat(y) : 0.0 - var left = y <= 0.0 ? CGFloat(y) : 0.0 - - // multiply the height of the rect with the phase - if (right > 0) + var right: CGFloat, left: CGFloat + if isInverted { - right *= phaseY + left = y >= yStart ? CGFloat(y) : CGFloat(yStart) + right = y <= yStart ? CGFloat(y) : CGFloat(yStart) } else { - left *= phaseY + right = y >= yStart ? CGFloat(y) : CGFloat(yStart) + left = y <= yStart ? CGFloat(y) : CGFloat(yStart) } + // multiply the height of the rect with the phase + right *= phaseY + left *= phaseY + barRect.origin.x = left barRect.size.width = right - left barRect.origin.y = top @@ -189,14 +193,14 @@ public class HorizontalBarChartRenderer: BarChartRenderer trans.rectValueToPixel(&barRect) - if (k == 0 && !viewPortHandler.isInBoundsLeft(barRect.origin.x + barRect.size.width)) + if (k == 0 && !viewPortHandler.isInBoundsTop(barRect.origin.y + barRect.size.height)) { // Skip to next bar break } // avoid drawing outofbounds values - if (!viewPortHandler.isInBoundsRight(barRect.origin.x)) + if (!viewPortHandler.isInBoundsBottom(barRect.origin.y)) { break } @@ -245,7 +249,6 @@ public class HorizontalBarChartRenderer: BarChartRenderer var dataSets = barData.dataSets var drawValueAboveBar = delegate!.barChartIsDrawValueAboveBarEnabled(self) - var drawValuesForWholeStackEnabled = delegate!.barChartIsDrawValuesForWholeStackEnabled(self) let textAlign = drawValueAboveBar ? NSTextAlignment.Left : NSTextAlignment.Right @@ -255,7 +258,7 @@ public class HorizontalBarChartRenderer: BarChartRenderer for (var i = 0, count = barData.dataSetCount; i < count; i++) { - var dataSet = dataSets[i] + var dataSet = dataSets[i] as! BarChartDataSet if (!dataSet.isDrawValuesEnabled) { @@ -281,18 +284,18 @@ public class HorizontalBarChartRenderer: BarChartRenderer var valuePoints = getTransformedValues(trans: trans, entries: entries, dataSetIndex: i) // if only single values are drawn (sum) - if (!drawValuesForWholeStackEnabled) + if (!dataSet.isStacked) { for (var j = 0, count = Int(ceil(CGFloat(valuePoints.count) * _animator.phaseX)); j < count; j++) { - if (!viewPortHandler.isInBoundsX(valuePoints[j].x)) + if (!viewPortHandler.isInBoundsTop(valuePoints[j].y)) { - continue + break } - if (!viewPortHandler.isInBoundsTop(valuePoints[j].y)) + if (!viewPortHandler.isInBoundsX(valuePoints[j].x)) { - break + continue } if (!viewPortHandler.isInBoundsBottom(valuePoints[j].y)) @@ -332,19 +335,19 @@ public class HorizontalBarChartRenderer: BarChartRenderer { var e = entries[j] - var vals = e.values + let values = e.values // we still draw stacked bars, but there is one non-stacked in between - if (vals == nil) + if (values == nil) { - if (!viewPortHandler.isInBoundsX(valuePoints[j].x)) + if (!viewPortHandler.isInBoundsTop(valuePoints[j].y)) { - continue + break } - if (!viewPortHandler.isInBoundsTop(valuePoints[j].y)) + if (!viewPortHandler.isInBoundsX(valuePoints[j].x)) { - break + continue } if (!viewPortHandler.isInBoundsBottom(valuePoints[j].y)) @@ -377,9 +380,11 @@ public class HorizontalBarChartRenderer: BarChartRenderer } else { + let vals = values! var transformed = [CGPoint]() - var allPos = e.positiveSum - var allNeg = e.negativeSum + + var posY = 0.0 + var negY = -e.negativeSum for (var k = 0; k < vals.count; k++) { @@ -388,13 +393,13 @@ public class HorizontalBarChartRenderer: BarChartRenderer if value >= 0.0 { - allPos -= value - y = value + allPos + posY += value + y = posY } else { - allNeg -= abs(value) - y = value + allNeg + y = negY + negY -= value } transformed.append(CGPoint(x: CGFloat(y) * _animator.phaseY, y: 0.0)) @@ -421,14 +426,14 @@ public class HorizontalBarChartRenderer: BarChartRenderer var x = transformed[k].x + (val >= 0 ? posOffset : negOffset) var y = valuePoints[j].y - if (!viewPortHandler.isInBoundsX(x)) + if (!viewPortHandler.isInBoundsTop(y)) { - continue + break } - if (!viewPortHandler.isInBoundsTop(y)) + if (!viewPortHandler.isInBoundsX(x)) { - break + continue } if (!viewPortHandler.isInBoundsBottom(y)) diff --git a/Charts/Classes/Utils/ChartUtils.swift b/Charts/Classes/Utils/ChartUtils.swift old mode 100755 new mode 100644 index bcbacdf33c..2c3ec826b2 --- a/Charts/Classes/Utils/ChartUtils.swift +++ b/Charts/Classes/Utils/ChartUtils.swift @@ -63,10 +63,10 @@ internal class ChartUtils } } - /// Returns the index of the DataSet that contains the closest value on the y-axis. This is needed for highlighting. + /// Returns the index of the DataSet that contains the closest value on the y-axis. This will return -Integer.MAX_VALUE if failure. internal class func closestDataSetIndex(valsAtIndex: [ChartSelectionDetail], value: Double, axis: ChartYAxis.AxisDependency?) -> Int { - var index = -1 + var index = -Int.max var distance = DBL_MAX for (var i = 0; i < valsAtIndex.count; i++) diff --git a/ChartsDemo/Classes/Demos/MultipleBarChartViewController.m b/ChartsDemo/Classes/Demos/MultipleBarChartViewController.m index cadcb861fc..6ed911b163 100644 --- a/ChartsDemo/Classes/Demos/MultipleBarChartViewController.m +++ b/ChartsDemo/Classes/Demos/MultipleBarChartViewController.m @@ -124,7 +124,7 @@ - (void)setDataCount:(int)count range:(double)range NSMutableArray *dataSets = [[NSMutableArray alloc] init]; [dataSets addObject:set1]; [dataSets addObject:set2]; - //[dataSets addObject:set3]; + [dataSets addObject:set3]; BarChartData *data = [[BarChartData alloc] initWithXVals:xVals dataSets:dataSets]; data.groupSpace = 0.8;