diff --git a/Source/Charts/Highlight/BarHighlighter.swift b/Source/Charts/Highlight/BarHighlighter.swift index ff115fe147..2bb81a2a33 100644 --- a/Source/Charts/Highlight/BarHighlighter.swift +++ b/Source/Charts/Highlight/BarHighlighter.swift @@ -17,30 +17,25 @@ open class BarHighlighter: ChartHighlighter { open override func getHighlight(x: CGFloat, y: CGFloat) -> Highlight? { - let high = super.getHighlight(x: x, y: y) + guard + let barData = (self.chart as? BarChartDataProvider)?.barData, + let high = super.getHighlight(x: x, y: y) + else { return nil } - if high == nil + let pos = getValsForTouch(x: x, y: y) + + if let set = barData.getDataSetByIndex(high.dataSetIndex) as? IBarChartDataSet, + set.isStacked { - return nil + return getStackedHighlight(high: high, + set: set, + xValue: Double(pos.x), + yValue: Double(pos.y)) } - - if let barData = (self.chart as? BarChartDataProvider)?.barData + else { - let pos = getValsForTouch(x: x, y: y) - - if - let set = barData.getDataSetByIndex(high!.dataSetIndex) as? IBarChartDataSet, - set.isStacked - { - return getStackedHighlight(high: high!, - set: set, - xValue: Double(pos.x), - yValue: Double(pos.y)) - } - return high } - return nil } internal override func getDistance(x1: CGFloat, y1: CGFloat, x2: CGFloat, y2: CGFloat) -> CGFloat @@ -75,25 +70,23 @@ open class BarHighlighter: ChartHighlighter return high } - if let ranges = entry.ranges, + guard + let ranges = entry.ranges, ranges.count > 0 - { - let stackIndex = getClosestStackIndex(ranges: ranges, value: yValue) - - let pixel = chart - .getTransformer(forAxis: set.axisDependency) - .pixelForValues(x: high.x, y: ranges[stackIndex].to) - - return Highlight(x: entry.x, - y: entry.y, - xPx: pixel.x, - yPx: pixel.y, - dataSetIndex: high.dataSetIndex, - stackIndex: stackIndex, - axis: high.axis) - } - - return nil + else { return nil } + + let stackIndex = getClosestStackIndex(ranges: ranges, value: yValue) + let pixel = chart + .getTransformer(forAxis: set.axisDependency) + .pixelForValues(x: high.x, y: ranges[stackIndex].to) + + return Highlight(x: entry.x, + y: entry.y, + xPx: pixel.x, + yPx: pixel.y, + dataSetIndex: high.dataSetIndex, + stackIndex: stackIndex, + axis: high.axis) } /// - returns: The index of the closest value inside the values array / ranges (stacked barchart) to the value given as a parameter. @@ -102,14 +95,11 @@ open class BarHighlighter: ChartHighlighter /// - returns: @objc open func getClosestStackIndex(ranges: [Range]?, value: Double) -> Int { - if ranges == nil - { - return 0 - } - + guard let ranges = ranges else { return 0 } + var stackIndex = 0 - for range in ranges! + for range in ranges { if range.contains(value) { @@ -121,8 +111,8 @@ open class BarHighlighter: ChartHighlighter } } - let length = max(ranges!.count - 1, 0) + let length = max(ranges.count - 1, 0) - return (value > ranges![length].to) ? length : 0 + return (value > ranges[length].to) ? length : 0 } } diff --git a/Source/Charts/Highlight/ChartHighlighter.swift b/Source/Charts/Highlight/ChartHighlighter.swift index 719f44e757..3fe679f20d 100644 --- a/Source/Charts/Highlight/ChartHighlighter.swift +++ b/Source/Charts/Highlight/ChartHighlighter.swift @@ -25,7 +25,6 @@ open class ChartHighlighter : NSObject, IHighlighter open func getHighlight(x: CGFloat, y: CGFloat) -> Highlight? { let xVal = Double(getValsForTouch(x: x, y: y).x) - return getHighlight(xValue: xVal, x: x, y: y) } @@ -34,11 +33,10 @@ open class ChartHighlighter : NSObject, IHighlighter /// - returns: @objc open func getValsForTouch(x: CGFloat, y: CGFloat) -> CGPoint { - guard let chart = self.chart as? BarLineScatterCandleBubbleChartDataProvider - else { return CGPoint.zero } + guard let chart = self.chart as? BarLineScatterCandleBubbleChartDataProvider else { return .zero } // take any transformer to determine the values - return chart.getTransformer(forAxis: YAxis.AxisDependency.left).valueForTouchPoint(x: x, y: y) + return chart.getTransformer(forAxis: .left).valueForTouchPoint(x: x, y: y) } /// - returns: The corresponding ChartHighlight for a given x-value and xy-touch position in pixels. @@ -48,19 +46,15 @@ open class ChartHighlighter : NSObject, IHighlighter /// - returns: @objc open func getHighlight(xValue xVal: Double, x: CGFloat, y: CGFloat) -> Highlight? { - guard let chart = chart - else { return nil } + guard let chart = chart else { return nil } let closestValues = getHighlights(xValue: xVal, x: x, y: y) - if closestValues.isEmpty - { - return nil - } + guard !closestValues.isEmpty else { return nil } - let leftAxisMinDist = getMinimumDistance(closestValues: closestValues, y: y, axis: YAxis.AxisDependency.left) - let rightAxisMinDist = getMinimumDistance(closestValues: closestValues, y: y, axis: YAxis.AxisDependency.right) + let leftAxisMinDist = getMinimumDistance(closestValues: closestValues, y: y, axis: .left) + let rightAxisMinDist = getMinimumDistance(closestValues: closestValues, y: y, axis: .right) - let axis = leftAxisMinDist < rightAxisMinDist ? YAxis.AxisDependency.left : YAxis.AxisDependency.right + let axis: YAxis.AxisDependency = leftAxisMinDist < rightAxisMinDist ? .left : .right let detail = closestSelectionDetailByPixel(closestValues: closestValues, x: x, y: y, axis: axis, minSelectionDistance: chart.maxHighlightDistance) @@ -77,24 +71,18 @@ open class ChartHighlighter : NSObject, IHighlighter { var vals = [Highlight]() - guard let - data = self.data - else { return vals } + guard let data = self.data else { return vals } for i in 0 ..< data.dataSetCount { - guard let dataSet = data.getDataSetByIndex(i) + guard + let dataSet = data.getDataSetByIndex(i), + dataSet.isHighlightEnabled // don't include datasets that cannot be highlighted else { continue } - // don't include datasets that cannot be highlighted - if !dataSet.isHighlightEnabled - { - continue - } - + // extract all y-values from all DataSets at the given x-value. // some datasets (i.e bubble charts) make sense to have multiple values for an x-value. We'll have to find a way to handle that later on. It's more complicated now when x-indices are floating point. - vals.append(contentsOf: buildHighlights(dataSet: dataSet, dataSetIndex: i, xValue: xValue, rounding: .closest)) } @@ -110,24 +98,21 @@ open class ChartHighlighter : NSObject, IHighlighter { var highlights = [Highlight]() - guard let chart = self.chart as? BarLineScatterCandleBubbleChartDataProvider - else { return highlights } + guard let chart = self.chart as? BarLineScatterCandleBubbleChartDataProvider else { return highlights } var entries = set.entriesForXValue(xValue) - if entries.count == 0 + if entries.count == 0, let closest = set.entryForXValue(xValue, closestToY: .nan, rounding: rounding) { // Try to find closest x-value and take all entries for that x-value - if let closest = set.entryForXValue(xValue, closestToY: Double.nan, rounding: rounding) - { - entries = set.entriesForXValue(closest.x) - } + entries = set.entriesForXValue(closest.x) } for e in entries { let px = chart.getTransformer(forAxis: set.axisDependency).pixelForValues(x: e.x, y: e.y) - - highlights.append(Highlight(x: e.x, y: e.y, xPx: px.x, yPx: px.y, dataSetIndex: dataSetIndex, axis: set.axisDependency)) + + let highlight = Highlight(x: e.x, y: e.y, xPx: px.x, yPx: px.y, dataSetIndex: dataSetIndex, axis: set.axisDependency) + highlights.append(highlight) } return highlights @@ -146,14 +131,12 @@ open class ChartHighlighter : NSObject, IHighlighter var distance = minSelectionDistance var closest: Highlight? - for i in 0 ..< closestValues.count + for high in closestValues { - let high = closestValues[i] - if axis == nil || high.axis == axis { let cDistance = getDistance(x1: x, y1: y, x2: high.xPx, y2: high.yPx) - + if cDistance < distance { closest = high @@ -173,10 +156,8 @@ open class ChartHighlighter : NSObject, IHighlighter { var distance = CGFloat.greatestFiniteMagnitude - for i in 0 ..< closestValues.count + for high in closestValues { - let high = closestValues[i] - if high.axis == axis { let tempDistance = abs(getHighlightPos(high: high) - y) diff --git a/Source/Charts/Highlight/CombinedHighlighter.swift b/Source/Charts/Highlight/CombinedHighlighter.swift index f7ca82f71c..7053df09d3 100644 --- a/Source/Charts/Highlight/CombinedHighlighter.swift +++ b/Source/Charts/Highlight/CombinedHighlighter.swift @@ -30,46 +30,38 @@ open class CombinedHighlighter: ChartHighlighter { var vals = [Highlight]() - guard let chart = self.chart as? CombinedChartDataProvider + guard + let chart = self.chart as? CombinedChartDataProvider, + let dataObjects = chart.combinedData?.allData else { return vals } - if let dataObjects = chart.combinedData?.allData + for i in 0.. Highlight? { - if let barData = self.chart?.data as? BarChartData + guard let barData = self.chart?.data as? BarChartData else { return nil } + + let pos = getValsForTouch(x: y, y: x) + guard let high = getHighlight(xValue: Double(pos.y), x: y, y: x) else { return nil } + + if let set = barData.getDataSetByIndex(high.dataSetIndex) as? IBarChartDataSet, + set.isStacked { - let pos = getValsForTouch(x: y, y: x) - - guard let high = getHighlight(xValue: Double(pos.y), x: y, y: x) - else { return nil } - - if let set = barData.getDataSetByIndex(high.dataSetIndex) as? IBarChartDataSet, - set.isStacked - { - return getStackedHighlight(high: high, - set: set, - xValue: Double(pos.y), - yValue: Double(pos.x)) - } - - return high + return getStackedHighlight(high: high, + set: set, + xValue: Double(pos.y), + yValue: Double(pos.x)) } - return nil + + return high } internal override func buildHighlights( @@ -46,17 +42,13 @@ open class HorizontalBarHighlighter: BarHighlighter { var highlights = [Highlight]() - guard let chart = self.chart as? BarLineScatterCandleBubbleChartDataProvider - else { return highlights } + guard let chart = self.chart as? BarLineScatterCandleBubbleChartDataProvider else { return highlights } var entries = set.entriesForXValue(xValue) - if entries.count == 0 + if entries.count == 0, let closest = set.entryForXValue(xValue, closestToY: .nan, rounding: rounding) { // Try to find closest x-value and take all entries for that x-value - if let closest = set.entryForXValue(xValue, closestToY: Double.nan, rounding: rounding) - { - entries = set.entriesForXValue(closest.x) - } + entries = set.entriesForXValue(closest.x) } for e in entries diff --git a/Source/Charts/Highlight/PieHighlighter.swift b/Source/Charts/Highlight/PieHighlighter.swift index 2d0a18534e..54bb3d7b83 100644 --- a/Source/Charts/Highlight/PieHighlighter.swift +++ b/Source/Charts/Highlight/PieHighlighter.swift @@ -17,12 +17,11 @@ open class PieHighlighter: PieRadarHighlighter { open override func closestHighlight(index: Int, x: CGFloat, y: CGFloat) -> Highlight? { - guard let set = chart?.data?.dataSets[0] + guard + let set = chart?.data?.dataSets[0], + let entry = set.entryForIndex(index) else { return nil } - - guard let entry = set.entryForIndex(index) - else { return nil } - + return Highlight(x: Double(index), y: entry.y, xPx: x, yPx: y, dataSetIndex: 0, axis: set.axisDependency) } } diff --git a/Source/Charts/Highlight/PieRadarHighlighter.swift b/Source/Charts/Highlight/PieRadarHighlighter.swift index abcea4aca8..ec77e72f5b 100644 --- a/Source/Charts/Highlight/PieRadarHighlighter.swift +++ b/Source/Charts/Highlight/PieRadarHighlighter.swift @@ -17,38 +17,36 @@ open class PieRadarHighlighter: ChartHighlighter { open override func getHighlight(x: CGFloat, y: CGFloat) -> Highlight? { - guard let chart = self.chart as? PieRadarChartViewBase - else { return nil } + guard let chart = self.chart as? PieRadarChartViewBase else { return nil } let touchDistanceToCenter = chart.distanceToCenter(x: x, y: y) // check if a slice was touched - if touchDistanceToCenter > chart.radius + guard touchDistanceToCenter <= chart.radius else { // if no slice was touched, highlight nothing return nil } + + var angle = chart.angleForPoint(x: x ,y: y) + + if chart is PieChartView + { + angle /= CGFloat(chart.chartAnimator.phaseY) + } + + let index = chart.indexForAngle(angle) + + // check if the index could be found + if index < 0 || index >= chart.data?.maxEntryCountSet?.entryCount ?? 0 + { + return nil + } else { - var angle = chart.angleForPoint(x: x ,y: y) - - if chart is PieChartView - { - angle /= CGFloat(chart.chartAnimator.phaseY) - } - - let index = chart.indexForAngle(angle) - - // check if the index could be found - if index < 0 || index >= chart.data?.maxEntryCountSet?.entryCount ?? 0 - { - return nil - } - else - { - return closestHighlight(index: index, x: x, y: y) - } + return closestHighlight(index: index, x: x, y: y) } + } /// - returns: The closest Highlight object of the given objects based on the touch position inside the chart. diff --git a/Source/Charts/Highlight/RadarHighlighter.swift b/Source/Charts/Highlight/RadarHighlighter.swift index bedd95037c..d54193c2f8 100644 --- a/Source/Charts/Highlight/RadarHighlighter.swift +++ b/Source/Charts/Highlight/RadarHighlighter.swift @@ -17,14 +17,13 @@ open class RadarHighlighter: PieRadarHighlighter { open override func closestHighlight(index: Int, x: CGFloat, y: CGFloat) -> Highlight? { - guard let chart = self.chart as? RadarChartView - else { return nil } + guard let chart = self.chart as? RadarChartView else { return nil } let highlights = getHighlights(forIndex: index) let distanceToCenter = Double(chart.distanceToCenter(x: x, y: y) / chart.factor) - var closest: Highlight? = nil + var closest: Highlight? var distance = Double.greatestFiniteMagnitude for high in highlights @@ -48,28 +47,30 @@ open class RadarHighlighter: PieRadarHighlighter { var vals = [Highlight]() - guard let chart = self.chart as? RadarChartView + guard + let chart = self.chart as? RadarChartView, + let chartData = chart.data else { return vals } let phaseX = chart.chartAnimator.phaseX let phaseY = chart.chartAnimator.phaseY let sliceangle = chart.sliceAngle let factor = chart.factor - - for i in 0..<(chart.data?.dataSetCount ?? 0) + + for i in chartData.dataSets.indices { - guard let dataSet = chart.data?.getDataSetByIndex(i) - else { continue } - - guard let entry = dataSet.entryForIndex(index) + guard + let dataSet = chartData.getDataSetByIndex(i), + let entry = dataSet.entryForIndex(index) else { continue } let y = (entry.y - chart.chartYMin) let p = chart.centerOffsets.moving(distance: CGFloat(y) * factor * CGFloat(phaseY), atAngle: sliceangle * CGFloat(index) * CGFloat(phaseX) + chart.rotationAngle) - - vals.append(Highlight(x: Double(index), y: entry.y, xPx: p.x, yPx: p.y, dataSetIndex: i, axis: dataSet.axisDependency)) + + let highlight = Highlight(x: Double(index), y: entry.y, xPx: p.x, yPx: p.y, dataSetIndex: i, axis: dataSet.axisDependency) + vals.append(highlight) } return vals