diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index c1f4a798..c8cebe2b 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -18,6 +18,8 @@ 01DF567021FA5AB300CC099B /* TextFieldListFormViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */; }; 01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */; }; + 0A7BAFA1232BE61800FB8E22 /* CheckBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* CheckBox.swift */; }; + 0A7BAFA3232BE63400FB8E22 /* CheckBoxWithLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA2232BE63400FB8E22 /* CheckBoxWithLabel.swift */; }; 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948DB67D2326DCD90011F916 /* MultiProgress.swift */; }; B8200E152280C4CF007245F4 /* ProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8200E142280C4CF007245F4 /* ProgressBar.swift */; }; B8200E192281DC1A007245F4 /* CornerLabels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8200E182281DC1A007245F4 /* CornerLabels.swift */; }; @@ -202,6 +204,8 @@ 01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MFTextFieldListView.swift; sourceTree = ""; }; 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldListFormViewController.swift; sourceTree = ""; }; 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionDetailWithImage.swift; sourceTree = ""; }; + 0A7BAFA0232BE61800FB8E22 /* CheckBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckBox.swift; sourceTree = ""; }; + 0A7BAFA2232BE63400FB8E22 /* CheckBoxWithLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckBoxWithLabel.swift; sourceTree = ""; }; 948DB67D2326DCD90011F916 /* MultiProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgress.swift; sourceTree = ""; }; B8200E142280C4CF007245F4 /* ProgressBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressBar.swift; sourceTree = ""; }; B8200E182281DC1A007245F4 /* CornerLabels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CornerLabels.swift; sourceTree = ""; }; @@ -719,6 +723,8 @@ DB891E822253FA8500022516 /* Label.swift */, 0198F7A02256A80A0066C936 /* MFRadioButton.h */, 0198F7A22256A80A0066C936 /* MFRadioButton.m */, + 0A7BAFA0232BE61800FB8E22 /* CheckBox.swift */, + 0A7BAFA2232BE63400FB8E22 /* CheckBoxWithLabel.swift */, ); path = Views; sourceTree = ""; @@ -1040,6 +1046,7 @@ D282AACB2243C61700C46919 /* ButtonView.swift in Sources */, D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */, 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */, + 0A7BAFA1232BE61800FB8E22 /* CheckBox.swift in Sources */, D22479962316AF6E003FCCF9 /* HeadlineBodyTextButton.swift in Sources */, D2E1FADD2268B25E00AEFD8C /* MoleculeTableViewCell.swift in Sources */, D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */, @@ -1067,6 +1074,7 @@ D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */, D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */, D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */, + 0A7BAFA3232BE63400FB8E22 /* CheckBoxWithLabel.swift in Sources */, D29DF11D21E684A9003B2FB9 /* MVMCoreUISplitViewController.m in Sources */, 0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */, D29DF29821E7ADB8003B2FB9 /* MFScrollingViewController.m in Sources */, diff --git a/MVMCoreUI/Atoms/Views/CheckBox.swift b/MVMCoreUI/Atoms/Views/CheckBox.swift new file mode 100644 index 00000000..a990aa90 --- /dev/null +++ b/MVMCoreUI/Atoms/Views/CheckBox.swift @@ -0,0 +1,165 @@ +// +// CheckBox.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 9/13/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import MVMCore + +class CheckBox: UIControl, MVMCoreViewProtocol, MVMCoreUIMoleculeViewProtocol, MVMCoreUIViewConstrainingProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + var lineWidth: CGFloat = 0.0 + var lineColor: UIColor? + + + let startXOffset: Float = 42.0 / 124.0 + let startYOffset: Float = 66.0 / 124.0 + let pivotXOffset: Float = 58.0 / 124.0 + let pivotYOffset: Float = 80.0 / 124.0 + let endXOffset: Float = 83.0 / 124.0 + let endYOffset: Float = 46.0 / 124.0 + let pivotPercentage: Float = 0.34 + let endPercentage = 1.0 - pivotPercentage + let animationInterval: Float = 0.01 + + + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + + private var drawPercentage: Float = 0.0 + private var animationTimer: Timer? + private var checkLayer: CAShapeLayer? + private var selected = false + + func setupView() { + super.setupView() + backgroundColor = UIColor.clear + drawPercentage = 1.0 + lineColor = UIColor.black + lineWidth = 1.0 + } + + func update(_ size: CGFloat) { + super.update(size) + } + + var lineWidth: CGFloat { + get { + return super.lineWidth + } + set(lineWidth) { + self.lineWidth = lineWidth + if checkLayer { + checkLayer.removeFromSuperlayer() + checkLayer = nil + updateCheckSelected(selected, animated: false) + } + } + } + + + //-------------------------------------------------- + // MARK: - Draw + //-------------------------------------------------- + + func drawCheck() { + if !checkLayer { + layoutIfNeeded() + let path = UIBezierPath() + path.move(to: CGPoint(x: lineWidth / 2, y: bounds.size.height * 0.55)) + path.addLine(to: CGPoint(x: bounds.size.width * 0.45, y: bounds.size.height * 0.85)) + path.addLine(to: CGPoint(x: bounds.size.width - lineWidth / 2, y: lineWidth / 2)) + + checkLayer = CAShapeLayer() + checkLayer.frame = bounds + layer.addSublayer(checkLayer) + checkLayer.strokeColor = lineColor.cgColor ?? UIColor.black.cgColor + checkLayer.fillColor = UIColor.clear.cgColor + checkLayer.path = path.cgPath + checkLayer.lineWidth = lineWidth + + CATransaction.begin() + CATransaction.setDisableActions(true) + checkLayer.strokeEnd = 0.0 + CATransaction.commit() + } + } + + //-------------------------------------------------- + // MARK: - Methods + //-------------------------------------------------- + + func updateCheckSelected(_ selected: Bool, animated: Bool) { + MVMCoreDispatchUtility.performBlock(onMainThread: { + self.selected = selected + + // animate this bar + self.drawCheck() + + var layer: CAShapeLayer? + if self.checkLayer.presentation() != nil && animated { + layer = self.checkLayer.presentation() + } else { + layer = self.checkLayer + } + + if animated { + let animateStrokeEnd = CABasicAnimation(keyPath: "strokeEnd") + animateStrokeEnd.fillMode = .both + animateStrokeEnd.isRemovedOnCompletion = false + animateStrokeEnd.duration = 0.3 + + animateStrokeEnd.fromValue = NSNumber(value: Float(layer?.strokeEnd ?? 0.0)) + if selected { + animateStrokeEnd.toValue = NSNumber(value: 1) + } else { + animateStrokeEnd.toValue = NSNumber(value: 0) + } + + animateStrokeEnd.timingFunction = CAMediaTimingFunction(name: .linear) + layer?.add(animateStrokeEnd, forKey: "strokeEndAnimation") + } else { + layer?.removeAllAnimations() + CATransaction.begin() + CATransaction.setDisableActions(true) + if selected { + layer?.strokeEnd = 1.0 + } else { + layer?.strokeEnd = 0.0 + } + CATransaction.commit() + } + }) + } + + + func setLineColor(_ lineColor: UIColor?) { + self.lineColor = lineColor + if checkLayer { + checkLayer.strokeColor = lineColor?.cgColor + updateCheckSelected(selected, animated: false) + } + } + + func layoutSubviews() { + drawCheck() + } + + //-------------------------------------------------- + // MARK: - Molecular + //-------------------------------------------------- + + func updateView(_ size: CGFloat) { + <#code#> + } + + func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + <#code#> + } +} diff --git a/MVMCoreUI/Atoms/Views/CheckBoxWithLabel.swift b/MVMCoreUI/Atoms/Views/CheckBoxWithLabel.swift new file mode 100644 index 00000000..5e7c7739 --- /dev/null +++ b/MVMCoreUI/Atoms/Views/CheckBoxWithLabel.swift @@ -0,0 +1,46 @@ +// +// CheckBoxWithLabel.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 9/13/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + + +class CheckBoxWithLabel: ViewConstrainingView { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + weak var checkMark: CheckBox? + private(set) var isSelected = false + var sizeObject: MFSizeObject? + //?????? + var checkedColor: UIColor? + var unCheckedColor: UIColor? + // Label to the right of the check box. + weak var descriptionLabel: Label? + // Setter for the descriptionLabel.text. Also sets the accessibility text. + var descriptionText: String? + var descriptionAttributedText: NSAttributedString? + // A block that is called when the switch is selected. + var switchSelected: ((_ selected: Bool) -> ())? + + //-------------------------------------------------- + // MARK: - Life Cycle + //-------------------------------------------------- + + // TODO: MVMCoreUICheckBox.m + + //-------------------------------------------------- + // MARK: - Molecular + //-------------------------------------------------- + + override func updateView(_ size: CGFloat) { + + } + + override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + + } +}