// // InsulinModelChart.swift // LoopKitUI // // Copyright © 2019 LoopKit Authors. All rights reserved. // import Foundation import LoopKit import SwiftCharts import UIKit public class InsulinModelChart: GlucoseChart, ChartProviding { /// The chart points for the selected model public private(set) var selectedInsulinModelChartPoints: [ChartPoint] = [] { didSet { if let lastDate = selectedInsulinModelChartPoints.last?.x as? ChartAxisValueDate { updateEndDate(lastDate.date) } } } public private(set) var unselectedInsulinModelChartPoints: [[ChartPoint]] = [] { didSet { for points in unselectedInsulinModelChartPoints { if let lastDate = points.last?.x as? ChartAxisValueDate { updateEndDate(lastDate.date) } } } } public private(set) var endDate: Date? private func updateEndDate(_ date: Date) { if endDate == nil || date > endDate! { self.endDate = date } } } extension InsulinModelChart { public func didReceiveMemoryWarning() { } 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 { let yAxisValues = ChartAxisValuesStaticGenerator.generateYAxisValuesWithChartPoints(glucoseDisplayRangePoints, minSegmentCount: 2, maxSegmentCount: 5, multiple: glucoseUnit.chartableIncrement / 2, axisValueGenerator: { ChartAxisValueDouble(round($0), labelSettings: axisLabelSettings) }, addPaddingSegmentIfEdge: false ) let yAxisModel = ChartAxisModel(axisValues: yAxisValues, lineColor: colors.axisLine, labelSpaceReservationMode: .fixed(labelsWidthY)) let coordsSpace = ChartCoordsSpaceLeftBottomSingleAxis( chartSettings: chartSettings, chartFrame: frame, xModel: xAxisModel, yModel: yAxisModel ) // Grid lines let gridLayer = ChartGuideLinesForValuesLayer( xAxis: coordsSpace.xAxisLayer.axis, yAxis: coordsSpace.yAxisLayer.axis, settings: guideLinesLayerSettings, axisValuesX: Array(xAxisValues.dropFirst().dropLast()), axisValuesY: yAxisValues ) // Selected line var selectedLayer: ChartLayer? if selectedInsulinModelChartPoints.count > 1 { let lineModel = ChartLineModel.predictionLine( points: selectedInsulinModelChartPoints, color: colors.glucoseTint, width: 2 ) selectedLayer = ChartPointsLineLayer( xAxis: coordsSpace.xAxisLayer.axis, yAxis: coordsSpace.yAxisLayer.axis, lineModels: [lineModel] ) } var unselectedLineModels = [ChartLineModel]() for points in unselectedInsulinModelChartPoints where points.count > 1 { unselectedLineModels.append(ChartLineModel.predictionLine( points: points, color: UIColor.secondaryLabel, width: 1 )) } // Unselected lines var unselectedLayer: ChartLayer? if !unselectedLineModels.isEmpty { unselectedLayer = ChartPointsLineLayer( xAxis: coordsSpace.xAxisLayer.axis, yAxis: coordsSpace.yAxisLayer.axis, lineModels: unselectedLineModels ) } let layers: [ChartLayer?] = [ gridLayer, coordsSpace.xAxisLayer, coordsSpace.yAxisLayer, unselectedLayer, selectedLayer ] return Chart( frame: frame, innerFrame: coordsSpace.chartInnerFrame, settings: chartSettings, layers: layers.compactMap { $0 } ) } } extension InsulinModelChart { public func setSelectedInsulinModelValues(_ values: [GlucoseValue]) { self.selectedInsulinModelChartPoints = glucosePointsFromValues(values) } public func setUnselectedInsulinModelValues(_ values: [[GlucoseValue]]) { self.unselectedInsulinModelChartPoints = values.map(glucosePointsFromValues) } }