InsulinModelChart.swift 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. //
  2. // InsulinModelChart.swift
  3. // LoopKitUI
  4. //
  5. // Copyright © 2019 LoopKit Authors. All rights reserved.
  6. //
  7. import Foundation
  8. import LoopKit
  9. import SwiftCharts
  10. import UIKit
  11. public class InsulinModelChart: GlucoseChart, ChartProviding {
  12. /// The chart points for the selected model
  13. public private(set) var selectedInsulinModelChartPoints: [ChartPoint] = [] {
  14. didSet {
  15. if let lastDate = selectedInsulinModelChartPoints.last?.x as? ChartAxisValueDate {
  16. updateEndDate(lastDate.date)
  17. }
  18. }
  19. }
  20. public private(set) var unselectedInsulinModelChartPoints: [[ChartPoint]] = [] {
  21. didSet {
  22. for points in unselectedInsulinModelChartPoints {
  23. if let lastDate = points.last?.x as? ChartAxisValueDate {
  24. updateEndDate(lastDate.date)
  25. }
  26. }
  27. }
  28. }
  29. public private(set) var endDate: Date?
  30. private func updateEndDate(_ date: Date) {
  31. if endDate == nil || date > endDate! {
  32. self.endDate = date
  33. }
  34. }
  35. }
  36. extension InsulinModelChart {
  37. public func didReceiveMemoryWarning() {
  38. }
  39. public func generate(withFrame frame: CGRect, xAxisModel: ChartAxisModel, xAxisValues: [ChartAxisValue], axisLabelSettings: ChartLabelSettings, guideLinesLayerSettings: ChartGuideLinesLayerSettings, colors: ChartColorPalette, chartSettings: ChartSettings, labelsWidthY: CGFloat, gestureRecognizer: UIGestureRecognizer?, traitCollection: UITraitCollection) -> Chart
  40. {
  41. let yAxisValues = ChartAxisValuesStaticGenerator.generateYAxisValuesWithChartPoints(glucoseDisplayRangePoints,
  42. minSegmentCount: 2,
  43. maxSegmentCount: 5,
  44. multiple: glucoseUnit.chartableIncrement / 2,
  45. axisValueGenerator: {
  46. ChartAxisValueDouble(round($0), labelSettings: axisLabelSettings)
  47. },
  48. addPaddingSegmentIfEdge: false
  49. )
  50. let yAxisModel = ChartAxisModel(axisValues: yAxisValues, lineColor: colors.axisLine, labelSpaceReservationMode: .fixed(labelsWidthY))
  51. let coordsSpace = ChartCoordsSpaceLeftBottomSingleAxis(
  52. chartSettings: chartSettings,
  53. chartFrame: frame,
  54. xModel: xAxisModel,
  55. yModel: yAxisModel
  56. )
  57. // Grid lines
  58. let gridLayer = ChartGuideLinesForValuesLayer(
  59. xAxis: coordsSpace.xAxisLayer.axis,
  60. yAxis: coordsSpace.yAxisLayer.axis,
  61. settings: guideLinesLayerSettings,
  62. axisValuesX: Array(xAxisValues.dropFirst().dropLast()),
  63. axisValuesY: yAxisValues
  64. )
  65. // Selected line
  66. var selectedLayer: ChartLayer?
  67. if selectedInsulinModelChartPoints.count > 1 {
  68. let lineModel = ChartLineModel.predictionLine(
  69. points: selectedInsulinModelChartPoints,
  70. color: colors.glucoseTint,
  71. width: 2
  72. )
  73. selectedLayer = ChartPointsLineLayer(
  74. xAxis: coordsSpace.xAxisLayer.axis,
  75. yAxis: coordsSpace.yAxisLayer.axis,
  76. lineModels: [lineModel]
  77. )
  78. }
  79. var unselectedLineModels = [ChartLineModel]()
  80. for points in unselectedInsulinModelChartPoints where points.count > 1 {
  81. unselectedLineModels.append(ChartLineModel.predictionLine(
  82. points: points,
  83. color: UIColor.secondaryLabel,
  84. width: 1
  85. ))
  86. }
  87. // Unselected lines
  88. var unselectedLayer: ChartLayer?
  89. if !unselectedLineModels.isEmpty {
  90. unselectedLayer = ChartPointsLineLayer(
  91. xAxis: coordsSpace.xAxisLayer.axis,
  92. yAxis: coordsSpace.yAxisLayer.axis,
  93. lineModels: unselectedLineModels
  94. )
  95. }
  96. let layers: [ChartLayer?] = [
  97. gridLayer,
  98. coordsSpace.xAxisLayer,
  99. coordsSpace.yAxisLayer,
  100. unselectedLayer,
  101. selectedLayer
  102. ]
  103. return Chart(
  104. frame: frame,
  105. innerFrame: coordsSpace.chartInnerFrame,
  106. settings: chartSettings,
  107. layers: layers.compactMap { $0 }
  108. )
  109. }
  110. }
  111. extension InsulinModelChart {
  112. public func setSelectedInsulinModelValues(_ values: [GlucoseValue]) {
  113. self.selectedInsulinModelChartPoints = glucosePointsFromValues(values)
  114. }
  115. public func setUnselectedInsulinModelValues(_ values: [[GlucoseValue]]) {
  116. self.unselectedInsulinModelChartPoints = values.map(glucosePointsFromValues)
  117. }
  118. }