From 4285bbcc57de559a43c2ecf479708c7b22e53208 Mon Sep 17 00:00:00 2001 From: jjatie Date: Mon, 15 Jan 2018 20:23:29 -0400 Subject: [PATCH] Chartdata collection conformance (#3023) * Added Collection conformances MutableCollection RandomAccessCollection RangeReplaceableCollection * Fixed required initializers * ChartData adopts ExressibleByArrayLiteral * Updates for PR Also added remove subrange. * PR review fixes * Removed unnecessary `get` from subscripts. * Disabled `remove(at:)` for CombinedChartView * Relocated `appendEntry(_:todataSet:)` * Removed methods from CombinedChartData --- .../Standard/BarChartData.swift | 9 +- .../BarLineScatterCandleBubbleChartData.swift | 7 +- .../Standard/BubbleChartData.swift | 9 +- .../Standard/CandleChartData.swift | 7 +- .../Implementations/Standard/ChartData.swift | 199 ++++++++++++++++-- .../Standard/CombinedChartData.swift | 7 +- .../Standard/LineChartData.swift | 7 +- .../Standard/PieChartData.swift | 7 +- .../Standard/RadarChartData.swift | 9 +- .../Standard/ScatterChartData.swift | 7 +- 10 files changed, 240 insertions(+), 28 deletions(-) diff --git a/Source/Charts/Data/Implementations/Standard/BarChartData.swift b/Source/Charts/Data/Implementations/Standard/BarChartData.swift index df85bbafc1..8bffa305da 100644 --- a/Source/Charts/Data/Implementations/Standard/BarChartData.swift +++ b/Source/Charts/Data/Implementations/Standard/BarChartData.swift @@ -14,7 +14,7 @@ import CoreGraphics open class BarChartData: BarLineScatterCandleBubbleChartData { - public override init() + public required init() { super.init() } @@ -23,7 +23,12 @@ open class BarChartData: BarLineScatterCandleBubbleChartData { super.init(dataSets: dataSets) } - + + public required init(arrayLiteral elements: ChartDataSetProtocol...) + { + super.init(dataSets: elements) + } + /// The width of the bars on the x-axis, in values (not pixels) /// /// **default**: 0.85 diff --git a/Source/Charts/Data/Implementations/Standard/BarLineScatterCandleBubbleChartData.swift b/Source/Charts/Data/Implementations/Standard/BarLineScatterCandleBubbleChartData.swift index 0325328f84..715709708b 100644 --- a/Source/Charts/Data/Implementations/Standard/BarLineScatterCandleBubbleChartData.swift +++ b/Source/Charts/Data/Implementations/Standard/BarLineScatterCandleBubbleChartData.swift @@ -13,7 +13,7 @@ import Foundation open class BarLineScatterCandleBubbleChartData: ChartData { - public override init() + public required init() { super.init() } @@ -22,4 +22,9 @@ open class BarLineScatterCandleBubbleChartData: ChartData { super.init(dataSets: dataSets) } + + public required init(arrayLiteral elements: ChartDataSetProtocol...) + { + super.init(dataSets: elements) + } } diff --git a/Source/Charts/Data/Implementations/Standard/BubbleChartData.swift b/Source/Charts/Data/Implementations/Standard/BubbleChartData.swift index f514340881..89fd484804 100644 --- a/Source/Charts/Data/Implementations/Standard/BubbleChartData.swift +++ b/Source/Charts/Data/Implementations/Standard/BubbleChartData.swift @@ -14,7 +14,7 @@ import CoreGraphics open class BubbleChartData: BarLineScatterCandleBubbleChartData { - public override init() + public required init() { super.init() } @@ -23,7 +23,12 @@ open class BubbleChartData: BarLineScatterCandleBubbleChartData { super.init(dataSets: dataSets) } - + + public required init(arrayLiteral elements: ChartDataSetProtocol...) + { + super.init(dataSets: elements) + } + /// Sets the width of the circle that surrounds the bubble when highlighted for all DataSet objects this data object contains @objc open func setHighlightCircleWidth(_ width: CGFloat) { diff --git a/Source/Charts/Data/Implementations/Standard/CandleChartData.swift b/Source/Charts/Data/Implementations/Standard/CandleChartData.swift index 5501ebc98b..2c0d3bd443 100644 --- a/Source/Charts/Data/Implementations/Standard/CandleChartData.swift +++ b/Source/Charts/Data/Implementations/Standard/CandleChartData.swift @@ -13,7 +13,7 @@ import Foundation open class CandleChartData: BarLineScatterCandleBubbleChartData { - public override init() + public required init() { super.init() } @@ -22,4 +22,9 @@ open class CandleChartData: BarLineScatterCandleBubbleChartData { super.init(dataSets: dataSets) } + + public required init(arrayLiteral elements: ChartDataSetProtocol...) + { + super.init(dataSets: elements) + } } diff --git a/Source/Charts/Data/Implementations/Standard/ChartData.swift b/Source/Charts/Data/Implementations/Standard/ChartData.swift index bb1bd869a3..5acb2ea926 100644 --- a/Source/Charts/Data/Implementations/Standard/ChartData.swift +++ b/Source/Charts/Data/Implementations/Standard/ChartData.swift @@ -11,7 +11,7 @@ import Foundation -open class ChartData: NSObject +open class ChartData: NSObject, ExpressibleByArrayLiteral { internal var _yMax: Double = -Double.greatestFiniteMagnitude internal var _yMin: Double = Double.greatestFiniteMagnitude @@ -24,13 +24,20 @@ open class ChartData: NSObject internal var _dataSets = [ChartDataSetProtocol]() - public override init() + public override required init() { super.init() - - _dataSets = [ChartDataSetProtocol]() } - + + public required init(arrayLiteral elements: ChartDataSetProtocol...) + { + super.init() + + _dataSets = elements + + self.initialize(dataSets: _dataSets) + } + @objc public init(dataSets: [ChartDataSetProtocol]?) { super.init() @@ -491,22 +498,20 @@ open class ChartData: NSObject } /// Adds an Entry to the DataSet at the specified index. Entries are added to the end of the list. - @objc open func addEntry(_ e: ChartDataEntry, dataSetIndex: Int) + @objc(addEntry:dataSetIndex:) + open func appendEntry(_ e: ChartDataEntry, toDataSet dataSetIndex: Index) { - if _dataSets.count > dataSetIndex && dataSetIndex >= 0 - { - let set = _dataSets[dataSetIndex] - - if !set.addEntry(e) { return } - - calcMinMax(entry: e, axis: set.axisDependency) - } - else + guard indices.contains(dataSetIndex) else { print("ChartData.addEntry() - Cannot add Entry because dataSetIndex too high or too low.", terminator: "\n") + return } + + let set = self[dataSetIndex] + if !set.addEntry(e) { return } + calcMinMax(entry: e, axis: set.axisDependency) } - + /// Removes the given Entry object from the DataSet at the specified index. @objc @discardableResult open func removeEntry(_ entry: ChartDataEntry, dataSetIndex: Int) -> Bool { @@ -757,3 +762,165 @@ open class ChartData: NSObject return max } } + +// MARK: MutableCollection +extension ChartData: MutableCollection +{ + public typealias Index = Int + public typealias Element = ChartDataSetProtocol + + public var startIndex: Index + { + return _dataSets.startIndex + } + + public var endIndex: Index + { + return _dataSets.endIndex + } + + public func index(after: Index) -> Index + { + return _dataSets.index(after: after) + } + + public subscript(position: Index) -> Element + { + get{ return _dataSets[position] } + set{ self._dataSets[position] = newValue } + } +} + +// MARK: RandomAccessCollection +extension ChartData: RandomAccessCollection +{ + public func index(before: Index) -> Index + { + return _dataSets.index(before: before) + } +} + +// MARK: RangeReplaceableCollection +extension ChartData: RangeReplaceableCollection +{ + public func append(_ newElement: Element) + { + guard !(self is CombinedChartData) else + { + fatalError("append(_:) not supported for CombinedData") + } + + _dataSets.append(newElement) + calcMinMax(dataSet: newElement) + } + + public func remove(at position: Index) -> Element + { + guard !(self is CombinedChartData) else + { + fatalError("remove(at:) not supported for CombinedData") + } + + let element = _dataSets.remove(at: position) + calcMinMax() + return element + } + + public func removeFirst() -> Element + { + guard !(self is CombinedChartData) else + { + fatalError("removeFirst() not supported for CombinedData") + } + + let element = _dataSets.removeFirst() + notifyDataChanged() + return element + } + + public func removeFirst(_ n: Int) + { + guard !(self is CombinedChartData) else + { + fatalError("removeFirst(_:) not supported for CombinedData") + } + + _dataSets.removeFirst(n) + notifyDataChanged() + } + + public func removeLast() -> Element + { + guard !(self is CombinedChartData) else + { + fatalError("removeLast() not supported for CombinedData") + } + + let element = _dataSets.removeLast() + notifyDataChanged() + return element + } + + public func removeLast(_ n: Int) + { + guard !(self is CombinedChartData) else + { + fatalError("removeLast(_:) not supported for CombinedData") + } + + _dataSets.removeLast(n) + notifyDataChanged() + } + + public func removeSubrange(_ bounds: R) where R : RangeExpression, ChartData.Index == R.Bound + { + guard !(self is CombinedChartData) else + { + fatalError("removeSubrange(_:) not supported for CombinedData") + } + + _dataSets.removeSubrange(bounds) + notifyDataChanged() + } + + public func removeAll(keepingCapacity keepCapacity: Bool) + { + guard !(self is CombinedChartData) else + { + fatalError("removeAll(keepingCapacity:) not supported for CombinedData") + } + + _dataSets.removeAll(keepingCapacity: keepCapacity) + notifyDataChanged() + } +} + +// MARK: Swift Accessors +extension ChartData +{ + /// Retrieve the index of a ChartDataSet with a specific label from the ChartData. Search can be case sensitive or not. + /// **IMPORTANT: This method does calculations at runtime, do not over-use in performance critical situations.** + /// + /// - Parameters: + /// - label: The label to search for + /// - ignoreCase: if true, the search is not case-sensitive + /// - Returns: The index of the DataSet Object with the given label. `nil` if not found + public func index(forLabel label: String, ignoreCase: Bool) -> Index? + { + return ignoreCase + ? index { $0.label?.caseInsensitiveCompare(label) == .orderedSame } + : index { $0.label == label } + } + + public subscript(label: String, ignoreCase: Bool) -> Element? + { + guard let index = index(forLabel: label, ignoreCase: ignoreCase) else { return nil } + return self[index] + } + + public subscript(entry: ChartDataEntry) -> Element? + { + guard let index = index(where: { $0.entryForXValue(entry.x, closestToY: entry.y) === entry }) else { return nil } + return self[index] + } +} diff --git a/Source/Charts/Data/Implementations/Standard/CombinedChartData.swift b/Source/Charts/Data/Implementations/Standard/CombinedChartData.swift index 59e1f2327b..4eaac60f34 100644 --- a/Source/Charts/Data/Implementations/Standard/CombinedChartData.swift +++ b/Source/Charts/Data/Implementations/Standard/CombinedChartData.swift @@ -19,7 +19,7 @@ open class CombinedChartData: BarLineScatterCandleBubbleChartData private var _candleData: CandleChartData! private var _bubbleData: BubbleChartData! - public override init() + public required init() { super.init() } @@ -28,6 +28,11 @@ open class CombinedChartData: BarLineScatterCandleBubbleChartData { super.init(dataSets: dataSets) } + + public required init(arrayLiteral elements: ChartDataSetProtocol...) + { + super.init(dataSets: elements) + } @objc open var lineData: LineChartData! { diff --git a/Source/Charts/Data/Implementations/Standard/LineChartData.swift b/Source/Charts/Data/Implementations/Standard/LineChartData.swift index cc19888cc0..468620ff49 100644 --- a/Source/Charts/Data/Implementations/Standard/LineChartData.swift +++ b/Source/Charts/Data/Implementations/Standard/LineChartData.swift @@ -14,7 +14,7 @@ import Foundation /// Data object that encapsulates all data associated with a LineChart. open class LineChartData: ChartData { - public override init() + public required init() { super.init() } @@ -23,4 +23,9 @@ open class LineChartData: ChartData { super.init(dataSets: dataSets) } + + public required init(arrayLiteral elements: ChartDataSetProtocol...) + { + super.init(dataSets: elements) + } } diff --git a/Source/Charts/Data/Implementations/Standard/PieChartData.swift b/Source/Charts/Data/Implementations/Standard/PieChartData.swift index e5bd22f23c..1ea1f2675a 100644 --- a/Source/Charts/Data/Implementations/Standard/PieChartData.swift +++ b/Source/Charts/Data/Implementations/Standard/PieChartData.swift @@ -13,7 +13,7 @@ import Foundation open class PieChartData: ChartData { - public override init() + public required init() { super.init() } @@ -23,6 +23,11 @@ open class PieChartData: ChartData super.init(dataSets: dataSets) } + public required init(arrayLiteral elements: ChartDataSetProtocol...) + { + super.init(dataSets: elements) + } + @objc var dataSet: PieChartDataSetProtocol? { get diff --git a/Source/Charts/Data/Implementations/Standard/RadarChartData.swift b/Source/Charts/Data/Implementations/Standard/RadarChartData.swift index 30203de084..313ca65147 100644 --- a/Source/Charts/Data/Implementations/Standard/RadarChartData.swift +++ b/Source/Charts/Data/Implementations/Standard/RadarChartData.swift @@ -29,7 +29,7 @@ open class RadarChartData: ChartData self.labels = labels } - public override init() + public required init() { super.init() } @@ -38,7 +38,12 @@ open class RadarChartData: ChartData { super.init(dataSets: dataSets) } - + + public required init(arrayLiteral elements: ChartDataSetProtocol...) + { + super.init(dataSets: elements) + } + open override func entryForHighlight(_ highlight: Highlight) -> ChartDataEntry? { return getDataSetByIndex(highlight.dataSetIndex)?.entryForIndex(Int(highlight.x)) diff --git a/Source/Charts/Data/Implementations/Standard/ScatterChartData.swift b/Source/Charts/Data/Implementations/Standard/ScatterChartData.swift index 4fe5127c34..c3c4ca1b8a 100644 --- a/Source/Charts/Data/Implementations/Standard/ScatterChartData.swift +++ b/Source/Charts/Data/Implementations/Standard/ScatterChartData.swift @@ -14,7 +14,7 @@ import CoreGraphics open class ScatterChartData: BarLineScatterCandleBubbleChartData { - public override init() + public required init() { super.init() } @@ -23,6 +23,11 @@ open class ScatterChartData: BarLineScatterCandleBubbleChartData { super.init(dataSets: dataSets) } + + public required init(arrayLiteral elements: ChartDataSetProtocol...) + { + super.init(dataSets: elements) + } /// - returns: The maximum shape-size across all DataSets. @objc open func getGreatestShapeSize() -> CGFloat