diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index fcbd1272..b54ad255 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -46,6 +46,8 @@ 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */; }; 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; }; 0ABD136B237B193A0081388D /* FormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD136A237B193A0081388D /* FormView.swift */; }; + 0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */; }; + 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */; }; 943784F5236B77BB006A1E82 /* GraphView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* GraphView.swift */; }; 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */; }; 9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */; }; @@ -239,6 +241,8 @@ 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxWithLabelView.swift; sourceTree = ""; }; 0A8321AE2355FE9500CB7F00 /* DigitBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitBox.swift; sourceTree = ""; }; 0ABD136A237B193A0081388D /* FormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormView.swift; sourceTree = ""; }; + 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryField.swift; sourceTree = ""; }; + 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDropdownEntryField.swift; sourceTree = ""; }; 943784F3236B77BB006A1E82 /* GraphView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphView.swift; sourceTree = ""; }; 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphViewAnimationHandler.swift; sourceTree = ""; }; 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MVMAnimationFramework.framework; path = ../SharedFrameworks/MVMAnimationFramework.framework; sourceTree = ""; }; @@ -804,6 +808,8 @@ 0A21DB82235DFBC500C160A2 /* MdnEntryField.swift */, 0A21DB93235E24ED00C160A2 /* DigitEntryField.swift */, 0A6BF4712360C56C0028F841 /* DropdownEntryField.swift */, + 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */, + 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */, ); path = TextFields; sourceTree = ""; @@ -1115,6 +1121,7 @@ D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */, 01509D952327ED1900EF99AA /* HeadlineBodyTextButtonSwitch.swift in Sources */, D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */, + 0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */, D28B4F8B21FF967C00712C7A /* MVMCoreUIObject.m in Sources */, 0A1B4A96233BB18F005B3FB4 /* CheckboxWithLabelView.swift in Sources */, 0A21DB8B235E06EF00C160A2 /* MFDigitTextBox.m in Sources */, @@ -1148,6 +1155,7 @@ D29DF29521E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m in Sources */, D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */, D29DF16121E69996003B2FB9 /* MFViewController.m in Sources */, + 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */, D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */, DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */, 0A21DB89235E06EF00C160A2 /* MFMdnTextField.m in Sources */, diff --git a/MVMCoreUI/Atoms/TextFields/DateDropdownEntryField.swift b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryField.swift new file mode 100644 index 00000000..e2f5b9f2 --- /dev/null +++ b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryField.swift @@ -0,0 +1,107 @@ +// +// DateDropdownEntryField.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 11/13/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + + +class DateDropdownEntryField: DropdownEntryField { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public weak var datePicker: UIDatePicker? + + private var calendar: Calendar = { + var calendar: Calendar = .current + calendar.timeZone = NSTimeZone.system + return calendar + }() + + // TODO: Pull this out into Styler or some class akin to it. + public var formatter: DateFormatter = { + + let formatter = DateFormatter() + formatter.dateStyle = .medium + formatter.timeZone = NSTimeZone.system + formatter.locale = .current + formatter.formatterBehavior = .default + + return formatter + }() + + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + + public override init(frame: CGRect) { + super.init(frame: frame) + + MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: textField.delegate) + datePicker = MVMCoreUICommonViewsUtility.addDatePicker(to: textField) + datePicker?.timeZone = NSTimeZone.system + } + + public convenience init() { + self.init(frame: .zero) + } + + public convenience init(startDate: Date, endDate: Date, showStartDate: Bool = true) { + self.init(frame: .zero) + + setDatePickerDuration(from: startDate, to: endDate, showStartDate: showStartDate) + } + + required public init?(coder: NSCoder) { + super.init(coder: coder) + fatalError("DateDropdownEntryField does not support xib.") + } + + //-------------------------------------------------- + // MARK: - Methods + //-------------------------------------------------- + + public func setDatePickerDuration(from startDate: Date?, to endDate: Date?, showStartDate: Bool = true) { + + datePicker?.minimumDate = startDate + datePicker?.maximumDate = endDate + + if showStartDate { + setTextWith(date: startDate) + } + } + + public func dismissDatePicker() -> Date? { + + let pickedDate = datePicker?.date + setTextWith(date: pickedDate) + + textField.resignFirstResponder() + return pickedDate + } + + private func setTextWith(date: Date?) { + + guard let date = date else { return } + + if calendar.isDate(date, inSameDayAs: Date()) { + text = MVMCoreUIUtility.hardcodedString(withKey: "textfield_today_string") + } else { + text = formatter.string(from: date) + } + } +} + +// MARK: - Molecular +extension DateDropdownEntryField { + + override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + + guard let dictionary = json, !dictionary.isEmpty else { return } + } +} diff --git a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift index 8a46a994..fe8340e0 100644 --- a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift @@ -294,31 +294,17 @@ import UIKit } } - //-------------------------------------------------- - // MARK: - Molecule - //-------------------------------------------------- - - open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + class func getEnabledTextfields(_ textFieldToDetermine: [TextEntryField]?) -> [AnyHashable]? { - guard let dictionary = json else { return } + var enabledTextFields = [AnyHashable]() - let digits = dictionary["digits"] as? Int ?? 4 - if digits != numberOfDigits { - numberOfDigits = digits - } - - if !dictionary.isEmpty{ - for digitBox in digitFields { - MVMCoreUICommonViewsUtility.addDismissToolbar(digitBox.digitField, delegate: delegateObject as? UITextFieldDelegate) + for textfield in textFieldToDetermine ?? [] { + if textfield.isEnabled { + enabledTextFields.append(textfield) } } - setupDigitFieldsView(size: MVMCoreUIUtility.getWidth()) - } - - open override class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { - return 44 + return enabledTextFields } //-------------------------------------------------- @@ -409,3 +395,30 @@ import UIKit return uiTextFieldDelegate?.textFieldShouldEndEditing?(textField) ?? true } } + +// MARK: - Molecular +extension DigitEntryField { + + open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + + guard let dictionary = json else { return } + + let digits = dictionary["digits"] as? Int ?? 4 + if digits != numberOfDigits { + numberOfDigits = digits + } + + if !dictionary.isEmpty{ + for digitBox in digitFields { + MVMCoreUICommonViewsUtility.addDismissToolbar(digitBox.digitField, delegate: delegateObject as? UITextFieldDelegate) + } + } + + setupDigitFieldsView(size: MVMCoreUIUtility.getWidth()) + } + + open override class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + return 44 + } +} diff --git a/MVMCoreUI/Atoms/TextFields/DropdownEntryField.swift b/MVMCoreUI/Atoms/TextFields/DropdownEntryField.swift index 951b0a1f..c36834c5 100644 --- a/MVMCoreUI/Atoms/TextFields/DropdownEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/DropdownEntryField.swift @@ -24,33 +24,18 @@ import UIKit return caret }() - //-------------------------------------------------- - // MARK: - Accessories - //-------------------------------------------------- - public weak var datePicker: UIDatePicker? - private var calendar: Calendar? - - //-------------------------------------------------- - // MARK: - Properties - //-------------------------------------------------- - - public var dropDownIsDisplayed = false //-------------------------------------------------- // MARK: - Property Observers //-------------------------------------------------- public override var isEnabled: Bool { - didSet { showDropDown(isEnabled) } + didSet { + dropDownCaretView.isEnabled = isEnabled + } } - //-------------------------------------------------- - // MARK: - Constraints - //-------------------------------------------------- - - public var dropDownCaretWidth: NSLayoutConstraint? - //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- @@ -63,14 +48,6 @@ import UIKit self.init(frame: .zero) } - /// - parameter bothDelegates: Sets both MF/UI Text Field Delegates. - public override init(bothDelegates: (UITextFieldDelegate & TextFieldDelegate)?) { - super.init(frame: .zero) - - MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: bothDelegates) - setBothTextDelegates(to: bothDelegates) - } - required public init?(coder: NSCoder) { super.init(coder: coder) fatalError("DropdownEntryField does not support xib.") @@ -89,6 +66,7 @@ import UIKit dropDownCaretView.topAnchor.constraint(greaterThanOrEqualTo: container.topAnchor, constant: 13).isActive = true textFieldTrailingConstraint = dropDownCaretView.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 6) textFieldTrailingConstraint?.isActive = true + container.trailingAnchor.constraint(equalTo: dropDownCaretView.trailingAnchor, constant: 16).isActive = true container.bottomAnchor.constraint(greaterThanOrEqualTo: dropDownCaretView.bottomAnchor, constant: 13).isActive = true @@ -97,103 +75,8 @@ import UIKit let caretTap = UITapGestureRecognizer(target: self, action: #selector(startEditing)) dropDownCaretView.addGestureRecognizer(caretTap) } - - //-------------------------------------------------- - // MARK: - Methods - //-------------------------------------------------- - - public func showDropDown(_ show: Bool) { - - dropDownCaretView.isHidden = !show - dropDownCaretWidth?.isActive = !show - setNeedsLayout() - layoutIfNeeded() - } - - //-------------------------------------------------- - // MARK: - Observing for change - //-------------------------------------------------- - - override func startEditing() { - super.startEditing() - - showDropDown(!showError) - } - - class func getEnabledTextfields(_ textFieldToDetermine: [TextEntryField]?) -> [AnyHashable]? { - - var enabledTextFields = [AnyHashable]() - - for textfield in textFieldToDetermine ?? [] { - if textfield.isEnabled { - enabledTextFields.append(textfield) - } - } - - return enabledTextFields - } } -// MARK: - Date Picker -extension DropdownEntryField { - - private func createDatePicker() { - - MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: textField.delegate) - datePicker = MVMCoreUICommonViewsUtility.addDatePicker(to: textField) - - var calendar: Calendar = .current - calendar.timeZone = NSTimeZone.system - self.calendar = calendar - } - - public func inputFromDatePicker(from fromDate: Date?, to toDate: Date?, showFromDateAsDefaultInput show: Bool) { - - createDatePicker() - - if show, let fromDate = fromDate { - if let calendar = calendar, calendar.isDate(fromDate, inSameDayAs: Date()) { - text = MVMCoreUIUtility.hardcodedString(withKey: "textfield_today_string") - } else { - text = formatter.string(from: fromDate) - } - } - - datePicker?.minimumDate = fromDate - datePicker?.maximumDate = toDate - } - - public func setDatePickerFrom(_ fromDate: Date?, to toDate: Date?) { - - if let fromDate = fromDate { - if let calendar = calendar, calendar.isDate(fromDate, inSameDayAs: Date()) { - text = MVMCoreUIUtility.hardcodedString(withKey: "textfield_today_string") - } else { - text = formatter.string(from: fromDate) - } - } - - datePicker?.minimumDate = fromDate - datePicker?.maximumDate = toDate - datePicker?.timeZone = NSTimeZone.system - } - - public func dismissDatePicker() -> Date? { - - let pickedDate = datePicker?.date - - if let pickedDate = pickedDate { - if let calendar = calendar, calendar.isDate(pickedDate, inSameDayAs: Date()) { - text = MVMCoreUIUtility.hardcodedString(withKey: "textfield_today_string") - } else { - text = formatter.string(from: pickedDate) - } - } - - textField.resignFirstResponder() - return pickedDate - } -} // MARK: - Molecular extension DropdownEntryField { @@ -216,11 +99,8 @@ extension DropdownEntryField { var accessibilityString = accessibilityString ?? "" - if dropDownIsDisplayed, let textPickerItem = MVMCoreUIUtility.hardcodedString(withKey: "textfield_picker_item") { + if let textPickerItem = MVMCoreUIUtility.hardcodedString(withKey: "textfield_picker_item") { accessibilityString += textPickerItem - - } else if let txtRegular = MVMCoreUIUtility.hardcodedString(withKey: "textfield_regular") { - accessibilityString += txtRegular } textField.accessibilityLabel = "\(accessibilityString) \(textField.isEnabled ? "" : MVMCoreUIUtility.hardcodedString(withKey: "textfield_disabled_state") ?? "")" diff --git a/MVMCoreUI/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atoms/TextFields/EntryField.swift index 64cde29c..63c506cc 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryField.swift @@ -135,18 +135,6 @@ import UIKit } } - // TODO: Pull this out into Styler or some class akin to it. - public var formatter: DateFormatter = { - - let formatter = DateFormatter() - formatter.dateStyle = .medium - formatter.timeZone = NSTimeZone.system - formatter.locale = .current - formatter.formatterBehavior = .default - - return formatter - }() - //-------------------------------------------------- // MARK: - Constraints //-------------------------------------------------- diff --git a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift new file mode 100644 index 00000000..44982d4d --- /dev/null +++ b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift @@ -0,0 +1,62 @@ +// +// ItemDropdownEntryField.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 11/14/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +class ItemDropdownEntryField: DropdownEntryField { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + var pickerData: [String] = [] + var pickerView: UIPickerView? + + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + + public convenience init() { + self.init(frame: .zero) + } + + public convenience init(pickerData: [String]) { + self.init(frame: .zero) + + pickerView = MVMCoreUICommonViewsUtility.addPicker(to: textField, delegate: self) + } +} + +// MARK:- Base Picker Delegate +extension ItemDropdownEntryField: UIPickerViewDelegate, UIPickerViewDataSource { + + public func numberOfComponents(in pickerView: UIPickerView) -> Int { + return 1 + } + + public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { + return pickerData.count + } + + public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { + return pickerData[row] + } + + public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { + textField.text = pickerData[row] + } +} + +// MARK: - Molecular +extension ItemDropdownEntryField { + + override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + + guard let dictionary = json, !dictionary.isEmpty else { return } + } +} diff --git a/MVMCoreUI/Atoms/Views/CaretView.swift b/MVMCoreUI/Atoms/Views/CaretView.swift index 70056219..aa1ad8e3 100644 --- a/MVMCoreUI/Atoms/Views/CaretView.swift +++ b/MVMCoreUI/Atoms/Views/CaretView.swift @@ -22,6 +22,10 @@ public var enabledColor: UIColor = .black public var disabledColor: UIColor = .mfSilver() + //------------------------------------------------------ + // MARK: - Property Observer + //------------------------------------------------------ + public var isEnabled: Bool = true { didSet { strokeColor = isEnabled ? enabledColor : disabledColor @@ -39,7 +43,7 @@ case medium(Orientation) case large(Orientation) - /// Orientation based on the longest line of the view + /// Orientation based on the longest line of the view. public enum Orientation { case vertical case horizontal