-
-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Chartdata collection conformance #3023
Changes from all commits
6e80eb0
36ca566
cb32b08
716f182
ca5afad
8976b95
f28d3d5
583dab6
c0b7d65
a71f87c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I saw There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From the
The index of the collection ( |
||
{ | ||
return _dataSets.index(before: before) | ||
} | ||
} | ||
|
||
// MARK: RangeReplaceableCollection | ||
extension ChartData: RangeReplaceableCollection | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Generally it should works fine with the collection protocol adoption. The devil may exist in CombinedChartData in the future, as it works differently than usual chart data. We actually don't append/remove data sets into a combined data, we just assign new sub chartData. e.g. open override func removeDataSetByIndex(_ index: Int) -> Bool
{
print("removeDataSet(index) not supported for CombinedData", terminator: "\n")
return false
} I think we should override the protocols in CombinedChartData to not allow such operations? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will do that right now : ) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||
{ | ||
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<R>(_ bounds: R) where R : RangeExpression, ChartData.Index == R.Bound | ||
{ | ||
guard !(self is CombinedChartData) else | ||
{ | ||
fatalError("removeSubrange<R>(_:) 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] | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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...) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. have you checked if any tricky bug or trap (like index to a wrong position) regards CombinedChartData collection conformance? CombinedChartData is a wrapper putting other data together like barData, lineData. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I made sure that all the new Swift methods/properties have the same implementations as the existing ones, so this shouldn't be an issue. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure. It will take more time, need to catch up the dataset protocol first. |
||
{ | ||
super.init(dataSets: elements) | ||
} | ||
|
||
@objc open var lineData: LineChartData! | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why many become required init() now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a requirement of
RangeReplaceableCollection
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm.. My Dash API Doc does not show this to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From Apple
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Found a Dash bug :)