Noobish1/WeatherRules

View on GitHub
App/Charts/WhatToWearCharts/Objects/Axis/YAxis.swift

Summary

Maintainability
A
0 mins
Test Coverage
import CoreGraphics
import Foundation
import UIKit
import WhatToWearCommonCore
import WhatToWearCore

public struct YAxis: AxisProtocol {
    // MARK: types
    public enum LabelPosition {
        case outsideChart
        case insideChart
    }

    public enum Dependency {
        case left
        case right
    }

    // MARK: computed properties
    internal var textAlignment: NSTextAlignment {
        switch (dependency, labelPosition) {
            case (.left, .outsideChart): return .right
            case (.left, .insideChart): return .left
            case (.right, .outsideChart): return .left
            case (.right, .insideChart): return .right
        }
    }

    // MARK: properties
    public let valueFormatter: AxisValueFormatterProtocol
    public let colorFormatter: AxisColorFormatterProtocol?
    public let labelConfig: LabelConfig
    public let labelOffset: CGFloat
    public let gridConfig: GridConfig
    public let offset: UIOffset
    public let labelPosition: LabelPosition
    public let dependency: Dependency

    public let range: ClosedRange<CGFloat>
    internal let entries: NonEmptyArray<CGFloat>

    // MARK: init
    public init(
        entries: NonEmptyArray<CGFloat>,
        labelConfig: LabelConfig,
        labelOffset: CGFloat,
        gridConfig: GridConfig,
        offset: UIOffset = UIOffset(horizontal: 5, vertical: 0),
        valueFormatter: AxisValueFormatterProtocol,
        colorFormatter: AxisColorFormatterProtocol? = nil,
        labelPosition: LabelPosition,
        dependency: Dependency
    ) {
        self.entries = entries
        self.range = entries.min()...entries.max()
        self.labelConfig = labelConfig
        self.labelOffset = labelOffset
        self.gridConfig = gridConfig
        self.offset = offset
        self.valueFormatter = valueFormatter
        self.colorFormatter = colorFormatter
        self.labelPosition = labelPosition
        self.dependency = dependency
    }

    // MARK: drawing positions
    internal func drawingXPosition(
        for viewPortHandler: ViewPortHandler,
        xOffset: CGFloat
    ) -> CGFloat {
        switch (dependency, labelPosition) {
            case (.left, .outsideChart):
                return viewPortHandler.offset.left - xOffset
            case (.left, .insideChart):
                return viewPortHandler.offset.left + xOffset
            case (.right, .outsideChart):
                return viewPortHandler.contentRect.maxX + xOffset
            case (.right, .insideChart):
                return viewPortHandler.contentRect.maxX - xOffset
        }
    }

    internal func preTransformedPoint(forEntry entry: CGFloat) -> CGPoint {
        return CGPoint(x: 0, y: entry)
    }

    internal func gridLines<T>(dataProvider: DataProvider<T>) -> NonEmptyArray<GridLine> {
        let trans = transformer(from: dataProvider)
        let viewPortHandler = dataProvider.viewPortHandler

        return entryPixelPoints(using: trans).map {
            GridLine(
                start: CGPoint(x: viewPortHandler.contentRect.minX, y: $0.y),
                end: CGPoint(x: viewPortHandler.contentRect.maxX, y: $0.y)
            )
        }
    }

    internal func pointToDrawAtForEntry<T>(at index: Int, dataProvider: DataProvider<T>) -> CGPoint {
        let trans = transformer(from: dataProvider)
        let viewPortHandler = dataProvider.viewPortHandler

        let xOffset = offset.horizontal
        let yOffset = labelConfig.font.lineHeight / 2.5 + offset.vertical
        let yPoint = pixelPointForEntry(at: index, using: trans).y

        return CGPoint(
            x: drawingXPosition(for: viewPortHandler, xOffset: xOffset),
            y: yPoint + (yOffset - labelConfig.font.lineHeight)
        )
    }

    internal func transformer<T>(from dataProvider: DataProvider<T>) -> Transformer {
        return dataProvider.transformer(forAxis: dependency)
    }
}