diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index ace76ad4..db68745a 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -55,8 +55,6 @@ 0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0198F79E225679870066C936 /* FormValidationProtocol.swift */; }; 0198F7A62256A80B0066C936 /* MFRadioButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 0198F7A02256A80A0066C936 /* MFRadioButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 0198F7A22256A80A0066C936 /* MFRadioButton.m */; }; - 01DF55E021F8FAA800CC099B /* MFTextFieldListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */; }; - 01DF567021FA5AB300CC099B /* TextFieldListFormViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */; }; 01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 01EB3684236097C0006832FA /* MoleculeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB3683236097C0006832FA /* MoleculeProtocol.swift */; }; 01EB368F23609801006832FA /* LabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368823609801006832FA /* LabelModel.swift */; }; @@ -69,6 +67,7 @@ 0A1B4A96233BB18F005B3FB4 /* CheckboxWithLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */; }; 0A209CD323A7E2810068F8B0 /* UIStackViewAlignment+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A209CD223A7E2810068F8B0 /* UIStackViewAlignment+Extension.swift */; }; 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */; }; + 0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */; }; 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */; }; 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; }; 0AA33B34239813C50067DD0F /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B33239813C50067DD0F /* UIColor+Extension.swift */; }; @@ -313,8 +312,6 @@ 0198F79E225679870066C936 /* FormValidationProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidationProtocol.swift; sourceTree = ""; }; 0198F7A02256A80A0066C936 /* MFRadioButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFRadioButton.h; sourceTree = ""; }; 0198F7A22256A80A0066C936 /* MFRadioButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFRadioButton.m; sourceTree = ""; }; - 01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MFTextFieldListView.swift; sourceTree = ""; }; - 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldListFormViewController.swift; sourceTree = ""; }; 01EB3683236097C0006832FA /* MoleculeProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeProtocol.swift; sourceTree = ""; }; 01EB368823609801006832FA /* LabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelModel.swift; sourceTree = ""; }; 01EB368923609801006832FA /* ListItemModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListItemModel.swift; sourceTree = ""; }; @@ -326,6 +323,7 @@ 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionDetailWithImage.swift; sourceTree = ""; }; 0A209CD223A7E2810068F8B0 /* UIStackViewAlignment+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIStackViewAlignment+Extension.swift"; sourceTree = ""; }; 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CATransaction+Extension.swift"; sourceTree = ""; }; + 0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleGuidelinesProtocol.swift; sourceTree = ""; }; 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButton.swift; sourceTree = ""; }; 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = ""; }; 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxWithLabelView.swift; sourceTree = ""; }; @@ -659,6 +657,14 @@ name = "Recovered References"; sourceTree = ""; }; + 0A5D59C323AD488600EFD9E9 /* Protocols */ = { + isa = PBXGroup; + children = ( + 0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */, + ); + path = Protocols; + sourceTree = ""; + }; D213347423842FE3008E41B3 /* Controllers */ = { isa = PBXGroup; children = ( @@ -809,7 +815,6 @@ D29DF0DF21E418B2003B2FB9 /* Templates */ = { isa = PBXGroup; children = ( - 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */, D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */, D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.swift */, D296E13B2295969C0051EBE7 /* MoleculeListCellProtocol.h */, @@ -847,7 +852,6 @@ D224798D2316A988003FCCF9 /* VerticalCombinationViews */, D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */, 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */, - 01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */, D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */, D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */, D2A514662213885800345BFB /* StandardHeaderView.swift */, @@ -1154,6 +1158,7 @@ children = ( D2B18B7E2360913400A9AEDC /* Control.swift */, D2B18B802360945C00A9AEDC /* View.swift */, + 0A5D59C323AD488600EFD9E9 /* Protocols */, ); path = BaseClasses; sourceTree = ""; @@ -1315,6 +1320,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */, 943784F5236B77BB006A1E82 /* GraphView.swift in Sources */, 012CA9E423888B1B003F810F /* (null) in Sources */, 9402C35023A2CEA3004B974C /* LeftRightLabelModel.swift in Sources */, @@ -1359,7 +1365,6 @@ D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */, 014AA72F23C5059B006F3E93 /* ThreeLayerPageTemplateModel.swift in Sources */, D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */, - 01DF567021FA5AB300CC099B /* TextFieldListFormViewController.swift in Sources */, D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */, D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */, D29DF24D21E6A177003B2FB9 /* MFTextField.m in Sources */, @@ -1423,7 +1428,6 @@ 94C2D9842386F3F80006CF46 /* LabelAttributeModel.swift in Sources */, 944589212385D6E900DE9FD4 /* DashLineModel.swift in Sources */, D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */, - 01DF55E021F8FAA800CC099B /* MFTextFieldListView.swift in Sources */, D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */, 012A88B1238C880100FE3DA1 /* PagingMoleculeProtocol.swift in Sources */, D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */, diff --git a/MVMCoreUI/BaseClasses/Control.swift b/MVMCoreUI/BaseClasses/Control.swift index a633f4e1..769e7acb 100644 --- a/MVMCoreUI/BaseClasses/Control.swift +++ b/MVMCoreUI/BaseClasses/Control.swift @@ -56,17 +56,14 @@ import UIKit } } - //-------------------------------------------------- - // MARK: - UITouch - //-------------------------------------------------- - +} + +// MARK: - AppleGuidelinesProtocol +extension Control: AppleGuidelinesProtocol { + override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool { - // If the control is smaller than 44pt by width or height, this will compensate. - let faultToleranceX: CGFloat = max((MinimumTappableArea - bounds.size.width) / 2.0, 0) - let faultToleranceY: CGFloat = max((MinimumTappableArea - bounds.size.height) / 2.0, 0) - let area = bounds.insetBy(dx: -faultToleranceX, dy: -faultToleranceY) - return area.contains(point) + return Self.acceptablyOutsideBounds(point: point, bounds: bounds) } } diff --git a/MVMCoreUI/BaseClasses/Protocols/AppleGuidelinesProtocol.swift b/MVMCoreUI/BaseClasses/Protocols/AppleGuidelinesProtocol.swift new file mode 100644 index 00000000..3498a274 --- /dev/null +++ b/MVMCoreUI/BaseClasses/Protocols/AppleGuidelinesProtocol.swift @@ -0,0 +1,32 @@ +// +// AppleGuidelinesProtocol.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 12/20/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + + +public protocol AppleGuidelinesProtocol { + static var minimumTappableArea: CGFloat { get } + static func acceptablyOutsideBounds(point: CGPoint, bounds: CGRect) -> Bool +} + +extension AppleGuidelinesProtocol { + + static public var minimumTappableArea: CGFloat { + return 44.0 + } + + // If the control is smaller than 44pt by width or height, this will compensate. + static public func acceptablyOutsideBounds(point: CGPoint, bounds: CGRect) -> Bool { + + let faultToleranceX: CGFloat = max((minimumTappableArea - bounds.size.width) / 2.0, 0) + let faultToleranceY: CGFloat = max((minimumTappableArea - bounds.size.height) / 2.0, 0) + let area = bounds.insetBy(dx: -faultToleranceX, dy: -faultToleranceY) + + return area.contains(point) + } +} diff --git a/MVMCoreUI/Models/Primitive Models/Color.swift b/MVMCoreUI/Models/Primitive Models/Color.swift index 027b826e..e4c0e4fa 100644 --- a/MVMCoreUI/Models/Primitive Models/Color.swift +++ b/MVMCoreUI/Models/Primitive Models/Color.swift @@ -8,7 +8,11 @@ import UIKit - +/* + UIColor is not supported by Codable. This Color class + effectively turns UIColor into a primitive class like + Int and String and can be used the same. + */ public final class Color: Codable { //-------------------------------------------------- // MARK: - Properties diff --git a/MVMCoreUI/Molecules/Items/TableViewCell.swift b/MVMCoreUI/Molecules/Items/TableViewCell.swift index ba017c4e..d2137730 100644 --- a/MVMCoreUI/Molecules/Items/TableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/TableViewCell.swift @@ -49,8 +49,10 @@ import UIKit switch styleString { case "standard": styleStandard() - case "header": - styleHeader() + case "shortDivider": + styleShortDivider() + case "tallDivider": + styleTallDivider() case "sectionFooter": styleFooter() case "none": @@ -66,13 +68,20 @@ import UIKit bottomSeparatorView?.setStyle(.standard) } - open func styleHeader() { + open func styleTallDivider() { topMarginPadding = 48 bottomMarginPadding = 16 topSeparatorView?.setStyle(.none) bottomSeparatorView?.setStyle(.thin) } + open func styleShortDivider() { + topMarginPadding = 32 + bottomMarginPadding = 16 + topSeparatorView?.style = .none + bottomSeparatorView?.style = .thin + } + open func styleFooter() { topMarginPadding = 24 bottomMarginPadding = 0 diff --git a/MVMCoreUI/Molecules/MFTextFieldListView.swift b/MVMCoreUI/Molecules/MFTextFieldListView.swift deleted file mode 100644 index 6d24e19a..00000000 --- a/MVMCoreUI/Molecules/MFTextFieldListView.swift +++ /dev/null @@ -1,123 +0,0 @@ -// -// MFTextFieldListView.swift -// MobileFirstFramework -// -// Created by Suresh, Kamlesh on 9/21/18. -// Copyright © 2018 Verizon Wireless. All rights reserved. -// - -import UIKit -import MVMCore - - -public class MFTextFieldListView: ViewConstrainingView { - - public var textFieldMapList: [[String: Any]]? - public var parentViewContoller: MFViewController? - public var textFieldsToValidate: [MFTextField] = [] - public var textFields: [MFTextField] = [] - public var primaryButton: PrimaryButton? - - public init(textFieldMapList: [[String: Any]], parentViewContoller: MFViewController, primaryButton: PrimaryButton?) { - self.textFieldMapList = textFieldMapList - self.parentViewContoller = parentViewContoller - self.primaryButton = primaryButton - super.init(frame: .zero) - } - - public required init?(coder decoder: NSCoder) { - super.init(coder: decoder) - } - - public override func updateView(_ size: CGFloat) { - super.updateView(size) - for textField in textFields { - textField.updateView(size) - } - } - - public override func setupView() { - super.setupView() - self.translatesAutoresizingMaskIntoConstraints = false - - guard let textFieldMapList = textFieldMapList else { - return - } - var viewList: [UIView] = [] - - for textFieldMap in textFieldMapList { - if let textField = MFTextField(map: textFieldMap, bothDelegates: self) { - - if textFieldMap.boolForKey("required") { - textFieldsToValidate.append(textField) - } - - textFields.append(textField) - if let fieldKey = textField.fieldKey { - parentViewContoller?.register(textField, forErrorKey: fieldKey as String) - } - viewList.append(textField) - } - } - - StackableViewController.populateView(self, withUIArray: viewList) { (viewObject) -> UIEdgeInsets in - var edgeInsets = StackableViewController.standardSpaceAroundUIObject() - edgeInsets.left = 0 - edgeInsets.right = 0 - edgeInsets.top = 0 - return edgeInsets - } - - primaryButton?.handleEnabling(with: textFieldsToValidate) - } - - public func addParams(requestParameters: MVMCoreRequestParameters) { - requestParameters.add(getTextParamsList()) - } - - public func getTextParamsList() -> [String: Any] { - var extraParam: [String: Any] = [:] - for textField in textFields { - if let fieldKey = textField.fieldKey { - extraParam[fieldKey as String] = textField.text ?? "" - } - } - return extraParam - } -} - -extension MFTextFieldListView: UITextFieldDelegate, UITextViewDelegate, MFTextFieldDelegate { - @objc open func textFieldDidEndEditing(_ textField: UITextField) { - parentViewContoller?.textFieldDidEndEditing(textField) - primaryButton?.handleEnabling(with: textFieldsToValidate) - } - - @objc open func dismissFieldInput(_ sender: Any?) { - parentViewContoller?.dismissFieldInput(sender) - } - - @objc open func textFieldShouldReturn(_ textField: UITextField) -> Bool { - textField.resignFirstResponder() - return true - } - - @objc open func textFieldDidBeginEditing(_ textField: UITextField) { - parentViewContoller?.textFieldDidBeginEditing(textField) - } - - @objc open func entryIsValid(_ textfield: MFTextField?) { - DispatchQueue.main.async { - if self.parentViewContoller?.responds(to: #selector(MFTextFieldDelegate.entryIsValid(_:))) ?? false { - self.parentViewContoller?.entryIsValid(textfield) - } - } - } - - @objc open func entryIsInvalid(_ textfield: MFTextField?) { - DispatchQueue.main.async { - if self.parentViewContoller?.responds(to: #selector(MFTextFieldDelegate.entryIsInvalid(_:))) ?? false { - self.parentViewContoller?.entryIsInvalid(textfield) - } - } - } -} diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m index e770ede5..2bc1a0dd 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m @@ -19,7 +19,6 @@ static NSMutableDictionary *viewControllerMapping; dispatch_once(&onceToken, ^{ viewControllerMapping = [@{ - @"textFieldListForm" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[TextFieldListFormViewController class]], @"moleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackTemplate class]], @"centerMoleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackCenteredTemplate class]], @"moleculeList" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeListTemplate class]], diff --git a/MVMCoreUI/Templates/TextFieldListFormViewController.swift b/MVMCoreUI/Templates/TextFieldListFormViewController.swift deleted file mode 100644 index bf3b0bea..00000000 --- a/MVMCoreUI/Templates/TextFieldListFormViewController.swift +++ /dev/null @@ -1,52 +0,0 @@ -// -// MVMCoreUITextFormViewController.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 1/24/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import UIKit - -public class TextFieldListFormViewController: TopLabelsAndBottomButtonsViewController { - - - public var textFieldListView: MFTextFieldListView? - - public override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view. - } - - public override func updateViews() { - super.updateViews() - } - - public override func newDataBuildScreen() { - super.newDataBuildScreen() - topLabelsView?.separatorView?.isHidden = true - } - - public override func buildViewsBetweenLabelsAndButtons() -> [UIView]? { - var viewList: [UIView] = [] - - if let textFieldsList = loadObject?.pageJSON?.arrayForKey("textFieldList") as? [[String: Any]] { - let textFieldListView = MFTextFieldListView(textFieldMapList: textFieldsList, - parentViewContoller: self, - primaryButton: self.primaryButton) - self.textFieldListView = textFieldListView - viewList.append(textFieldListView) - } - return viewList - } - - public override func handleOpenPage(for requestParameters: MVMCoreRequestParameters, actionInformation: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?) { - textFieldListView?.addParams(requestParameters: requestParameters) - super.handleOpenPage(for: requestParameters, actionInformation: actionInformation, additionalData: additionalData) - } - - public override func spaceAboveBetweenView() -> NSNumber? { - return PaddingFour as NSNumber - } - -}