COBChart.swift 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. //
  2. // COBChart.swift
  3. // LoopUI
  4. //
  5. // Copyright © 2019 LoopKit Authors. All rights reserved.
  6. //
  7. import Foundation
  8. import HealthKit
  9. import LoopKit
  10. import SwiftCharts
  11. import UIKit
  12. public class COBChart: ChartProviding {
  13. public init() {
  14. }
  15. /// The chart points for COB
  16. public private(set) var cobPoints: [ChartPoint] = [] {
  17. didSet {
  18. if let lastDate = cobPoints.last?.x as? ChartAxisValueDate {
  19. endDate = lastDate.date
  20. }
  21. }
  22. }
  23. /// The minimum range to display for COB values.
  24. private var cobDisplayRangePoints: [ChartPoint] = [0, 10].map {
  25. return ChartPoint(
  26. x: ChartAxisValue(scalar: 0),
  27. y: ChartAxisValueInt($0)
  28. )
  29. }
  30. public private(set) var endDate: Date?
  31. private var cobChartCache: ChartPointsTouchHighlightLayerViewCache?
  32. }
  33. public extension COBChart {
  34. func didReceiveMemoryWarning() {
  35. cobPoints = []
  36. cobChartCache = nil
  37. }
  38. func generate(withFrame frame: CGRect, xAxisModel: ChartAxisModel, xAxisValues: [ChartAxisValue], axisLabelSettings: ChartLabelSettings, guideLinesLayerSettings: ChartGuideLinesLayerSettings, colors: ChartColorPalette, chartSettings: ChartSettings, labelsWidthY: CGFloat, gestureRecognizer: UIGestureRecognizer?, traitCollection: UITraitCollection) -> Chart
  39. {
  40. let yAxisValues = ChartAxisValuesStaticGenerator.generateYAxisValuesWithChartPoints(cobPoints + cobDisplayRangePoints, minSegmentCount: 2, maxSegmentCount: 3, multiple: 10, axisValueGenerator: { ChartAxisValueDouble($0, labelSettings: axisLabelSettings) }, addPaddingSegmentIfEdge: false)
  41. let yAxisModel = ChartAxisModel(axisValues: yAxisValues, lineColor: colors.axisLine, labelSpaceReservationMode: .fixed(labelsWidthY))
  42. let coordsSpace = ChartCoordsSpaceLeftBottomSingleAxis(chartSettings: chartSettings, chartFrame: frame, xModel: xAxisModel, yModel: yAxisModel)
  43. let (xAxisLayer, yAxisLayer, innerFrame) = (coordsSpace.xAxisLayer, coordsSpace.yAxisLayer, coordsSpace.chartInnerFrame)
  44. // The COB area
  45. let lineModel = ChartLineModel(chartPoints: cobPoints, lineColor: colors.carbTint, lineWidth: 2, animDuration: 0, animDelay: 0)
  46. let cobLine = ChartPointsLineLayer(xAxis: xAxisLayer.axis, yAxis: yAxisLayer.axis, lineModels: [lineModel])
  47. let cobArea = ChartPointsFillsLayer(xAxis: xAxisLayer.axis, yAxis: yAxisLayer.axis, fills: [ChartPointsFill(chartPoints: cobPoints, fillColor: colors.carbTint.withAlphaComponent(0.5))])
  48. // Grid lines
  49. let gridLayer = ChartGuideLinesForValuesLayer(xAxis: xAxisLayer.axis, yAxis: yAxisLayer.axis, settings: guideLinesLayerSettings, axisValuesX: Array(xAxisValues.dropFirst().dropLast()), axisValuesY: yAxisValues)
  50. if gestureRecognizer != nil {
  51. cobChartCache = ChartPointsTouchHighlightLayerViewCache(
  52. xAxisLayer: xAxisLayer,
  53. yAxisLayer: yAxisLayer,
  54. axisLabelSettings: axisLabelSettings,
  55. chartPoints: cobPoints,
  56. tintColor: colors.carbTint,
  57. gestureRecognizer: gestureRecognizer
  58. )
  59. }
  60. let layers: [ChartLayer?] = [
  61. gridLayer,
  62. xAxisLayer,
  63. yAxisLayer,
  64. cobChartCache?.highlightLayer,
  65. cobArea,
  66. cobLine
  67. ]
  68. return Chart(frame: frame, innerFrame: innerFrame, settings: chartSettings, layers: layers.compactMap { $0 })
  69. }
  70. }
  71. public extension COBChart {
  72. func setCOBValues(_ cobValues: [CarbValue]) {
  73. let dateFormatter = DateFormatter(timeStyle: .short)
  74. let integerFormatter = NumberFormatter.integer
  75. let unit = HKUnit.gram()
  76. let unitString = unit.unitString
  77. cobPoints = cobValues.map {
  78. ChartPoint(
  79. x: ChartAxisValueDate(date: $0.startDate, formatter: dateFormatter),
  80. y: ChartAxisValueDoubleUnit($0.quantity.doubleValue(for: unit), unitString: unitString, formatter: integerFormatter)
  81. )
  82. }
  83. }
  84. }