ChartBaseDataSet.swift 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. //
  2. // BaseDataSet.swift
  3. // Charts
  4. //
  5. // Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
  6. // A port of MPAndroidChart for iOS
  7. // Licensed under Apache License 2.0
  8. //
  9. // https://github.com/danielgindi/Charts
  10. //
  11. import Foundation
  12. import CoreGraphics
  13. open class ChartBaseDataSet: NSObject, ChartDataSetProtocol, NSCopying
  14. {
  15. public required override init()
  16. {
  17. super.init()
  18. // default color
  19. colors.append(NSUIColor(red: 140.0/255.0, green: 234.0/255.0, blue: 255.0/255.0, alpha: 1.0))
  20. valueColors.append(.labelOrBlack)
  21. }
  22. @objc public init(label: String)
  23. {
  24. super.init()
  25. // default color
  26. colors.append(NSUIColor(red: 140.0/255.0, green: 234.0/255.0, blue: 255.0/255.0, alpha: 1.0))
  27. valueColors.append(.labelOrBlack)
  28. self.label = label
  29. }
  30. // MARK: - Data functions and accessors
  31. /// Use this method to tell the data set that the underlying data has changed
  32. open func notifyDataSetChanged()
  33. {
  34. calcMinMax()
  35. }
  36. open func calcMinMax()
  37. {
  38. fatalError("calcMinMax is not implemented in ChartBaseDataSet")
  39. }
  40. open func calcMinMaxY(fromX: Double, toX: Double)
  41. {
  42. fatalError("calcMinMaxY(fromX:, toX:) is not implemented in ChartBaseDataSet")
  43. }
  44. open var yMin: Double
  45. {
  46. fatalError("yMin is not implemented in ChartBaseDataSet")
  47. }
  48. open var yMax: Double
  49. {
  50. fatalError("yMax is not implemented in ChartBaseDataSet")
  51. }
  52. open var xMin: Double
  53. {
  54. fatalError("xMin is not implemented in ChartBaseDataSet")
  55. }
  56. open var xMax: Double
  57. {
  58. fatalError("xMax is not implemented in ChartBaseDataSet")
  59. }
  60. open var entryCount: Int
  61. {
  62. fatalError("entryCount is not implemented in ChartBaseDataSet")
  63. }
  64. open func entryForIndex(_ i: Int) -> ChartDataEntry?
  65. {
  66. fatalError("entryForIndex is not implemented in ChartBaseDataSet")
  67. }
  68. open func entryForXValue(
  69. _ x: Double,
  70. closestToY y: Double,
  71. rounding: ChartDataSetRounding) -> ChartDataEntry?
  72. {
  73. fatalError("entryForXValue(x, closestToY, rounding) is not implemented in ChartBaseDataSet")
  74. }
  75. open func entryForXValue(
  76. _ x: Double,
  77. closestToY y: Double) -> ChartDataEntry?
  78. {
  79. fatalError("entryForXValue(x, closestToY) is not implemented in ChartBaseDataSet")
  80. }
  81. open func entriesForXValue(_ x: Double) -> [ChartDataEntry]
  82. {
  83. fatalError("entriesForXValue is not implemented in ChartBaseDataSet")
  84. }
  85. open func entryIndex(
  86. x xValue: Double,
  87. closestToY y: Double,
  88. rounding: ChartDataSetRounding) -> Int
  89. {
  90. fatalError("entryIndex(x, closestToY, rounding) is not implemented in ChartBaseDataSet")
  91. }
  92. open func entryIndex(entry e: ChartDataEntry) -> Int
  93. {
  94. fatalError("entryIndex(entry) is not implemented in ChartBaseDataSet")
  95. }
  96. @discardableResult open func addEntry(_ e: ChartDataEntry) -> Bool
  97. {
  98. fatalError("addEntry is not implemented in ChartBaseDataSet")
  99. }
  100. @discardableResult open func addEntryOrdered(_ e: ChartDataEntry) -> Bool
  101. {
  102. fatalError("addEntryOrdered is not implemented in ChartBaseDataSet")
  103. }
  104. @discardableResult open func removeEntry(_ entry: ChartDataEntry) -> Bool
  105. {
  106. fatalError("removeEntry is not implemented in ChartBaseDataSet")
  107. }
  108. @discardableResult open func removeEntry(index: Int) -> Bool
  109. {
  110. if let entry = entryForIndex(index)
  111. {
  112. return removeEntry(entry)
  113. }
  114. return false
  115. }
  116. @discardableResult open func removeEntry(x: Double) -> Bool
  117. {
  118. if let entry = entryForXValue(x, closestToY: Double.nan)
  119. {
  120. return removeEntry(entry)
  121. }
  122. return false
  123. }
  124. @discardableResult open func removeFirst() -> Bool
  125. {
  126. if entryCount > 0
  127. {
  128. if let entry = entryForIndex(0)
  129. {
  130. return removeEntry(entry)
  131. }
  132. }
  133. return false
  134. }
  135. @discardableResult open func removeLast() -> Bool
  136. {
  137. if entryCount > 0
  138. {
  139. if let entry = entryForIndex(entryCount - 1)
  140. {
  141. return removeEntry(entry)
  142. }
  143. }
  144. return false
  145. }
  146. open func contains(_ e: ChartDataEntry) -> Bool
  147. {
  148. fatalError("removeEntry is not implemented in ChartBaseDataSet")
  149. }
  150. open func clear()
  151. {
  152. fatalError("clear is not implemented in ChartBaseDataSet")
  153. }
  154. // MARK: - Styling functions and accessors
  155. /// All the colors that are used for this DataSet.
  156. /// Colors are reused as soon as the number of Entries the DataSet represents is higher than the size of the colors array.
  157. open var colors = [NSUIColor]()
  158. /// List representing all colors that are used for drawing the actual values for this DataSet
  159. open var valueColors = [NSUIColor]()
  160. /// The label string that describes the DataSet.
  161. open var label: String? = "DataSet"
  162. /// The axis this DataSet should be plotted against.
  163. open var axisDependency = YAxis.AxisDependency.left
  164. /// - Returns: The color at the given index of the DataSet's color array.
  165. /// This prevents out-of-bounds by performing a modulus on the color index, so colours will repeat themselves.
  166. open func color(atIndex index: Int) -> NSUIColor
  167. {
  168. var index = index
  169. if index < 0
  170. {
  171. index = 0
  172. }
  173. return colors[index % colors.count]
  174. }
  175. /// Resets all colors of this DataSet and recreates the colors array.
  176. open func resetColors()
  177. {
  178. colors.removeAll(keepingCapacity: false)
  179. }
  180. /// Adds a new color to the colors array of the DataSet.
  181. ///
  182. /// - Parameters:
  183. /// - color: the color to add
  184. open func addColor(_ color: NSUIColor)
  185. {
  186. colors.append(color)
  187. }
  188. /// Sets the one and **only** color that should be used for this DataSet.
  189. /// Internally, this recreates the colors array and adds the specified color.
  190. ///
  191. /// - Parameters:
  192. /// - color: the color to set
  193. open func setColor(_ color: NSUIColor)
  194. {
  195. colors.removeAll(keepingCapacity: false)
  196. colors.append(color)
  197. }
  198. /// Sets colors to a single color a specific alpha value.
  199. ///
  200. /// - Parameters:
  201. /// - color: the color to set
  202. /// - alpha: alpha to apply to the set `color`
  203. @objc open func setColor(_ color: NSUIColor, alpha: CGFloat)
  204. {
  205. setColor(color.withAlphaComponent(alpha))
  206. }
  207. /// Sets colors with a specific alpha value.
  208. ///
  209. /// - Parameters:
  210. /// - colors: the colors to set
  211. /// - alpha: alpha to apply to the set `colors`
  212. @objc open func setColors(_ colors: [NSUIColor], alpha: CGFloat)
  213. {
  214. self.colors = colors.map { $0.withAlphaComponent(alpha) }
  215. }
  216. /// Sets colors with a specific alpha value.
  217. ///
  218. /// - Parameters:
  219. /// - colors: the colors to set
  220. /// - alpha: alpha to apply to the set `colors`
  221. open func setColors(_ colors: NSUIColor...)
  222. {
  223. self.colors = colors
  224. }
  225. /// if true, value highlighting is enabled
  226. open var highlightEnabled = true
  227. /// `true` if value highlighting is enabled for this dataset
  228. open var isHighlightEnabled: Bool { return highlightEnabled }
  229. /// Custom formatter that is used instead of the auto-formatter if set
  230. open lazy var valueFormatter: ValueFormatter = DefaultValueFormatter()
  231. /// Sets/get a single color for value text.
  232. /// Setting the color clears the colors array and adds a single color.
  233. /// Getting will return the first color in the array.
  234. open var valueTextColor: NSUIColor
  235. {
  236. get
  237. {
  238. return valueColors[0]
  239. }
  240. set
  241. {
  242. valueColors.removeAll(keepingCapacity: false)
  243. valueColors.append(newValue)
  244. }
  245. }
  246. /// - Returns: The color at the specified index that is used for drawing the values inside the chart. Uses modulus internally.
  247. open func valueTextColorAt(_ index: Int) -> NSUIColor
  248. {
  249. var index = index
  250. if index < 0
  251. {
  252. index = 0
  253. }
  254. return valueColors[index % valueColors.count]
  255. }
  256. /// the font for the value-text labels
  257. open var valueFont: NSUIFont = NSUIFont.systemFont(ofSize: 7.0)
  258. /// The rotation angle (in degrees) for value-text labels
  259. open var valueLabelAngle: CGFloat = CGFloat(0.0)
  260. /// The form to draw for this dataset in the legend.
  261. open var form = Legend.Form.default
  262. /// The form size to draw for this dataset in the legend.
  263. ///
  264. /// Return `NaN` to use the default legend form size.
  265. open var formSize: CGFloat = CGFloat.nan
  266. /// The line width for drawing the form of this dataset in the legend
  267. ///
  268. /// Return `NaN` to use the default legend form line width.
  269. open var formLineWidth: CGFloat = CGFloat.nan
  270. /// Line dash configuration for legend shapes that consist of lines.
  271. ///
  272. /// This is how much (in pixels) into the dash pattern are we starting from.
  273. open var formLineDashPhase: CGFloat = 0.0
  274. /// Line dash configuration for legend shapes that consist of lines.
  275. ///
  276. /// This is the actual dash pattern.
  277. /// I.e. [2, 3] will paint [-- -- ]
  278. /// [1, 3, 4, 2] will paint [- ---- - ---- ]
  279. open var formLineDashLengths: [CGFloat]? = nil
  280. /// Set this to true to draw y-values on the chart.
  281. ///
  282. /// - Note: For bar and line charts: if `maxVisibleCount` is reached, no values will be drawn even if this is enabled.
  283. open var drawValuesEnabled = true
  284. /// `true` if y-value drawing is enabled, `false` ifnot
  285. open var isDrawValuesEnabled: Bool
  286. {
  287. return drawValuesEnabled
  288. }
  289. /// Set this to true to draw y-icons on the chart.
  290. ///
  291. /// - Note: For bar and line charts: if `maxVisibleCount` is reached, no icons will be drawn even if this is enabled.
  292. open var drawIconsEnabled = true
  293. /// Returns true if y-icon drawing is enabled, false if not
  294. open var isDrawIconsEnabled: Bool
  295. {
  296. return drawIconsEnabled
  297. }
  298. /// Offset of icons drawn on the chart.
  299. ///
  300. /// For all charts except Pie and Radar it will be ordinary (x offset, y offset).
  301. ///
  302. /// For Pie and Radar chart it will be (y offset, distance from center offset); so if you want icon to be rendered under value, you should increase X component of CGPoint, and if you want icon to be rendered closet to center, you should decrease height component of CGPoint.
  303. open var iconsOffset = CGPoint(x: 0, y: 0)
  304. /// Set the visibility of this DataSet. If not visible, the DataSet will not be drawn to the chart upon refreshing it.
  305. open var visible = true
  306. /// `true` if this DataSet is visible inside the chart, or `false` ifit is currently hidden.
  307. open var isVisible: Bool
  308. {
  309. return visible
  310. }
  311. // MARK: - NSObject
  312. open override var description: String
  313. {
  314. return String(format: "%@, label: %@, %i entries", arguments: [NSStringFromClass(type(of: self)), self.label ?? "", self.entryCount])
  315. }
  316. open override var debugDescription: String
  317. {
  318. return (0..<entryCount).reduce(description + ":") {
  319. "\($0)\n\(self.entryForIndex($1)?.description ?? "")"
  320. }
  321. }
  322. // MARK: - NSCopying
  323. open func copy(with zone: NSZone? = nil) -> Any
  324. {
  325. let copy = type(of: self).init()
  326. copy.colors = colors
  327. copy.valueColors = valueColors
  328. copy.label = label
  329. copy.axisDependency = axisDependency
  330. copy.highlightEnabled = highlightEnabled
  331. copy.valueFormatter = valueFormatter
  332. copy.valueFont = valueFont
  333. copy.form = form
  334. copy.formSize = formSize
  335. copy.formLineWidth = formLineWidth
  336. copy.formLineDashPhase = formLineDashPhase
  337. copy.formLineDashLengths = formLineDashLengths
  338. copy.drawValuesEnabled = drawValuesEnabled
  339. copy.drawIconsEnabled = drawIconsEnabled
  340. copy.iconsOffset = iconsOffset
  341. copy.visible = visible
  342. return copy
  343. }
  344. }