From 9f07e155789fe497fc78aebffbf647e3428d4852 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 6 Apr 2020 14:31:53 -0400 Subject: [PATCH 01/14] color added. --- MVMCoreUI/Categories/UIColor+MFConvenience.h | 1 + MVMCoreUI/Categories/UIColor+MFConvenience.m | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/MVMCoreUI/Categories/UIColor+MFConvenience.h b/MVMCoreUI/Categories/UIColor+MFConvenience.h index c3c78c7a..92b28a36 100644 --- a/MVMCoreUI/Categories/UIColor+MFConvenience.h +++ b/MVMCoreUI/Categories/UIColor+MFConvenience.h @@ -24,6 +24,7 @@ + (nonnull UIColor *)mvmOrange; + (nonnull UIColor *)mfPumpkinColor; + (nonnull UIColor *)mfShamrock; ++ (nonnull UIColor *)mvmGreen; + (nonnull UIColor *)mfCerulean; + (nonnull UIColor *)mfWhiteTwo; diff --git a/MVMCoreUI/Categories/UIColor+MFConvenience.m b/MVMCoreUI/Categories/UIColor+MFConvenience.m index 6ff8f70f..33df3848 100644 --- a/MVMCoreUI/Categories/UIColor+MFConvenience.m +++ b/MVMCoreUI/Categories/UIColor+MFConvenience.m @@ -61,6 +61,10 @@ return [UIColor mfColor8bitsWithRed:0 green:134 blue:49 alpha:1.0]; } ++ (nonnull UIColor *)mvmGreen { + return [UIColor mfColor8bitsWithRed:0 green:134 blue:48 alpha:1.0]; +} + + (nonnull UIColor *)mfCerulean { return [UIColor mfColor8bitsWithRed:0 green:122 blue:184 alpha:1.0]; } From 7a221da7ba330d8e5cb5ee5eb97560f7704b6277 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 6 Apr 2020 14:32:55 -0400 Subject: [PATCH 02/14] asd --- MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m index 930828f6..4e79ee6f 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m @@ -117,7 +117,7 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed."; if ([type isEqualToString:ValueTypeError]) { return [UIColor mvmOrange]; } else { - return [UIColor mfShamrock]; + return [UIColor mvmGreen]; } } From 9079d6dcae44899e35659d83fb0831007ee2e7ce Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 7 Apr 2020 11:22:01 -0400 Subject: [PATCH 03/14] more chanes made for design request --- .../Atomic/Atoms/Buttons/CaretLink.swift | 6 ++--- .../Atoms/TextFields/DigitEntryField.swift | 2 +- .../Atomic/Atoms/TextFields/EntryField.swift | 18 ++++++++------- .../Atoms/TextFields/TextEntryField.swift | 21 +++++++++++++----- MVMCoreUI/Atomic/Atoms/Views/Toggle.swift | 6 ++--- .../Views/EntryFieldContainer.swift | 22 +++++++++---------- 6 files changed, 43 insertions(+), 32 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift index 697f4282..2e042824 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift @@ -25,11 +25,11 @@ open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol { @objc public var rightViewHeight: NSNumber? @objc public var rightViewWidth: NSNumber? - @objc public var enabledColor: UIColor = .black { + @objc public var enabledColor: UIColor = .mvmBlack { didSet { changeCaretColor() } } - @objc public var disabledColor: UIColor = .mfSilver() { + @objc public var disabledColor: UIColor = .mvmCoolGray3 { didSet { changeCaretColor() } } @@ -114,7 +114,7 @@ open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol { caretView.widthAnchor.constraint(equalToConstant: width).isActive = true caretView.heightAnchor.constraint(equalToConstant: height).isActive = true - let caretLabelSpacing = NSLayoutConstraint(item: caretView, attribute: .left, relatedBy: .equal, toItem: titleLabel, attribute: .right, multiplier: 1.0, constant: 4) + let caretLabelSpacing = NSLayoutConstraint(item: caretView, attribute: .left, relatedBy: .equal, toItem: titleLabel, attribute: .right, multiplier: 1.0, constant: 7) caretLabelSpacing.isActive = true caretSpacingConstraint = caretLabelSpacing diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift index 091f9e51..38adee03 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/DigitEntryField.swift @@ -116,7 +116,7 @@ import UIKit for (index, field) in digitBoxes.enumerated() { if index < newValue.count { let indexChar = newValue.index(newValue.startIndex, offsetBy: index) - field.digitField.attributedPlaceholder = NSAttributedString(string: String(newValue[indexChar]), attributes: [NSAttributedString.Key.foregroundColor: UIColor.mfBattleshipGrey()]) + field.digitField.attributedPlaceholder = NSAttributedString(string: String(newValue[indexChar]), attributes: [NSAttributedString.Key.foregroundColor: UIColor.mvmCoolGray6]) } } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift index 7fb3a458..658af357 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift @@ -20,8 +20,8 @@ import UIKit public private(set) var titleLabel: Label = { let label = Label() - label.font = MFStyler.fontB3() - label.textColor = .mvmCoolGray6 + label.font = MFStyler.fontRegularMicro() + label.textColor = .mvmBlack label.setContentCompressionResistancePriority(.required, for: .vertical) return label }() @@ -31,7 +31,7 @@ import UIKit /// Provides contextual information on the TextField. public private(set) var feedbackLabel: Label = { let label = Label() - label.font = MFStyler.fontForTextFieldUnderLabel() + label.font = MFStyler.fontRegularMicro() label.textColor = .mvmBlack label.setContentCompressionResistancePriority(.required, for: .vertical) return label @@ -65,7 +65,8 @@ import UIKit public var isEnabled: Bool { get { return entryFieldContainer.isEnabled } set (enabled) { - self.feedbackLabel.textColor = enabled ? .black : .mfSilver() + self.titleLabel.textColor = enabled ? .mvmBlack : .mvmCoolGray3 + self.feedbackLabel.textColor = enabled ? .mvmBlack : .mvmCoolGray3 self.entryFieldContainer.isEnabled = enabled } } @@ -233,15 +234,16 @@ import UIKit //-------------------------------------------------- // MARK: - MoleculeViewProtocol //-------------------------------------------------- + @objc open override func reset() { super.reset() backgroundColor = .clear isAccessibilityElement = false - titleLabel.font = MFStyler.fontB3() - titleLabel.textColor = .mfBattleshipGrey() - feedbackLabel.font = MFStyler.fontForTextFieldUnderLabel() - feedbackLabel.textColor = .black + titleLabel.font = MFStyler.fontRegularMicro() + titleLabel.textColor = .mvmBlack + feedbackLabel.font = MFStyler.fontRegularMicro() + feedbackLabel.textColor = .mvmBlack entryFieldContainer.reset() } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index 2e7df5ee..cf927c03 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -28,7 +28,8 @@ import UIKit let textField = TextField() textField.isAccessibilityElement = true textField.setContentCompressionResistancePriority(.required, for: .vertical) - textField.font = MFStyler.fontForTextField() + textField.font = MFStyler.fontRegularBodyLarge() + textField.textColor = .mvmBlack textField.smartQuotesType = .no textField.smartDashesType = .no textField.smartInsertDeleteType = .no @@ -40,7 +41,7 @@ import UIKit //-------------------------------------------------- /// Set enabled and disabled colors to be utilized when setting this texfield's isEnabled property. - public var textColor: (enabled: UIColor?, disabled: UIColor?) = (.black, .mfSilver()) + public var textColor: (enabled: UIColor?, disabled: UIColor?) = (.mvmBlack, .mvmCoolGray3) private var observingForChange: Bool = false @@ -78,7 +79,9 @@ import UIKit if error { textField.accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "textfield_error_message") ?? "", textField.text ?? "", errorMessage ?? "") + errorIconWidthContraint?.constant = 20 } else { + errorIconWidthContraint?.constant = 0 textField.accessibilityValue = nil } @@ -140,6 +143,7 @@ import UIKit //-------------------------------------------------- public var textFieldTrailingConstraint: NSLayoutConstraint? + public var errorIconWidthContraint: NSLayoutConstraint? //-------------------------------------------------- // MARK: - Initializers @@ -168,7 +172,7 @@ import UIKit @objc open override func setupFieldContainerContent(_ container: UIView) { - MFStyler.styleTextField(textField) + textField.font = MFStyler.fontRegularBodyLarge() container.addSubview(textField) NSLayoutConstraint.activate([ @@ -193,14 +197,14 @@ import UIKit @objc open override func updateView(_ size: CGFloat) { super.updateView(size) - MFStyler.styleTextField(textField) + textField.font = MFStyler.fontRegularBodyLarge() layoutIfNeeded() } open override func reset() { super.reset() - textField.font = MFStyler.fontForTextField() + textField.font = MFStyler.fontRegularBodyLarge() } @objc deinit { @@ -252,6 +256,7 @@ import UIKit observingTextFieldDelegate?.isValid?(textfield: self) } } + /// Executes on UITextField.textDidBeginEditingNotification @objc func startEditing() { isSelected = true @@ -270,7 +275,7 @@ import UIKit resignFirstResponder() if isValid { showError = false - entryFieldContainer.bottomBar?.backgroundColor = UIColor.black.cgColor + entryFieldContainer.bottomBar?.backgroundColor = UIColor.mvmBlack.cgColor } } @@ -278,6 +283,10 @@ import UIKit resignFirstResponder() } + //-------------------------------------------------- + // MARK: - MoleculeViewProtocol + //-------------------------------------------------- + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift index 1e072faf..956c2afc 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift @@ -25,13 +25,13 @@ public typealias ActionBlockConfirmation = () -> (Bool) //-------------------------------------------------- /// Holds the on and off colors for the container. - public var containerTintColor: (on: UIColor?, off: UIColor?)? = (on: .mvmGreen, off: .black) + public var containerTintColor: (on: UIColor?, off: UIColor?)? = (on: .mvmGreen, off: .mvmBlack) /// Holds the on and off colors for the knob. - public var knobTintColor: (on: UIColor?, off: UIColor?)? = (on: .white, off: .white) + public var knobTintColor: (on: UIColor?, off: UIColor?)? = (on: .mvmWhite, off: .mvmWhite) /// Holds the on and off colors for the disabled state.. - public var disabledTintColor: (container: UIColor?, knob: UIColor?)? = (container: .mvmCoolGray3, knob: .white) + public var disabledTintColor: (container: UIColor?, knob: UIColor?)? = (container: .mvmCoolGray3, knob: .mvmWhite) /// Set this flag to false if you do not want to animate state changes. public var isAnimated = true diff --git a/MVMCoreUI/Containers/Views/EntryFieldContainer.swift b/MVMCoreUI/Containers/Views/EntryFieldContainer.swift index cf56fb9d..3a8fac64 100644 --- a/MVMCoreUI/Containers/Views/EntryFieldContainer.swift +++ b/MVMCoreUI/Containers/Views/EntryFieldContainer.swift @@ -17,7 +17,7 @@ import UIKit /// The bottom border line. Height is dynamic based on scenario. public var bottomBar: CAShapeLayer? = { let layer = CAShapeLayer() - layer.backgroundColor = UIColor.black.cgColor + layer.backgroundColor = UIColor.mvmBlack.cgColor layer.drawsAsynchronously = true layer.anchorPoint = CGPoint(x: 0.5, y: 1.0); return layer @@ -46,7 +46,7 @@ import UIKit /// Determines if the top, left, and right borders should be drawn. private var hideBorders = false - public var borderStrokeColor: UIColor = .mfSilver() + public var borderStrokeColor: UIColor = .mvmCoolGray3 private var borderPath: UIBezierPath = UIBezierPath() //-------------------------------------------------- @@ -210,8 +210,8 @@ import UIKit isUserInteractionEnabled = true hideBorders = false - borderStrokeColor = .mfSilver() - bottomBar?.backgroundColor = UIColor.black.cgColor + borderStrokeColor = .mvmCoolGray3 + bottomBar?.backgroundColor = UIColor.mvmBlack.cgColor refreshUI(bottomBarSize: 1) } @@ -219,8 +219,8 @@ import UIKit isUserInteractionEnabled = true hideBorders = false - borderStrokeColor = .mfPumpkin() - bottomBar?.backgroundColor = UIColor.mfPumpkin().cgColor + borderStrokeColor = .mvmOrange + bottomBar?.backgroundColor = UIColor.mvmOrange.cgColor refreshUI(bottomBarSize: 4) } @@ -228,8 +228,8 @@ import UIKit isUserInteractionEnabled = true hideBorders = false - borderStrokeColor = .black - bottomBar?.backgroundColor = UIColor.mfPumpkin().cgColor + borderStrokeColor = .mvmBlack + bottomBar?.backgroundColor = UIColor.mvmOrange.cgColor refreshUI(bottomBarSize: 4) } @@ -237,8 +237,8 @@ import UIKit isUserInteractionEnabled = true hideBorders = false - borderStrokeColor = .black - bottomBar?.backgroundColor = UIColor.black.cgColor + borderStrokeColor = .mvmBlack + bottomBar?.backgroundColor = UIColor.mvmBlack.cgColor refreshUI(bottomBarSize: 1) } @@ -255,7 +255,7 @@ import UIKit isUserInteractionEnabled = false hideBorders = false - borderStrokeColor = .mfSilver() + borderStrokeColor = .mvmCoolGray3 bottomBar?.backgroundColor = UIColor.mvmCoolGray3.cgColor refreshUI(bottomBarSize: 1) } From 1ac94059dbcc084aa5138e81ab435f42d2e1423b Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 7 Apr 2020 11:27:56 -0400 Subject: [PATCH 04/14] mild updates to caret --- .../Atomic/Atoms/Buttons/CaretLink.swift | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift index 2e042824..75c44eb3 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift @@ -103,8 +103,10 @@ open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol { let width = CGFloat(rightViewWidth?.floatValue ?? CARET_VIEW_WIDTH) let height = CGFloat(rightViewHeight?.floatValue ?? CARET_VIEW_HEIGHT) - let edgeInsets: UIEdgeInsets = contentEdgeInsets - contentEdgeInsets = UIEdgeInsets(top: edgeInsets.top, left: edgeInsets.left, bottom: edgeInsets.bottom, right: 4 + width) + contentEdgeInsets = UIEdgeInsets(top: contentEdgeInsets.top, + left: contentEdgeInsets.left, + bottom: contentEdgeInsets.bottom, + right: 4 + width) let caretView: UIView = rightView ?? createCaretView() rightView = caretView @@ -118,8 +120,8 @@ open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol { caretLabelSpacing.isActive = true caretSpacingConstraint = caretLabelSpacing - NSLayoutConstraint(item: caretView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1.0, constant: 0).isActive = true - NSLayoutConstraint(item: self, attribute: .right, relatedBy: .greaterThanOrEqual, toItem: caretView, attribute: .right, multiplier: 1.0, constant: 0).isActive = true + caretView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true + trailingAnchor.constraint(greaterThanOrEqualTo: caretView.trailingAnchor).isActive = true caretView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true bottomAnchor.constraint(greaterThanOrEqualTo: caretView.bottomAnchor).isActive = true contentHorizontalAlignment = .left @@ -137,17 +139,21 @@ open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol { // MARK: - Atomization //------------------------------------------------------ public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - guard let caretLinkModel = model as? CaretLinkModel else { return } - if let color = caretLinkModel.backgroundColor { + + guard let model = model as? CaretLinkModel else { return } + + if let color = model.backgroundColor { backgroundColor = color.uiColor } - enabledColor = caretLinkModel.enabledColor.uiColor - if let color = caretLinkModel.disabledColor { + + enabledColor = model.enabledColor.uiColor + if let color = model.disabledColor { disabledColor = color.uiColor } - isEnabled = caretLinkModel.enabled - set(with: caretLinkModel.action, delegateObject: delegateObject, additionalData: additionalData) - setTitle(caretLinkModel.title, for: .normal) + + isEnabled = model.enabled + set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) + setTitle(model.title, for: .normal) } public func needsToBeConstrained() -> Bool { From 2b065d1b80032653eeafd623d10116509e04998b Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 7 Apr 2020 11:34:12 -0400 Subject: [PATCH 05/14] improvedment --- MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift index 75c44eb3..b437a56f 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift @@ -103,10 +103,7 @@ open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol { let width = CGFloat(rightViewWidth?.floatValue ?? CARET_VIEW_WIDTH) let height = CGFloat(rightViewHeight?.floatValue ?? CARET_VIEW_HEIGHT) - contentEdgeInsets = UIEdgeInsets(top: contentEdgeInsets.top, - left: contentEdgeInsets.left, - bottom: contentEdgeInsets.bottom, - right: 4 + width) + contentEdgeInsets.right = 4 + width let caretView: UIView = rightView ?? createCaretView() rightView = caretView From 544a630ffb164ee59043773b2e47365e807e1520 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 7 Apr 2020 11:35:33 -0400 Subject: [PATCH 06/14] readable consteaint --- MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift index b437a56f..4ba95472 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift @@ -113,7 +113,7 @@ open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol { caretView.widthAnchor.constraint(equalToConstant: width).isActive = true caretView.heightAnchor.constraint(equalToConstant: height).isActive = true - let caretLabelSpacing = NSLayoutConstraint(item: caretView, attribute: .left, relatedBy: .equal, toItem: titleLabel, attribute: .right, multiplier: 1.0, constant: 7) + let caretLabelSpacing = caretView.leadingAnchor.constraint(equalTo: titleLabel?.trailingAnchor, constant: 7) caretLabelSpacing.isActive = true caretSpacingConstraint = caretLabelSpacing From d96aa1c310687f34116245af8dd9e0fa47369a35 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 7 Apr 2020 11:36:34 -0400 Subject: [PATCH 07/14] undo --- MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift index 4ba95472..b437a56f 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift @@ -113,7 +113,7 @@ open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol { caretView.widthAnchor.constraint(equalToConstant: width).isActive = true caretView.heightAnchor.constraint(equalToConstant: height).isActive = true - let caretLabelSpacing = caretView.leadingAnchor.constraint(equalTo: titleLabel?.trailingAnchor, constant: 7) + let caretLabelSpacing = NSLayoutConstraint(item: caretView, attribute: .left, relatedBy: .equal, toItem: titleLabel, attribute: .right, multiplier: 1.0, constant: 7) caretLabelSpacing.isActive = true caretSpacingConstraint = caretLabelSpacing From d9337cadff6bee8405d15840fa5bee0d8eaeb51c Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 7 Apr 2020 13:37:12 -0400 Subject: [PATCH 08/14] cleaning and revising donut --- MVMCoreUI.xcodeproj/project.pbxproj | 8 + .../Doughnut/ColorViewWithLabel.swift | 73 +++++ .../Molecules/Doughnut/DoughnutChart.swift | 292 ++++++++++-------- .../Doughnut/DoughnutChartItemModel.swift | 44 +++ .../Doughnut/DoughnutChartModel.swift | 24 +- .../Doughnut/DoughnutChartView.swift | 76 ++--- 6 files changed, 312 insertions(+), 205 deletions(-) create mode 100644 MVMCoreUI/Atomic/Molecules/Doughnut/ColorViewWithLabel.swift create mode 100644 MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartItemModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index c0a56ebc..67f83ce7 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -91,6 +91,8 @@ 0A6BF4722360C56C0028F841 /* BaseDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A6BF4712360C56C0028F841 /* BaseDropdownEntryField.swift */; }; 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */; }; 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; }; + 0A7ECC5D243CE85300C828E8 /* DoughnutChartItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC5C243CE85300C828E8 /* DoughnutChartItemModel.swift */; }; + 0A7ECC5F243CEB1200C828E8 /* ColorViewWithLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC5E243CEB1200C828E8 /* ColorViewWithLabel.swift */; }; 0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */; }; 0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */; }; 0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */; }; @@ -488,6 +490,8 @@ 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButton.swift; sourceTree = ""; }; 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = ""; }; 0A7BAFA2232BE63400FB8E22 /* CheckboxLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxLabel.swift; sourceTree = ""; }; + 0A7ECC5C243CE85300C828E8 /* DoughnutChartItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoughnutChartItemModel.swift; sourceTree = ""; }; + 0A7ECC5E243CEB1200C828E8 /* ColorViewWithLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorViewWithLabel.swift; sourceTree = ""; }; 0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryFieldModel.swift; sourceTree = ""; }; 0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextEntryFieldModel.swift; sourceTree = ""; }; 0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MdnEntryFieldModel.swift; sourceTree = ""; }; @@ -1340,9 +1344,11 @@ D260105723CF9CC500764D80 /* Doughnut */ = { isa = PBXGroup; children = ( + 0A7ECC5C243CE85300C828E8 /* DoughnutChartItemModel.swift */, C695A69323C9909000BFB94E /* DoughnutChartModel.swift */, C695A69523C990BC00BFB94E /* DoughnutChart.swift */, C695A69723C990C200BFB94E /* DoughnutChartView.swift */, + 0A7ECC5E243CEB1200C828E8 /* ColorViewWithLabel.swift */, ); path = Doughnut; sourceTree = ""; @@ -2067,6 +2073,7 @@ D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */, DBEFFA04225A829700230692 /* Label.swift in Sources */, D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */, + 0A7ECC5D243CE85300C828E8 /* DoughnutChartItemModel.swift in Sources */, 0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */, 011D959B240451E3000E3791 /* RuleRequiredModel.swift in Sources */, 526A265C240D1FF700B0D828 /* ListTwoColumnCompareChangesModel.swift in Sources */, @@ -2173,6 +2180,7 @@ C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */, 0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */, D2D90B442404789000DD6EC9 /* MoleculeContainerProtocol.swift in Sources */, + 0A7ECC5F243CEB1200C828E8 /* ColorViewWithLabel.swift in Sources */, 94C0150A24215643005811A9 /* ActionTopAlertModel.swift in Sources */, 012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */, D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */, diff --git a/MVMCoreUI/Atomic/Molecules/Doughnut/ColorViewWithLabel.swift b/MVMCoreUI/Atomic/Molecules/Doughnut/ColorViewWithLabel.swift new file mode 100644 index 00000000..f8dd4b5c --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/Doughnut/ColorViewWithLabel.swift @@ -0,0 +1,73 @@ +// +// ColorViewWithLabel.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 4/7/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + + +open class ColorViewWithLabel: View { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public var label = Label.createLabelRegularBodySmall(true) + public var colorView = View() + private var sizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: 8)! + + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + + public var heightConstraint: NSLayoutConstraint? + + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + + open override func setupView() { + super.setupView() + + addSubview(colorView) + addSubview(label) + + heightConstraint = colorView.heightAnchor.constraint(equalToConstant: sizeObject.getValueBasedOnApplicationWidth()) + heightConstraint?.isActive = true + colorView.widthAnchor.constraint(equalTo: colorView.heightAnchor).isActive = true + colorView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true + colorView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true + + label.leadingAnchor.constraint(equalTo: colorView.trailingAnchor, constant: PaddingOne).isActive = true + label.topAnchor.constraint(equalTo: topAnchor).isActive = true + trailingAnchor.constraint(equalTo: label.trailingAnchor).isActive = true + bottomAnchor.constraint(equalTo: label.bottomAnchor).isActive = true + } + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + label.updateView(size) + heightConstraint?.constant = sizeObject.getValueBased(onSize: size) + setNeedsDisplay() + } + + open override func reset() { + super.reset() + label.reset() + } + + //-------------------------------------------------- + // MARK: - MoleculeViewProtocol + //-------------------------------------------------- + + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) + + guard let chartItemModel = model as? DoughnutChartItemModel else { return } + + label.set(with: chartItemModel.label, delegateObject, additionalData) + colorView.backgroundColor = chartItemModel.color.uiColor + } +} diff --git a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChart.swift b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChart.swift index d84c7dc0..c7025b0f 100644 --- a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChart.swift +++ b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChart.swift @@ -8,23 +8,38 @@ import UIKit + open class DoughnutChart: View { - var doughnutLayer = CALayer() - var titleLabel = Label.commonLabelH3(true) - var subTitleLabel = Label.commonLabelB2(true) - var doughnutChartModel: DoughnutChartModel? { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public var doughnutLayer = CALayer() + public var titleLabel = Label.createLabelRegularTitleLarge(true) + public var subTitleLabel = Label.createLabelRegularMicro(true) + public var labelContainer = View() + public static let heightConstant: CGFloat = 136 + private var sizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: heightConstant)! + + //-------------------------------------------------- + // MARK: - Constraints + //-------------------------------------------------- + + public var labelContainerLeftConstraint: NSLayoutConstraint? + public var labelContainerTopConstraint: NSLayoutConstraint? + public var labelContainerBottomConstraint: NSLayoutConstraint? + public var labelContainerRightConstraint: NSLayoutConstraint? + public var heightConstraint: NSLayoutConstraint? + + //-------------------------------------------------- + // MARK: - Computed Properties + //-------------------------------------------------- + + public var doughnutChartModel: DoughnutChartModel? { get { return model as? DoughnutChartModel } - } - var labelContainer = MVMCoreUICommonViewsUtility.commonView() - var labelContainerLeftConstraint: NSLayoutConstraint? - var labelContainerTopConstraint: NSLayoutConstraint? - var labelContainerBottomConstraint: NSLayoutConstraint? - var labelContainerRightConstraint: NSLayoutConstraint? - var heightConstraint: NSLayoutConstraint? - - static let heightConstant: CGFloat = 150 - private var sizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: heightConstant)! - var height: CGFloat = heightConstant { + } + + public var height: CGFloat = heightConstant { didSet { if height != oldValue { sizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: height)! @@ -32,69 +47,73 @@ open class DoughnutChart: View { drawGraph() } } - } - - open override func updateView(_ size: CGFloat) { - super.updateView(size) - titleLabel.updateView(size) - subTitleLabel.updateView(size) - updateContainer() - drawGraph() - } - - open override func reset() { - super.reset() - titleLabel.reset() - subTitleLabel.reset() - clearLayers() - } - - open override func setupView() { - super.setupView() - guard labelContainer.superview == nil else { - return - } - addSubview(labelContainer) - - labelContainer.addSubview(titleLabel) - labelContainer.addSubview(subTitleLabel) - titleLabel.textAlignment = .center - subTitleLabel.textAlignment = .center - - //Make label font size to adjust width if label content is high - titleLabel.numberOfLines = 1 - titleLabel.adjustsFontSizeToFitWidth = true - - layer.addSublayer(doughnutLayer) - heightConstraint = heightAnchor.constraint(equalToConstant: - sizeObject.getValueBasedOnApplicationWidth()) - heightConstraint?.isActive = true - widthAnchor.constraint(equalTo: heightAnchor).isActive = true - - labelContainerLeftConstraint = labelContainer.leftAnchor.constraint(greaterThanOrEqualTo: leftAnchor, constant: lineWidth()) - labelContainerLeftConstraint?.isActive = true - labelContainerTopConstraint = labelContainer.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: lineWidth()) - labelContainerTopConstraint?.isActive = true - labelContainerRightConstraint = rightAnchor.constraint(greaterThanOrEqualTo: labelContainer.rightAnchor, constant: lineWidth()) - labelContainerRightConstraint?.isActive = true - labelContainerBottomConstraint = bottomAnchor.constraint(greaterThanOrEqualTo: labelContainer.bottomAnchor, constant: lineWidth()) - labelContainerBottomConstraint?.isActive = true - labelContainer.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true - labelContainer.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true - - NSLayoutConstraint.constraintPinSubview(titleLabel, pinTop: true, pinBottom: false, pinLeft: true, pinRight: true) - NSLayoutConstraint.constraintPinSubview(subTitleLabel, pinTop: false, pinBottom: true, pinLeft: true, pinRight: true) - _ = NSLayoutConstraint(pinFirstView: titleLabel, toSecondView: subTitleLabel, withConstant: 0, directionVertical: true) - //Rotate view for initial draw - doughnutLayer.transform = CATransform3DMakeRotation(1 * .pi, 0.0, 0.0, 1.0) } - open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + titleLabel.updateView(size) + subTitleLabel.updateView(size) + updateContainer() + drawGraph() + } + + open override func reset() { + super.reset() + titleLabel.reset() + subTitleLabel.reset() + clearLayers() + } + + open override func setupView() { + super.setupView() + + addSubview(labelContainer) + + labelContainer.addSubview(titleLabel) + labelContainer.addSubview(subTitleLabel) + titleLabel.textAlignment = .center + subTitleLabel.textAlignment = .center + + //Make label font size to adjust width if label content is high + titleLabel.numberOfLines = 1 + titleLabel.adjustsFontSizeToFitWidth = true + + layer.addSublayer(doughnutLayer) + heightConstraint = heightAnchor.constraint(equalToConstant: sizeObject.getValueBasedOnApplicationWidth()) + heightConstraint?.isActive = true + widthAnchor.constraint(equalTo: heightAnchor).isActive = true + + labelContainerLeftConstraint = labelContainer.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor, constant: lineWidth()) + labelContainerLeftConstraint?.isActive = true + labelContainerTopConstraint = labelContainer.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: lineWidth()) + labelContainerTopConstraint?.isActive = true + labelContainerRightConstraint = trailingAnchor.constraint(greaterThanOrEqualTo: labelContainer.trailingAnchor, constant: lineWidth()) + labelContainerRightConstraint?.isActive = true + labelContainerBottomConstraint = bottomAnchor.constraint(greaterThanOrEqualTo: labelContainer.bottomAnchor, constant: lineWidth()) + labelContainerBottomConstraint?.isActive = true + labelContainer.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true + labelContainer.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true + + NSLayoutConstraint.constraintPinSubview(titleLabel, pinTop: true, pinBottom: false, pinLeft: true, pinRight: true) + NSLayoutConstraint.constraintPinSubview(subTitleLabel, pinTop: false, pinBottom: true, pinLeft: true, pinRight: true) + _ = NSLayoutConstraint(pinFirstView: titleLabel, toSecondView: subTitleLabel, withConstant: 0, directionVertical: true) + //Rotate view for initial draw + doughnutLayer.transform = CATransform3DMakeRotation(1 * .pi, 0, 0, 1) + } + + //-------------------------------------------------- + // MARK: - MoleculeViewProtocol + //-------------------------------------------------- + + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) clearLayers() - guard let doughnutChartModel = doughnutChartModel else { - return - } + guard let doughnutChartModel = doughnutChartModel else { return } + titleLabel.setOptional(with: doughnutChartModel.title, delegateObject, additionalData) subTitleLabel.setOptional(with: doughnutChartModel.subtitle, delegateObject, additionalData) titleLabel.textAlignment = .center @@ -103,78 +122,83 @@ open class DoughnutChart: View { drawGraph() } - func drawGraph() { - clearLayers() - let widthHeight = sizeObject.getValueBasedOnApplicationWidth() - doughnutLayer.frame = CGRect(x: 0, y: 0, - width: widthHeight, - height: widthHeight) - if let doughnutChart = doughnutChartModel { - var prevPercent: CGFloat = 0.0 - for model in doughnutChart.sections { + //-------------------------------------------------- + // MARK: - Draw Graph + //-------------------------------------------------- + + private func drawGraph() { + clearLayers() + let widthHeight = sizeObject.getValueBasedOnApplicationWidth() + doughnutLayer.frame = CGRect(x: 0, y: 0, width: widthHeight, height: widthHeight) + + if let doughnutChart = doughnutChartModel { + var prevPercent: CGFloat = 0.0 + for model in doughnutChart.sections { prevPercent += drawBar(model, prevPercent) - } - } - } - - func drawBar(_ chartModel: DoughnutChartItemModel, _ prevPercent: CGFloat) -> CGFloat { - - let shapeLayer = CAShapeLayer() - shapeLayer.frame = doughnutLayer.frame - shapeLayer.lineWidth = lineWidth() - shapeLayer.fillColor = nil - shapeLayer.strokeColor = chartModel.color.uiColor.cgColor - - let arcCenter = shapeLayer.position - let radius = shapeLayer.bounds.size.width / 2.0 - lineWidth()/2.0 - - let value: CGFloat = chartModel.percent - let gap: CGFloat = spaceRequired() ? lineGap() : 0.0 - let startAngle = ((prevPercent / 100.0) * 2 * .pi) - (0.5 * .pi) - let endAngle = ((value / 100.0) * 2 * .pi) + startAngle - gap - let circlePath = UIBezierPath(arcCenter: arcCenter, - radius: radius, - startAngle: startAngle, - endAngle: endAngle, - clockwise: true) - - shapeLayer.path = circlePath.cgPath - doughnutLayer.addSublayer(shapeLayer) - return value - } - - func clearLayers() { - doughnutLayer.sublayers?.forEach({ $0.removeFromSuperlayer() }) - } + } + } + } - func updateContainer() { - heightConstraint?.constant = sizeObject.getValueBasedOnApplicationWidth() - updateLabelContainer() - setNeedsDisplay() - } + private func drawBar(_ chartModel: DoughnutChartItemModel, _ prevPercent: CGFloat) -> CGFloat { + + let shapeLayer = CAShapeLayer() + shapeLayer.frame = doughnutLayer.frame + shapeLayer.lineWidth = lineWidth() + shapeLayer.fillColor = nil + shapeLayer.strokeColor = chartModel.color.uiColor.cgColor + + let arcCenter = shapeLayer.position + let radius = shapeLayer.bounds.size.width / 2.0 - lineWidth() / 2.0 + + let value: CGFloat = chartModel.percent + let gap: CGFloat = spaceRequired() ? lineGap() : 0.0 + let startAngle = ((prevPercent / 100.0) * 2 * .pi) - (0.5 * .pi) + let endAngle = ((value / 100.0) * 2 * .pi) + startAngle - gap + let circlePath = UIBezierPath(arcCenter: arcCenter, + radius: radius, + startAngle: startAngle, + endAngle: endAngle, + clockwise: true) + + shapeLayer.path = circlePath.cgPath + doughnutLayer.addSublayer(shapeLayer) + return value + } - func lineWidth() -> CGFloat { - return 30 - } + private func clearLayers() { + doughnutLayer.sublayers?.forEach{ $0.removeFromSuperlayer() } + } - func lineGap() -> CGFloat { + public func updateContainer() { + + heightConstraint?.constant = sizeObject.getValueBasedOnApplicationWidth() + updateLabelContainer() + setNeedsDisplay() + } + + public func lineWidth() -> CGFloat { + return 12 + } + + public func lineGap() -> CGFloat { //If array is having the single item then no space required return doughnutChartModel?.sections.count == 1 ? 0.0 : 0.05 - } + } - func spaceRequired() -> Bool { + public func spaceRequired() -> Bool { return doughnutChartModel?.spaceRequired ?? true - } + } - func updateLabelContainer() { + public func updateLabelContainer() { + labelContainer.setNeedsDisplay() labelContainer.layoutIfNeeded() - let radius = sizeObject.getValueBasedOnApplicationWidth()/2 - lineWidth() - let labelheight = labelContainer.frame.height/2 - let padding = sizeObject.getValueBasedOnApplicationWidth()/2 - sqrt(max(0, pow(radius, 2) - pow(labelheight, 2))) + let radius = sizeObject.getValueBasedOnApplicationWidth() / 2 - lineWidth() + let labelheight = labelContainer.frame.height / 2 + let padding = sizeObject.getValueBasedOnApplicationWidth() / 2 - sqrt(max(0, pow(radius, 2) - pow(labelheight, 2))) - labelContainerLeftConstraint?.constant = padding - labelContainerRightConstraint?.constant = padding + labelContainerLeftConstraint?.constant = round(padding) + labelContainerRightConstraint?.constant = round(padding) labelContainerTopConstraint?.constant = max(radius - labelheight, labelheight) labelContainerBottomConstraint?.constant = max(radius - labelheight, labelheight) } diff --git a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartItemModel.swift b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartItemModel.swift new file mode 100644 index 00000000..ee4e664a --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartItemModel.swift @@ -0,0 +1,44 @@ +// +// DoughnutChartItemModel.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 4/7/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + + +@objcMembers public class DoughnutChartItemModel: MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public var backgroundColor: Color? + public static var identifier: String = "doughnutChartItem" + public var moleculeName: String = DoughnutChartItemModel.identifier + public var label: LabelModel + @Percent public var percent: CGFloat + public var color: Color + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + + private enum CodingKeys: String, CodingKey { + case backgroundColor + case label + case percent + case color + } + + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + + public init(percent: CGFloat, color: Color, label: LabelModel) { + self.percent = percent + self.color = color + self.label = label + } +} diff --git a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartModel.swift b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartModel.swift index ff9b1bf6..fbb034c6 100644 --- a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartModel.swift @@ -8,7 +8,12 @@ import Foundation + @objcMembers public class DoughnutChartModel: MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public var backgroundColor: Color? public static var identifier: String = "doughnutChart" public var moleculeName: String = DoughnutChartModel.identifier @@ -17,22 +22,11 @@ import Foundation public var sections: [DoughnutChartItemModel] public var spaceRequired: Bool? + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + public init(sections: [DoughnutChartItemModel]) { self.sections = sections } } - -@objcMembers public class DoughnutChartItemModel: MoleculeModelProtocol { - public var backgroundColor: Color? - public static var identifier: String = "doughnutChartItem" - public var moleculeName: String = DoughnutChartItemModel.identifier - public var label: LabelModel - @Percent public var percent: CGFloat - public var color: Color - - public init(percent: CGFloat, color: Color, label: LabelModel) { - self.percent = percent - self.color = color - self.label = label - } -} diff --git a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift index 280385cb..e037c984 100644 --- a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift +++ b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift @@ -8,18 +8,26 @@ import Foundation + @objcMembers open class DoughnutChartView: View { - var doughnutChart = DoughnutChart(frame: CGRect.zero) + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + var doughnutChart = DoughnutChart(frame: .zero) var colorLablesStack = ColorViewLabelsStack() + var doughnutChartModel: DoughnutChartModel? { - get { return model as? DoughnutChartModel } + get { return model as? DoughnutChartModel } } + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + open override func setupView() { super.setupView() - guard doughnutChart.superview == nil else { - return - } + doughnutChart.translatesAutoresizingMaskIntoConstraints = false addSubview(doughnutChart) colorLablesStack.translatesAutoresizingMaskIntoConstraints = false @@ -65,12 +73,16 @@ import Foundation colorLablesStack.reset() } + //-------------------------------------------------- + // MARK: - MoleculeViewProtocol + //-------------------------------------------------- + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.set(with: model, delegateObject, additionalData) guard let model = doughnutChartModel else { return } doughnutChart.set(with: model, delegateObject, additionalData) - + // Create the stack model var stackItems: [MoleculeStackItemModel] = [] for item in model.sections { @@ -82,6 +94,7 @@ import Foundation } } +// MARK: - MVMCoreUIViewConstrainingProtocol extension DoughnutChartView: MVMCoreUIViewConstrainingProtocol { open func horizontalAlignment() -> UIStackView.Alignment { return .leading @@ -89,6 +102,7 @@ extension DoughnutChartView: MVMCoreUIViewConstrainingProtocol { } class ColorViewLabelsStack: MoleculeStackView { + override func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { guard let stackItemModels = stackModel?.molecules else { return } for model in stackItemModels { @@ -99,53 +113,3 @@ class ColorViewLabelsStack: MoleculeStackView { } } } - -class ColorViewWithLabel: View { - - var label = Label.commonLabelB2(true) - var colorView = MVMCoreUICommonViewsUtility.commonView() - private var sizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: 8)! - var heightConstraint: NSLayoutConstraint? - - override func setupView() { - super.setupView() - guard colorView.superview == nil else { - return - } - translatesAutoresizingMaskIntoConstraints = false - addSubview(colorView) - addSubview(label) - - heightConstraint = colorView.heightAnchor.constraint(equalToConstant: sizeObject.getValueBasedOnApplicationWidth()) - heightConstraint?.isActive = true - colorView.widthAnchor.constraint(equalTo: colorView.heightAnchor).isActive = true - colorView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true - colorView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true - - label.leadingAnchor.constraint(equalTo: colorView.trailingAnchor, constant: PaddingOne).isActive = true - label.topAnchor.constraint(equalTo: topAnchor).isActive = true - trailingAnchor.constraint(equalTo: label.trailingAnchor).isActive = true - bottomAnchor.constraint(equalTo: label.bottomAnchor).isActive = true - } - - override func updateView(_ size: CGFloat) { - super.updateView(size) - label.updateView(size) - heightConstraint?.constant = sizeObject.getValueBased(onSize: size) - setNeedsDisplay() - } - - override func reset() { - super.reset() - label.reset() - } - - override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { - super.set(with: model, delegateObject, additionalData) - guard let chartItemModel = model as? DoughnutChartItemModel else { - return - } - label.set(with: chartItemModel.label, delegateObject, additionalData) - colorView.backgroundColor = chartItemModel.color.uiColor - } -} From f125d55962e7b8f43885429c38de7b0442c3d395 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 7 Apr 2020 14:10:32 -0400 Subject: [PATCH 09/14] improved constraints to center align as requested by design --- .../Molecules/Doughnut/DoughnutChart.swift | 18 ++++++++++++++++- .../Doughnut/DoughnutChartView.swift | 20 +++++++++---------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChart.swift b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChart.swift index c7025b0f..2908a90d 100644 --- a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChart.swift +++ b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChart.swift @@ -15,7 +15,7 @@ open class DoughnutChart: View { //-------------------------------------------------- public var doughnutLayer = CALayer() - public var titleLabel = Label.createLabelRegularTitleLarge(true) + public var titleLabel = Label.createLabelBoldTitleLarge(true) public var subTitleLabel = Label.createLabelRegularMicro(true) public var labelContainer = View() public static let heightConstant: CGFloat = 136 @@ -49,6 +49,22 @@ open class DoughnutChart: View { } } + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + + public override init(frame: CGRect) { + super.init(frame: .zero) + } + + public convenience init() { + self.init(frame: .zero) + } + + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift index e037c984..2b3afdd5 100644 --- a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift +++ b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift @@ -28,35 +28,33 @@ import Foundation open override func setupView() { super.setupView() - doughnutChart.translatesAutoresizingMaskIntoConstraints = false addSubview(doughnutChart) - colorLablesStack.translatesAutoresizingMaskIntoConstraints = false addSubview(colorLablesStack) doughnutChart.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true - doughnutChart.topAnchor.constraint(equalTo: topAnchor).isActive = true + doughnutChart.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true + bottomAnchor.constraint(greaterThanOrEqualTo: doughnutChart.bottomAnchor).isActive = true let doughnutBottomAnchor = bottomAnchor.constraint(equalTo: doughnutChart.bottomAnchor) doughnutBottomAnchor.priority = UILayoutPriority(rawValue: 200) doughnutBottomAnchor.isActive = true + bottomAnchor.constraint(greaterThanOrEqualTo: colorLablesStack.bottomAnchor).isActive = true + let colorLablesBottomAnchor = bottomAnchor.constraint(equalTo: colorLablesStack.bottomAnchor) colorLablesBottomAnchor.priority = UILayoutPriority(rawValue: 204) colorLablesBottomAnchor.isActive = true - let colorLablesTopAnchor = colorLablesStack.topAnchor.constraint(equalTo: doughnutChart.topAnchor) + colorLablesStack.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true + + let colorLablesTopAnchor = colorLablesStack.topAnchor.constraint(equalTo: topAnchor) colorLablesTopAnchor.priority = .defaultLow colorLablesTopAnchor.isActive = true - colorLablesStack.topAnchor.constraint(greaterThanOrEqualTo: doughnutChart.topAnchor).isActive = true - bottomAnchor.constraint(greaterThanOrEqualTo: colorLablesStack.bottomAnchor).isActive = true trailingAnchor.constraint(equalTo: colorLablesStack.trailingAnchor).isActive = true - - let centerY = colorLablesStack.centerYAnchor.constraint(equalTo: doughnutChart.centerYAnchor) - centerY.priority = UILayoutPriority(rawValue: 500) - centerY.isActive = true - + doughnutChart.centerYAnchor.constraint(equalTo: colorLablesStack.centerYAnchor).isActive = true + colorLablesStack.leadingAnchor.constraint(equalTo: doughnutChart.trailingAnchor, constant: PaddingThree).isActive = true colorLablesStack.backgroundColor = .clear } From 752ff76e79f6bac7f1a6724a0fca3a4e108ad5dc Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 7 Apr 2020 14:22:06 -0400 Subject: [PATCH 10/14] access modified --- .../Atomic/Molecules/Doughnut/DoughnutChartView.swift | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift index 2b3afdd5..1c0ea963 100644 --- a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift +++ b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChartView.swift @@ -14,10 +14,10 @@ import Foundation // MARK: - Properties //-------------------------------------------------- - var doughnutChart = DoughnutChart(frame: .zero) + public var doughnutChart = DoughnutChart() var colorLablesStack = ColorViewLabelsStack() - var doughnutChartModel: DoughnutChartModel? { + public var doughnutChartModel: DoughnutChartModel? { get { return model as? DoughnutChartModel } } @@ -75,7 +75,7 @@ import Foundation // MARK: - MoleculeViewProtocol //-------------------------------------------------- - open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) guard let model = doughnutChartModel else { return } @@ -94,6 +94,7 @@ import Foundation // MARK: - MVMCoreUIViewConstrainingProtocol extension DoughnutChartView: MVMCoreUIViewConstrainingProtocol { + open func horizontalAlignment() -> UIStackView.Alignment { return .leading } @@ -101,7 +102,7 @@ extension DoughnutChartView: MVMCoreUIViewConstrainingProtocol { class ColorViewLabelsStack: MoleculeStackView { - override func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + override func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let stackItemModels = stackModel?.molecules else { return } for model in stackItemModels { let view = ColorViewWithLabel() From 8072d8d4aa585a19df1a7e55d5748e7d7d0cf5ba Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 7 Apr 2020 14:33:57 -0400 Subject: [PATCH 11/14] organized radio --- .../Atomic/Atoms/Buttons/RadioButton.swift | 23 +++++++-------- .../Buttons/RadioButtonSelectionHelper.swift | 28 ++++++++++++++----- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/RadioButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/RadioButton.swift index 98532549..b73ddc8b 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/RadioButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/RadioButton.swift @@ -8,6 +8,7 @@ import UIKit + @objcMembers open class RadioButton: Control { //-------------------------------------------------- // MARK: - Properties @@ -18,19 +19,19 @@ import UIKit widthConstraint?.constant = diameter } } - - public var enabledColor: UIColor = .black - public var disabledColor: UIColor = .mfSilver() + + public var enabledColor: UIColor = .mvmBlack + public var disabledColor: UIColor = .mvmCoolGray6 public var delegateObject: MVMCoreUIDelegateObject? public var radioModel: RadioButtonModel? { return model as? RadioButtonModel } - + lazy public var radioGroupName: String? = { return radioModel?.fieldKey }() - + lazy public var radioButtonSelectionHelper: RadioButtonSelectionHelper? = { if let radioGroupName = radioGroupName, let radioButtonModel = delegateObject?.formHolderDelegate?.formValidator?.radioButtonsModelByGroup[radioGroupName] { @@ -100,7 +101,7 @@ import UIKit public func formFieldValue() -> AnyHashable? { return radioModel?.fieldValue } - + //-------------------------------------------------- // MARK: - MVMViewProtocol //-------------------------------------------------- @@ -108,7 +109,7 @@ import UIKit open override func setupView() { super.setupView() - backgroundColor = .white + backgroundColor = .mvmWhite clipsToBounds = true widthConstraint = widthAnchor.constraint(equalToConstant: 30) widthConstraint?.isActive = true @@ -120,7 +121,7 @@ import UIKit accessibilityTraits = .button accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") } - + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) @@ -130,9 +131,9 @@ import UIKit isSelected = model.state RadioButtonSelectionHelper.setupForRadioButtonGroup(model, self, delegateObject: delegateObject) } - + public override func reset() { - super.reset() - backgroundColor = .white + super.reset() + backgroundColor = .white } } diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonSelectionHelper.swift b/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonSelectionHelper.swift index 3decadb5..c7208802 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonSelectionHelper.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonSelectionHelper.swift @@ -7,29 +7,41 @@ // import Foundation -import UIKit + @objcMembers public class RadioButtonSelectionHelper: FormFieldProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public var fieldKey: String? public var groupName: String = FormValidator.defaultGroupName private var selectedRadioButton: RadioButton? private var fieldGroupName: String? public var baseValue: AnyHashable? - + + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + init(_ fieldKey: String?) { self.fieldKey = fieldKey } + //-------------------------------------------------- + // MARK: - Methods + //-------------------------------------------------- + public static func setupForRadioButtonGroup(_ radioButtonModel: RadioButtonModel, _ radioButton: RadioButton, delegateObject: MVMCoreUIDelegateObject?) { + guard let groupName = radioButtonModel.fieldKey, - let formValidator = delegateObject?.formHolderDelegate?.formValidator else { - return - } + let formValidator = delegateObject?.formHolderDelegate?.formValidator + else { return } let radioButtonSelectionHelper = formValidator.radioButtonsModelByGroup[groupName] ?? RadioButtonSelectionHelper(radioButtonModel.fieldKey) radioButtonSelectionHelper.fieldGroupName = radioButtonModel.fieldKey formValidator.radioButtonsModelByGroup[groupName] = radioButtonSelectionHelper - + if radioButtonModel.state { radioButtonSelectionHelper.selectedRadioButton = radioButton } @@ -37,6 +49,7 @@ import UIKit } public func selected(_ radioButton: RadioButton) { + selectedRadioButton?.isSelected = false selectedRadioButton = radioButton selectedRadioButton?.isSelected = true @@ -45,8 +58,9 @@ import UIKit // MARK: - FormValidationFormFieldProtocol extension RadioButtonSelectionHelper { + public func formFieldGroupName() -> String? { - return selectedRadioButton?.formFieldGroupName() ?? self.fieldGroupName + return selectedRadioButton?.formFieldGroupName() ?? fieldGroupName } public func formFieldValue() -> AnyHashable? { From 6ca54fce6a4679ddb01c31dec363297e4bc406d2 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 7 Apr 2020 15:22:33 -0400 Subject: [PATCH 12/14] settingup new accessor --- MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift index 658af357..c12b7dd3 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift @@ -57,6 +57,12 @@ import UIKit } } + public var accessoryInput: View? { + didSet { + + } + } + //-------------------------------------------------- // MARK: - Computed Properties //-------------------------------------------------- @@ -209,6 +215,9 @@ import UIKit feedbackLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: feedbackLabel.trailingAnchor) feedbackLabelTrailing?.isActive = true layoutMarginsGuide.bottomAnchor.constraint(equalTo: feedbackLabel.bottomAnchor).isActive = true + + container.trailingAnchor.constraint(equalTo: dropDownCaretView.trailingAnchor, constant: 16).isActive = true + dropDownCaretView.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true } @objc open override func layoutSubviews() { From dcf168b53ecec3030eaddf717e8446ee400c35cc Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 8 Apr 2020 08:19:06 -0400 Subject: [PATCH 13/14] rolaback --- MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift | 3 --- MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift | 3 --- MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChart.swift | 2 +- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift index c12b7dd3..da46c26e 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift @@ -215,9 +215,6 @@ import UIKit feedbackLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: feedbackLabel.trailingAnchor) feedbackLabelTrailing?.isActive = true layoutMarginsGuide.bottomAnchor.constraint(equalTo: feedbackLabel.bottomAnchor).isActive = true - - container.trailingAnchor.constraint(equalTo: dropDownCaretView.trailingAnchor, constant: 16).isActive = true - dropDownCaretView.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true } @objc open override func layoutSubviews() { diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index cf927c03..de0d1789 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -79,9 +79,7 @@ import UIKit if error { textField.accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "textfield_error_message") ?? "", textField.text ?? "", errorMessage ?? "") - errorIconWidthContraint?.constant = 20 } else { - errorIconWidthContraint?.constant = 0 textField.accessibilityValue = nil } @@ -143,7 +141,6 @@ import UIKit //-------------------------------------------------- public var textFieldTrailingConstraint: NSLayoutConstraint? - public var errorIconWidthContraint: NSLayoutConstraint? //-------------------------------------------------- // MARK: - Initializers diff --git a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChart.swift b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChart.swift index 2908a90d..bad0492d 100644 --- a/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChart.swift +++ b/MVMCoreUI/Atomic/Molecules/Doughnut/DoughnutChart.swift @@ -17,7 +17,7 @@ open class DoughnutChart: View { public var doughnutLayer = CALayer() public var titleLabel = Label.createLabelBoldTitleLarge(true) public var subTitleLabel = Label.createLabelRegularMicro(true) - public var labelContainer = View() + public var labelContainer = MVMCoreUICommonViewsUtility.commonView() public static let heightConstant: CGFloat = 136 private var sizeObject = MFStyler.sizeObjectGeneric(forCurrentDevice: heightConstant)! From d755709daa37b4bd4b01ee0c125001e876a35923 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 8 Apr 2020 08:35:21 -0400 Subject: [PATCH 14/14] remove code for later change --- MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift | 6 ------ 1 file changed, 6 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift index da46c26e..658af357 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift @@ -57,12 +57,6 @@ import UIKit } } - public var accessoryInput: View? { - didSet { - - } - } - //-------------------------------------------------- // MARK: - Computed Properties //--------------------------------------------------