<commit_before>//
//  StepProgressView.swift
//  Step
//  Note: Currently the only supported order is:
//      1. Set appearence properties. (optional)
//      2. Set steps.
//      3. Change currentStep.
//
//  Created by <NAME> on 13/2/15.
//  Copyright (c) 2015 <NAME>. All rights reserved.
//

import UIKit

class StepProgressView: UIView {

    // MARK: - Behavior

    /// Titles of the step-by-step progression stages
    var steps: [String] = []    { didSet {setupStepViews()} }

    /// Current active step: -1 = not started, steps.count = all done.
    var currentStep: Int = -1   { didSet {colorSteps()} }

    // MARK: - Appearance

    enum Shape {
        case Circle
        case Square
    }

    var stepShape = Shape.Circle
    var firstStepShape = Shape.Circle
    var lastStepShape = Shape.Square

    var shapeSize: CGFloat = UIFont.systemFontSize()
    var lineWidth: CGFloat = 1
    var verticalPadding: CGFloat = UIFont.systemFontSize() // between steps
    var horizontalPadding: CGFloat = UIFont.systemFontSize() / 2 // between shape and text
    var textFont = UIFont.systemFontOfSize(UIFont.systemFontSize())

    // MARK: - Colors

    var futureStepColor = UIColor.lightGrayColor()
    var pastStepColor = UIColor.blackColor()
    var currentStepColor = UIColor.blackColor()

    var futureStepFillColor = UIColor.clearColor()
    var pastStepFillColor = UIColor.blackColor()
    var currentStepFillColor = UIColor.lightGrayColor()

    var futureTextColor = UIColor.lightGrayColor()
    var pastTextColor = UIColor.blackColor()
    var currentTextColor = UIColor.blackColor()


    // MARK: - Private

    private var stepViews: [SingleStepView] = []

    private func setupStepViews() {
        stepViews.map { $0.removeFromSuperview() }
        stepViews.removeAll(keepCapacity: true)

        for i in 0 ..< steps.count {

            // create step view
            var shape: Shape
            switch i {
            case 0:             shape = firstStepShape
            case steps.count-1: shape = lastStepShape
            default:            shape = stepShape
            }
            let stepView = SingleStepView(text: steps[i], font: textFont, shape: shape, shapeSize: shapeSize, lineWidth: lineWidth, hPadding: horizontalPadding, vPadding: verticalPadding)
            stepView.color(text: futureTextColor, stroke: futureStepColor, fill: futureStepFillColor, line: futureStepColor)
            addSubview(stepView)
            stepViews.append(stepView)

            // layout step view
            let prevView = (i == 0) ? self : stepViews[i-1]
            let prevAttribute: NSLayoutAttribute = (i == 0) ? .Top : .Bottom
            addConstraints([
                NSLayoutConstraint(item: stepView, attribute: .Top, relatedBy: .Equal, toItem: prevView, attribute: prevAttribute, multiplier: 1, constant: 0),
                NSLayoutConstraint(item: stepView, attribute: .Leading, relatedBy: .Equal, toItem: self, attribute: .Leading, multiplier: 1, constant: 0),
                NSLayoutConstraint(item: stepView, attribute: .Trailing, relatedBy: .Equal, toItem: self, attribute: .Trailing, multiplier: 1, constant: 0)
            ])
        }
        stepViews.last?.lineView.hidden = true
    }

    private func colorSteps() {
        let n = stepViews.count
        if currentStep < n {
            stepViews[currentStep+1 ..< n].map { $0.color(text: self.futureTextColor, stroke: self.futureStepColor, fill: self.futureStepFillColor, line: self.futureStepColor) }
            if currentStep >= 0 {
                stepViews[currentStep].color(text: currentTextColor, stroke: currentStepColor, fill: currentStepFillColor, line: futureStepColor)
            }
        }
        if currentStep > 0 {
            stepViews[0 ..< currentStep].map { $0.color(text: self.pastTextColor, stroke: self.pastStepColor, fill: self.pastStepFillColor, line: self.pastStepColor) }
        }
    }
}

private class SingleStepView: UIView {
    var textLabel: UILabel = UILabel()
    var shapeLayer: CAShapeLayer = CAShapeLayer()
    var lineView: UIView = UIView()

    convenience init(text: String, font: UIFont, shape: StepProgressView.Shape, shapeSize: CGFloat, lineWidth: CGFloat, hPadding: CGFloat, vPadding: CGFloat) {
        self.init()
        setTranslatesAutoresizingMaskIntoConstraints(false)

        // shape
        shapeLayer.frame = CGRect(origin: CGPoint(x: floor(lineWidth/2), y: floor(lineWidth/2)), size: CGSize(width: shapeSize, height: shapeSize))
        shapeLayer.path = UIBezierPath(shape: shape, frame: shapeLayer.bounds).CGPath
        shapeLayer.lineWidth = lineWidth
        layer.addSublayer(shapeLayer)

        // text<commit_msg>Added documentation<commit_after>//
//  StepProgressView.swift
//  Show step-by-step progress.
//
//  Usage:
//      progress = StepProgressView(frame: someFrame)
//      progress.steps = ["First", "Second", "Third", "Last"]
//      progress.currentStep = 0
//      ... when all done:
//      progress.currentStep = 4
//
//  Note: Currently the only supported usage order is:
//      1. Set frame and appearence properties. (optional)
//      2. Set steps.
//      3. Change currentStep.
//
//  Created by <NAME> on 13/2/15.
//  Copyright (c) 2015 <NAME>. All rights reserved.
//

import UIKit

class StepProgressView: UIView {

    // MARK: - Behavior

    /// Titles of the step-by-step progression stages
    var steps: [String] = []    { didSet {setupStepViews()} }

    /// Current active step: -1 = not started, steps.count = all done.
    var currentStep: Int = -1   { didSet {colorSteps()} }

    // MARK: - Appearance

    enum Shape {
        case Circle
        case Square
    }

    var stepShape = Shape.Circle
    var firstStepShape = Shape.Circle
    var lastStepShape = Shape.Square

    var shapeSize: CGFloat = UIFont.systemFontSize()
    var lineWidth: CGFloat = 1
    var verticalPadding: CGFloat = UIFont.systemFontSize() // between steps
    var horizontalPadding: CGFloat = UIFont.systemFontSize() / 2 // between shape and text
    var textFont = UIFont.systemFontOfSize(UIFont.systemFontSize())

    // MARK: - Colors

    var futureStepColor = UIColor.lightGrayColor()
    var pastStepColor = UIColor.blackColor()
    var currentStepColor = UIColor.blackColor()

    var futureStepFillColor = UIColor.clearColor()
    var pastStepFillColor = UIColor.blackColor()
    var currentStepFillColor = UIColor.lightGrayColor()

    var futureTextColor = UIColor.lightGrayColor()
    var pastTextColor = UIColor.blackColor()
    var currentTextColor = UIColor.blackColor()


    // MARK: - Private

    private var stepViews: [SingleStepView] = []

    private func setupStepViews() {
        stepViews.map { $0.removeFromSuperview() }
        stepViews.removeAll(keepCapacity: true)

        for i in 0 ..< steps.count {

            // create step view
            var shape: Shape
            switch i {
            case 0:             shape = firstStepShape
            case steps.count-1: shape = lastStepShape
            default:            shape = stepShape
            }
            let stepView = SingleStepView(text: steps[i], font: textFont, shape: shape, shapeSize: shapeSize, lineWidth: lineWidth, hPadding: horizontalPadding, vPadding: verticalPadding)
            stepView.color(text: futureTextColor, stroke: futureStepColor, fill: futureStepFillColor, line: futureStepColor)
            addSubview(stepView)
            stepViews.append(stepView)

            // layout step view
            let prevView = (i == 0) ? self : stepViews[i-1]
            let prevAttribute: NSLayoutAttribute = (i == 0) ? .Top : .Bottom
            addConstraints([
                NSLayoutConstraint(item: stepView, attribute: .Top, relatedBy: .Equal, toItem: prevView, attribute: prevAttribute, multiplier: 1, constant: 0),
                NSLayoutConstraint(item: stepView, attribute: .Leading, relatedBy: .Equal, toItem: self, attribute: .Leading, multiplier: 1, constant: 0),
                NSLayoutConstraint(item: stepView, attribute: .Trailing, relatedBy: .Equal, toItem: self, attribute: .Trailing, multiplier: 1, constant: 0)
            ])
        }
        stepViews.last?.lineView.hidden = true
    }

    private func colorSteps() {
        let n = stepViews.count
        if currentStep < n {
            // color future steps
            stepViews[currentStep+1 ..< n].map { $0.color(text: self.futureTextColor, stroke: self.futureStepColor, fill: self.futureStepFillColor, line: self.futureStepColor) }

            // color current step
            if currentStep >= 0 {
                stepViews[currentStep].color(text: currentTextColor, stroke: currentStepColor, fill: currentStepFillColor, line: futureStepColor)
            }
        }

        // color past steps
        if currentStep > 0 {
            stepViews[0 ..< currentStep].map { $0.color(text: self.pastTextColor, stroke: self.pastStepColor, fill: self.pastStepFillColor, line: self.pastStepColor) }
        }
    }
}

private class SingleStepView: UIView {
    var textLabel: UILabel = UILabel()
    var shapeLayer: CAShapeLayer = CAShapeLayer()
    var lineView: UIView = UIView()

    convenience init(text: String, font: UIFont, shape: StepProgressView.Shape, shapeSize: CGFloat, lineWidth: CGFloat, hPadding: CGFloat, vPadding: CGFloat) {
        self.init()
        setTranslatesAutoresizingMaskIntoConstraints(false)

        // shape
        shapeLayer.frame = CGRect(origin: CGPoint(x: floor(lineWidth/2), y: floor(lineWidth/2)), size: CGSize(width: shapeSize, height: shapeSize))
        shapeLayer.path = UIBezierPath(shape: shape, frame: shapeLayer.bounds).CGPath
        shapeLayer.lineWidth = lineWidth
        layer.addSublayer(shapeLayer)

        // text
{'fraction_non_alphanumeric': 0.10485933503836317, 'fraction_numerical': 0.007774936061381074, 'mean_word_length': 2.603391079985256, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4402193', 'n_tokens_mistral': 2904, 'n_tokens_neox': 2783, 'n_words': 748}