From ba8058ccebe76cbb0f363ec759f6ffe31d22324f Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 28 Jan 2020 12:58:51 -0500 Subject: [PATCH] button swift --- MVMCoreUI.xcodeproj/project.pbxproj | 16 ++- MVMCoreUI/Atoms/Buttons/ButtonModel.swift | 8 +- MVMCoreUI/Atoms/Buttons/Link.swift | 2 +- MVMCoreUI/Atoms/Buttons/PillButton.swift | 132 ++++++++++++++++++ MVMCoreUI/BaseClasses/Button.swift | 4 + .../BaseClasses/ButtonModelProtocol.swift | 14 ++ .../Buttons => Legacy/Views}/ButtonView.swift | 0 .../DisableableModelProtocol.swift | 13 ++ .../Items/DropDownFilterTableViewCell.swift | 2 +- .../OtherHandlers/MoleculeObjectMapping.swift | 2 +- 10 files changed, 187 insertions(+), 6 deletions(-) create mode 100644 MVMCoreUI/Atoms/Buttons/PillButton.swift create mode 100644 MVMCoreUI/BaseClasses/ButtonModelProtocol.swift rename MVMCoreUI/{Atoms/Buttons => Legacy/Views}/ButtonView.swift (100%) create mode 100644 MVMCoreUI/Models/ModelProtocols/DisableableModelProtocol.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 410cf3c5..c5b03e04 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -313,6 +313,9 @@ D2E2A99A23D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A99923D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift */; }; D2E2A99C23D8D975000B42E6 /* ImageHeadlineBodyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A99B23D8D975000B42E6 /* ImageHeadlineBodyModel.swift */; }; D2E2A99D23DA3217000B42E6 /* UIStackViewAlignment+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A209CD223A7E2810068F8B0 /* UIStackViewAlignment+Extension.swift */; }; + D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A99E23E07F8A000B42E6 /* PillButton.swift */; }; + D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */; }; + D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */; }; D2FB151B23A2B65B00C20E10 /* MoleculeContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */; }; D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FB151C23A40F1500C20E10 /* MoleculeStackItem.swift */; }; DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */; }; @@ -633,6 +636,9 @@ D2E2A99723D8D63C000B42E6 /* ActionDetailWithImageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionDetailWithImageModel.swift; sourceTree = ""; }; D2E2A99923D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButtonModel.swift; sourceTree = ""; }; D2E2A99B23D8D975000B42E6 /* ImageHeadlineBodyModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageHeadlineBodyModel.swift; sourceTree = ""; }; + D2E2A99E23E07F8A000B42E6 /* PillButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillButton.swift; sourceTree = ""; }; + D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonModelProtocol.swift; sourceTree = ""; }; + D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableableModelProtocol.swift; sourceTree = ""; }; D2F4DDE52371A4CB00CD28BB /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeContainer.swift; sourceTree = ""; }; D2FB151C23A40F1500C20E10 /* MoleculeStackItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackItem.swift; sourceTree = ""; }; @@ -668,6 +674,7 @@ 012A889B23889E8400FE3DA1 /* TemplateModelProtocol.swift */, D28A837823C7D5BC00DFE4FC /* PageModelProtocol.swift */, 011B58EF23A2AA980085F53C /* ListItemModelProtocol.swift */, + D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */, ); path = ModelProtocols; sourceTree = ""; @@ -816,6 +823,7 @@ D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */, D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */, D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */, + D282AACA2243C61700C46919 /* ButtonView.swift */, ); path = Views; sourceTree = ""; @@ -1144,11 +1152,11 @@ 01F2A03123A4498200D954D8 /* CaretLinkModel.swift */, DBC4391A224421A0001AB423 /* CaretButton.swift */, D28A838A23CCDA6B00DFE4FC /* ButtonModel.swift */, - D282AACA2243C61700C46919 /* ButtonView.swift */, + D2E2A99E23E07F8A000B42E6 /* PillButton.swift */, D28A838823CCCFCB00DFE4FC /* LinkModel.swift */, + C07065C32395677300FBF997 /* Link.swift */, D28A838C23CCDCC200DFE4FC /* PrimaryButton+MoleculeProtocolExtension.swift */, D28A837623C79FC600DFE4FC /* MFCustomButton+ActionModel.swift */, - C07065C32395677300FBF997 /* Link.swift */, ); path = Buttons; sourceTree = ""; @@ -1346,6 +1354,7 @@ D2B18B7D236090D500A9AEDC /* BaseClasses */ = { isa = PBXGroup; children = ( + D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */, C003506023AA94CD00B6AC29 /* Button.swift */, D2B18B7E2360913400A9AEDC /* Control.swift */, D2B18B802360945C00A9AEDC /* View.swift */, @@ -1559,6 +1568,7 @@ D2E2A99D23DA3217000B42E6 /* UIStackViewAlignment+Extension.swift in Sources */, 01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */, 0A21DB7F235DECC500C160A2 /* EntryField.swift in Sources */, + D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */, D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */, D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */, D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */, @@ -1574,6 +1584,7 @@ 014AA72D23C5059B006F3E93 /* StackPageTemplateModel.swift in Sources */, D260106123D0C02A00764D80 /* StackItemModelProtocol.swift in Sources */, 012A88C4238D86E600FE3DA1 /* CarouselItemModelProtocol.swift in Sources */, + D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */, 94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */, D2E2A99A23D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift in Sources */, 014AA73123C5059B006F3E93 /* ListPageTemplateModel.swift in Sources */, @@ -1705,6 +1716,7 @@ D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */, 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */, D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */, + D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */, D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */, 94C2D9A323872C110006CF46 /* LabelAttributeStrikeThroughModel.swift in Sources */, D28A838523CCCA8900DFE4FC /* ScrollerModel.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift index 61e3ca3e..ce513a03 100644 --- a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift @@ -18,12 +18,13 @@ public enum ButtonSize: String, Codable { case tiny } -public class ButtonModel: MoleculeModelProtocol { +public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol { public static var identifier: String = "button" public var moleculeName: String? public var backgroundColor: Color? public var title: String public var action: ActionModelProtocol + public var enabled: Bool = true public var style: ButtonStyle? public var size: ButtonSize? = .standard public var required: Bool? @@ -39,6 +40,7 @@ public class ButtonModel: MoleculeModelProtocol { case backgroundColor case title case action + case enabled case style case size case required @@ -60,6 +62,9 @@ public class ButtonModel: MoleculeModelProtocol { if let size = try typeContainer.decodeIfPresent(ButtonSize.self, forKey: .size) { self.size = size } + if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { + self.enabled = enabled + } } public func encode(to encoder: Encoder) throws { @@ -68,6 +73,7 @@ public class ButtonModel: MoleculeModelProtocol { try container.encode(title, forKey: .title) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeModel(action, forKey: .action) + try container.encode(enabled, forKey: .enabled) try container.encodeIfPresent(style, forKey: .style) try container.encodeIfPresent(size, forKey: .size) try container.encodeIfPresent(required, forKey: .required) diff --git a/MVMCoreUI/Atoms/Buttons/Link.swift b/MVMCoreUI/Atoms/Buttons/Link.swift index 8cb9bb49..b4c00c94 100644 --- a/MVMCoreUI/Atoms/Buttons/Link.swift +++ b/MVMCoreUI/Atoms/Buttons/Link.swift @@ -46,7 +46,7 @@ import UIKit set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) } - public static func estimatedHeight(forRow molecule: ModuleMoleculeModel?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 31.0 } } diff --git a/MVMCoreUI/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atoms/Buttons/PillButton.swift new file mode 100644 index 00000000..6cf21c40 --- /dev/null +++ b/MVMCoreUI/Atoms/Buttons/PillButton.swift @@ -0,0 +1,132 @@ +// +// PillButton.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 1/28/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +open class PillButton: Button { + var size = MVMCoreUIUtility.getWidth() + var buttonModel: ButtonModel? { + get { return model as? ButtonModel } + } + + open override var isEnabled: Bool { + didSet { + style() + } + } + + public func stylePrimary() { + setTitleColor(.white, for: .normal) + setTitleColor(.white, for: .disabled) + layer.borderWidth = 0; + if isEnabled { + backgroundColor = .black + } else { + backgroundColor = .mvmCoolGray6 + } + } + + public func styleSecondary() { + setTitleColor(.black, for: .normal) + setTitleColor(.mvmCoolGray6, for: .disabled) + backgroundColor = .clear + layer.borderWidth = 1; + if isEnabled { + layer.borderColor = UIColor.black.cgColor + } else { + layer.borderColor = UIColor.mvmCoolGray6.cgColor + } + } + + private func style() { + guard let model = buttonModel else { return } + if let style = model.style { + switch style { + case .primary: + stylePrimary() + case .secondary: + styleSecondary() + } + } + } + + private func getInnerPadding() -> CGFloat { + return (getHeight() / 2.0) + } + + private func getHeight() -> CGFloat { + PillButton.getHeight(for: (model as? ButtonModel)?.size, size: size) + } + + public static func getHeight(for buttonSize: ButtonSize?, size: CGFloat) -> CGFloat { + switch buttonSize { + case .tiny: + return MFSizeObject(standardSize: 20, standardiPadPortraitSize: 34, iPadProLandscapeSize: 38)?.getValueBased(onSize: size) ?? 20 + default: + return MFSizeObject(standardSize: 42, standardiPadPortraitSize: 46, iPadProLandscapeSize: 50)?.getValueBased(onSize: size) ?? 42 + } + } + + private func getMinimumWidth() -> CGFloat { + switch buttonModel?.size ?? .standard { + case .tiny: + return MFSizeObject(standardSize: 49.0, standardiPadPortraitSize: 90.0, iPadProLandscapeSize: 135.0)?.getValueBased(onSize: size) ?? 49.0 + default: + return MFSizeObject(standardSize: 102.0, standardiPadPortraitSize: 136.0, iPadProLandscapeSize: 153.0)?.getValueBased(onSize: size) ?? 102.0 + } + } + + open override var intrinsicContentSize: CGSize { + let size = super.intrinsicContentSize + let width = size.width + (2 * getInnerPadding()) + return CGSize(width: max(width, getMinimumWidth()), height: getHeight()) + } + + // MARK: - ModelMoleculeViewProtocol + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.setWithModel(model, delegateObject, additionalData) + guard let model = model as? ButtonModel else { return } + setTitle(model.title, for: .normal) + + /*self.validationRequired = model.required ?? false + self.requiredGroupsList = model.requiredGroups + + if self.validationRequired, + let selfForm = self as? FormValidationEnableDisableProtocol { + FormValidator.setupValidation(molecule: selfForm, delegate: delegateObject?.formValidationProtocol) + }*/ + style() + } + + open override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + PillButton.getHeight(for: (molecule as? ButtonModel)?.size, size: MVMCoreUIUtility.getWidth()) + } + + // MARK: - MVMCoreViewProtocol + open override func updateView(_ size: CGFloat) { + super.updateView(size) + self.size = size + invalidateIntrinsicContentSize() + titleLabel?.font = MFStyler.fontB1(forWidth: size) + self.layer.cornerRadius = getInnerPadding() + } + + open override func setupView() { + super.setupView() + titleLabel?.numberOfLines = 1 + titleLabel?.lineBreakMode = .byTruncatingTail + titleLabel?.textAlignment = .center + contentHorizontalAlignment = .center + stylePrimary() + } + + // MARK: - MVMCoreUIViewConstrainingProtocol + open func horizontalAlignment() -> UIStackView.Alignment { + return .center + } +} diff --git a/MVMCoreUI/BaseClasses/Button.swift b/MVMCoreUI/BaseClasses/Button.swift index 0a382705..a780151a 100644 --- a/MVMCoreUI/BaseClasses/Button.swift +++ b/MVMCoreUI/BaseClasses/Button.swift @@ -91,6 +91,10 @@ public typealias ButtonAction = (Button) -> () if let backgroundColor = model?.backgroundColor { self.backgroundColor = backgroundColor.uiColor } + + guard let model = model as? ButtonModelProtocol else { return } + isEnabled = model.enabled + set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) } open class func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { diff --git a/MVMCoreUI/BaseClasses/ButtonModelProtocol.swift b/MVMCoreUI/BaseClasses/ButtonModelProtocol.swift new file mode 100644 index 00000000..d16c2464 --- /dev/null +++ b/MVMCoreUI/BaseClasses/ButtonModelProtocol.swift @@ -0,0 +1,14 @@ +// +// ButtonModelProtocol.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 1/28/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol ButtonModelProtocol: EnableableModelProtocol { + var enabled: Bool { get set } + var action: ActionModelProtocol { get set } +} diff --git a/MVMCoreUI/Atoms/Buttons/ButtonView.swift b/MVMCoreUI/Legacy/Views/ButtonView.swift similarity index 100% rename from MVMCoreUI/Atoms/Buttons/ButtonView.swift rename to MVMCoreUI/Legacy/Views/ButtonView.swift diff --git a/MVMCoreUI/Models/ModelProtocols/DisableableModelProtocol.swift b/MVMCoreUI/Models/ModelProtocols/DisableableModelProtocol.swift new file mode 100644 index 00000000..1e49bd8c --- /dev/null +++ b/MVMCoreUI/Models/ModelProtocols/DisableableModelProtocol.swift @@ -0,0 +1,13 @@ +// +// EnableableModelProtocol.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 1/28/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol EnableableModelProtocol { + var enabled: Bool { get set } +} diff --git a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift index 46139a37..8c813d24 100644 --- a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift @@ -60,7 +60,7 @@ import UIKit bottomSeparatorView?.setStyle(.none) } - public override static func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + public override class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return 80 } } diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 34b8e6ca..71331e73 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -27,7 +27,7 @@ import Foundation ModelRegistry.register(LabelAttributeActionModel.self) // Buttons - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: PrimaryButton.self, viewModelClass: ButtonModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: PillButton.self, viewModelClass: ButtonModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: TwoButtonView.self, viewModelClass: TwoButtonViewModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Link.self, viewModelClass: LinkModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: CaretButton.self, viewModelClass: CaretLinkModel.self)