Merge branch 'develop' into feature/revised_accessibility

This commit is contained in:
Kevin G Christiano 2020-05-07 16:38:31 -04:00
commit 3abe936d7d
13 changed files with 418 additions and 125 deletions

View File

@ -2103,7 +2103,7 @@
0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */,
011B58F023A2AA980085F53C /* ListItemModelProtocol.swift in Sources */,
D22479962316AF6E003FCCF9 /* HeadlineBodyLink.swift in Sources */,
8DE5BECD2456F7A200772E76 /* ListTwoColumnDropdownSelectorsModel.swift in Sources */,
8DE5BECD2456F7A200772E76 /* ListTwoColumnDropdownSelectorsModel.swift in Sources */,
0A41BA7F23453A6400D4C0BC /* TextEntryField.swift in Sources */,
BB55B51D244482C1002001AD /* ListRightVariablePriceChangeBodyText.swift in Sources */,
017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */,

View File

@ -8,40 +8,75 @@
import UIKit
public enum ButtonStyle: String, Codable {
case primary
case secondary
}
public typealias FacadeElements = (fill: UIColor?, text: UIColor?, border: UIColor?)
public enum ButtonSize: String, Codable {
case standard
case tiny
}
public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWatcherFieldProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "button"
public var backgroundColor: Color?
public var title: String
public var action: ActionModelProtocol
public var enabled: Bool = true
public var style: ButtonStyle?
public var size: ButtonSize? = .standard
public var fillColor: Color?
public var textColor: Color?
public var borderColor: Color?
public var style: Styler.Button.Style? {
didSet {
guard let style = style else { return }
switch style {
case .primary:
setPrimaryFacade()
case .secondary:
setSecondaryFacade()
}
}
}
public var size: Styler.Button.Size? = .standard
public var groupName: String = ""
public var inverted: Bool = false
public lazy var enabledColors: FacadeElements = (fill: enabled_fillColor(),
text: enabled_textColor(),
border: enabled_borderColor())
public lazy var disabledColors: FacadeElements = (fill: disabled_fillColor(),
text: disabled_textColor(),
border: disabled_borderColor())
public var enabledFillColor: Color?
public var enabledTextColor: Color?
public var enabledBorderColor: Color?
public var enabledFillColor_inverted: Color?
public var enabledTextColor_inverted: Color?
public var enabledBorderColor_inverted: Color?
public var disabledFillColor: Color?
public var disabledTextColor: Color?
public var disabledBorderColor: Color?
public var groupName: String = ""
public var disabledFillColor_inverted: Color?
public var disabledTextColor_inverted: Color?
public var disabledBorderColor_inverted: Color?
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
public func setValidity(_ valid: Bool, group: FormGroupRule) {
enabled = valid
updateUI?()
}
/// Temporary binding mechanism for the view to update on enable changes.
public var updateUI: (() -> Void)?
public var updateUI: ActionBlock?
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
public init(with title: String, action: ActionModelProtocol) {
self.title = title
self.action = action
@ -52,71 +87,173 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupW
self.action = action
style = .secondary
}
public init(primaryButtonWith title: String, action: ActionModelProtocol) {
self.title = title
self.action = action
style = .primary
}
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
public func enabled_fillColor() -> UIColor? {
return (inverted ? enabledFillColor_inverted : enabledFillColor)?.uiColor
}
public func enabled_textColor() -> UIColor? {
return (inverted ? enabledTextColor_inverted : enabledTextColor)?.uiColor
}
public func enabled_borderColor() -> UIColor? {
return (inverted ? enabledBorderColor_inverted : enabledBorderColor)?.uiColor
}
public func disabled_fillColor() -> UIColor? {
return (inverted ? disabledFillColor_inverted : disabledFillColor)?.uiColor
}
public func disabled_textColor() -> UIColor? {
return (inverted ? disabledTextColor_inverted : disabledTextColor)?.uiColor
}
public func disabled_borderColor() -> UIColor? {
return (inverted ? disabledBorderColor_inverted : disabledBorderColor)?.uiColor
}
/// Defines the default appearance for the primary style.
func setPrimaryFacade() {
if enabledFillColor == nil && enabledTextColor == nil {
enabledFillColor = Color(uiColor: .mvmBlack)
enabledTextColor = Color(uiColor: .mvmWhite)
}
if disabledFillColor == nil && disabledTextColor == nil {
disabledFillColor = Color(uiColor: .mvmCoolGray6)
disabledTextColor = Color(uiColor: .mvmWhite)
}
enabledFillColor_inverted = Color(uiColor: .mvmWhite)
enabledTextColor_inverted = Color(uiColor: .mvmBlack)
disabledFillColor_inverted = Color(uiColor: .mvmCoolGray6)
disabledTextColor_inverted = Color(uiColor: .mvmBlack)
}
/// Defines the default appearance for the Secondary style.
func setSecondaryFacade() {
if enabledTextColor == nil && enabledBorderColor == nil {
enabledTextColor = Color(uiColor: .mvmBlack)
enabledBorderColor = Color(uiColor: .mvmBlack)
}
if disabledTextColor == nil && disabledBorderColor == nil {
disabledTextColor = Color(uiColor: .mvmCoolGray6)
disabledBorderColor = Color(uiColor: .mvmCoolGray6)
}
enabledTextColor_inverted = Color(uiColor: .mvmWhite)
enabledBorderColor_inverted = Color(uiColor: .mvmWhite)
disabledTextColor_inverted = Color(uiColor: .mvmCoolGray6)
disabledBorderColor_inverted = Color(uiColor: .mvmCoolGray6)
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case title
case inverted
case action
case enabled
case style
case size
case groupName
case fillColor
case textColor
case borderColor
case disabledFillColor
case disabledTextColor
case disabledBorderColor
case groupName
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
title = try typeContainer.decode(String.self, forKey: .title)
action = try typeContainer.decodeModel(codingKey: .action)
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
self.groupName = groupName
}
if let style = try typeContainer.decodeIfPresent(ButtonStyle.self, forKey: .style) {
if let style = try typeContainer.decodeIfPresent(Styler.Button.Style.self, forKey: .style) {
self.style = style
}
if let size = try typeContainer.decodeIfPresent(ButtonSize.self, forKey: .size) {
if let size = try typeContainer.decodeIfPresent(Styler.Button.Size.self, forKey: .size) {
self.size = size
}
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
self.enabled = enabled
}
fillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .fillColor)
textColor = try typeContainer.decodeIfPresent(Color.self, forKey: .textColor)
borderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor)
disabledFillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledFillColor)
disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor)
disabledBorderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledBorderColor)
if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) {
self.inverted = inverted
}
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
self.groupName = groupName
}
if let enabledFillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .fillColor) {
self.enabledFillColor = enabledFillColor
}
if let enabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .textColor) {
self.enabledTextColor = enabledTextColor
}
if let enabledBorderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor) {
self.enabledBorderColor = enabledBorderColor
}
if let disabledFillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledFillColor) {
self.disabledFillColor = disabledFillColor
}
if let disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor) {
self.disabledTextColor = disabledTextColor
}
if let disabledBorderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledBorderColor) {
self.disabledBorderColor = disabledBorderColor
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(title, forKey: .title)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeModel(action, forKey: .action)
try container.encode(enabled, forKey: .enabled)
try container.encodeIfPresent(style, forKey: .style)
try container.encodeIfPresent(size, forKey: .size)
try container.encodeIfPresent(fillColor, forKey: .fillColor)
try container.encodeIfPresent(textColor, forKey: .textColor)
try container.encodeIfPresent(borderColor, forKey: .borderColor)
try container.encode(inverted, forKey: .inverted)
try container.encodeModel(action, forKey: .action)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(enabledFillColor, forKey: .fillColor)
try container.encodeIfPresent(enabledTextColor, forKey: .textColor)
try container.encodeIfPresent(enabledBorderColor, forKey: .borderColor)
try container.encodeIfPresent(disabledFillColor, forKey: .disabledFillColor)
try container.encodeIfPresent(disabledTextColor, forKey: .disabledTextColor)
try container.encodeIfPresent(disabledBorderColor, forKey: .disabledBorderColor)
try container.encodeIfPresent(style, forKey: .style)
try container.encodeIfPresent(size, forKey: .size)
try container.encodeIfPresent(groupName, forKey: .groupName)
}
}

View File

@ -8,80 +8,105 @@
import UIKit
open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
// Used to size the button.
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
/// Used to size the button.
var size = MVMCoreUIUtility.getWidth()
var buttonModel: ButtonModel? {
get { return model as? ButtonModel }
}
// Need to re-style on set.
/// Need to re-style on set.
open override var isEnabled: Bool {
didSet {
style()
}
didSet { style() }
}
private enum ButtonHeight: CGFloat {
case tiny = 20
case standard = 42
//--------------------------------------------------
// MARK: - Computed Properties
//--------------------------------------------------
public var enabledTitleColor: UIColor? {
get { return titleColor(for: .normal) }
set { setTitleColor(newValue, for: .normal) }
}
public var disabledTitleColor: UIColor? {
get { return titleColor(for: .disabled) }
set { setTitleColor(newValue, for: .disabled) }
}
public var borderColor: UIColor? {
get {
guard let currentColor = layer.borderColor else { return nil }
return UIColor(cgColor: currentColor)
}
set { layer.borderColor = newValue?.cgColor }
}
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
/// The primary styling for a button. Should be used for main buttons
public func stylePrimary() {
setTitleColor(.white, for: .normal)
setTitleColor(.white, for: .disabled)
enabledTitleColor = buttonModel?.enabledColors.text ?? .mvmWhite
disabledTitleColor = buttonModel?.disabledColors.text ?? .mvmWhite
layer.borderWidth = 0
if isEnabled {
backgroundColor = .black
} else {
backgroundColor = .mvmCoolGray6
}
backgroundColor = isEnabled ? buttonModel?.enabledColors.fill ?? .mvmBlack : buttonModel?.disabledColors.fill ?? .mvmCoolGray6
}
/// The secondary styling for a button. Should be used for secondary buttons
public func styleSecondary() {
setTitleColor(.black, for: .normal)
setTitleColor(.mvmCoolGray6, for: .disabled)
enabledTitleColor = buttonModel?.enabledColors.text ?? .mvmBlack
disabledTitleColor = buttonModel?.disabledColors.text ?? .mvmCoolGray6
backgroundColor = .clear
layer.borderWidth = 1
if isEnabled {
layer.borderColor = UIColor.black.cgColor
} else {
layer.borderColor = UIColor.mvmCoolGray6.cgColor
}
borderColor = isEnabled ? buttonModel?.enabledColors.border ?? .mvmBlack : buttonModel?.disabledColors.border ?? .mvmCoolGray6
}
/// Styles the button based on the model style
private func style() {
switch buttonModel?.style {
case .secondary:
styleSecondary()
default:
stylePrimary()
}
if let titleColor = buttonModel?.textColor {
setTitleColor(titleColor.uiColor, for: .normal)
if let titleColor = buttonModel?.enabledColors.text {
enabledTitleColor = titleColor
}
if let disabledTitleColor = buttonModel?.disabledTextColor {
setTitleColor(disabledTitleColor.uiColor, for: .disabled)
if let disabledTitleColor = buttonModel?.disabledColors.text {
self.disabledTitleColor = disabledTitleColor
}
if isEnabled {
if let fillColor = buttonModel?.fillColor {
backgroundColor = fillColor.uiColor
if let fillColor = buttonModel?.enabledColors.fill {
backgroundColor = fillColor
}
if let borderColor = buttonModel?.borderColor {
if let borderColor = buttonModel?.enabledColors.border {
layer.borderWidth = 1
layer.borderColor = borderColor.cgColor
self.borderColor = borderColor
}
} else {
if let fillColor = buttonModel?.disabledFillColor {
backgroundColor = fillColor.uiColor
if let fillColor = buttonModel?.disabledColors.fill {
backgroundColor = fillColor
}
if let borderColor = buttonModel?.disabledBorderColor {
if let borderColor = buttonModel?.disabledColors.border {
layer.borderWidth = 1
layer.borderColor = borderColor.cgColor
self.borderColor = borderColor
}
}
}
@ -94,38 +119,53 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
PillButton.getHeight(for: buttonModel?.size, size: size)
}
public static func getHeight(for buttonSize: ButtonSize?, size: CGFloat) -> CGFloat {
public static func getHeight(for buttonSize: Styler.Button.Size?, size: CGFloat) -> CGFloat {
switch buttonSize {
case .tiny:
return MFSizeObject(standardSize: ButtonHeight.tiny.rawValue, standardiPadPortraitSize: 34, iPadProLandscapeSize: 38)?.getValueBased(onSize: size) ?? ButtonHeight.tiny.rawValue
let tinyHeight = Styler.Button.Size.tiny.getHeight()
return MFSizeObject(standardSize: tinyHeight,
standardiPadPortraitSize: 34,
iPadProLandscapeSize: 38)?.getValueBased(onSize: size) ?? tinyHeight
default:
return MFSizeObject(standardSize: ButtonHeight.standard.rawValue, standardiPadPortraitSize: 46, iPadProLandscapeSize: 50)?.getValueBased(onSize: size) ?? ButtonHeight.standard.rawValue
let standardHeight = Styler.Button.Size.standard.getHeight()
return MFSizeObject(standardSize: standardHeight,
standardiPadPortraitSize: 46,
iPadProLandscapeSize: 50)?.getValueBased(onSize: size) ?? standardHeight
}
}
private func getMinimumWidth() -> CGFloat {
switch buttonModel?.size {
case .tiny:
return MFSizeObject(standardSize: 49.0, standardiPadPortraitSize: 90.0, iPadProLandscapeSize: 135.0)?.getValueBased(onSize: size) ?? 49.0
default:
return 151.0
return MFSizeObject(standardSize: 49,
standardiPadPortraitSize: 90,
iPadProLandscapeSize: 135)?.getValueBased(onSize: size) ?? 49
default: return 151
}
}
open override var intrinsicContentSize: CGSize {
let size = super.intrinsicContentSize
let width = size.width + (2 * getInnerPadding())
return CGSize(width: max(width, getMinimumWidth()), height: getHeight())
}
// MARK: - MoleculeViewProtocol
//--------------------------------------------------
// MARK: - MVMCoreViewProtocol
//--------------------------------------------------
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
// The button will get styled in the enable check in super.
super.set(with: model, delegateObject, additionalData)
guard let model = model as? ButtonModel else { return }
setTitle(model.title, for: .normal)
model.updateUI = { [weak self] in
MVMCoreDispatchUtility.performBlock(onMainThread: {
self?.enableField(model.enabled)
@ -134,39 +174,46 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
PillButton.getHeight(for: (model as? ButtonModel)?.size, size: MVMCoreUIUtility.getWidth())
}
// MARK: - MVMCoreViewProtocol
open override func updateView(_ size: CGFloat) {
super.updateView(size)
self.size = size
invalidateIntrinsicContentSize()
switch buttonModel?.size {
case .tiny:
titleLabel?.font = MFFonts.mfFont75Bd(11 * (intrinsicContentSize.height / ButtonHeight.tiny.rawValue))
titleLabel?.font = MFFonts.mfFont75Bd(11 * (intrinsicContentSize.height / Styler.Button.Size.tiny.getHeight()))
default:
titleLabel?.font = MFFonts.mfFont75Bd(13 * (intrinsicContentSize.height / ButtonHeight.standard.rawValue))
titleLabel?.font = MFFonts.mfFont75Bd(13 * (intrinsicContentSize.height / Styler.Button.Size.standard.getHeight()))
}
layer.cornerRadius = getInnerPadding()
}
open override func setupView() {
super.setupView()
titleLabel?.numberOfLines = 1
titleLabel?.lineBreakMode = .byTruncatingTail
titleLabel?.textAlignment = .center
contentHorizontalAlignment = .center
stylePrimary()
}
//--------------------------------------------------
// MARK: - MVMCoreUIViewConstrainingProtocol
//--------------------------------------------------
open func horizontalAlignment() -> UIStackView.Alignment {
return .center
}
public func enableField(_ enable: Bool) {
isEnabled = enable
}

View File

@ -22,7 +22,7 @@ public class ListRightVariableButtonAllTextAndLinksModel: ListItemModel, Molecul
override public func setDefaults() {
super.setDefaults()
self.button.size = .tiny
self.button.style = ButtonStyle.secondary
self.button.style = .secondary
}
private enum CodingKeys: String, CodingKey {

View File

@ -9,11 +9,24 @@
import UIKit
@objcMembers open class TwoButtonView: View, MVMCoreUIViewConstrainingProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
open var primaryButton: PillButton = PillButton()
open var secondaryButton: PillButton = PillButton()
private var stack = UIStackView()
//--------------------------------------------------
// MARK: - Constraints
//--------------------------------------------------
private var equalWidthConstraint: NSLayoutConstraint?
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
public init() {
super.init(frame: .zero)
}
@ -26,16 +39,21 @@ import UIKit
super.init(frame: frame)
}
public func setDefault() {
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
public func setDefaultAppearance() {
primaryButton.stylePrimary()
secondaryButton.styleSecondary()
}
// MARK: - MVMCoreViewProtocol
open override func updateView(_ size: CGFloat) {
super.updateView(size)
self.primaryButton.updateView(size)
self.secondaryButton.updateView(size)
primaryButton.updateView(size)
secondaryButton.updateView(size)
}
open override func setupView() {
@ -52,58 +70,70 @@ import UIKit
equalWidthConstraint?.isActive = true
}
//--------------------------------------------------
// MARK: - Stack Manipulation
//--------------------------------------------------
public func showPrimaryButton() {
if !stack.arrangedSubviews.contains(primaryButton) {
stack.addArrangedSubview(primaryButton)
primaryButton.isHidden = false
}
if secondaryButton.superview != nil {
equalWidthConstraint?.isActive = true
}
}
public func showSecondaryButton() {
if !stack.arrangedSubviews.contains(secondaryButton) {
stack.insertArrangedSubview(secondaryButton, at: 0)
secondaryButton.isHidden = false
}
if primaryButton.superview != nil {
equalWidthConstraint?.isActive = true
}
}
public func hidePrimaryButton() {
if primaryButton.superview != nil {
stack.removeArrangedSubview(primaryButton)
primaryButton.isHidden = true
}
equalWidthConstraint?.isActive = false
}
public func hideSecondaryButton() {
if secondaryButton.superview != nil {
stack.removeArrangedSubview(secondaryButton)
secondaryButton.isHidden = true
}
equalWidthConstraint?.isActive = false
}
//--------------------------------------------------
// MARK: - MoleculeViewProtocol
//--------------------------------------------------
open override func reset() {
super.reset()
setDefault()
}
// MARK: - MVMCoreUIViewConstrainingProtocol
open func horizontalAlignment() -> UIStackView.Alignment {
return .center
setDefaultAppearance()
}
// MARK: - MoleculeViewProtocol
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
guard let model = model as? TwoButtonViewModel,
let buttonModel = model.primaryButton ?? model.secondaryButton else { return 0 }
let buttonModel = model.primaryButton ?? model.secondaryButton
else { return 0 }
return PillButton.estimatedHeight(with: buttonModel, delegateObject)
}
@ -118,6 +148,7 @@ import UIKit
} else {
hideSecondaryButton()
}
if let primaryModel = model.primaryButton {
showPrimaryButton()
primaryButton.set(with: primaryModel, delegateObject, additionalData)
@ -125,4 +156,11 @@ import UIKit
hidePrimaryButton()
}
}
//--------------------------------------------------
// MARK: - MVMCoreUIViewConstrainingProtocol
//--------------------------------------------------
open func horizontalAlignment() -> UIStackView.Alignment {
return .center
}
}

View File

@ -8,35 +8,54 @@
import UIKit
public class TwoButtonViewModel: MoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "twoButtonView"
public var backgroundColor: Color?
public var primaryButton: ButtonModel?
public var secondaryButton: ButtonModel?
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case primaryButton
case secondaryButton
}
//--------------------------------------------------
// MARK: - Initialzer
//--------------------------------------------------
public init(_ primaryButton: ButtonModel?, _ secondaryButton: ButtonModel?) {
self.primaryButton = primaryButton
self.secondaryButton = secondaryButton
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
primaryButton = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .primaryButton)
if primaryButton?.style == nil {
primaryButton?.style = .primary
}
secondaryButton = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .secondaryButton)
// Default value
if secondaryButton?.style == nil {
secondaryButton?.style = .secondary
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)

View File

@ -8,24 +8,39 @@
import Foundation
@objcMembers public class TemplateModel: MVMControllerModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public class var identifier: String {
return ""
}
public var pageType: String
public var template: String {
// Although this is done in the extension, it is needed for the encoding.
return Self.identifier
}
public var backgroundColor: Color?
public var screenHeading: String?
public var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)?
public var formRules: [FormGroupRule]?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(pageType: String) {
self.pageType = pageType
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case pageType
case template
@ -34,6 +49,10 @@ import Foundation
case formRules
case navigationItem
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)

View File

@ -24,25 +24,25 @@ import UIKit
open override func viewForTop() -> UIView? {
guard let headerModel = templateModel?.header,
let molecule = MoleculeObjectMapping.shared()?.createMolecule(headerModel, delegateObject: delegateObjectIVar) else {
return nil
}
let molecule = MoleculeObjectMapping.shared()?.createMolecule(headerModel, delegateObject: delegateObjectIVar)
else { return nil }
return molecule
}
open override func viewForMiddle() -> UIView? {
guard let middleModel = templateModel?.middle,
let molecule = MoleculeObjectMapping.shared()?.createMolecule(middleModel, delegateObject: delegateObjectIVar) else {
return nil
}
let molecule = MoleculeObjectMapping.shared()?.createMolecule(middleModel, delegateObject: delegateObjectIVar)
else { return nil }
return molecule
}
override open func viewForBottom() -> UIView? {
guard let footerModel = templateModel?.footer,
let molecule = MoleculeObjectMapping.shared()?.createMolecule(footerModel, delegateObject: delegateObjectIVar) else {
return nil
}
let molecule = MoleculeObjectMapping.shared()?.createMolecule(footerModel, delegateObject: delegateObjectIVar)
else { return nil }
return molecule
}

View File

@ -81,6 +81,7 @@ open class TextViewModel: TextEntryFieldModel {
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
try container.encodeIfPresent(height, forKey: .height)

View File

@ -258,7 +258,7 @@ import UIKit
viewRespectsSystemMinimumLayoutMargins = false
// Presents from the bottom.
modalPresentationStyle = MVMCoreGetterUtility.isOnIPad() ? UIModalPresentationStyle.formSheet : UIModalPresentationStyle.overCurrentContext
modalPresentationStyle = MVMCoreGetterUtility.isOnIPad() ? .formSheet : .overCurrentContext
// Create the default delegate object.
delegateObjectIVar = MVMCoreUIDelegateObject.create(withDelegateForAll: self)
@ -339,18 +339,18 @@ import UIKit
}
// MARK: - MVMCoreActionDelegateProtocol
open func handleOpenPage(for requestParameters: MVMCoreRequestParameters, actionInformation: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?) {
open func handleOpenPage(for requestParameters: MVMCoreRequestParameters, actionInformation: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?) {
formValidator?.addFormParams(requestParameters: requestParameters)
requestParameters.parentPageType = loadObject?.pageJSON?.optionalStringForKey("parentPageType")
MVMCoreActionHandler.defaultHandleOpenPage(for: requestParameters, additionalData: additionalData, delegateObject: delegateObject())
}
open func logAction(withActionInformation actionInformation: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?) {
open func logAction(withActionInformation actionInformation: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?) {
MVMCoreUILoggingHandler.shared()?.defaultLogAction(forController: self, actionInformation: actionInformation, additionalData: additionalData)
}
// MARK: - MoleculeDelegateProtocol
open func getModuleWithName(_ name: String?) -> [AnyHashable : Any]? {
open func getModuleWithName(_ name: String?) -> [AnyHashable: Any]? {
guard let name = name else { return nil }
return loadObject?.modulesJSON?.optionalDictionaryForKey(name)
}
@ -391,7 +391,7 @@ import UIKit
view.accessibilityElements = [pickerView, toolBar]
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
UIAccessibility.post(notification: UIAccessibility.Notification.layoutChanged, argument: textField.inputView)
UIAccessibility.post(notification: .layoutChanged, argument: textField.inputView)
}
}
}
@ -400,7 +400,7 @@ import UIKit
if textField === selectedField {
if UIAccessibility.isVoiceOverRunning {
view.accessibilityElements = nil
UIAccessibility.post(notification: UIAccessibility.Notification.layoutChanged, argument: textField)
UIAccessibility.post(notification: .layoutChanged, argument: textField)
}
selectedField = nil
}

View File

@ -9,8 +9,10 @@
import UIKit
open class Container: View, ContainerProtocol {
public var view: UIView?
let containerHelper = ContainerHelper()
var containerModel: ContainerModelProtocol? {
get { return model as? ContainerModelProtocol }
}

View File

@ -55,6 +55,13 @@ public final class Color: Codable {
determineRGBA()
}
public init?(uiColor: UIColor?) {
guard let uiColor = uiColor else { return nil }
self.uiColor = uiColor
hex = UIColor.hexString(for: uiColor) ?? ""
determineRGBA()
}
init?(name: String) {
guard let colorTuple = UIColor.names[name] else { return nil }
self.uiColor = colorTuple.uiColor

View File

@ -172,6 +172,29 @@ open class Styler {
}
}
public enum Button {
public enum Style: String, Codable {
case primary
case secondary
}
public enum Size: String, Codable {
case standard
case tiny
func getHeight() -> CGFloat {
switch self {
case .standard:
return 42
case .tiny:
return 20
}
}
}
}
//--------------------------------------------------
// MARK: - Functions
//--------------------------------------------------