From c75337bfdf03461953defbc53b36be884e10471d Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 26 Sep 2019 11:42:16 -0400 Subject: [PATCH] Getting closer to testing phase. --- MVMCoreUI/Atoms/Views/Checkbox.swift | 154 +++++++--------- .../Atoms/Views/CheckboxWithLabelView.swift | 164 +++++++----------- 2 files changed, 130 insertions(+), 188 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Checkbox.swift b/MVMCoreUI/Atoms/Views/Checkbox.swift index f29940f6..4408ea6d 100644 --- a/MVMCoreUI/Atoms/Views/Checkbox.swift +++ b/MVMCoreUI/Atoms/Views/Checkbox.swift @@ -15,67 +15,27 @@ import MVMCore //-------------------------------------------------- public static let defaultHeightWidth: CGFloat = 18.0 - /* - //Offsets based on the 124x124 example checkmark - 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 - */ + /// The color of the box and line when checked. public var checkedColor: UIColor = .black - public var unCheckedColor: UIColor = .mfPaleGrey() + /// The color of the border when unChecked. + public var unCheckedColor: UIColor = .black + + /// If true the border of this checkbox will be circular. public var hasRoundCorners = false + // Internal values to manage the appearance of the checkbox. private var shapeLayer: CAShapeLayer? - private var _lineColor: UIColor = .black - private var _borderColor: UIColor = .black - private var _lineWidth: CGFloat = 1 - private var _cornerRadius: CGFloat = 0 - public func setCheckMarkLayer() { - layer.cornerRadius = hasRoundCorners ? 5 : 0 + public var cornerRadiusValue: CGFloat { + return bounds.height / 2.0 } - public var lineWidth: CGFloat { - get { return _lineWidth } - set (newLineWidth) { - _lineWidth = newLineWidth - if shapeLayer != nil { - shapeLayer?.removeFromSuperlayer() - shapeLayer = nil - updateCheckSelected(isSelected, animated: false) - } - } - } - - public var lineColor: UIColor { - get { return _lineColor } - set (newLineColor) { - _lineColor = newLineColor - if let shapeLayer = shapeLayer { - shapeLayer.strokeColor = lineColor.cgColor - updateCheckSelected(isSelected, animated: false) - } - } - } - - public var borderColor: UIColor { - get { return _borderColor } - set (newBorderColor) { - _borderColor = newBorderColor - if let shapeLayer = shapeLayer { - shapeLayer.strokeColor = borderColor.cgColor - updateCheckSelected(isSelected, animated: false) - } - } - } + public var lineWidth: CGFloat = 1 + public var lineColor: UIColor = .black + public var borderColor: UIColor = .black + private var checkedBackgroundColor: UIColor = .white override open var isSelected: Bool { didSet { @@ -104,6 +64,7 @@ import MVMCore lazy private var uncheckedAnimation: CABasicAnimation = { let unCheck = CABasicAnimation(keyPath: "strokeEnd") + unCheck.timingFunction = CAMediaTimingFunction(name: .linear) unCheck.fillMode = .both unCheck.duration = 0.33 unCheck.fromValue = 0 @@ -120,20 +81,21 @@ import MVMCore setupView() } - public convenience init() { - self.init(frame:.zero) - } - /// There is currently no intention on using xib files. required public init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) fatalError("xib file is not implemented for CheckBox.") } - public convenience init(checkedColor: UIColor, uncheckColor: UIColor, isChecked: Bool) { + public convenience init() { + self.init(frame:.zero) + } + + public convenience init(checkedColor: UIColor, unCheckedColor: UIColor, isChecked: Bool = false) { self.init(frame: .zero) isSelected = isChecked - // TODO: define the rest.... + self.checkedColor = checkedColor + self.unCheckedColor = unCheckedColor } //-------------------------------------------------- @@ -149,8 +111,6 @@ import MVMCore translatesAutoresizingMaskIntoConstraints = false backgroundColor = .white - lineColor = .black - lineWidth = 1.0 let path = UIBezierPath() path.move(to: CGPoint(x: lineWidth / 2, y: bounds.size.height * 0.55)) @@ -172,8 +132,16 @@ import MVMCore // MARK: - Methods //-------------------------------------------------- - private func drawCheck() { + open override func sendAction(_ action: Selector, to target: Any?, for event: UIEvent?) { + print("Action initiated") + } + open override func sendActions(for controlEvents: UIControl.Event) { + print("Actions Inititaled") + } + + private func drawCheck() { + if shapeLayer == nil { layoutIfNeeded() @@ -199,12 +167,27 @@ import MVMCore } } - public func updateCheckSelected(_ selected: Bool, animated: Bool) { + /* + //Offsets based on the 124x124 example checkmark + 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 + */ + + public func updateCheckboxSelection(_ selected: Bool, animated: Bool) { + + shapeLayer?.removeFromSuperlayer() + shapeLayer = nil DispatchQueue.main.async { self.isSelected = selected - self.drawCheck() var layer: CAShapeLayer? @@ -227,12 +210,13 @@ import MVMCore layer?.removeAllAnimations() CATransaction.begin() CATransaction.setDisableActions(true) + CATransaction.setAnimationDuration(0) layer?.strokeEnd = selected ? 1 : 0 CATransaction.commit() } } } - + //-------------------------------------------------- // MARK: - Molecular //-------------------------------------------------- @@ -250,39 +234,35 @@ import MVMCore } public func updateView(_ size: CGFloat) { - + // TODO: Ensure the check logic is resized. } public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { guard let dictionary = json else { return } - if let borderColor = dictionary["borderColor"] as? String { - layer.borderColor = UIColor.mfGet(forHex: borderColor).cgColor + if let borderColorHex = dictionary["borderColor"] as? String { + layer.borderColor = UIColor.mfGet(forHex: borderColorHex).cgColor } - if let checkColor = dictionary["lineColor"] as? String { - _lineColor = UIColor.mfGet(forHex: checkColor) - } - - if let checkColor = dictionary["checkedColor"] as? String { - checkedColor = UIColor.mfGet(forHex: checkColor) - } - - if let unCheckedColor = dictionary["unCheckedColor"] as? String { - uncheckedColor = UIColor.mfGet(forHex: unCheckedColor) - } - - if let backroundColor = dictionary["backroundColor"] as? String { - self.backgroundColor = UIColor.mfGet(forHex: backroundColor) - } - if let borderWidth = dictionary["borderWidth"] as? CGFloat { - _lineWidth = borderWidth + layer.borderWidth = borderWidth } - - if let cornerRadius = dictionary["cornerRadius"] as? CGFloat { - _cornerRadius = cornerRadius + + if let checkColorHex = dictionary["lineColor"] as? String { + lineColor = UIColor.mfGet(forHex: checkColorHex) + } + + if let checkColorHex = dictionary["checkedColor"] as? String { + checkedColor = UIColor.mfGet(forHex: checkColorHex) + } + + if let unCheckedColorHex = dictionary["unCheckedColor"] as? String { + unCheckedColor = UIColor.mfGet(forHex: unCheckedColorHex) + } + + if let backroundColorHex = dictionary["backroundColor"] as? String { + backgroundColor = UIColor.mfGet(forHex: backroundColorHex) } } } diff --git a/MVMCoreUI/Atoms/Views/CheckboxWithLabelView.swift b/MVMCoreUI/Atoms/Views/CheckboxWithLabelView.swift index 62589b43..93f8a894 100644 --- a/MVMCoreUI/Atoms/Views/CheckboxWithLabelView.swift +++ b/MVMCoreUI/Atoms/Views/CheckboxWithLabelView.swift @@ -24,34 +24,13 @@ var checkboxWidthConstraint: NSLayoutConstraint? var checkboxHeightConstraint: NSLayoutConstraint? - - // Setter for the descriptionLabel.text. Also sets the accessibility text. - var labelText: String? - var labelAttributedText: NSAttributedString? - // A block that is called when the switch is selected. - public var checkBoxAction: ((_ selected: Bool) -> ())? - - func setDescriptionAttributedText(_ descriptionAttributedText: NSAttributedString?) { - descriptionLabel?.text = nil - descriptionLabel?.attributedText = descriptionAttributedText - self.valueForAccessibilityText = descriptionAttributedText?.string - } - - var descriptionText: String { - get { return super.descriptionText } - set(descriptionText) { - descriptionLabel?.attributedText = nil - descriptionLabel.text = descriptionText - self.valueForAccessibilityText = descriptionText - } - } + public var checkboxAction: ((_ selected: Bool) -> ())? var isRequired = false var fieldKey: String? var delegate: DelegateObject? - //-------------------------------------------------- // MARK: - Life Cycle //-------------------------------------------------- @@ -66,7 +45,6 @@ addSubview(checkbox) let dimension = sizeObject?.getValueBasedOnApplicationWidth() ?? Checkbox.defaultHeightWidth - checkboxWidthConstraint = checkbox.heightAnchor.constraint(equalToConstant: dimension) checkboxWidthConstraint?.isActive = true checkboxHeightConstraint = checkbox.widthAnchor.constraint(equalToConstant: dimension) @@ -75,11 +53,10 @@ NSLayoutConstraint.constraintPinSubview(checkbox, pinTop: true, pinBottom: true, pinLeft: true, pinRight: false) checkbox.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true checkbox.lineWidth = 2.0 + addSubview(label) - - NSLayoutConstraint.constraintPinSubview(label, pinCenterX: false, pinCenterY: true) - NSLayoutConstraint.constraintPinSubview(label, pinTop: false, pinBottom: false, pinLeft: false, pinRight: true) - + label.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true + trailingAnchor.constraint(equalTo: label.trailingAnchor).isActive = true label.leadingAnchor.constraint(equalTo: checkbox.trailingAnchor, constant: PaddingTwo).isActive = true } @@ -87,111 +64,99 @@ // MARK: - Initializers //-------------------------------------------------- - //default inits required public init?(coder: NSCoder) { super.init(coder: coder) fatalError("xib file is not implemented for CheckboxWithLabelView") } - override init(frame: CGRect) { + override public init(frame: CGRect) { super.init(frame: frame) setupView() - addAccessibleProperties() +// addAccessibleProperties() } - convenience init() { + public convenience init() { self.init(frame: .zero) } - init(checkedColor: UIColor?, unCheckedColor: UIColor?, text: String?) { - super.init(frame: .zero) + public convenience init(checkedColor: UIColor, unCheckedColor: UIColor, text: String?, isChecked: Bool = false) { + self.init(frame: .zero) + checkbox.checkedColor = checkedColor checkbox.unCheckedColor = unCheckedColor label.text = text - addAccessibleProperties() } - init(checkedColor: UIColor?, unCheck unCheckedColor: UIColor?, attributedText: NSAttributedString?) { - super.init(frame: .zero) - setup(withCheckedColor: checkedColor, unCheck: unCheckedColor, text: nil) - setDescriptionAttributedText = attributedText - addAccessibleProperties() - } - - init(hasRoundedCheckbox: Bool) { - super.init(frame: .zero) + public convenience init(checkedColor: UIColor, unCheck unCheckedColor: UIColor, attributedText: NSAttributedString, isChecked: Bool = false) { + self.init(frame: .zero) - checkbox.hasRoundBorder = hasRoundRectCheckbox - setup(withCheckedColor: .white, unCheck: .white, text: nil) - addAccessibleProperties() - setCheckMarkLayer() + checkbox.checkedColor = checkedColor + checkbox.unCheckedColor = unCheckedColor + label.attributedText = attributedText + } + + public convenience init(isRoundedCheckbox: Bool) { + self.init(frame: .zero) + + checkbox.hasRoundCorners = isRoundedCheckbox } //-------------------------------------------------- // MARK: - Methods //-------------------------------------------------- - override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { - return CGFloat(CheckBoxHeightWidth) + override open class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + return CGFloat(Checkbox.defaultHeightWidth) } - // MARK: - control methods - func setSelected(_ selected: Bool) { - setSelected(selected, animated: true) - checkbox?.is - } - - func setSelected(_ selected: Bool, animated: Bool) { - setSelected(selected, animated: animated, runBlock: true) - } - - func setSelected(_ selected: Bool, animated: Bool, runBlock: Bool) { - addAccessibilityLabel(selected) + @objc public func checkboxTapped(checkbox: Checkbox) { +// addAccessibilityLabel(selected) - isSelected = selected - if (switchSelected != nil) && runBlock { - switchSelected(selected) + checkbox.isSelected.toggle() + + if let checkboxAction = checkboxAction { + checkboxAction(checkbox.isSelected) } - if selected { - UIView.animate(withDuration: 0.2, delay: 0.1, options: .curveEaseOut, animations: { - self.checkedSquare.backgroundColor = self.checkedColor - }) - checkMark.updateCheckSelected(true, animated: animated) - } else { - UIView.animate(withDuration: 0.2, delay: 0.1, options: .curveEaseOut, animations: { - self.checkedSquare.backgroundColor = self.unCheckedColor - }) - checkMark?.updateCheckSelected(false, animated: animated) - } +// if checkbox.isSelected { +// UIView.animate(withDuration: 0.2, delay: 0.1, options: .curveEaseOut, animations: { +// self.checkbox.backgroundColor = self.checkedColor +// }) +// checkbox.updateCheckSelected(true, animated: animated) +// } else { +// UIView.animate(withDuration: 0.2, delay: 0.1, options: .curveEaseOut, animations: { +// self.checkbox.backgroundColor = self.unCheckedColor +// }) +// +// checkbox.updateCheckSelected(false, animated: animated) +// } - if delegate && delegate.responds(to: #selector(formValidationProtocol)) && delegate.perform(#selector(formValidationProtocol)).responds(to: #selector(Unmanaged.formValidatorModel)) { - let formValidator = delegate.perform(#selector(formValidationProtocol)).perform(#selector(Unmanaged.formValidatorModel)) as? FormValidator - formValidator?.enableByValidation() - } + // if delegate && delegate.responds(to: #selector(formValidationProtocol)) && delegate.perform(#selector(formValidationProtocol)).responds(to: #selector(Unmanaged.formValidatorModel)) { + // let formValidator = delegate.perform(#selector(formValidationProtocol)).perform(#selector(Unmanaged.formValidatorModel)) as? FormValidator + // formValidator?.enableByValidation() + // } } - + //-------------------------------------------------- // MARK: - UITouch //-------------------------------------------------- func touchesEnded(_ touches: Set, with event: UIEvent) { - if touchIsOutside(touches.first) { - sendActions(for: .touchUpOutside) + if touchIsAcceptablyOutside(touches.first) { + checkbox.sendActions(for: .touchUpOutside) } else { - self.selected = !isSelected() - sendActions(for: .touchUpInside) + checkbox.sendActions(for: .touchUpInside) } } - func touchIsOutside(_ touch: UITouch?) -> Bool { + func touchIsAcceptablyOutside(_ touch: UITouch?) -> Bool { let endLocation = touch?.location(in: self) let x = endLocation?.x ?? 0.0 let y = endLocation?.y ?? 0.0 let faultTolerance: CGFloat = 20.0 - let widthLimit = CGFloat(frame.size.width + faultTolerance) - let heightLimt = CGFloat(frame.size.height + faultTolerance) + let widthLimit = CGFloat(bounds.size.width + faultTolerance) + let heightLimt = CGFloat(bounds.size.height + faultTolerance) return x < -faultTolerance || y < -faultTolerance || x > widthLimit || y > heightLimt } @@ -225,8 +190,13 @@ extension CheckboxWithLabelView { guard let dictionary = json else { return } - fieldKey = dictionary.string(for: KeyFieldKey) - isRequired = dictionary.bool(forKey: KeyRequired) + if let fieldKey = dictionary[KeyFieldKey] as? String { + self.fieldKey = fieldKey + } + + if let isRequired = dictionary[KeyRequired] as? Bool { + self.isRequired = isRequired + } checkbox.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) label.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) @@ -253,20 +223,12 @@ extension CheckboxWithLabelView: FormValidationProtocol { extension CheckboxWithLabelView { func addAccessibleProperties() { - accessibilityTraits = .none - accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "checkbox_action_hint") +// accessibilityTraits = .none +// accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "checkbox_action_hint") } func addAccessibilityLabel(_ selected: Bool) { - let state = selected ? MVMCoreUIUtility.hardcodedString(withKey: "checkbox_checked_state") : MVMCoreUIUtility.hardcodedString(withKey: "checkbox_unchecked_state") - let description = accessibilityText.length ? accessibilityText : "" - accessibilityLabel = String(format: MVMCoreUIUtility.hardcodedString(withKey: "checkbox_desc_state"), description, state) - } - - func hideDescriptionLabelAndPinCheckboxToRight() { - - descriptionLabel?.hidden = true - checkboxRightPinConstraint.active = true - descriptionLabelLeadingConstraint.constant = 0 +// let state = selected ? MVMCoreUIUtility.hardcodedString(withKey: "checkbox_checked_state") : MVMCoreUIUtility.hardcodedString(withKey: "checkbox_unchecked_state") +// accessibilityLabel = String(format: MVMCoreUIUtility.hardcodedString(withKey: "checkbox_desc_state"), label.text ?? "", state) } }