Merge branch 'feature/test_no_arm64_config' into 'develop'

MVM UI/Unit Testing implementation

See merge request BPHV_MIPS/mvm_core_ui!641
This commit is contained in:
Pfeil, Scott Robert 2021-02-03 12:11:51 -05:00
commit def376c67a
79 changed files with 499 additions and 350 deletions

View File

@ -105,6 +105,7 @@
0A9D09212433796500D2E6C0 /* CarouselIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9D091B2433796500D2E6C0 /* CarouselIndicatorModel.swift */; }; 0A9D09212433796500D2E6C0 /* CarouselIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9D091B2433796500D2E6C0 /* CarouselIndicatorModel.swift */; };
0A9D09222433796500D2E6C0 /* CarouselIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9D091C2433796500D2E6C0 /* CarouselIndicator.swift */; }; 0A9D09222433796500D2E6C0 /* CarouselIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9D091C2433796500D2E6C0 /* CarouselIndicator.swift */; };
0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B392398524F0067DD0F /* Toggle.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 */; }; 0AB000BA24BF63490090C5E7 /* ModalListPageTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AB000B924BF63490090C5E7 /* ModalListPageTemplateModel.swift */; };
0AB000BC24BF64A50090C5E7 /* ModalStackPageTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AB000BB24BF64A50090C5E7 /* ModalStackPageTemplateModel.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 */; }; 0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AB764D024460F6300E7FE72 /* UIDatePicker+Extension.swift */; };
@ -650,6 +651,7 @@
0A9D091C2433796500D2E6C0 /* CarouselIndicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CarouselIndicator.swift; sourceTree = "<group>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 0AB764D024460F6300E7FE72 /* UIDatePicker+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIDatePicker+Extension.swift"; sourceTree = "<group>"; };
@ -1109,6 +1111,7 @@
011B58EE23A2AA850085F53C /* ModelProtocols */ = { 011B58EE23A2AA850085F53C /* ModelProtocols */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
0AA4D2E025CAEC72008DB32D /* AccessibilityModelProtocol.swift */,
D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */, D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */,
014AA72323C501E2006F3E93 /* ContainerModelProtocol.swift */, 014AA72323C501E2006F3E93 /* ContainerModelProtocol.swift */,
D23EA7FA2475F09800D60C34 /* CarouselItemProtocol.swift */, D23EA7FA2475F09800D60C34 /* CarouselItemProtocol.swift */,
@ -1710,6 +1713,8 @@
D2092348244A51D40044AD09 /* RadioSwatchModel.swift */, D2092348244A51D40044AD09 /* RadioSwatchModel.swift */,
AAB9C109243496DD00151545 /* RadioSwatch.swift */, AAB9C109243496DD00151545 /* RadioSwatch.swift */,
AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */, AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */,
D260105223CEA61600764D80 /* ToggleModel.swift */,
0AA33B392398524F0067DD0F /* Toggle.swift */,
AAA7CD68250641F90045B959 /* HeartModel.swift */, AAA7CD68250641F90045B959 /* HeartModel.swift */,
AAA7CD6A250642080045B959 /* Heart.swift */, AAA7CD6A250642080045B959 /* Heart.swift */,
); );
@ -2007,8 +2012,6 @@
D28A838223CCBD3F00DFE4FC /* WheelModel.swift */, D28A838223CCBD3F00DFE4FC /* WheelModel.swift */,
943784F3236B77BB006A1E82 /* Wheel.swift */, 943784F3236B77BB006A1E82 /* Wheel.swift */,
943784F4236B77BB006A1E82 /* WheelAnimationHandler.swift */, 943784F4236B77BB006A1E82 /* WheelAnimationHandler.swift */,
D260105223CEA61600764D80 /* ToggleModel.swift */,
0AA33B392398524F0067DD0F /* Toggle.swift */,
0AE98BB623FF18E9004C5109 /* ArrowModel.swift */, 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */,
0AE98BB423FF18D2004C5109 /* Arrow.swift */, 0AE98BB423FF18D2004C5109 /* Arrow.swift */,
94382085243238D100B43AF3 /* WebViewModel.swift */, 94382085243238D100B43AF3 /* WebViewModel.swift */,
@ -2027,10 +2030,10 @@
D29DF22B21E6A0FA003B2FB9 /* TextFields */ = { D29DF22B21E6A0FA003B2FB9 /* TextFields */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */,
0A41BA7E23453A6400D4C0BC /* TextEntryField.swift */,
0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */, 0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */,
0A21DB7E235DECC500C160A2 /* EntryField.swift */, 0A21DB7E235DECC500C160A2 /* EntryField.swift */,
0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */,
0A41BA7E23453A6400D4C0BC /* TextEntryField.swift */,
0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */, 0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */,
0A21DB82235DFBC500C160A2 /* MdnEntryField.swift */, 0A21DB82235DFBC500C160A2 /* MdnEntryField.swift */,
0A8321AE2355FE9500CB7F00 /* DigitBox.swift */, 0A8321AE2355FE9500CB7F00 /* DigitBox.swift */,
@ -2157,6 +2160,7 @@
D2B18B7D236090D500A9AEDC /* BaseClasses */ = { D2B18B7D236090D500A9AEDC /* BaseClasses */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
0A5D59C323AD488600EFD9E9 /* Protocols */,
0A6682B3243769C700AD3CA1 /* TextView.swift */, 0A6682B3243769C700AD3CA1 /* TextView.swift */,
C003506023AA94CD00B6AC29 /* Button.swift */, C003506023AA94CD00B6AC29 /* Button.swift */,
D2B18B7E2360913400A9AEDC /* Control.swift */, D2B18B7E2360913400A9AEDC /* Control.swift */,
@ -2167,7 +2171,6 @@
BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */, BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */,
D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */, D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */,
D264FAA92440F97600D98315 /* CollectionView.swift */, D264FAA92440F97600D98315 /* CollectionView.swift */,
0A5D59C323AD488600EFD9E9 /* Protocols */,
0A7918F423F5E7EA00772FF4 /* ImageView.swift */, 0A7918F423F5E7EA00772FF4 /* ImageView.swift */,
D272F5F82473163100BD1A8F /* BarButtonItem.swift */, D272F5F82473163100BD1A8F /* BarButtonItem.swift */,
D2EC7BDC2527B83700F540AF /* SectionHeaderFooterView.swift */, D2EC7BDC2527B83700F540AF /* SectionHeaderFooterView.swift */,
@ -2844,6 +2847,7 @@
012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */, 012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */,
52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */, 52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */,
D2ED2812254B0EB800A1C293 /* MVMCoreTopAlertObject.m in Sources */, D2ED2812254B0EB800A1C293 /* MVMCoreTopAlertObject.m in Sources */,
0AA4D2E125CAEC72008DB32D /* AccessibilityModelProtocol.swift in Sources */,
C003506123AA94CD00B6AC29 /* Button.swift in Sources */, C003506123AA94CD00B6AC29 /* Button.swift in Sources */,
DBC4391B224421A0001AB423 /* CaretLink.swift in Sources */, DBC4391B224421A0001AB423 /* CaretLink.swift in Sources */,
D264FA90243BCE6800D98315 /* ThreeLayerCollectionViewController.swift in Sources */, D264FA90243BCE6800D98315 /* ThreeLayerCollectionViewController.swift in Sources */,
@ -2961,6 +2965,7 @@
DEBUG_INFORMATION_FORMAT = dwarf; DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES; ENABLE_TESTABILITY = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
@ -3026,6 +3031,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = 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 static var identifier: String = "button"
public var backgroundColor: Color? public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var title: String public var title: String
public var action: ActionModelProtocol public var action: ActionModelProtocol
public var enabled: Bool = true public var enabled: Bool = true
@ -93,27 +94,27 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupW
//-------------------------------------------------- //--------------------------------------------------
public func enabled_fillColor() -> UIColor? { public func enabled_fillColor() -> UIColor? {
return (inverted ? enabledFillColor_inverted : enabledFillColor)?.uiColor (inverted ? enabledFillColor_inverted : enabledFillColor)?.uiColor
} }
public func enabled_textColor() -> UIColor? { public func enabled_textColor() -> UIColor? {
return (inverted ? enabledTextColor_inverted : enabledTextColor)?.uiColor (inverted ? enabledTextColor_inverted : enabledTextColor)?.uiColor
} }
public func enabled_borderColor() -> UIColor? { public func enabled_borderColor() -> UIColor? {
return (inverted ? enabledBorderColor_inverted : enabledBorderColor)?.uiColor (inverted ? enabledBorderColor_inverted : enabledBorderColor)?.uiColor
} }
public func disabled_fillColor() -> UIColor? { public func disabled_fillColor() -> UIColor? {
return (inverted ? disabledFillColor_inverted : disabledFillColor)?.uiColor (inverted ? disabledFillColor_inverted : disabledFillColor)?.uiColor
} }
public func disabled_textColor() -> UIColor? { public func disabled_textColor() -> UIColor? {
return (inverted ? disabledTextColor_inverted : disabledTextColor)?.uiColor (inverted ? disabledTextColor_inverted : disabledTextColor)?.uiColor
} }
public func disabled_borderColor() -> 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. /// Defines the default appearance for the primary style.
@ -172,6 +173,7 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupW
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case backgroundColor case backgroundColor
case accessibilityIdentifier
case title case title
case inverted case inverted
case action case action
@ -195,6 +197,7 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupW
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
title = try typeContainer.decode(String.self, forKey: .title) title = try typeContainer.decode(String.self, forKey: .title)
action = try typeContainer.decodeModel(codingKey: .action) action = try typeContainer.decodeModel(codingKey: .action)
@ -252,6 +255,7 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupW
try container.encode(inverted, forKey: .inverted) try container.encode(inverted, forKey: .inverted)
try container.encodeModel(action, forKey: .action) try container.encodeModel(action, forKey: .action)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encodeIfPresent(enabledFillColor, forKey: .fillColor) try container.encodeIfPresent(enabledFillColor, forKey: .fillColor)
try container.encodeIfPresent(enabledTextColor, forKey: .textColor) try container.encodeIfPresent(enabledTextColor, forKey: .textColor)
try container.encodeIfPresent(enabledBorderColor, forKey: .borderColor) try container.encodeIfPresent(enabledBorderColor, forKey: .borderColor)

View File

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

View File

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

View File

@ -58,9 +58,7 @@ import UIKit
set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) set(with: model.action, delegateObject: delegateObject, additionalData: additionalData)
} }
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 31 }
return 31
}
} }
// MARK: - MVMCoreViewProtocol // MARK: - MVMCoreViewProtocol
@ -98,7 +96,5 @@ extension Link {
// MARK: - MVMCoreUIViewConstrainingProtocol // MARK: - MVMCoreUIViewConstrainingProtocol
extension Link: MVMCoreUIViewConstrainingProtocol { extension Link: MVMCoreUIViewConstrainingProtocol {
open func horizontalAlignment() -> UIStackView.Alignment { open func horizontalAlignment() -> UIStackView.Alignment { .leading }
return .leading
}
} }

View File

@ -19,6 +19,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
} }
public var backgroundColor: Color? public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var title: String public var title: String
public var action: ActionModelProtocol public var action: ActionModelProtocol
public var enabled = true public var enabled = true
@ -44,6 +45,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case backgroundColor case backgroundColor
case accessibilityIdentifier
case title case title
case action case action
case enabled case enabled
@ -62,6 +64,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
title = try typeContainer.decode(String.self, forKey: .title) title = try typeContainer.decode(String.self, forKey: .title)
action = try typeContainer.decodeModel(codingKey: .action) action = try typeContainer.decodeModel(codingKey: .action)
@ -95,6 +98,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
try container.encode(title, forKey: .title) try container.encode(title, forKey: .title)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encodeModel(action, forKey: .action) try container.encodeModel(action, forKey: .action)
try container.encode(inverted, forKey: .inverted) try container.encode(inverted, forKey: .inverted)
try container.encode(enabled, forKey: .enabled) try container.encode(enabled, forKey: .enabled)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -6,16 +6,24 @@
// Copyright © 2020 Verizon Wireless. All rights reserved. // Copyright © 2020 Verizon Wireless. All rights reserved.
// //
import Foundation
@objcMembers public class RadioSwatchesModel: MoleculeModelProtocol, FormFieldProtocol { @objcMembers public class RadioSwatchesModel: MoleculeModelProtocol, FormFieldProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "radioSwatches" public static var identifier: String = "radioSwatches"
public var backgroundColor: Color? public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var swatches: [RadioSwatchModel] public var swatches: [RadioSwatchModel]
public var fieldKey: String? public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName public var groupName: String = FormValidator.defaultGroupName
public var baseValue: AnyHashable? public var baseValue: AnyHashable?
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
/// Returns the fieldValue of the selected swatch, otherwise the text of selected swatch. /// Returns the fieldValue of the selected swatch, otherwise the text of selected swatch.
public func formFieldValue() -> AnyHashable? { public func formFieldValue() -> AnyHashable? {
let selectedSwatch = swatches.first { (swatch) -> Bool in let selectedSwatch = swatches.first { (swatch) -> Bool in
@ -24,17 +32,27 @@ import Foundation
return selectedSwatch?.fieldValue ?? selectedSwatch?.text return selectedSwatch?.fieldValue ?? selectedSwatch?.text
} }
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case backgroundColor case backgroundColor
case accessibilityIdentifier
case swatches case swatches
case fieldKey case fieldKey
case groupName case groupName
} }
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
swatches = try typeContainer.decode([RadioSwatchModel].self, forKey: .swatches) swatches = try typeContainer.decode([RadioSwatchModel].self, forKey: .swatches)
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
@ -47,6 +65,7 @@ import Foundation
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encode(swatches, forKey: .swatches) try container.encode(swatches, forKey: .swatches)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encode(groupName, forKey: .groupName) 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. /// Executes logic before state change. If false, then toggle state will not change and the didToggleAction will not execute.
public var shouldToggleAction: ActionBlockConfirmation? = { public var shouldToggleAction: ActionBlockConfirmation? = {
return { return true } return { true }
}() }()
// Sizes are from InVision design specs. // Sizes are from InVision design specs.
@ -69,9 +69,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
/// Simple means to prevent user interaction with the toggle. /// Simple means to prevent user interaction with the toggle.
public var isLocked: Bool = false { public var isLocked: Bool = false {
didSet { didSet { isUserInteractionEnabled = !isLocked }
isUserInteractionEnabled = !isLocked
}
} }
/// The state on the toggle. Default value: false. /// The state on the toggle. Default value: false.
@ -109,7 +107,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
} }
public var toggleModel: ToggleModel? { 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? { public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return Self.getContainerHeight() Self.getContainerHeight()
} }
} }
// MARK: - MVMCoreUIViewConstrainingProtocol // MARK: - MVMCoreUIViewConstrainingProtocol
extension Toggle { extension Toggle {
public func needsToBeConstrained() -> Bool { public func needsToBeConstrained() -> Bool { true }
return true
}
public func horizontalAlignment() -> UIStackView.Alignment { public func horizontalAlignment() -> UIStackView.Alignment { .trailing }
return .trailing
}
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -17,7 +17,7 @@ import UIKit
private let stack = Stack<StackModel>() private let stack = Stack<StackModel>()
var multiProgressModel: MultiProgressBarModel? { var multiProgressModel: MultiProgressBarModel? {
get { return model as? MultiProgressBarModel } get { model as? MultiProgressBarModel }
} }
var roundedCorners: Bool = false { var roundedCorners: Bool = false {
@ -85,7 +85,7 @@ import UIKit
//-------------------------------------------------- //--------------------------------------------------
/// Creates the bars /// 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() stack.removeAllItemViews()
guard let stackModel = stack.stackModel else { return } guard let stackModel = stack.stackModel else { return }
@ -103,7 +103,6 @@ import UIKit
stack.set(with: stackModel, delegateObject, additionalData) stack.set(with: stackModel, delegateObject, additionalData)
} }
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
@ -115,6 +114,6 @@ import UIKit
} }
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 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. // Copyright © 2020 Verizon Wireless. All rights reserved.
// //
import Foundation
open class HeaderView: Container { open class HeaderView: Container {
public let line = Line() public let line = Line()
@ -15,7 +14,7 @@ open class HeaderView: Container {
open var molecule: MoleculeViewProtocol? open var molecule: MoleculeViewProtocol?
var headerModel: HeaderModel? { var headerModel: HeaderModel? {
get { return model as? HeaderModel } get { model as? HeaderModel }
} }
/// Convenience function to add a molecule to the view. /// 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? { 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. // Copyright © 2019 Suresh, Kamlesh. All rights reserved.
// //
import Foundation
@objcMembers public class MoleculeHeaderModel: HeaderModel, MoleculeModelProtocol, MoleculeContainerModelProtocol { @objcMembers public class MoleculeHeaderModel: HeaderModel, MoleculeModelProtocol, MoleculeContainerModelProtocol {
public static var identifier: String = "header" public static var identifier: String = "header"

View File

@ -17,7 +17,7 @@ public class MoleculeHeaderView: MoleculeContainer {
var line = Line() var line = Line()
var headerModel: MoleculeHeaderModel? { 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. // Copyright © 2020 Verizon Wireless. All rights reserved.
// //
import Foundation
@objcMembers open class TabBar: UITabBar, MoleculeViewProtocol, TabBarProtocol, UITabBarDelegate { @objcMembers open class TabBar: UITabBar, MoleculeViewProtocol, TabBarProtocol, UITabBarDelegate {
@ -15,9 +14,7 @@ import Foundation
public let line = Line() public let line = Line()
required public init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { required public init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let model = model as? TabBarModel else { guard let model = model as? TabBarModel else { fatalError("model is not TabBarModel") }
fatalError("model is not TabBarModel")
}
self.model = model self.model = model
super.init(frame: .zero) super.init(frame: .zero)
@ -32,7 +29,7 @@ import Foundation
fatalError("init(coder:) has not been implemented") 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 } guard let model = model as? TabBarModel else { return }
self.model = model self.model = model
@ -103,10 +100,7 @@ import Foundation
}) })
} }
public func currentTabIndex() -> Int { public func currentTabIndex() -> Int { model.selectedTab }
return model.selectedTab
}
} }
extension UITabBarItem: MFButtonProtocol { extension UITabBarItem: MFButtonProtocol { }
}

View File

@ -6,17 +6,15 @@
// Copyright © 2020 Verizon Wireless. All rights reserved. // Copyright © 2020 Verizon Wireless. All rights reserved.
// //
import Foundation
@objcMembers open class ImageBarButtonItem: BarButtonItem { @objcMembers open class ImageBarButtonItem: BarButtonItem {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
//-------------------------------------------------- //--------------------------------------------------
public static func create(with image: UIImage?) -> Self { public static func create(with image: UIImage?) -> Self {
let actionObject = ActionDelegate() 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 button.actionDelegate = actionObject
return button return button
} }
@ -29,7 +27,7 @@ import Foundation
} }
/// Creates the item with the passed in action map. /// 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) let button = create(with: image)
button.set(with: actionMap, delegateObject: delegateObject, additionalData: additionalData) button.set(with: actionMap, delegateObject: delegateObject, additionalData: additionalData)
return button return button
@ -42,4 +40,3 @@ import Foundation
return button return button
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -6,11 +6,10 @@
// Copyright © 2020 Verizon Wireless. All rights reserved. // Copyright © 2020 Verizon Wireless. All rights reserved.
// //
import Foundation
extension MVMCoreUITopAlertExpandableView: MoleculeViewProtocol { 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() defaultSetup()
guard let model = model as? CollapsableNotificationModel else { return } guard let model = model as? CollapsableNotificationModel else { return }
backgroundColor = model.backgroundColor?.uiColor ?? .mvmGreen backgroundColor = model.backgroundColor?.uiColor ?? .mvmGreen
@ -30,6 +29,10 @@ extension MVMCoreUITopAlertExpandableView: MoleculeViewProtocol {
MVMCoreUITopAlertBaseView.addAction(to: button, actionMap: topActionMap, additionalData: nil) MVMCoreUITopAlertBaseView.addAction(to: button, actionMap: topActionMap, additionalData: nil)
shortView?.label?.accessibilityTraits = .button 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. // Copyright © 2020 Verizon Wireless. All rights reserved.
// //
import Foundation
extension MVMCoreUITopAlertMainView: MoleculeViewProtocol { 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() defaultSetup()
guard let model = model as? NotificationModel else { return } guard let model = model as? NotificationModel else { return }
backgroundColor = model.backgroundColor?.uiColor ?? .mvmGreen backgroundColor = model.backgroundColor?.uiColor ?? .mvmGreen
var actionMap = model.button?.action.toJSON() var actionMap = model.button?.action.toJSON()
if let title = model.button?.title { if let title = model.button?.title {
actionMap?.updateValue(title, forKey: KeyTitle) actionMap?.updateValue(title, forKey: KeyTitle)
} }
if let accessibilityIdentifier = model.accessibilityIdentifier {
self.accessibilityIdentifier = accessibilityIdentifier
}
setupCloseButton(model.closeButton != nil, animationDelegate: MVMCoreUITopAlertView.sharedGlobal()?.animationDelegate) 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) 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. // Copyright © 2020 Verizon Wireless. All rights reserved.
// //
import Foundation
open class NotificationModel: MoleculeModelProtocol { 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 backgroundColor: Color?
public var headline: LabelModel public var headline: LabelModel
public var body: LabelModel? public var body: LabelModel?
public var button: ButtonModel? public var button: ButtonModel?
public var closeButton: NotificationXButtonModel? public var closeButton: NotificationXButtonModel?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(with headline: LabelModel) { public init(with headline: LabelModel) {
self.headline = headline self.headline = headline
} }
//--------------------------------------------------
// MARK: - Default
//--------------------------------------------------
open func setDefault() { open func setDefault() {
if backgroundColor == nil { if backgroundColor == nil {
backgroundColor = Color(uiColor: .mvmGreen()) backgroundColor = Color(uiColor: .mvmGreen)
} }
if headline.textColor == nil { if headline.textColor == nil {
headline.textColor = Color(uiColor: .white) headline.textColor = Color(uiColor: .mvmWhite)
} }
if body?.textColor == nil { if body?.textColor == nil {
body?.textColor = Color(uiColor: .white) body?.textColor = Color(uiColor: .mvmWhite)
} }
if button?.style == nil { if button?.style == nil {
button?.style = .secondary button?.style = .secondary
} }
button?.size = .tiny button?.size = .tiny
button?.enabledTextColor = Color(uiColor: .white) button?.enabledTextColor = Color(uiColor: .mvmWhite)
button?.enabledBorderColor = Color(uiColor: .white) button?.enabledBorderColor = Color(uiColor: .mvmWhite)
} }
//--------------------------------------------------
// MARK: - Coding Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case backgroundColor case backgroundColor
case accessibilityIdentifier
case headline case headline
case body case body
case button case button
case closeButton case closeButton
} }
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
headline = try typeContainer.decode(LabelModel.self, forKey: .headline) headline = try typeContainer.decode(LabelModel.self, forKey: .headline)
body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body) body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body)
button = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .button) button = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .button)
@ -63,6 +83,7 @@ open class NotificationModel: MoleculeModelProtocol {
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encode(headline, forKey: .headline) try container.encode(headline, forKey: .headline)
try container.encodeIfPresent(body, forKey: .body) try container.encodeIfPresent(body, forKey: .body)
try container.encodeIfPresent(button, forKey: .button) try container.encodeIfPresent(button, forKey: .button)

View File

@ -16,7 +16,7 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
open var stackItems: [UIView] = [] open var stackItems: [UIView] = []
open var stackModel: T? { 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 moleculeName: String { get }
var backgroundColor: Color? { get set } var backgroundColor: Color? { get set }
} }
public extension MoleculeModelProtocol { public extension MoleculeModelProtocol {
var moleculeName: String { var moleculeName: String { Self.identifier }
get { return Self.identifier }
}
static var categoryName: String { static var categoryName: String { "\(MoleculeModelProtocol.self)" }
return "\(MoleculeModelProtocol.self)"
}
static var categoryCodingKey: String { static var categoryCodingKey: String { "moleculeName" }
return "moleculeName"
}
} }

View File

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

View File

@ -8,6 +8,7 @@
public typealias ButtonAction = (Button) -> () public typealias ButtonAction = (Button) -> ()
@objcMembers open class Button: UIButton, MFButtonProtocol, MoleculeViewProtocol { @objcMembers open class Button: UIButton, MFButtonProtocol, MoleculeViewProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
@ -65,7 +66,7 @@ public typealias ButtonAction = (Button) -> ()
/// Adds a block to be performed for the given event. /// Adds a block to be performed for the given event.
open func addActionBlock(event: Event, _ buttonBlock: @escaping ButtonAction) { open func addActionBlock(event: Event, _ buttonBlock: @escaping ButtonAction) {
self.buttonAction = buttonBlock self.buttonAction = buttonBlock
addTarget(self, action: #selector(callActionBlock(_:)), for: event) addTarget(self, action: #selector(callActionBlock), for: event)
} }
@objc func callActionBlock(_ sender: Button) { @objc func callActionBlock(_ sender: Button) {
@ -103,6 +104,10 @@ public typealias ButtonAction = (Button) -> ()
self.backgroundColor = backgroundColor.uiColor self.backgroundColor = backgroundColor.uiColor
} }
if let accessibilityIdentifier = model.accessibilityIdentifier {
self.accessibilityIdentifier = accessibilityIdentifier
}
if let model = model as? EnableableModelProtocol { if let model = model as? EnableableModelProtocol {
isEnabled = model.enabled isEnabled = model.enabled
} }
@ -119,25 +124,23 @@ public typealias ButtonAction = (Button) -> ()
// MARK: Overridables // 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. // 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? { 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? { open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { nil }
return nil
}
open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? { open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? { nil }
return nil
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Accessibility // MARK: - Accessibility
//-------------------------------------------------- //--------------------------------------------------
open override func accessibilityActivate() -> Bool { open override func accessibilityActivate() -> Bool {
guard isEnabled else { return false }
buttonAction?(self) buttonAction?(self)
return buttonAction != nil return buttonAction != nil
} }
} }
// MARK: - MVMCoreViewProtocol // MARK: - MVMCoreViewProtocol
@ -160,6 +163,6 @@ extension Button: MVMCoreViewProtocol {
extension Button: AppleGuidelinesProtocol { extension Button: AppleGuidelinesProtocol {
override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool { 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 // MARK:- MoleculeViewProtocol
open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
self.model = model self.model = model
if let backgroundColor = model.backgroundColor { if let backgroundColor = model.backgroundColor {
self.backgroundColor = backgroundColor.uiColor self.backgroundColor = backgroundColor.uiColor
} }
if let accessibilityIdentifier = model.accessibilityIdentifier {
self.accessibilityIdentifier = accessibilityIdentifier
}
} }
open func reset() { open func reset() {
@ -63,22 +68,18 @@ import UIKit
// MARK: Overridables // 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. // 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? { 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? { open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { nil }
return nil
}
open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? { open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? { nil }
return nil
}
} }
// MARK: - AppleGuidelinesProtocol // MARK: - AppleGuidelinesProtocol
extension Control: AppleGuidelinesProtocol { extension Control: AppleGuidelinesProtocol {
override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool { 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() { public func reset() {
backgroundColor = .clear backgroundColor = .clear
} }
public func setAsMolecule() { } public func setAsMolecule() { }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - ModelMoleculeViewProtocol // 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 self.model = model
if let backgroundColor = model.backgroundColor { if let backgroundColor = model.backgroundColor {
self.backgroundColor = backgroundColor.uiColor self.backgroundColor = backgroundColor.uiColor
} }
if let accessibilityIdentifier = model.accessibilityIdentifier {
self.accessibilityIdentifier = accessibilityIdentifier
}
} }
open class func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { open class func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
return model?.moleculeName model?.moleculeName
} }
open class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { nil }
return nil
}
open class func requiredModules(_ molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? { open class func requiredModules(_ molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? { nil }
return nil
}
} }
// MARK:- MVMCoreViewProtocol // MARK:- MVMCoreViewProtocol
@ -94,4 +96,3 @@ extension ImageView: MVMCoreViewProtocol {
MVMCoreUIUtility.setMarginsFor(self, leading: 0, top: 0, trailing: 0, bottom: 0) MVMCoreUIUtility.setMarginsFor(self, leading: 0, top: 0, trailing: 0, bottom: 0)
} }
} }

View File

@ -6,7 +6,6 @@
// Copyright © 2020 Verizon Wireless. All rights reserved. // Copyright © 2020 Verizon Wireless. All rights reserved.
// //
import Foundation
@objcMembers open class SectionHeaderFooterView: UITableViewHeaderFooterView, MoleculeViewProtocol { @objcMembers open class SectionHeaderFooterView: UITableViewHeaderFooterView, MoleculeViewProtocol {
//-------------------------------------------------- //--------------------------------------------------
@ -43,10 +42,16 @@ import Foundation
//-------------------------------------------------- //--------------------------------------------------
open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
self.model = model self.model = model
if let backgroundColor = model.backgroundColor { if let backgroundColor = model.backgroundColor {
contentView.backgroundColor = backgroundColor.uiColor contentView.backgroundColor = backgroundColor.uiColor
} }
if let accessibilityIdentifier = model.accessibilityIdentifier {
self.accessibilityIdentifier = accessibilityIdentifier
}
} }
open func reset() { open func reset() {
@ -56,16 +61,12 @@ import Foundation
// MARK: Overridables // 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. // 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? { 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? { open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { nil }
return nil
}
open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? { open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? { nil }
return nil
}
} }
// MARK:- MVMCoreViewProtocol // MARK:- MVMCoreViewProtocol

View File

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

View File

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

View File

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

View File

@ -58,6 +58,10 @@ import UIKit
if let backgroundColor = model.backgroundColor { if let backgroundColor = model.backgroundColor {
self.backgroundColor = backgroundColor.uiColor self.backgroundColor = backgroundColor.uiColor
} }
if let accessibilityIdentifier = model.accessibilityIdentifier {
self.accessibilityIdentifier = accessibilityIdentifier
}
} }
open func reset() { open func reset() {
@ -67,16 +71,12 @@ import UIKit
// MARK: Overridables // 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. // 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? { 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? { open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { nil }
return nil
}
open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? { open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? { nil }
return nil
}
} }
// MARK:- MVMCoreViewProtocol // MARK:- MVMCoreViewProtocol

View File

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

View File

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

View File

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