This commit is contained in:
Pfeil, Scott Robert 2021-02-11 17:20:30 -05:00
commit 2d05cbe3a8
85 changed files with 574 additions and 435 deletions

View File

@ -105,6 +105,7 @@
0A9D09212433796500D2E6C0 /* CarouselIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9D091B2433796500D2E6C0 /* CarouselIndicatorModel.swift */; };
0A9D09222433796500D2E6C0 /* CarouselIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9D091C2433796500D2E6C0 /* CarouselIndicator.swift */; };
0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B392398524F0067DD0F /* Toggle.swift */; };
0AA4D2E125CAEC72008DB32D /* AccessibilityModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA4D2E025CAEC72008DB32D /* AccessibilityModelProtocol.swift */; };
0AB000BA24BF63490090C5E7 /* ModalListPageTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AB000B924BF63490090C5E7 /* ModalListPageTemplateModel.swift */; };
0AB000BC24BF64A50090C5E7 /* ModalStackPageTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AB000BB24BF64A50090C5E7 /* ModalStackPageTemplateModel.swift */; };
0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AB764D024460F6300E7FE72 /* UIDatePicker+Extension.swift */; };
@ -656,6 +657,7 @@
0A9D091C2433796500D2E6C0 /* CarouselIndicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CarouselIndicator.swift; sourceTree = "<group>"; };
0AA33B33239813C50067DD0F /* UIColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extension.swift"; sourceTree = "<group>"; };
0AA33B392398524F0067DD0F /* Toggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toggle.swift; sourceTree = "<group>"; };
0AA4D2E025CAEC72008DB32D /* AccessibilityModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityModelProtocol.swift; sourceTree = "<group>"; };
0AB000B924BF63490090C5E7 /* ModalListPageTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalListPageTemplateModel.swift; sourceTree = "<group>"; };
0AB000BB24BF64A50090C5E7 /* ModalStackPageTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalStackPageTemplateModel.swift; sourceTree = "<group>"; };
0AB764D024460F6300E7FE72 /* UIDatePicker+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIDatePicker+Extension.swift"; sourceTree = "<group>"; };
@ -1121,6 +1123,7 @@
011B58EE23A2AA850085F53C /* ModelProtocols */ = {
isa = PBXGroup;
children = (
0AA4D2E025CAEC72008DB32D /* AccessibilityModelProtocol.swift */,
D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */,
014AA72323C501E2006F3E93 /* ContainerModelProtocol.swift */,
D23EA7FA2475F09800D60C34 /* CarouselItemProtocol.swift */,
@ -1724,6 +1727,8 @@
D2092348244A51D40044AD09 /* RadioSwatchModel.swift */,
AAB9C109243496DD00151545 /* RadioSwatch.swift */,
AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */,
D260105223CEA61600764D80 /* ToggleModel.swift */,
0AA33B392398524F0067DD0F /* Toggle.swift */,
AAA7CD68250641F90045B959 /* HeartModel.swift */,
AAA7CD6A250642080045B959 /* Heart.swift */,
);
@ -2021,8 +2026,6 @@
D28A838223CCBD3F00DFE4FC /* WheelModel.swift */,
943784F3236B77BB006A1E82 /* Wheel.swift */,
943784F4236B77BB006A1E82 /* WheelAnimationHandler.swift */,
D260105223CEA61600764D80 /* ToggleModel.swift */,
0AA33B392398524F0067DD0F /* Toggle.swift */,
0AE98BB623FF18E9004C5109 /* ArrowModel.swift */,
0AE98BB423FF18D2004C5109 /* Arrow.swift */,
94382085243238D100B43AF3 /* WebViewModel.swift */,
@ -2045,10 +2048,10 @@
D29DF22B21E6A0FA003B2FB9 /* TextFields */ = {
isa = PBXGroup;
children = (
0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */,
0A41BA7E23453A6400D4C0BC /* TextEntryField.swift */,
0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */,
0A21DB7E235DECC500C160A2 /* EntryField.swift */,
0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */,
0A41BA7E23453A6400D4C0BC /* TextEntryField.swift */,
0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */,
0A21DB82235DFBC500C160A2 /* MdnEntryField.swift */,
0A8321AE2355FE9500CB7F00 /* DigitBox.swift */,
@ -2175,6 +2178,7 @@
D2B18B7D236090D500A9AEDC /* BaseClasses */ = {
isa = PBXGroup;
children = (
0A5D59C323AD488600EFD9E9 /* Protocols */,
0A6682B3243769C700AD3CA1 /* TextView.swift */,
C003506023AA94CD00B6AC29 /* Button.swift */,
D2B18B7E2360913400A9AEDC /* Control.swift */,
@ -2185,7 +2189,6 @@
BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */,
D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */,
D264FAA92440F97600D98315 /* CollectionView.swift */,
0A5D59C323AD488600EFD9E9 /* Protocols */,
0A7918F423F5E7EA00772FF4 /* ImageView.swift */,
D272F5F82473163100BD1A8F /* BarButtonItem.swift */,
D2EC7BDC2527B83700F540AF /* SectionHeaderFooterView.swift */,
@ -2865,6 +2868,7 @@
012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */,
52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */,
D2ED2812254B0EB800A1C293 /* MVMCoreTopAlertObject.m in Sources */,
0AA4D2E125CAEC72008DB32D /* AccessibilityModelProtocol.swift in Sources */,
C003506123AA94CD00B6AC29 /* Button.swift in Sources */,
DBC4391B224421A0001AB423 /* CaretLink.swift in Sources */,
D29C559025C095210082E7D6 /* Video.swift in Sources */,
@ -2985,6 +2989,7 @@
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
@ -3050,6 +3055,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;

View File

@ -18,6 +18,7 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupW
public static var identifier: String = "button"
public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var title: String
public var action: ActionModelProtocol
public var enabled: Bool = true
@ -93,27 +94,27 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupW
//--------------------------------------------------
public func enabled_fillColor() -> UIColor? {
return (inverted ? enabledFillColor_inverted : enabledFillColor)?.uiColor
(inverted ? enabledFillColor_inverted : enabledFillColor)?.uiColor
}
public func enabled_textColor() -> UIColor? {
return (inverted ? enabledTextColor_inverted : enabledTextColor)?.uiColor
(inverted ? enabledTextColor_inverted : enabledTextColor)?.uiColor
}
public func enabled_borderColor() -> UIColor? {
return (inverted ? enabledBorderColor_inverted : enabledBorderColor)?.uiColor
(inverted ? enabledBorderColor_inverted : enabledBorderColor)?.uiColor
}
public func disabled_fillColor() -> UIColor? {
return (inverted ? disabledFillColor_inverted : disabledFillColor)?.uiColor
(inverted ? disabledFillColor_inverted : disabledFillColor)?.uiColor
}
public func disabled_textColor() -> UIColor? {
return (inverted ? disabledTextColor_inverted : disabledTextColor)?.uiColor
(inverted ? disabledTextColor_inverted : disabledTextColor)?.uiColor
}
public func disabled_borderColor() -> UIColor? {
return (inverted ? disabledBorderColor_inverted : disabledBorderColor)?.uiColor
(inverted ? disabledBorderColor_inverted : disabledBorderColor)?.uiColor
}
/// Defines the default appearance for the primary style.
@ -172,6 +173,7 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupW
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case accessibilityIdentifier
case title
case inverted
case action
@ -195,6 +197,7 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupW
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
title = try typeContainer.decode(String.self, forKey: .title)
action = try typeContainer.decodeModel(codingKey: .action)
@ -252,6 +255,7 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupW
try container.encode(inverted, forKey: .inverted)
try container.encodeModel(action, forKey: .action)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encodeIfPresent(enabledFillColor, forKey: .fillColor)
try container.encodeIfPresent(enabledTextColor, forKey: .textColor)
try container.encodeIfPresent(enabledBorderColor, forKey: .borderColor)

View File

@ -127,7 +127,6 @@ open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol {
}
public func updateCaretSpacing(_ spacing: CGFloat) {
caretSpacingConstraint?.constant = spacing
}
@ -151,15 +150,9 @@ open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol {
setTitle(model.title, for: .normal)
}
public func needsToBeConstrained() -> Bool {
return true
}
public func needsToBeConstrained() -> Bool { true }
open func horizontalAlignment() -> UIStackView.Alignment {
return .leading
}
open func horizontalAlignment() -> UIStackView.Alignment { .leading }
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 10.5
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 10.5 }
}

View File

@ -17,6 +17,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol, Enablea
public static var identifier: String = "caretLink"
public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var title: String
public var action: ActionModelProtocol
public var enabledColor: Color = Color(uiColor: .mvmBlack)
@ -41,6 +42,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol, Enablea
private enum CodingKeys: String, CodingKey {
case backgroundColor
case accessibilityIdentifier
case title
case action
case enabledColor_inverted
@ -60,6 +62,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol, Enablea
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
title = try typeContainer.decode(String.self, forKey: .title)
if let enabledColor_inverted = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledColor_inverted) {
@ -94,6 +97,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol, Enablea
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(title, forKey: .title)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encodeModel(action, forKey: .action)
try container.encode(enabled, forKey: .enabledColor)
try container.encodeIfPresent(disabledColor, forKey: .disabledColor)

View File

@ -11,18 +11,18 @@ import UIKit
@objcMembers open class Link: Button {
//--------------------------------------------------
// MARK: - Lifecycle
// MARK: - Draw
//--------------------------------------------------
open override func draw(_ rect: CGRect) {
guard let textRect = titleLabel?.frame else { return }
let context = UIGraphicsGetCurrentContext()
guard let textRect = titleLabel?.frame,
let context = UIGraphicsGetCurrentContext()
else { return }
// Set line to the same color as the text
if let color = titleLabel?.textColor?.cgColor {
context?.setStrokeColor(color)
context.setStrokeColor(color)
}
// x should be according to the text, not the button
@ -31,9 +31,9 @@ import UIKit
// Line is 1 point below the text
let y = textRect.origin.y + textRect.size.height + 1
context?.move(to: CGPoint(x: x, y: y))
context?.addLine(to: CGPoint(x: x + textRect.size.width, y: y))
context?.strokePath()
context.move(to: CGPoint(x: x, y: y))
context.addLine(to: CGPoint(x: x + textRect.size.width, y: y))
context.strokePath()
}
open override var intrinsicContentSize: CGSize {
@ -58,9 +58,7 @@ import UIKit
set(with: model.action, delegateObject: delegateObject, additionalData: additionalData)
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 31
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 31 }
}
// MARK: - MVMCoreViewProtocol
@ -69,16 +67,12 @@ extension Link {
open override func updateView(_ size: CGFloat) {
super.updateView(size)
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
var width = size
if MVMCoreGetterUtility.fequal(a: Float.leastNormalMagnitude, b: Float(size)) {
width = MVMCoreUIUtility.getWidth()
}
self.titleLabel?.font = MFStyler.fontB2(forWidth: width)
var width = size
if MVMCoreGetterUtility.fequal(a: Float.leastNormalMagnitude, b: Float(size)) {
width = MVMCoreUIUtility.getWidth()
}
titleLabel?.font = MFStyler.fontB2(forWidth: width)
}
open override func setupView() {
@ -98,7 +92,5 @@ extension Link {
// MARK: - MVMCoreUIViewConstrainingProtocol
extension Link: MVMCoreUIViewConstrainingProtocol {
open func horizontalAlignment() -> UIStackView.Alignment {
return .leading
}
open func horizontalAlignment() -> UIStackView.Alignment { .leading }
}

View File

@ -14,11 +14,10 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
// MARK: - Properties
//--------------------------------------------------
public class var identifier: String {
return "link"
}
public class var identifier: String { "link" }
public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var title: String
public var action: ActionModelProtocol
public var enabled = true
@ -44,6 +43,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case accessibilityIdentifier
case title
case action
case enabled
@ -62,6 +62,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
title = try typeContainer.decode(String.self, forKey: .title)
action = try typeContainer.decodeModel(codingKey: .action)
@ -95,6 +96,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
try container.encode(title, forKey: .title)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encodeModel(action, forKey: .action)
try container.encode(inverted, forKey: .inverted)
try container.encode(enabled, forKey: .enabled)

View File

@ -18,7 +18,7 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
var size = MVMCoreUIUtility.getWidth()
var buttonModel: ButtonModel? {
get { return model as? ButtonModel }
get { model as? ButtonModel }
}
/// Need to re-style on set.
@ -27,9 +27,7 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
}
open var buttonSize: Styler.Button.Size = .standard {
didSet {
buttonModel?.size = buttonSize
}
didSet { buttonModel?.size = buttonSize }
}
//--------------------------------------------------
@ -47,12 +45,12 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
//--------------------------------------------------
public var enabledTitleColor: UIColor? {
get { return titleColor(for: .normal) }
get { titleColor(for: .normal) }
set { setTitleColor(newValue, for: .normal) }
}
public var disabledTitleColor: UIColor? {
get { return titleColor(for: .disabled) }
get { titleColor(for: .disabled) }
set { setTitleColor(newValue, for: .disabled) }
}
@ -106,6 +104,11 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
self.disabledTitleColor = disabledTitleColor
}
#if DEBUG
// Useful to detect with isHittable when performing UI testing.
isAccessibilityElement = isEnabled
#endif
if isEnabled {
if let fillColor = buttonModel?.enabledColors.fill {
backgroundColor = fillColor
@ -128,7 +131,7 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
}
private func getInnerPadding() -> CGFloat {
return getHeight() / 2.0
getHeight() / 2.0
}
private func getHeight() -> CGFloat {
@ -181,9 +184,11 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
guard let model = model as? ButtonModel else { return }
setTitle(model.title, for: .normal)
if let size = model.size {
buttonSize = size
}
model.updateUI = { [weak self] in
MVMCoreDispatchUtility.performBlock(onMainThread: {
self?.enableField(model.enabled)
@ -228,9 +233,7 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
// MARK: - MVMCoreUIViewConstrainingProtocol
//--------------------------------------------------
open func horizontalAlignment() -> UIStackView.Alignment {
return .center
}
open func horizontalAlignment() -> UIStackView.Alignment { .center }
public func enableField(_ enable: Bool) {
isEnabled = enable

View File

@ -14,9 +14,7 @@
public var caretView: CaretViewModel?
public var action: ActionModelProtocol?
public override class var identifier: String {
return ""
}
public override class var identifier: String { "" }
//--------------------------------------------------
// MARK: - Keys

View File

@ -23,15 +23,15 @@ import UIKit
}()
public var dateFormat: String? {
get { dateDropdownModel?.dateFormat }
set {
guard let newValue = newValue else { return }
dateDropdownModel?.dateFormat = newValue
}
get { return dateDropdownModel?.dateFormat }
}
public var dateDropdownModel: DateDropdownEntryFieldModel? {
return model as? DateDropdownEntryFieldModel
model as? DateDropdownEntryFieldModel
}
//--------------------------------------------------

View File

@ -11,9 +11,7 @@
// MARK: - Properties
//--------------------------------------------------
public override class var identifier: String {
return "dateDropdownEntryField"
}
public override class var identifier: String { "dateDropdownEntryField" }
public var dateFormatter: DateFormatter = {
let formatter = DateFormatter()

View File

@ -43,7 +43,7 @@ import UIKit
//--------------------------------------------------
public override var showError: Bool {
get { return super.showError }
get { super.showError }
set (error) {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }

View File

@ -357,9 +357,7 @@ import UIKit
super.set(with: model, delegateObject, additionalData)
}
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 115
}
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 115 }
}
// MARK: - TextField Delegate

View File

@ -12,9 +12,7 @@
// MARK: - Properties
//--------------------------------------------------
public override class var identifier: String {
return "digitTextField"
}
public override class var identifier: String { "digitTextField" }
public var digits: Int = 4

View File

@ -345,9 +345,7 @@ import UIKit
}
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 115
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 115 }
}
// MARK: - Accessibility

View File

@ -14,9 +14,7 @@ import Foundation
// MARK: - Properties
//--------------------------------------------------
public class var identifier: String {
return ""
}
public class var identifier: String { "" }
public var backgroundColor: Color?
public var accessibilityIdentifier: String?

View File

@ -120,12 +120,10 @@ open class ItemDropdownEntryField: BaseDropdownEntryField {
// MARK:- Base Picker Delegate
extension ItemDropdownEntryField: UIPickerViewDelegate, UIPickerViewDataSource {
@objc public func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
@objc public func numberOfComponents(in pickerView: UIPickerView) -> Int { 1 }
@objc public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerData.count
pickerData.count
}
@objc public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {

View File

@ -11,9 +11,7 @@
// MARK: - Properties
//--------------------------------------------------
public override class var identifier: String {
return "dropDown"
}
public override class var identifier: String { "dropDown" }
public var options: [String] = []
public var selectedIndex: Int?

View File

@ -211,17 +211,14 @@ import MVMCore
}
@objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
return proprietorTextDelegate?.textFieldShouldBeginEditing?(textField) ?? true
proprietorTextDelegate?.textFieldShouldBeginEditing?(textField) ?? true
}
@objc public func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
return proprietorTextDelegate?.textFieldShouldEndEditing?(textField) ?? true
proprietorTextDelegate?.textFieldShouldEndEditing?(textField) ?? true
}
@objc public func textFieldShouldClear(_ textField: UITextField) -> Bool {
return proprietorTextDelegate?.textFieldShouldClear?(textField) ?? true
proprietorTextDelegate?.textFieldShouldClear?(textField) ?? true
}
}

View File

@ -11,7 +11,5 @@
// MARK: - Properties
//--------------------------------------------------
public override class var identifier: String {
return "mdnEntryField"
}
public override class var identifier: String { "mdnEntryField" }
}

View File

@ -54,9 +54,7 @@ import UIKit
/// Validate when user resigns editing. Default: true
public var validateWhenDoneEditing: Bool = true
public var textEntryFieldModel: TextEntryFieldModel? {
return model as? TextEntryFieldModel
}
public var textEntryFieldModel: TextEntryFieldModel? { model as? TextEntryFieldModel }
//--------------------------------------------------
// MARK: - Computed Properties
@ -96,7 +94,7 @@ import UIKit
/// The text of this TextField.
open override var text: String? {
get { return textField.text }
get { textField.text }
set {
textField.text = newValue
textEntryFieldModel?.text = newValue
@ -105,7 +103,7 @@ import UIKit
/// Placeholder access for the TextField.
public var placeholder: String? {
get { return textField.placeholder }
get { textField.placeholder }
set { textField.placeholder = newValue }
}
@ -133,7 +131,7 @@ import UIKit
/// If you're using a ViewController, you must set this to it
public weak var uiTextFieldDelegate: UITextFieldDelegate? {
get { return textField.delegate }
get { textField.delegate }
set { textField.delegate = newValue }
}
@ -330,6 +328,7 @@ import UIKit
break
}
textField.accessibilityIdentifier = model.accessibilityIdentifier
uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate
observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate
setupTextFieldToolbar()

View File

@ -25,9 +25,7 @@
// MARK: - Properties
//--------------------------------------------------
public override class var identifier: String {
return "textField"
}
public override class var identifier: String { "textField" }
public var placeholder: String?
public var enabledTextColor: Color = Color(uiColor: .mvmBlack)

View File

@ -31,11 +31,11 @@ class TextViewEntryField: EntryField, UITextViewDelegate, ObservingTextFieldDele
//--------------------------------------------------
public var textViewEntryFieldModel: TextViewEntryFieldModel? {
return model as? TextViewEntryFieldModel
model as? TextViewEntryFieldModel
}
public override var isEnabled: Bool {
get { return super.isEnabled }
get { super.isEnabled }
set (enabled) {
super.isEnabled = enabled
@ -53,7 +53,7 @@ class TextViewEntryField: EntryField, UITextViewDelegate, ObservingTextFieldDele
}
public override var showError: Bool {
get { return super.showError }
get { super.showError }
set (error) {
if error {
@ -68,7 +68,7 @@ class TextViewEntryField: EntryField, UITextViewDelegate, ObservingTextFieldDele
/// The text of this textView.
open override var text: String? {
get { return textViewEntryFieldModel?.text }
get { textViewEntryFieldModel?.text }
set {
textView.text = newValue
textViewEntryFieldModel?.text = newValue
@ -77,7 +77,7 @@ class TextViewEntryField: EntryField, UITextViewDelegate, ObservingTextFieldDele
/// Placeholder access for the textView.
public var placeholder: String? {
get { return textViewEntryFieldModel?.placeholder }
get { textViewEntryFieldModel?.placeholder }
set {
textView.placeholder = newValue ?? ""
textViewEntryFieldModel?.placeholder = newValue
@ -127,7 +127,7 @@ class TextViewEntryField: EntryField, UITextViewDelegate, ObservingTextFieldDele
/// If you're using a ViewController, you must set this to it
public weak var uiTextViewDelegate: UITextViewDelegate? {
get { return textView.delegate }
get { textView.delegate }
set { textView.delegate = newValue }
}
@ -241,6 +241,7 @@ class TextViewEntryField: EntryField, UITextViewDelegate, ObservingTextFieldDele
textView.isEditable = model.editable
textView.textAlignment = model.textAlignment
textView.accessibilityIdentifier = model.accessibilityIdentifier
textView.textColor = model.enabled ? model.enabledTextColor.uiColor : model.disabledTextColor.uiColor
textView.font = model.fontStyle.getFont()
textView.placeholder = model.placeholder ?? ""
@ -258,7 +259,7 @@ class TextViewEntryField: EntryField, UITextViewDelegate, ObservingTextFieldDele
case .email:
textView.keyboardType = .emailAddress
default: break
default: break
}
/// No point in configuring if the TextView is Read-only.

View File

@ -14,9 +14,7 @@ class TextViewEntryFieldModel: TextEntryFieldModel {
// MARK: - Properties
//--------------------------------------------------
public override class var identifier: String {
return "textView"
}
public override class var identifier: String { "textView" }
public var accessibilityText: String?
public var fontStyle: Styler.Font = Styler.Font.RegularBodyLarge

View File

@ -25,7 +25,7 @@ import MVMCore
var delegateObject: MVMCoreUIDelegateObject?
public var checkboxModel: CheckboxModel? {
return model as? CheckboxModel
model as? CheckboxModel
}
public static let defaultHeightWidth: CGFloat = 18.0
@ -59,7 +59,7 @@ import MVMCore
/// Retrieves ideeal radius value to curve square into a circle.
public var cornerRadiusValue: CGFloat {
return bounds.size.height / 2
bounds.size.height / 2
}
/// Action Block called when the switch is selected.
@ -102,23 +102,17 @@ import MVMCore
/// Color of the check mark.
public var checkColor: UIColor = .mvmBlack {
didSet {
setShapeLayerStrokeColor(checkColor)
}
didSet { setShapeLayerStrokeColor(checkColor) }
}
/// Border width of the checkbox
public var borderWidth: CGFloat = 1 {
didSet {
layer.borderWidth = borderWidth
}
didSet { layer.borderWidth = borderWidth }
}
/// border color of the Checkbox
public var borderColor: UIColor = .mvmBlack {
didSet {
layer.borderColor = borderColor.cgColor
}
didSet { layer.borderColor = borderColor.cgColor }
}
/**
@ -359,6 +353,7 @@ import MVMCore
}
override open func accessibilityActivate() -> Bool {
guard isEnabled else { return false }
sendActions(for: .touchUpInside)
return true
}
@ -367,9 +362,7 @@ import MVMCore
// MARK: - Molecular
//--------------------------------------------------
open func needsToBeConstrained() -> Bool {
return true
}
open func needsToBeConstrained() -> Bool { true }
open override func reset() {
super.reset()

View File

@ -16,6 +16,7 @@ import Foundation
public static var identifier: String = "checkbox"
public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var checked: Bool = false
public var enabled: Bool = true
public var animated: Bool = true
@ -44,6 +45,7 @@ import Foundation
private enum CodingKeys: String, CodingKey {
case moleculeName
case accessibilityIdentifier
case checked
case enabled
case inverted
@ -69,9 +71,7 @@ import Foundation
// MARK: - Methods
//--------------------------------------------------
public func formFieldValue() -> AnyHashable? {
return checked
}
public func formFieldValue() -> AnyHashable? { checked }
//--------------------------------------------------
// MARK: - Initializer
@ -89,6 +89,8 @@ import Foundation
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
if let borderWidth = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .borderWidth) {
self.borderWidth = borderWidth
}
@ -169,6 +171,7 @@ import Foundation
try container.encode(borderWidth, forKey: .borderWidth)
try container.encode(checked, forKey: .checked)
try container.encode(inverted, forKey: .inverted)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encodeIfPresent(checkColor, forKey: .checkColor)
try container.encodeIfPresent(invertedColor, forKey: .invertedColor)
try container.encodeIfPresent(invertedBackgroundColor, forKey: .invertedBackgroundColor)

View File

@ -71,6 +71,7 @@ import UIKit
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
open override func setupView() {
super.setupView()
addTarget(self, action: #selector(tapAction), for: .touchUpInside)

View File

@ -6,15 +6,16 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "heart"
public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var isActive: Bool = false
public var activeColor: Color = Color(uiColor: .mvmRed)
public var inActiveColor: Color = Color(uiColor: .clear)
@ -24,9 +25,11 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol {
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case accessibilityIdentifier
case isActive
case activeColor
case inActiveColor
@ -43,13 +46,18 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol {
if let isActive = try typeContainer.decodeIfPresent(Bool.self, forKey: .isActive) {
self.isActive = isActive
}
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
if let activeColor = try typeContainer.decodeIfPresent(Color.self, forKey: .activeColor) {
self.activeColor = activeColor
}
if let inActiveColor = try typeContainer.decodeIfPresent(Color.self, forKey: .inActiveColor) {
self.inActiveColor = inActiveColor
}
if let action: ActionModelProtocol = try typeContainer.decodeModelIfPresent(codingKey: .action) {
self.action = action
}
@ -61,6 +69,7 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol {
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(isActive, forKey: .isActive)
try container.encode(activeColor, forKey: .activeColor)

View File

@ -6,9 +6,12 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
open class RadioBox: Control, MFButtonProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public let label = Label(fontStyle: .RegularBodySmall)
public let subTextLabel = Label(fontStyle: .RegularMicro)
public var isOutOfStock = false
@ -26,22 +29,20 @@ open class RadioBox: Control, MFButtonProtocol {
var additionalData: [AnyHashable: Any]?
public var radioBoxModel: RadioBoxModel? {
return model as? RadioBoxModel
model as? RadioBoxModel
}
public override var isSelected: Bool {
didSet {
updateAccessibility()
}
didSet { updateAccessibility() }
}
public override var isEnabled: Bool {
didSet {
updateAccessibility()
}
didSet { updateAccessibility() }
}
//--------------------------------------------------
// MARK: - MVMCoreViewProtocol
//--------------------------------------------------
open override func updateView(_ size: CGFloat) {
super.updateView(size)
@ -75,8 +76,6 @@ open class RadioBox: Control, MFButtonProtocol {
isAccessibilityElement = true
}
// MARK: - MoleculeViewProtocol
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? RadioBoxModel else { return }
@ -99,7 +98,9 @@ open class RadioBox: Control, MFButtonProtocol {
accentColor = .mvmRed
}
//--------------------------------------------------
// MARK: - State Handling
//--------------------------------------------------
open override func draw(_ layer: CALayer, in ctx: CGContext) {
// Draw the strikethrough
@ -213,21 +214,29 @@ open class RadioBox: Control, MFButtonProtocol {
return mask
}
//--------------------------------------------------
// MARK: - Accessibility
//--------------------------------------------------
public func updateAccessibility() {
var message = ""
if let labelText = label.text, label.hasText {
message += labelText + ", "
}
if let subLabelText = subTextLabel.text, subTextLabel.hasText {
message += subLabelText + ", "
}
accessibilityLabel = message
accessibilityLabel = message
accessibilityTraits = .button
if isSelected {
accessibilityTraits.insert(.selected)
}
if !isEnabled {
accessibilityTraits.insert(.notEnabled)
}

View File

@ -6,10 +6,17 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
open class RadioBoxCollectionViewCell: CollectionViewCell {
//--------------------------------------------------
// MARK: - Outlets
//--------------------------------------------------
public let radioBox = RadioBox()
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
open override func reset() {
super.reset()
backgroundColor = .clear

View File

@ -6,12 +6,16 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers public class RadioBoxModel: MoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "radioBox"
public var text: String
public var subText: String?
public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var selectedAccentColor: Color?
public var selected: Bool = false
public var enabled: Bool = true
@ -19,12 +23,17 @@ import Foundation
public var fieldValue: String?
public var action: ActionModelProtocol?
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case text
case subText
case selectedAccentColor
case backgroundColor
case accessibilityIdentifier
case selected
case enabled
case strikethrough
@ -32,18 +41,26 @@ import Foundation
case action
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
text = try typeContainer.decode(String.self, forKey: .text)
subText = try typeContainer.decodeIfPresent(String.self, forKey: .subText)
selectedAccentColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
if let isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) {
selected = isSelected
}
if let isEnabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
enabled = isEnabled
}
if let isStrikeTrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) {
strikethrough = isStrikeTrough
}
@ -59,6 +76,7 @@ import Foundation
try container.encodeIfPresent(subText, forKey: .subText)
try container.encodeIfPresent(selectedAccentColor, forKey: .selectedAccentColor)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encode(selected, forKey: .selected)
try container.encode(enabled, forKey: .enabled)
try container.encode(strikethrough, forKey: .strikethrough)

View File

@ -57,11 +57,12 @@ open class RadioBoxes: View {
super.set(with: model, delegateObject, additionalData)
self.delegateObject = delegateObject
guard let radioBoxesModel = model as? RadioBoxesModel else { return }
boxes = radioBoxesModel.boxes
FormValidator.setupValidation(for: radioBoxesModel, delegate: delegateObject?.formHolderDelegate)
guard let model = model as? RadioBoxesModel else { return }
boxes = model.boxes
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
backgroundColor = radioBoxesModel.backgroundColor?.uiColor
backgroundColor = model.backgroundColor?.uiColor
registerCells()
setHeight()
collectionView.reloadData()
@ -168,4 +169,3 @@ extension RadioBoxes: UICollectionViewDelegate {
cell.updateAccessibility()
}
}

View File

@ -6,17 +6,25 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers public class RadioBoxesModel: MoleculeModelProtocol, FormFieldProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "radioBoxes"
public var boxes: [RadioBoxModel]
public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var selectedAccentColor: Color?
public var boxesColor: Color?
public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName
public var baseValue: AnyHashable?
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
/// Returns the fieldValue of the selected box, otherwise the text of the selected box.
public func formFieldValue() -> AnyHashable? {
let selectedBox = boxes.first { (box) -> Bool in
@ -25,20 +33,30 @@ import Foundation
return selectedBox?.fieldValue ?? selectedBox?.text
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case selectedAccentColor
case backgroundColor
case accessibilityIdentifier
case boxesColor
case boxes
case fieldKey
case groupName
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
selectedAccentColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
boxesColor = try typeContainer.decodeIfPresent(Color.self, forKey: .boxesColor)
boxes = try typeContainer.decode([RadioBoxModel].self, forKey: .boxes)
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
@ -54,6 +72,7 @@ import Foundation
try container.encode(boxes, forKey: .boxes)
try container.encodeIfPresent(selectedAccentColor, forKey: .selectedAccentColor)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encode(groupName, forKey: .groupName)
}

View File

@ -15,9 +15,7 @@ import UIKit
//--------------------------------------------------
public var diameter: CGFloat = 30 {
didSet {
widthConstraint?.constant = diameter
}
didSet { widthConstraint?.constant = diameter }
}
@objc public override var isSelected: Bool {
@ -33,12 +31,10 @@ import UIKit
var additionalData: [AnyHashable: Any]?
public var radioModel: RadioButtonModel? {
return model as? RadioButtonModel
model as? RadioButtonModel
}
lazy public var radioGroupName: String? = {
return radioModel?.fieldKey
}()
lazy public var radioGroupName: String? = { radioModel?.fieldKey }()
lazy public var radioButtonSelectionHelper: RadioButtonSelectionHelper? = {
@ -95,33 +91,34 @@ import UIKit
if !isEnabled {
return
}
let wasPreviouslySelected = isSelected
if let radioButtonModel = radioButtonSelectionHelper {
radioButtonModel.selected(self)
} else {
isSelected = !isSelected
}
if let radioModel = radioModel, let actionModel = radioModel.action, isSelected, !wasPreviouslySelected {
Button.performButtonAction(with: actionModel, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: radioModel)
}
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
setNeedsDisplay()
}
public func isValidField() -> Bool {
return isSelected
}
public func isValidField() -> Bool { isSelected }
public func formFieldName() -> String? {
return radioModel?.fieldKey
radioModel?.fieldKey
}
public func formFieldGroupName() -> String? {
return radioModel?.fieldKey
radioModel?.fieldKey
}
public func formFieldValue() -> AnyHashable? {
return radioModel?.fieldValue
radioModel?.fieldValue
}
//--------------------------------------------------

View File

@ -6,7 +6,6 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
import MVMCore
@ -17,6 +16,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
public static var identifier: String = "radioButton"
public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var state: Bool = false
public var enabled: Bool = true
@ -35,6 +35,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case accessibilityIdentifier
case state
case enabled
case fieldValue
@ -56,9 +57,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
// MARK: - Validation
//--------------------------------------------------
public func formFieldValue() -> AnyHashable? {
return fieldValue
}
public func formFieldValue() -> AnyHashable? { fieldValue }
//--------------------------------------------------
// MARK: - Codec
@ -76,6 +75,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
}
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
baseValue = state
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
@ -89,6 +89,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(state, forKey: .state)
try container.encode(enabled, forKey: .enabled)

View File

@ -6,8 +6,6 @@
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers public class RadioButtonSelectionHelper: FormFieldProtocol {
//--------------------------------------------------
@ -77,7 +75,5 @@ import Foundation
// MARK: - FormValidationFormFieldProtocol
extension RadioButtonSelectionHelper {
public func formFieldValue() -> AnyHashable? {
return selectedRadioButtonModel?.fieldValue
}
public func formFieldValue() -> AnyHashable? { selectedRadioButtonModel?.fieldValue }
}

View File

@ -77,6 +77,7 @@ open class RadioSwatch: Control, MFButtonProtocol {
//------------------------------------------------------
// MARK: - State Handling
//------------------------------------------------------
open override func draw(_ layer: CALayer, in ctx: CGContext) {
//Draw the swatch
circleLayer?.removeFromSuperlayer()

View File

@ -6,7 +6,7 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
open class RadioSwatchCollectionViewCell: CollectionViewCell {
public let radioSwatch = RadioSwatch()

View File

@ -6,11 +6,15 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers public class RadioSwatchModel: MoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "radioSwatch"
public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var color: Color = Color(uiColor: .mvmBlue)
public var text: String?
public var selected: Bool = false
@ -19,9 +23,14 @@ import Foundation
public var fieldValue: String?
public var action: ActionModelProtocol?
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case accessibilityIdentifier
case color
case text
case selected
@ -31,22 +40,33 @@ import Foundation
case action
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) {
self.color = color
}
text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
if let selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) {
self.selected = selected
}
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
self.enabled = enabled
}
if let strikethrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) {
self.strikethrough = strikethrough
}
fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue)
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
}
@ -55,6 +75,7 @@ import Foundation
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encode(color, forKey: .color)
try container.encodeIfPresent(text, forKey: .text)
try container.encode(selected, forKey: .selected)
@ -64,5 +85,3 @@ import Foundation
try container.encodeModelIfPresent(action, forKey: .action)
}
}

View File

@ -55,9 +55,9 @@ open class RadioSwatches: View {
super.set(with: model, delegateObject, additionalData)
self.delegateObject = delegateObject
guard let radioSwatchesModel = model as? RadioSwatchesModel else { return }
swatches = radioSwatchesModel.swatches
FormValidator.setupValidation(for: radioSwatchesModel, delegate: delegateObject?.formHolderDelegate)
guard let model = model as? RadioSwatchesModel else { return }
swatches = model.swatches
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
collectionView.reloadData()
}

View File

@ -6,16 +6,24 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers public class RadioSwatchesModel: MoleculeModelProtocol, FormFieldProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "radioSwatches"
public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var swatches: [RadioSwatchModel]
public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName
public var baseValue: AnyHashable?
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
/// Returns the fieldValue of the selected swatch, otherwise the text of selected swatch.
public func formFieldValue() -> AnyHashable? {
let selectedSwatch = swatches.first { (swatch) -> Bool in
@ -24,17 +32,27 @@ import Foundation
return selectedSwatch?.fieldValue ?? selectedSwatch?.text
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case accessibilityIdentifier
case swatches
case fieldKey
case groupName
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
swatches = try typeContainer.decode([RadioSwatchModel].self, forKey: .swatches)
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
@ -47,6 +65,7 @@ import Foundation
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encode(swatches, forKey: .swatches)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encode(groupName, forKey: .groupName)

View File

@ -40,7 +40,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
/// Executes logic before state change. If false, then toggle state will not change and the didToggleAction will not execute.
public var shouldToggleAction: ActionBlockConfirmation? = {
return { return true }
return { true }
}()
// Sizes are from InVision design specs.
@ -69,9 +69,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
/// Simple means to prevent user interaction with the toggle.
public var isLocked: Bool = false {
didSet {
isUserInteractionEnabled = !isLocked
}
didSet { isUserInteractionEnabled = !isLocked }
}
/// The state on the toggle. Default value: false.
@ -109,7 +107,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
}
public var toggleModel: ToggleModel? {
return model as? ToggleModel
model as? ToggleModel
}
//--------------------------------------------------
@ -410,18 +408,14 @@ public typealias ActionBlockConfirmation = () -> (Bool)
}
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return Self.getContainerHeight()
Self.getContainerHeight()
}
}
// MARK: - MVMCoreUIViewConstrainingProtocol
extension Toggle {
public func needsToBeConstrained() -> Bool {
return true
}
public func needsToBeConstrained() -> Bool { true }
public func horizontalAlignment() -> UIStackView.Alignment {
return .trailing
}
public func horizontalAlignment() -> UIStackView.Alignment { .trailing }
}

View File

@ -6,8 +6,6 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import UIKit
public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableModelProtocol {
//--------------------------------------------------
@ -15,6 +13,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
//--------------------------------------------------
public static var identifier: String = "toggle"
public var accessibilityIdentifier: String?
public var backgroundColor: Color?
public var state: Bool = false
public var animated: Bool = true
@ -42,6 +41,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
case enabled
case action
case backgroundColor
case accessibilityIdentifier
case alternateAction
case accessibilityText
case onTintColor
@ -56,9 +56,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
// MARK: - Methods
//--------------------------------------------------
public func formFieldValue() -> AnyHashable? {
return state
}
public func formFieldValue() -> AnyHashable? { state }
//--------------------------------------------------
// MARK: - Initializer
@ -91,6 +89,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
alternateAction = try typeContainer.decodeModelIfPresent(codingKey: .alternateAction)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
if let onTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onTintColor) {
self.onTintColor = onTintColor
@ -120,6 +119,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encodeModelIfPresent(action, forKey: .action)
try container.encodeModelIfPresent(alternateAction, forKey: .alternateAction)
try container.encode(moleculeName, forKey: .moleculeName)

View File

@ -16,6 +16,7 @@ import Foundation
public static var identifier: String = "dashLine"
public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var dashColor: Color = Color(uiColor: .mvmCoolGray3)
public var dashColor_inverted: Color = Color(uiColor: .mvmWhite)
public var isHidden: Bool = false
@ -36,6 +37,7 @@ import Foundation
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case accessibilityIdentifier
case dashColor_inverted
case dashColor
case isHidden
@ -57,6 +59,7 @@ import Foundation
}
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
if let isHidden = try typeContainer.decodeIfPresent(Bool.self, forKey: .isHidden) {
self.isHidden = isHidden
@ -69,5 +72,6 @@ import Foundation
try container.encode(dashColor, forKey: .dashColor)
try container.encode(isHidden, forKey: .isHidden)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
}
}

View File

@ -38,7 +38,7 @@ public typealias ActionBlock = () -> ()
}
public var getRange: NSRange {
return NSRange(location: 0, length: text?.count ?? 0)
NSRange(location: 0, length: text?.count ?? 0)
}
//------------------------------------------------------
@ -209,7 +209,7 @@ public typealias ActionBlock = () -> ()
/// Default
@objc open class func label() -> Label {
return Label(frame: .zero)
Label(frame: .zero)
}
//------------------------------------------------------
@ -792,17 +792,11 @@ extension Label {
accessibilityTraits = .staticText
}
public func needsToBeConstrained() -> Bool {
return true
}
public func needsToBeConstrained() -> Bool { true }
public func horizontalAlignment() -> UIStackView.Alignment {
return .leading
}
public func horizontalAlignment() -> UIStackView.Alignment { .leading }
public func copyBackgroundColor() -> Bool {
return true
}
public func copyBackgroundColor() -> Bool { true }
}
// MARK: - Multi-Link Functionality
@ -914,6 +908,7 @@ extension UITapGestureRecognizer {
if label.makeWholeViewClickable {
return true
}
guard let abstractContainer = label.abstractTextContainer() else { return false }
let textContainer = abstractContainer.0
let layoutManager = abstractContainer.1
@ -988,6 +983,7 @@ extension Label {
}
}
}
return false
}
}

View File

@ -12,9 +12,7 @@ open class LabelAttributeActionModel: LabelAttributeModel {
// MARK: - Properties
//--------------------------------------------------
override public class var identifier: String {
return "action"
}
override public class var identifier: String { "action" }
var action: ActionModelProtocol

View File

@ -12,9 +12,7 @@
// MARK: - Properties
//--------------------------------------------------
override public class var identifier: String {
return "color"
}
override public class var identifier: String { "color" }
var textColor: Color?

View File

@ -12,9 +12,7 @@
// MARK: - Properties
//--------------------------------------------------
override public class var identifier: String {
return "font"
}
override public class var identifier: String { "font" }
var style: Styler.Font?
var name: String?

View File

@ -12,9 +12,7 @@ class LabelAttributeImageModel: LabelAttributeModel {
// MARK: - Properties
//--------------------------------------------------
override public class var identifier: String {
return "image"
}
override public class var identifier: String { "image" }
var size: CGFloat?
var name: String?

View File

@ -12,20 +12,14 @@
// MARK: - Properties
//--------------------------------------------------
public static var categoryName: String {
return "\(LabelAttributeModel.self)"
}
public static var categoryName: String { "\(LabelAttributeModel.self)" }
public static var categoryCodingKey: String {
return "type"
}
public static var categoryCodingKey: String { "type" }
public class var identifier: String {
return ""
}
public class var identifier: String { "" }
var type: String {
get { return Self.identifier }
get { Self.identifier }
}
var location: Int

View File

@ -12,9 +12,7 @@
// MARK: - Properties
//--------------------------------------------------
override public class var identifier: String {
return "strikethrough"
}
override public class var identifier: String { "strikethrough" }
//--------------------------------------------------
// MARK: - Initializer

View File

@ -14,9 +14,7 @@ import UIKit
// MARK: - Properties
//--------------------------------------------------
override public class var identifier: String {
return "underline"
}
override public class var identifier: String { "underline" }
/// This returns the NSUnderlineStyle used in NSAttributedValue. If there is a pattern, it will return
/// a new NSUnderlineStyle derived from the bitmask of style | pattern.

View File

@ -234,7 +234,7 @@
}
// Constrains the image view to be the size provided. Used to size it to the image to fix aspect fit defect.
func addConstraints(width: NSNumber?, height: NSNumber?, size: CGSize?) {
func addConstraints(width: CGFloat?, height: CGFloat?, size: CGSize?) {
widthConstraint?.isActive = false
heightConstraint?.isActive = false
@ -242,15 +242,15 @@
guard addSizeConstraintsForAspectRatio else { return }
if let width = width, let height = height {
setHeight(height.cgfloat())
setWidth(width.cgfloat())
setHeight(height)
setWidth(width)
} else if let width = width, let size = size {
setWidth(width.cgfloat())
setWidth(width)
heightConstraint = imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor, multiplier: size.height/size.width)
heightConstraint?.priority = UILayoutPriority(rawValue: 900)
heightConstraint?.isActive = true
} else if let height = height, let size = size {
setHeight(height.cgfloat())
setHeight(height)
widthConstraint = imageView.widthAnchor.constraint(equalTo: imageView.heightAnchor, multiplier: size.width/size.height)
widthConstraint?.priority = UILayoutPriority(rawValue: 900)
widthConstraint?.isActive = true
@ -288,7 +288,7 @@
if shouldLoadImage(withName: imageModel.image, width: width, height: height) {
imageView.image = nil
imageView.animatedImage = nil
loadImage(withName: imageModel.image, format: imageModel.imageFormat, width: width as NSNumber?, height: height as NSNumber?, customFallbackImage: imageModel.fallbackImage, localBundle: imageModel.localBundle)
loadImage(withName: imageModel.image, format: imageModel.imageFormat, width: width, height: height, customFallbackImage: imageModel.fallbackImage, localBundle: imageModel.localBundle)
}
if let contentMode = imageModel.contentMode {
@ -309,13 +309,13 @@
// MARK: - Load Methods
//--------------------------------------------------
public func loadImage(withName imageName: String?, format: String? = nil, width: NSNumber? = nil, height: NSNumber? = nil, customFallbackImage: String? = nil, allowServerParameters: Bool = false, localBundle: Bundle? = nil, completionHandler: MVMCoreGetImageBlock? = nil) {
public func loadImage(withName imageName: String?, format: String? = nil, width: CGFloat? = nil, height: CGFloat? = nil, customFallbackImage: String? = nil, allowServerParameters: Bool = false, localBundle: Bundle? = nil, completionHandler: MVMCoreGetImageBlock? = nil) {
let completionBlock = completionHandler ?? defaultCompletionBlock()
MVMCoreDispatchUtility.performBlock(onMainThread: { [unowned self] in
self.currentImageName = imageName
self.currentImageWidth = width?.cgfloat()
self.currentImageHeight = height?.cgfloat()
self.currentImageWidth = width
self.currentImageHeight = height
if MVMCoreCache.isHostedImage(imageName) {
self.loadingSpinner.resumeSpinnerAfterDelay()
self.loadingSpinnerHeightConstraint?.constant = self.spinnerHeight
@ -338,9 +338,9 @@
let fallbackImageName = customFallbackImage ?? MVMCoreUIUtility.localizedImageName("fallback")
if let format = format, format.lowercased().contains("gif") {
// Gifs aren't supported by default and need special handling
MVMCoreCache.shared()?.getGif(imageName, useWidth: width != nil, widthForS7: width?.intValue ?? 0, useHeight: height != nil, heightForS7: height?.intValue ?? 0, format: format, localFallbackImageName: fallbackImageName, allowServerQueryParameters: allowServerParameters, localBundle: localBundle, completionHandler: finishedLoadingBlock)
MVMCoreCache.shared()?.getGif(imageName, useWidth: width != nil, widthForS7: Int(width ?? 0), useHeight: height != nil, heightForS7: Int(height ?? 0), format: format, localFallbackImageName: fallbackImageName, allowServerQueryParameters: allowServerParameters, localBundle: localBundle, completionHandler: finishedLoadingBlock)
} else {
MVMCoreCache.shared()?.getImage(imageName, useWidth: width != nil, widthForS7: width?.intValue ?? 0, useHeight: height != nil, heightForS7: height?.intValue ?? 0, format: format, localFallbackImageName: fallbackImageName, allowServerQueryParameters: allowServerParameters, localBundle: localBundle, completionHandler: finishedLoadingBlock)
MVMCoreCache.shared()?.getImage(imageName, useWidth: width != nil, widthForS7: Int(width ?? 0), useHeight: height != nil, heightForS7: Int(height ?? 0), format: format, localFallbackImageName: fallbackImageName, allowServerQueryParameters: allowServerParameters, localBundle: localBundle, completionHandler: finishedLoadingBlock)
}
})
}
@ -409,6 +409,6 @@
}
public func loadImage(withName imageName: String?, format: String?, width: NSNumber?, height: NSNumber?, customFallbackImage: String?, completionHandler: @escaping MVMCoreGetImageBlock) {
loadImage(withName: imageName, format: format, width: width, height: height, customFallbackImage: customFallbackImage, allowServerParameters: false, completionHandler: completionHandler)
loadImage(withName: imageName, format: format, width: width?.cgfloat(), height: height?.cgfloat(), customFallbackImage: customFallbackImage, allowServerParameters: false, completionHandler: completionHandler)
}
}

View File

@ -17,7 +17,7 @@ import UIKit
private let stack = Stack<StackModel>()
var multiProgressModel: MultiProgressBarModel? {
get { return model as? MultiProgressBarModel }
get { model as? MultiProgressBarModel }
}
var roundedCorners: Bool = false {
@ -85,7 +85,7 @@ import UIKit
//--------------------------------------------------
/// Creates the bars
open func set(with progressList: Array<SingleProgressBarModel>, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
open func set(with progressList: [SingleProgressBarModel], _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
stack.removeAllItemViews()
guard let stackModel = stack.stackModel else { return }
@ -103,7 +103,6 @@ import UIKit
stack.set(with: stackModel, delegateObject, additionalData)
}
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
@ -115,6 +114,6 @@ import UIKit
}
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return (model as? MultiProgressBarModel)?.thickness ?? 8
(model as? MultiProgressBarModel)?.thickness ?? 8
}
}

View File

@ -6,7 +6,6 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
open class HeaderView: Container {
public let line = Line()
@ -15,7 +14,7 @@ open class HeaderView: Container {
open var molecule: MoleculeViewProtocol?
var headerModel: HeaderModel? {
get { return model as? HeaderModel }
get { model as? HeaderModel }
}
/// Convenience function to add a molecule to the view.
@ -58,6 +57,6 @@ open class HeaderView: Container {
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return PaddingDefaultVerticalSpacing + PaddingDefaultVerticalSpacing
PaddingDefaultVerticalSpacing + PaddingDefaultVerticalSpacing
}
}

View File

@ -6,7 +6,6 @@
// Copyright © 2019 Suresh, Kamlesh. All rights reserved.
//
import Foundation
@objcMembers public class MoleculeHeaderModel: HeaderModel, MoleculeModelProtocol, MoleculeContainerModelProtocol {
public static var identifier: String = "header"

View File

@ -17,7 +17,7 @@ public class MoleculeHeaderView: MoleculeContainer {
var line = Line()
var headerModel: MoleculeHeaderModel? {
get { return model as? MoleculeHeaderModel }
get { model as? MoleculeHeaderModel }
}
//--------------------------------------------------

View File

@ -6,7 +6,6 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers open class TabBar: UITabBar, MoleculeViewProtocol, TabBarProtocol, UITabBarDelegate {
@ -15,9 +14,7 @@ import Foundation
public let line = Line()
required public init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let model = model as? TabBarModel else {
fatalError("model is not TabBarModel")
}
guard let model = model as? TabBarModel else { fatalError("model is not TabBarModel") }
self.model = model
super.init(frame: .zero)
@ -32,7 +29,7 @@ import Foundation
fatalError("init(coder:) has not been implemented")
}
open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let model = model as? TabBarModel else { return }
self.model = model
@ -57,8 +54,12 @@ import Foundation
var tabs: [UITabBarItem] = []
for (index, tab) in model.tabs.enumerated() {
let tabBarItem = UITabBarItem(title: tab.title, image: MVMCoreCache.shared()?.getImageFromRegisteredBundles(tab.image), tag: index)
tabBarItem.titlePositionAdjustment = UIOffset(horizontal: 0, vertical: -3)
tabBarItem.setTitleTextAttributes([NSAttributedString.Key.font: MFFonts.mfFontTXRegular(8)], for: .normal)
tabBarItem.accessibilityLabel = tab.accessibilityText
if #available(iOS 13.0, *) {
} else {
tabBarItem.titlePositionAdjustment = UIOffset(horizontal: 0, vertical: -3)
tabBarItem.setTitleTextAttributes([NSAttributedString.Key.font: MFFonts.mfFontTXRegular(8)], for: .normal)
}
tabs.append(tabBarItem)
}
setItems(tabs, animated: false)
@ -100,10 +101,7 @@ import Foundation
})
}
public func currentTabIndex() -> Int {
return model.selectedTab
}
public func currentTabIndex() -> Int { model.selectedTab }
}
extension UITabBarItem: MFButtonProtocol {
}
extension UITabBarItem: MFButtonProtocol { }

View File

@ -63,11 +63,13 @@ public class TabBarItemModel: Codable {
var title: String?
var image: String
var action: ActionModelProtocol
var accessibilityText: String?
private enum CodingKeys: String, CodingKey {
case title
case image
case action
case accessibilityText
}
public init(with title: String?, image: String, action: ActionModelProtocol) {
@ -81,6 +83,7 @@ public class TabBarItemModel: Codable {
title = try typeContainer.decodeIfPresent(String.self, forKey: .title)
image = try typeContainer.decode(String.self, forKey: .image)
action = try typeContainer.decodeModel(codingKey: .action)
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
}
public func encode(to encoder: Encoder) throws {
@ -88,5 +91,6 @@ public class TabBarItemModel: Codable {
try container.encodeIfPresent(title, forKey: .title)
try container.encode(image, forKey: .image)
try container.encodeModel(action, forKey: .action)
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
}
}

View File

@ -6,17 +6,15 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers open class ImageBarButtonItem: BarButtonItem {
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
public static func create(with image: UIImage?) -> Self {
let actionObject = ActionDelegate()
let button = self.init(image: image, style: .plain, target: actionObject, action: #selector(actionObject.callActionBlock(_:)))
let button = self.init(image: image, style: .plain, target: actionObject, action: #selector(actionObject.callActionBlock))
button.actionDelegate = actionObject
return button
}
@ -29,7 +27,7 @@ import Foundation
}
/// Creates the item with the passed in action map.
public static func create(with image: UIImage?, actionMap: [AnyHashable : Any], delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Self {
public static func create(with image: UIImage?, actionMap: [AnyHashable: Any], delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Self {
let button = create(with: image)
button.set(with: actionMap, delegateObject: delegateObject, additionalData: additionalData)
return button
@ -42,4 +40,3 @@ import Foundation
return button
}
}

View File

@ -6,10 +6,8 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers open class LabelBarButtonItem: BarButtonItem {
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------

View File

@ -5,30 +5,47 @@
// Created by Scott Pfeil on 5/18/20.
//
import Foundation
public class NavigationImageButtonModel: NavigationButtonModelProtocol, MoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public static var identifier: String = "navigationImageButton"
public var image: String
public var action: ActionModelProtocol
public var accessibilityText: String?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(with image: String, action: ActionModelProtocol) {
self.image = image
self.action = action
}
//--------------------------------------------------
// MARK: - Coding Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case image
case action
case accessibilityIdentifier
case moleculeName
case accessibilityText
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
image = try typeContainer.decode(String.self, forKey: .image)
action = try typeContainer.decodeModel(codingKey: .action)
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
@ -37,19 +54,26 @@ public class NavigationImageButtonModel: NavigationButtonModelProtocol, Molecule
open func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(image, forKey: .image)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeModel(action, forKey: .action)
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
}
//--------------------------------------------------
// MARK: - Method
//--------------------------------------------------
/// Convenience function that creates a BarButtonItem for the model.
public func createNavigationItemButton(delegateObject: MVMCoreUIDelegateObject? = nil, additionalData: [AnyHashable: Any]? = nil) -> UIBarButtonItem {
let uiImage = MVMCoreCache.shared()?.getImageFromRegisteredBundles(image)
let navigationImageButton = ImageBarButtonItem.create(with: uiImage, actionModel: action, delegateObject: delegateObject, additionalData: additionalData)
let buttonItem = ImageBarButtonItem.create(with: uiImage, actionModel: action, delegateObject: delegateObject, additionalData: additionalData)
buttonItem.accessibilityIdentifier = accessibilityIdentifier ?? image
if let accessibilityString = accessibilityText {
navigationImageButton.accessibilityLabel = accessibilityString
navigationImageButton.isAccessibilityElement = true
buttonItem.accessibilityLabel = accessibilityString
buttonItem.isAccessibilityElement = true
}
return navigationImageButton
return buttonItem
}
}

View File

@ -6,28 +6,45 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public class NavigationLabelButtonModel: NavigationButtonModelProtocol, MoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public var backgroundColor: Color?
public static var identifier: String = "navigationLabelButton"
public var accessibilityIdentifier: String?
public var title: String
public var action: ActionModelProtocol
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(with title: String, action: ActionModelProtocol) {
self.title = title
self.action = action
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case accessibilityIdentifier
case title
case action
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
title = try typeContainer.decode(String.self, forKey: .title)
action = try typeContainer.decodeModel(codingKey: .action)
}
@ -35,10 +52,15 @@ public class NavigationLabelButtonModel: NavigationButtonModelProtocol, Molecule
open func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encode(title, forKey: .title)
try container.encodeModel(action, forKey: .action)
}
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
/// Convenience function that creates a BarButtonItem for the model.
public func createNavigationItemButton(delegateObject: MVMCoreUIDelegateObject? = nil, additionalData: [AnyHashable: Any]? = nil) -> UIBarButtonItem {
return LabelBarButtonItem.create(with: title, actionModel: action, delegateObject: delegateObject, additionalData: additionalData)

View File

@ -6,12 +6,13 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtocol {
open class var identifier: String {
return "navigationBar"
}
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
open class var identifier: String { "navigationBar" }
open var title: String?
open var hidden: Bool
@ -28,13 +29,21 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc
open var additionalRightButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]?
open var titleView: MoleculeModelProtocol?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init() {
hidden = false
backgroundColor = Color(uiColor: .white)
tintColor = Color(uiColor: .black)
backgroundColor = Color(uiColor: .mvmWhite)
tintColor = Color(uiColor: .mvmBlack)
line = LineModel(type: .standard)
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case title
@ -48,13 +57,17 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc
case additionalRightButtons
case titleView
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
title = try typeContainer.decodeIfPresent(String.self, forKey: .title)
hidden = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidden) ?? false
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) ?? Color(uiColor: .white)
tintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .tintColor) ?? Color(uiColor: .black)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) ?? Color(uiColor: .mvmWhite)
tintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .tintColor) ?? Color(uiColor: .mvmBlack)
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) ?? LineModel(type: .standard)
alwaysShowBackButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .alwaysShowBackButton)
backButton = try typeContainer.decodeModelIfPresent(codingKey: .backButton)

View File

@ -6,11 +6,10 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
extension MVMCoreUITopAlertExpandableView: MoleculeViewProtocol {
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
defaultSetup()
guard let model = model as? CollapsableNotificationModel else { return }
backgroundColor = model.backgroundColor?.uiColor ?? .mvmGreen
@ -30,6 +29,10 @@ extension MVMCoreUITopAlertExpandableView: MoleculeViewProtocol {
MVMCoreUITopAlertBaseView.addAction(to: button, actionMap: topActionMap, additionalData: nil)
shortView?.label?.accessibilityTraits = .button
}
if let accessibilityIdentifier = model.accessibilityIdentifier {
self.accessibilityIdentifier = accessibilityIdentifier
}
}
}

View File

@ -6,17 +6,24 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
extension MVMCoreUITopAlertMainView: MoleculeViewProtocol {
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
defaultSetup()
guard let model = model as? NotificationModel else { return }
backgroundColor = model.backgroundColor?.uiColor ?? .mvmGreen
var actionMap = model.button?.action.toJSON()
if let title = model.button?.title {
actionMap?.updateValue(title, forKey: KeyTitle)
}
if let accessibilityIdentifier = model.accessibilityIdentifier {
self.accessibilityIdentifier = accessibilityIdentifier
}
setupCloseButton(model.closeButton != nil, animationDelegate: MVMCoreUITopAlertView.sharedGlobal()?.animationDelegate)
setup(withMessage: model.headline.text, subMessage: model.body?.text, color: model.headline.textColor?.uiColor ?? .white, actionMap: actionMap, additionalData: nil)
}

View File

@ -6,52 +6,72 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
open class NotificationModel: MoleculeModelProtocol {
public class var identifier: String {
return "notification"
}
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public class var identifier: String { "notification" }
public var accessibilityIdentifier: String?
public var backgroundColor: Color?
public var headline: LabelModel
public var body: LabelModel?
public var button: ButtonModel?
public var closeButton: NotificationXButtonModel?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(with headline: LabelModel) {
self.headline = headline
}
//--------------------------------------------------
// MARK: - Default
//--------------------------------------------------
open func setDefault() {
if backgroundColor == nil {
backgroundColor = Color(uiColor: .mvmGreen())
backgroundColor = Color(uiColor: .mvmGreen)
}
if headline.textColor == nil {
headline.textColor = Color(uiColor: .white)
headline.textColor = Color(uiColor: .mvmWhite)
}
if body?.textColor == nil {
body?.textColor = Color(uiColor: .white)
body?.textColor = Color(uiColor: .mvmWhite)
}
if button?.style == nil {
button?.style = .secondary
}
button?.size = .tiny
button?.enabledTextColor = Color(uiColor: .white)
button?.enabledBorderColor = Color(uiColor: .white)
button?.enabledTextColor = Color(uiColor: .mvmWhite)
button?.enabledBorderColor = Color(uiColor: .mvmWhite)
}
//--------------------------------------------------
// MARK: - Coding Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case accessibilityIdentifier
case headline
case body
case button
case closeButton
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
headline = try typeContainer.decode(LabelModel.self, forKey: .headline)
body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body)
button = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .button)
@ -63,6 +83,7 @@ open class NotificationModel: MoleculeModelProtocol {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encode(headline, forKey: .headline)
try container.encodeIfPresent(body, forKey: .body)
try container.encodeIfPresent(button, forKey: .button)

View File

@ -19,19 +19,15 @@ open class HeadlineBody: View {
// MARK: - Constraints
//--------------------------------------------------
var spaceBetweenLabelsConstant = PaddingOne
var spaceBetweenLabelsConstant = Padding.One
var spaceBetweenLabels: NSLayoutConstraint?
var leftConstraintTitle: NSLayoutConstraint?
var rightConstraintTitle: NSLayoutConstraint?
var leftConstraintMessage: NSLayoutConstraint?
var rightConstraintMessage: NSLayoutConstraint?
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
func hasText() -> Bool {
return headlineLabel.hasText || messageLabel.hasText
headlineLabel.hasText || messageLabel.hasText
}
// MARK: - Styling
@ -54,25 +50,25 @@ open class HeadlineBody: View {
}
}
func styleLandingPageHeader() {
public func styleLandingPageHeader() {
headlineLabel.setFontStyle(.Title2XLarge)
messageLabel.setFontStyle(.RegularBodySmall)
spaceBetweenLabelsConstant = PaddingTwo
spaceBetweenLabelsConstant = Padding.Two
}
func stylePageHeader() {
public func stylePageHeader() {
headlineLabel.setFontStyle(.BoldTitleLarge)
messageLabel.setFontStyle(.RegularBodySmall)
spaceBetweenLabelsConstant = PaddingOne
spaceBetweenLabelsConstant = Padding.One
}
func styleListItem() {
public func styleListItem() {
headlineLabel.setFontStyle(.BoldBodySmall)
messageLabel.setFontStyle(.RegularBodySmall)
spaceBetweenLabelsConstant = 0
}
func styleListItemDivider() {
public func styleListItemDivider() {
headlineLabel.setFontStyle(.BoldTitleMedium)
messageLabel.setFontStyle(.RegularBodySmall)
spaceBetweenLabelsConstant = 0
@ -86,48 +82,41 @@ open class HeadlineBody: View {
super.setupView()
backgroundColor = .clear
clipsToBounds = true
isAccessibilityElement = false
shouldGroupAccessibilityChildren = true
accessibilityElements = [headlineLabel, messageLabel]
let view = MVMCoreUICommonViewsUtility.commonView()
addSubview(view)
NSLayoutConstraint.constraintPinSubview(toSuperview: view)
view.isAccessibilityElement = false
view.shouldGroupAccessibilityChildren = true
view.accessibilityElements = [headlineLabel, messageLabel]
view.addSubview(headlineLabel)
view.addSubview(messageLabel)
addSubview(headlineLabel)
addSubview(messageLabel)
headlineLabel.setContentCompressionResistancePriority(.required, for: .vertical)
headlineLabel.setContentHuggingPriority(.required, for: .vertical)
messageLabel.setContentCompressionResistancePriority(.required, for: .vertical)
messageLabel.setContentHuggingPriority(.required, for: .vertical)
view.setContentHuggingPriority(.required, for: .vertical)
headlineLabel.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
headlineLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true
spaceBetweenLabels = messageLabel.topAnchor.constraint(equalTo: headlineLabel.bottomAnchor, constant: spaceBetweenLabelsConstant)
spaceBetweenLabels?.isActive = true
leftConstraintTitle = headlineLabel.leftAnchor.constraint(equalTo: view.leftAnchor)
leftConstraintTitle?.isActive = true
rightConstraintTitle = view.rightAnchor.constraint(equalTo: headlineLabel.rightAnchor)
rightConstraintTitle?.isActive = true
leftConstraintMessage = messageLabel.leftAnchor.constraint(equalTo: view.leftAnchor)
leftConstraintMessage?.isActive = true
rightConstraintMessage = view.rightAnchor.constraint(equalTo: messageLabel.rightAnchor)
rightConstraintMessage?.isActive = true
view.bottomAnchor.constraint(equalTo: messageLabel.bottomAnchor).isActive = true
NSLayoutConstraint.activate([
headlineLabel.leadingAnchor.constraint(equalTo: leadingAnchor),
trailingAnchor.constraint(equalTo: headlineLabel.trailingAnchor),
messageLabel.leadingAnchor.constraint(equalTo: leadingAnchor),
trailingAnchor.constraint(equalTo: messageLabel.trailingAnchor),
bottomAnchor.constraint(equalTo: messageLabel.bottomAnchor)
])
}
open override func updateView(_ size: CGFloat) {
super.updateView(size)
setSpacing()
headlineLabel.updateView(size)
messageLabel.updateView(size)
setSpacing()
// Provide the label additional size information to help calculate its intrinsic height.
let padding = MFStyler.defaultHorizontalPadding(forSize: size) * 2
messageLabel.preferredMaxLayoutWidth = size - padding
}
//--------------------------------------------------
@ -146,19 +135,18 @@ open class HeadlineBody: View {
// MARK: - MoleculeViewProtocol
//--------------------------------------------------
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 58
}
public override class func estimatedHeight(with model: MoleculeModelProtocol,
_ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 58 }
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let headlineBodyModel = model as? HeadlineBodyModel else { return }
guard let model = model as? HeadlineBodyModel else { return }
style(with: headlineBodyModel.style)
style(with: model.style)
headlineLabel.setOptional(with: headlineBodyModel.headline, delegateObject, additionalData)
messageLabel.setOptional(with: headlineBodyModel.body, delegateObject, additionalData)
headlineLabel.setOptional(with: model.headline, delegateObject, additionalData)
messageLabel.setOptional(with: model.body, delegateObject, additionalData)
}
open override func reset() {

View File

@ -16,7 +16,7 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
open var stackItems: [UIView] = []
open var stackModel: T? {
get { return model as? T }
get { model as? T }
}
//--------------------------------------------------

View File

@ -0,0 +1,23 @@
//
// AccessibilityModelProtocol.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 2/3/21.
// Copyright © 2021 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol AccessibilityModelProtocol {
var accessibilityIdentifier: String? { get set }
}
public extension AccessibilityModelProtocol {
var accessibilityIdentifier: String? {
get { nil }
set { }
}
}

View File

@ -7,22 +7,16 @@ public enum MolecularError: Swift.Error {
}
public protocol MoleculeModelProtocol: ModelProtocol {
public protocol MoleculeModelProtocol: ModelProtocol, AccessibilityModelProtocol {
var moleculeName: String { get }
var backgroundColor: Color? { get set }
}
public extension MoleculeModelProtocol {
var moleculeName: String {
get { return Self.identifier }
}
var moleculeName: String { Self.identifier }
static var categoryName: String {
return "\(MoleculeModelProtocol.self)"
}
static var categoryName: String { "\(MoleculeModelProtocol.self)" }
static var categoryCodingKey: String {
return "moleculeName"
}
static var categoryCodingKey: String { "moleculeName" }
}

View File

@ -8,6 +8,7 @@
public typealias BarButtonAction = (BarButtonItem) -> ()
@objc class ActionDelegate: NSObject {
var buttonAction: BarButtonAction?
@objc func callActionBlock(_ sender: BarButtonItem) {
@ -16,7 +17,6 @@ public typealias BarButtonAction = (BarButtonItem) -> ()
}
@objcMembers open class BarButtonItem: UIBarButtonItem, MFButtonProtocol {
//--------------------------------------------------
// MARK: - Delegate
//--------------------------------------------------
@ -43,4 +43,3 @@ public typealias BarButtonAction = (BarButtonItem) -> ()
}
}
}

View File

@ -8,6 +8,7 @@
public typealias ButtonAction = (Button) -> ()
@objcMembers open class Button: UIButton, MFButtonProtocol, MoleculeViewProtocol {
//--------------------------------------------------
// MARK: - Properties
@ -65,7 +66,7 @@ public typealias ButtonAction = (Button) -> ()
/// Adds a block to be performed for the given event.
open func addActionBlock(event: Event, _ buttonBlock: @escaping ButtonAction) {
self.buttonAction = buttonBlock
addTarget(self, action: #selector(callActionBlock(_:)), for: event)
addTarget(self, action: #selector(callActionBlock), for: event)
}
@objc func callActionBlock(_ sender: Button) {
@ -103,6 +104,10 @@ public typealias ButtonAction = (Button) -> ()
self.backgroundColor = backgroundColor.uiColor
}
if let accessibilityIdentifier = model.accessibilityIdentifier {
self.accessibilityIdentifier = accessibilityIdentifier
}
if let model = model as? EnableableModelProtocol {
isEnabled = model.enabled
}
@ -119,25 +124,23 @@ public typealias ButtonAction = (Button) -> ()
// MARK: Overridables
// Base classes need to implement these functions otherwise swift won't respect the subclass functions and use the ones in the protocol extension instead.
open class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
return model.moleculeName
model.moleculeName
}
open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return nil
}
open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { nil }
open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
return nil
}
open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? { nil }
//--------------------------------------------------
// MARK: - Accessibility
//--------------------------------------------------
open override func accessibilityActivate() -> Bool {
guard isEnabled else { return false }
buttonAction?(self)
return buttonAction != nil
}
}
// MARK: - MVMCoreViewProtocol
@ -160,6 +163,6 @@ extension Button: MVMCoreViewProtocol {
extension Button: AppleGuidelinesProtocol {
override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
return Self.acceptablyOutsideBounds(point: point, bounds: bounds)
Self.acceptablyOutsideBounds(point: point, bounds: bounds)
}
}

View File

@ -51,9 +51,14 @@ import UIKit
// MARK:- MoleculeViewProtocol
open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
self.model = model
if let backgroundColor = model.backgroundColor {
self.backgroundColor = backgroundColor.uiColor
}
if let accessibilityIdentifier = model.accessibilityIdentifier {
self.accessibilityIdentifier = accessibilityIdentifier
}
}
open func reset() {
@ -63,22 +68,18 @@ import UIKit
// MARK: Overridables
// Base classes need to implement these functions otherwise swift won't respect the subclass functions and use the ones in the protocol extension instead.
open class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
return model.moleculeName
model.moleculeName
}
open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return nil
}
open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { nil }
open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
return nil
}
open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? { nil }
}
// MARK: - AppleGuidelinesProtocol
extension Control: AppleGuidelinesProtocol {
override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
return Self.acceptablyOutsideBounds(point: point, bounds: bounds)
Self.acceptablyOutsideBounds(point: point, bounds: bounds)
}
}

View File

@ -53,33 +53,35 @@ open class ImageView: UIImageView, MoleculeViewProtocol {
}
public func reset() {
backgroundColor = .clear
}
backgroundColor = .clear
}
public func setAsMolecule() { }
//--------------------------------------------------
// MARK: - ModelMoleculeViewProtocol
//--------------------------------------------------
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
self.model = model
if let backgroundColor = model.backgroundColor {
self.backgroundColor = backgroundColor.uiColor
}
if let accessibilityIdentifier = model.accessibilityIdentifier {
self.accessibilityIdentifier = accessibilityIdentifier
}
}
open class func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
return model?.moleculeName
model?.moleculeName
}
open class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return nil
}
open class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { nil }
open class func requiredModules(_ molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
return nil
}
open class func requiredModules(_ molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? { nil }
}
// MARK:- MVMCoreViewProtocol
@ -94,4 +96,3 @@ extension ImageView: MVMCoreViewProtocol {
MVMCoreUIUtility.setMarginsFor(self, leading: 0, top: 0, trailing: 0, bottom: 0)
}
}

View File

@ -6,7 +6,6 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers open class SectionHeaderFooterView: UITableViewHeaderFooterView, MoleculeViewProtocol {
//--------------------------------------------------
@ -43,10 +42,16 @@ import Foundation
//--------------------------------------------------
open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
self.model = model
if let backgroundColor = model.backgroundColor {
contentView.backgroundColor = backgroundColor.uiColor
}
if let accessibilityIdentifier = model.accessibilityIdentifier {
self.accessibilityIdentifier = accessibilityIdentifier
}
}
open func reset() {
@ -56,16 +61,12 @@ import Foundation
// MARK: Overridables
// Base classes need to implement these functions otherwise swift won't respect the subclass functions and use the ones in the protocol extension instead.
open class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
return model.moleculeName
model.moleculeName
}
open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return nil
}
open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { nil }
open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
return nil
}
open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? { nil }
}
// MARK:- MVMCoreViewProtocol

View File

@ -11,7 +11,7 @@ import Foundation
@objcMembers open class TableView: UITableView {
/// A block that gets called on tableview frame changes
public var frameChangeAction: (() -> Void)?
public var frameChangeAction: (() -> ())?
private var previousFrame = CGRect.zero

View File

@ -93,6 +93,10 @@ extension TextField: MoleculeViewProtocol {
if let color = model.backgroundColor?.uiColor {
backgroundColor = color
}
if let accessibilityIdentifier = model.accessibilityIdentifier {
self.accessibilityIdentifier = accessibilityIdentifier
}
}
open func reset() {

View File

@ -106,8 +106,8 @@ import UIKit
open func reset() {
fontStyle = Styler.Font.RegularBodyLarge
placeholderFontStyle = Styler.Font.RegularMicro
fontStyle = .RegularBodyLarge
placeholderFontStyle = .RegularMicro
placeholderTextColor = .mvmCoolGray3
textColor = .mvmBlack
isEnabled = true

View File

@ -58,6 +58,10 @@ import UIKit
if let backgroundColor = model.backgroundColor {
self.backgroundColor = backgroundColor.uiColor
}
if let accessibilityIdentifier = model.accessibilityIdentifier {
self.accessibilityIdentifier = accessibilityIdentifier
}
}
open func reset() {
@ -67,16 +71,12 @@ import UIKit
// MARK: Overridables
// Base classes need to implement these functions otherwise swift won't respect the subclass functions and use the ones in the protocol extension instead.
open class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
return model.moleculeName
model.moleculeName
}
open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return nil
}
open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { nil }
open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
return nil
}
open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? { nil }
}
// MARK:- MVMCoreViewProtocol

View File

@ -74,7 +74,7 @@ import UIKit
}
open func modulesToListenFor() -> [String]? {
loadObject?.requestParameters?.modules as? [String]
loadObject?.requestParameters?.allModules()
}
@objc open func responseJSONUpdated(notification: Notification) {

View File

@ -10,23 +10,22 @@ import Foundation
public protocol PageBehaviorProtocol: ModelProtocol {
// The type of rule
/// The type of rule
var behaviorName: String { get }
}
public extension PageBehaviorProtocol {
var behaviorName: String {
get { return Self.identifier }
get { Self.identifier }
}
static var categoryCodingKey: String {
return "behaviorName"
"behaviorName"
}
static var categoryName: String {
return "\(PageBehaviorProtocol.self)"
"\(PageBehaviorProtocol.self)"
}
}
@ -34,7 +33,6 @@ public protocol PageVisibilityBehavior: PageBehaviorProtocol {
func onPageShown()
func onPageHidden()
}
public protocol PageScrolledBehavior: PageBehaviorProtocol {
@ -45,5 +43,4 @@ public protocol PageScrolledBehavior: PageBehaviorProtocol {
public protocol PageBehaviorsTemplateProtocol {
var behaviors: [PageBehaviorProtocol]? { get set }
}

View File

@ -75,11 +75,12 @@ import MVMCore
/// Convenience function. Gets the form validator from the holder and asks it to validate.
public static func validate(delegate: FormHolderProtocol?) -> Bool? {
return delegate?.formValidator?.validate()
delegate?.formValidator?.validate()
}
/// Validates all rule groups. Returns if valid
public func validate() -> Bool {
var valid = true
guard let formRules = formRules else { return valid }
@ -109,9 +110,10 @@ import MVMCore
}
}
// mark Form params
// MARK: Form params
// TODO: Temporary hacks, rewrite architecture to support this.
@objc public extension FormValidator {
@objc func addFormParams(requestParameters: MVMCoreRequestParameters) {
let groupName = getGroupName(forPageType: requestParameters.pageType) ?? FormValidator.defaultGroupName
let formParams = self.getFormParams(forGroup: groupName)
@ -119,6 +121,7 @@ import MVMCore
}
@objc func getFormParams( forGroup groupName: String) -> [String: Any] {
var extraParam: [String: Any] = [:]
for (fieldKey, field) in fields {
if let formFieldValue = field.formFieldValue(),
@ -126,6 +129,7 @@ import MVMCore
extraParam[fieldKey] = formFieldValue
}
}
return extraParam
}
}
@ -145,4 +149,3 @@ public extension FormValidator {
return nil
}
}

View File

@ -31,17 +31,11 @@ public protocol RulesProtocol: ModelProtocol {
public extension RulesProtocol {
var type: String {
get { return Self.identifier }
}
var type: String { Self.identifier }
static var categoryCodingKey: String {
return "type"
}
static var categoryCodingKey: String { "type" }
static var categoryName: String {
return "\(RulesProtocol.self)"
}
static var categoryName: String { "\(RulesProtocol.self)" }
// Individual rule can override the function to validate based on the rule type.
func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool {

View File

@ -211,7 +211,7 @@
if (topMessage && (!self.onlyShowTopMessageWhenCollapsed || !self.expanded)) {
self.shortViewHeight.active = NO;
} else if (!topMessage && self.onlyShowTopMessageWhenCollapsed && self.expanded) {
} else if (!topMessage || (self.onlyShowTopMessageWhenCollapsed && self.expanded)) {
self.shortViewHeight.active = YES;
}
}];

View File

@ -113,8 +113,8 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
- (void)pinATopViewController:(UIViewController *)viewController {
self.statusBarHeightConstraint.active = NO;
id topGuide = viewController.topLayoutGuide;
self.statusBarBottomConstraint = [NSLayoutConstraint constraintWithItem:self.statusBarView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:topGuide attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
id topGuide = viewController.view.safeAreaLayoutGuide;
self.statusBarBottomConstraint = [NSLayoutConstraint constraintWithItem:self.statusBarView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:topGuide attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
self.statusBarBottomConstraint.active = YES;
}