diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 9215b753..97e84a3c 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -85,6 +85,8 @@ D260D7B122D65BDD007E7233 /* MVMCoreUIPageControl.h in Headers */ = {isa = PBXBuildFile; fileRef = D260D7AF22D65BDD007E7233 /* MVMCoreUIPageControl.h */; settings = {ATTRIBUTES = (Public, ); }; }; D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */ = {isa = PBXBuildFile; fileRef = D260D7B022D65BDD007E7233 /* MVMCoreUIPageControl.m */; }; D260D7B622D68514007E7233 /* MVMCoreUIPagingProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */; }; + D268C712238D6699007F2C1C /* DropDown.swift in Sources */ = {isa = PBXBuildFile; fileRef = D268C711238D6699007F2C1C /* DropDown.swift */; }; D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368A23609801006832FA /* MoleculeStackItemModel.swift */; }; D274CA332236A78900B01B62 /* StandardFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D274CA322236A78900B01B62 /* StandardFooterView.swift */; }; D2755D7B23689C7500485468 /* TableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2755D7A23689C7500485468 /* TableViewCell.swift */; }; @@ -318,6 +320,8 @@ D260D7AF22D65BDD007E7233 /* MVMCoreUIPageControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIPageControl.h; sourceTree = ""; }; D260D7B022D65BDD007E7233 /* MVMCoreUIPageControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIPageControl.m; sourceTree = ""; }; D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIPagingProtocol.h; sourceTree = ""; }; + D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropDownFilterTableViewCell.swift; sourceTree = ""; }; + D268C711238D6699007F2C1C /* DropDown.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropDown.swift; sourceTree = ""; }; D274CA322236A78900B01B62 /* StandardFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StandardFooterView.swift; sourceTree = ""; }; D2755D7A23689C7500485468 /* TableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewCell.swift; sourceTree = ""; }; D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsTableViewCell.swift; sourceTree = ""; }; @@ -589,6 +593,12 @@ D29DF31F21ED0CBA003B2FB9 /* LabelView.m */, D29DF15921E697DA003B2FB9 /* SeparatorView.h */, D29DF15A21E697DA003B2FB9 /* SeparatorView.m */, + D22D1F1C220343560077CEC0 /* MVMCoreUICheckMarkView.h */, + D22D1F1D220343560077CEC0 /* MVMCoreUICheckMarkView.m */, + D22D1F18220341F50077CEC0 /* MVMCoreUICheckBox.h */, + D22D1F19220341F50077CEC0 /* MVMCoreUICheckBox.m */, + 0198F7A02256A80A0066C936 /* MFRadioButton.h */, + 0198F7A22256A80A0066C936 /* MFRadioButton.m */, ); path = Views; sourceTree = ""; @@ -648,6 +658,7 @@ D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */, D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */, D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */, + D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */, ); path = Items; sourceTree = ""; @@ -904,23 +915,18 @@ D29DF2AD21E7B3A4003B2FB9 /* MFTextView.h */, D29DF2AB21E7B3A4003B2FB9 /* MFTextView.m */, D29DF2AC21E7B3A4003B2FB9 /* MFTextView.xib */, + D268C711238D6699007F2C1C /* DropDown.swift */, D29DF2B121E7B76C003B2FB9 /* MFLoadingSpinner.h */, D29DF2B221E7B76D003B2FB9 /* MFLoadingSpinner.m */, D29DF32321ED0DA2003B2FB9 /* TextButtonView.h */, D29DF32221ED0DA2003B2FB9 /* TextButtonView.m */, D29770FB21F7C77400B2F0D0 /* MVMCoreUITextFieldView.h */, D29770FA21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m */, - D22D1F1C220343560077CEC0 /* MVMCoreUICheckMarkView.h */, - D22D1F1D220343560077CEC0 /* MVMCoreUICheckMarkView.m */, - D22D1F18220341F50077CEC0 /* MVMCoreUICheckBox.h */, - D22D1F19220341F50077CEC0 /* MVMCoreUICheckBox.m */, D22D1F44220496A30077CEC0 /* MVMCoreUISwitch.h */, D22D1F45220496A30077CEC0 /* MVMCoreUISwitch.m */, DBC4391C2245232D001AB423 /* LabelWithInternalButton.swift */, DB891E822253FA8500022516 /* Label.swift */, - 94C2D9822386F3E30006CF46 /* LabelModel */, - 0198F7A02256A80A0066C936 /* MFRadioButton.h */, - 0198F7A22256A80A0066C936 /* MFRadioButton.m */, + 94C2D9822386F3E30006CF46 /* LabelModel */, 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */, 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */, 01004F2F22721C3800991ECC /* RadioButton.swift */, @@ -1232,6 +1238,7 @@ D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */, D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */, 01004F3022721C3800991ECC /* RadioButton.swift in Sources */, + D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */, 017BEB3C2361EA1D0024EF95 /* MFViewController+Model.swift in Sources */, D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */, D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */, @@ -1344,6 +1351,7 @@ D29DF25121E6A177003B2FB9 /* MFDigitTextBox.m in Sources */, DBC4391B224421A0001AB423 /* CaretButton.swift in Sources */, 0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */, + D268C712238D6699007F2C1C /* DropDown.swift in Sources */, 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */, D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */, D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */, diff --git a/MVMCoreUI/Atoms/TextFields/MFTextField.h b/MVMCoreUI/Atoms/TextFields/MFTextField.h index 8ccbe22e..aa3ab573 100644 --- a/MVMCoreUI/Atoms/TextFields/MFTextField.h +++ b/MVMCoreUI/Atoms/TextFields/MFTextField.h @@ -74,6 +74,7 @@ //default error message @property (nullable, strong, nonatomic) NSString *errMessage; +@property (nullable, strong, nonatomic) IBOutlet NSLayoutConstraint *errorHeightConstraint; @property (nullable, copy, nonatomic) void (^editCompleteAction)(NSString * _Nullable text); diff --git a/MVMCoreUI/Atoms/TextFields/MFTextField.m b/MVMCoreUI/Atoms/TextFields/MFTextField.m index cfef9090..fec796bf 100644 --- a/MVMCoreUI/Atoms/TextFields/MFTextField.m +++ b/MVMCoreUI/Atoms/TextFields/MFTextField.m @@ -558,6 +558,7 @@ #pragma mark - MVMCoreUIMoleculeViewProtocol - (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { + [super setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; if ([delegateObject isKindOfClass:[MVMCoreUIDelegateObject class]]) { [FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol]; FormValidator *formValidator = [FormValidator getFormValidatorForDelegate:delegateObject.formValidationProtocol]; diff --git a/MVMCoreUI/Atoms/TextFields/MFTextField.xib b/MVMCoreUI/Atoms/TextFields/MFTextField.xib index cb9821f1..c11beb5c 100644 --- a/MVMCoreUI/Atoms/TextFields/MFTextField.xib +++ b/MVMCoreUI/Atoms/TextFields/MFTextField.xib @@ -1,11 +1,9 @@ - - - - + + - + @@ -15,6 +13,7 @@ + diff --git a/MVMCoreUI/Atoms/Views/DropDown.swift b/MVMCoreUI/Atoms/Views/DropDown.swift new file mode 100644 index 00000000..929bd67f --- /dev/null +++ b/MVMCoreUI/Atoms/Views/DropDown.swift @@ -0,0 +1,55 @@ +// +// DropDown.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 11/26/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +@objcMembers public class DropDown: MFTextField { + let picker = MVMCoreUICommonViewsUtility.commonPickerView()! + + public override func getNib() -> UINib? { + return UINib(nibName: String(describing: MFTextField.self), bundle: MVMCoreUIUtility.bundleForMVMCoreUI()) + } + + public override func setupView() { + super.setupView() + dropDownCarrotWidth?.isActive = false + errorHeightConstraint?.constant = 0 + } + + override public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + guard let textField = textField, textField.inputView == nil else { return } + picker.delegate = self + picker.dataSource = self + picker.tag = textField.tag + textField.inputView = picker + picker.reloadAllComponents() + MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: delegateObject?.uiTextFieldDelegate) + textField.text = json?.stringWithChainOfKeysOrIndexes(["options",picker.selectedRow(inComponent: 0)]) + } +} + +extension DropDown: UIPickerViewDelegate { + public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { + return json?.stringWithChainOfKeysOrIndexes(["options",row]) + } + + public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { + textField?.text = json?.stringWithChainOfKeysOrIndexes(["options",row]) + } +} + +extension DropDown: UIPickerViewDataSource { + public func numberOfComponents(in pickerView: UIPickerView) -> Int { + return 1 + } + + public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { + return json?.optionalArrayForKey("options")?.count ?? 0 + } +} diff --git a/MVMCoreUI/Atoms/Views/GraphView.swift b/MVMCoreUI/Atoms/Views/GraphView.swift index 0a828259..ca63c67f 100644 --- a/MVMCoreUI/Atoms/Views/GraphView.swift +++ b/MVMCoreUI/Atoms/Views/GraphView.swift @@ -93,8 +93,8 @@ public struct GraphObject { mutating func updateSize() { switch size { case .small: - diameter = MFSizeObject(standardSize: 24)?.getValueBasedOnApplicationWidth() ?? 24 - lineWidth = MFSizeObject(standardSize: 5)?.getValueBasedOnApplicationWidth() ?? 5 + diameter = MFSizeObject(standardSize: 20)?.getValueBasedOnApplicationWidth() ?? 20 + lineWidth = MFSizeObject(standardSize: 4)?.getValueBasedOnApplicationWidth() ?? 4 break case .medium: diameter = MFSizeObject(standardSize: 100)?.getValueBasedOnApplicationWidth() ?? 100 diff --git a/MVMCoreUI/Atoms/Views/Label.swift b/MVMCoreUI/Atoms/Views/Label.swift index 388f40cb..ca112b9a 100644 --- a/MVMCoreUI/Atoms/Views/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label.swift @@ -319,9 +319,12 @@ public typealias ActionBlock = () -> () } @objc public static func setUILabel(_ label: UILabel?, withJSON json: [AnyHashable: Any]?, delegate: DelegateObject?, additionalData: [AnyHashable: Any]?) { - guard let label = label else { return } - label.attributedText = nil + + // Some properties can only be set on Label. + // Label fonts should not be scaled because it will be scaled in updateView. + let mvmLabel = label as? Label + label.text = json?.optionalStringForKey(KeyText) setLabel(label, withHTML: json?.optionalStringForKey("html")) @@ -337,9 +340,7 @@ public typealias ActionBlock = () -> () } } - if let wholeViewIsClickable = json?.boolForKey("makeWholeViewClickable") { - (label as? Label)?.makeWholeViewClickable = wholeViewIsClickable - } + mvmLabel?.makeWholeViewClickable = json?.boolForKey("makeWholeViewClickable") ?? false if let backgroundColorHex = json?.optionalStringForKey(KeyBackgroundColor), !backgroundColorHex.isEmpty { label.backgroundColor = UIColor.mfGet(forHex: backgroundColorHex) @@ -348,12 +349,16 @@ public typealias ActionBlock = () -> () label.accessibilityLabel = json?.optionalStringForKey("accessibilityText") if let fontStyle = json?.optionalStringForKey("fontStyle") { - MFStyler.styleLabel(label, withStyle: fontStyle) + MFStyler.styleLabel(label, withStyle: fontStyle, genericScaling: mvmLabel == nil) + mvmLabel?.standardFontSize = label.font.pointSize } else { let fontSize = json?["fontSize"] as? CGFloat + if let fontSize = fontSize { + mvmLabel?.standardFontSize = fontSize + } if let fontName = json?.optionalStringForKey("fontName") { - label.font = MFFonts.mfFont(withName: fontName, size: fontSize ?? label.font.pointSize) + label.font = MFFonts.mfFont(withName: fontName, size: fontSize ?? mvmLabel?.standardFontSize ?? label.font.pointSize) } else if let fontSize = fontSize { label.font = label.font.withSize(fontSize) } @@ -363,8 +368,8 @@ public typealias ActionBlock = () -> () label.textColor = UIColor.mfGet(forHex: textColorHex) } - if let attributes = json?.arrayForKey("attributes"), let labelText = label.text { - let attributedString = NSMutableAttributedString(string: labelText, attributes: [NSAttributedString.Key.font: label.font as UIFont, + if let attributes = json?.optionalArrayForKey("attributes"), let labelText = label.text { + let attributedString = NSMutableAttributedString(string: labelText, attributes: [NSAttributedString.Key.font: mvmLabel?.font.withSize(mvmLabel!.standardFontSize) ?? label.font as UIFont, NSAttributedString.Key.foregroundColor: label.textColor as UIColor]) for case let attribute as [String: Any] in attributes { guard let attributeType = attribute.optionalStringForKey(KeyType), @@ -405,7 +410,7 @@ public typealias ActionBlock = () -> () case "font": if let fontStyle = attribute.optionalStringForKey("style") { - let styles = MFStyler.styleGetAttributedString("0", withStyle: fontStyle) + let styles = MFStyler.styleGetAttributedString("0", withStyle: fontStyle, genericScaling: mvmLabel == nil) attributedString.removeAttribute(.font, range: range) attributedString.removeAttribute(.foregroundColor, range: range) attributedString.addAttributes(styles.attributes(at: 0, effectiveRange: nil), range: range) @@ -414,7 +419,7 @@ public typealias ActionBlock = () -> () var font: UIFont? if let fontName = attribute.optionalStringForKey("name") { - font = MFFonts.mfFont(withName: fontName, size: fontSize ?? label.font.pointSize) + font = MFFonts.mfFont(withName: fontName, size: fontSize ?? mvmLabel?.standardFontSize ?? label.font.pointSize) } else if let fontSize = fontSize { font = label.font.withSize(fontSize) } @@ -437,6 +442,7 @@ public typealias ActionBlock = () -> () } } label.attributedText = attributedString + mvmLabel?.originalAttributedString = attributedString } } @@ -526,7 +532,7 @@ public typealias ActionBlock = () -> () if let floatScale = scaleSize?.floatValue { updateView(CGFloat(floatScale)) } else { - updateView(MVMCoreUISplitViewController.getApplicationViewWidth()) + updateView(MVMCoreUIUtility.getWidth()) } } else { standardFontSize = 0 @@ -688,8 +694,6 @@ extension Label { @objc public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { clauses = [] Label.setUILabel(self, withJSON: json, delegate: delegateObject, additionalData: additionalData) - originalAttributedString = attributedText - hero = json?["hero"] as? Int } diff --git a/MVMCoreUI/Atoms/Views/Line.swift b/MVMCoreUI/Atoms/Views/Line.swift index f7a81ac5..d5f4f4b6 100644 --- a/MVMCoreUI/Atoms/Views/Line.swift +++ b/MVMCoreUI/Atoms/Views/Line.swift @@ -38,8 +38,6 @@ import UIKit case .none: heightConstraint?.constant = 0 } - setNeedsLayout() - layoutIfNeeded() } } diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m index 4983020e..1de41832 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m @@ -356,7 +356,6 @@ if (!self.constrainedView) { [super setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; } - [self.molecule setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; if (self.shouldSetupMoleculeFromJSON) { NSDictionary *moleculeJSON = [json dict:KeyMolecule]; if (self.molecule) { diff --git a/MVMCoreUI/BaseControllers/MFScrollingViewController.m b/MVMCoreUI/BaseControllers/MFScrollingViewController.m index 56019cb7..67e01d93 100644 --- a/MVMCoreUI/BaseControllers/MFScrollingViewController.m +++ b/MVMCoreUI/BaseControllers/MFScrollingViewController.m @@ -91,7 +91,7 @@ static NSTimeInterval const HandScrollAnimationTiming = 7.f; - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; - BOOL automaticInset = self.navigationController && self.scrollView.contentInsetAdjustmentBehavior == UIScrollViewContentInsetAdjustmentAutomatic; + BOOL automaticInset = self.scrollView.contentInsetAdjustmentBehavior == UIScrollViewContentInsetAdjustmentAutomatic; // Takes into account the navigation bar. if (!automaticInset && (self.edgesForExtendedLayout & UIRectEdgeTop)) { diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUIDetailViewProtocol.h b/MVMCoreUI/Containers/SplitViewController/MVMCoreUIDetailViewProtocol.h index 038769fb..377508c7 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUIDetailViewProtocol.h +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUIDetailViewProtocol.h @@ -16,7 +16,9 @@ NS_ASSUME_NONNULL_BEGIN @optional - (void)panelWillAppear:(nonnull NSObject *)panel; +- (void)panelWillAppear:(nonnull NSObject *)panel overtakingDetail:(BOOL)willOvertake; - (void)panelDidAppear:(nonnull NSObject *)panel; +- (void)panelDidAppear:(nonnull NSObject *)panel overtakingDetail:(BOOL)didOvertake; - (void)panelWillDisappear:(nonnull NSObject *)panel; - (void)panelDidDisappear:(nonnull NSObject *)panel; diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m index b529ac19..b5177b9b 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m @@ -357,16 +357,19 @@ CGFloat const PanelAnimationDuration = 0.2; - (void)showLeftPanelAnimated:(BOOL)animated explict:(BOOL)explict { [MVMCoreDispatchUtility performBlockOnMainThread:^{ if (self.mainViewLeading.constant < .1) { + BOOL shouldExtendLeftPanel = [self shouldExtendLeftPanel]; + if (explict) { self.explictlyShowingPanel = self.leftPanel; } + void (^animations)(void) = [self getLeftPanelShowAnimationBlock]; void (^completion)(BOOL) = ^(BOOL finished){ - [self panelDidAppear:self.leftPanel animated:animated]; + [self panelDidAppear:self.leftPanel didExtend:shouldExtendLeftPanel animated:animated]; }; - if (![self shouldExtendLeftPanel]) { + if (!shouldExtendLeftPanel) { if ([self.leftPanel respondsToSelector:@selector(showArrow)]){ [self.leftPanel showArrow]; } @@ -389,7 +392,7 @@ CGFloat const PanelAnimationDuration = 0.2; } self.mainViewCoverView.hidden = NO; - [self panelWillAppear:self.leftPanel animated:animated]; + [self panelWillAppear:self.leftPanel willExtend:shouldExtendLeftPanel animated:animated]; if (animated) { [UIView animateWithDuration:PanelAnimationDuration delay:0 options:UIViewAnimationOptionCurveLinear animations:animations completion:completion]; } else { @@ -547,19 +550,22 @@ CGFloat const PanelAnimationDuration = 0.2; - (void)showRightPanelAnimated:(BOOL)animated explict:(BOOL)explict { [MVMCoreDispatchUtility performBlockOnMainThread:^{ if (self.mainViewTrailing.constant < .1) { + BOOL shouldExtendRightPanel = [self shouldExtendRightPanel]; + if (explict) { self.explictlyShowingPanel = self.rightPanel; } + void (^animations)(void) = [self getRightPanelShowAnimationBlock]; void (^completion)(BOOL) = ^(BOOL finished){ - [self panelDidAppear:self.rightPanel animated:animated]; + [self panelDidAppear:self.rightPanel didExtend:shouldExtendRightPanel animated:animated]; self.mainView.accessibilityElementsHidden = YES; UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self.rightPanel); }; self.mainViewCoverView.hidden = NO; - if (![self shouldExtendRightPanel]) { + if (!shouldExtendRightPanel) { if ([self.rightPanel respondsToSelector:@selector(showArrow)]){ [self.rightPanel showArrow]; } @@ -579,7 +585,7 @@ CGFloat const PanelAnimationDuration = 0.2; self.rightPanelSeparator = rightPanelSeparator; } - [self panelWillAppear:self.rightPanel animated:animated]; + [self panelWillAppear:self.rightPanel willExtend:shouldExtendRightPanel animated:animated]; if (animated) { [UIView animateWithDuration:PanelAnimationDuration delay:0 options:UIViewAnimationOptionCurveLinear animations:animations completion:completion]; } else { @@ -612,7 +618,7 @@ CGFloat const PanelAnimationDuration = 0.2; [self hideRightPanelIfNeededAnimated:YES]; } -- (void)panelWillAppear:(UIViewController *)panel animated:(BOOL)animated { +- (void)panelWillAppear:(UIViewController *)panel willExtend:(BOOL)willExtend animated:(BOOL)animated { if ([panel respondsToSelector:@selector(willAppear:)]) { [panel willAppear:animated]; } else { @@ -621,13 +627,15 @@ CGFloat const PanelAnimationDuration = 0.2; UIViewController *controller = [self getCurrentDetailViewController]; if ([controller.class conformsToProtocol:@protocol(MVMCoreUIDetailViewProtocol)]) { UIViewController * protocolController = (UIViewController *)controller; - if ([protocolController respondsToSelector:@selector(panelWillAppear:)]) { + if ([protocolController respondsToSelector:@selector(panelWillAppear:overtakingDetail:)]) { + [protocolController panelWillAppear:panel overtakingDetail:!willExtend]; + } else if ([protocolController respondsToSelector:@selector(panelWillAppear:)]) { [protocolController panelWillAppear:panel]; } } } -- (void)panelDidAppear:(UIViewController *)panel animated:(BOOL)animated { +- (void)panelDidAppear:(UIViewController *)panel didExtend:(BOOL)didExtend animated:(BOOL)animated { if ([panel respondsToSelector:@selector(didAppear:)]) { [panel didAppear:animated]; } else { @@ -636,7 +644,9 @@ CGFloat const PanelAnimationDuration = 0.2; UIViewController *controller = [self getCurrentDetailViewController]; if ([controller.class conformsToProtocol:@protocol(MVMCoreUIDetailViewProtocol)]) { UIViewController * protocolController = (UIViewController *)controller; - if ([protocolController respondsToSelector:@selector(panelDidAppear:)]) { + if ([protocolController respondsToSelector:@selector(panelDidAppear:overtakingDetail:)]) { + [protocolController panelDidAppear:panel overtakingDetail:!didExtend]; + } else if ([protocolController respondsToSelector:@selector(panelDidAppear:)]) { [protocolController panelDidAppear:panel]; } } diff --git a/MVMCoreUI/Atoms/Views/MFRadioButton.h b/MVMCoreUI/Legacy/Views/MFRadioButton.h similarity index 100% rename from MVMCoreUI/Atoms/Views/MFRadioButton.h rename to MVMCoreUI/Legacy/Views/MFRadioButton.h diff --git a/MVMCoreUI/Atoms/Views/MFRadioButton.m b/MVMCoreUI/Legacy/Views/MFRadioButton.m similarity index 100% rename from MVMCoreUI/Atoms/Views/MFRadioButton.m rename to MVMCoreUI/Legacy/Views/MFRadioButton.m diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h b/MVMCoreUI/Legacy/Views/MVMCoreUICheckBox.h similarity index 100% rename from MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h rename to MVMCoreUI/Legacy/Views/MVMCoreUICheckBox.h diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m b/MVMCoreUI/Legacy/Views/MVMCoreUICheckBox.m similarity index 100% rename from MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m rename to MVMCoreUI/Legacy/Views/MVMCoreUICheckBox.m diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckMarkView.h b/MVMCoreUI/Legacy/Views/MVMCoreUICheckMarkView.h similarity index 100% rename from MVMCoreUI/Atoms/Views/MVMCoreUICheckMarkView.h rename to MVMCoreUI/Legacy/Views/MVMCoreUICheckMarkView.h diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckMarkView.m b/MVMCoreUI/Legacy/Views/MVMCoreUICheckMarkView.m similarity index 100% rename from MVMCoreUI/Atoms/Views/MVMCoreUICheckMarkView.m rename to MVMCoreUI/Legacy/Views/MVMCoreUICheckMarkView.m diff --git a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift new file mode 100644 index 00000000..31a6cc61 --- /dev/null +++ b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift @@ -0,0 +1,70 @@ +// +// DropDownFilterTableViewCell.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 9/6/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +@objcMembers public class DropDownFilterTableViewCell: TableViewCell { + let dropDown = DropDown(forDropDownWithBothDelegates: nil) + var delegateObject: MVMCoreUIDelegateObject? + var previousIndex = NSNotFound + var dropDownSelectionObservation: NSKeyValueObservation? + + // MARK: - MFViewProtocol + override public func setupView() { + super.setupView() + guard let dropDown = dropDown, dropDown.superview == nil else { + return + } + bottomMarginPadding = 0 + + dropDown.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(dropDown) + + NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: dropDown, useMargins: true).values)) + + #warning("Once we have the state manager, we will need to change this logic to only add or remove on user selection...Want to avoid re-use crashes from array size differences") + dropDownSelectionObservation = observe( + \.dropDown?.textField?.text, + options: [.old, .new] + ) { [weak self] object, change in + guard change.newValue != change.oldValue, let self = self, + let options = self.dropDown?.json?.optionalArrayForKey("options") as? [NSString], + let index = options.firstIndex(of: change.newValue!! as NSString), + let moleculesArrays = self.json?.arrayForKey(KeyMolecules) as? [[[AnyHashable: Any]]] else { return } + + if self.previousIndex != NSNotFound { + let previousMolecules = moleculesArrays[self.previousIndex] + self.delegateObject?.moleculeDelegate?.removeMolecules?(previousMolecules, sender: self, animation: .fade) + } + let molecules = moleculesArrays[index] + self.delegateObject?.moleculeDelegate?.addMolecules?(molecules, sender: self, animation: .fade) + self.previousIndex = index + } + } + + public override func updateView(_ size: CGFloat) { + super.updateView(size) + dropDown?.updateView(size) + } + + // MARK: - MoleculeDelegateProtocol + public override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + bottomSeparatorView?.style = .none + self.delegateObject = delegateObject + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + dropDown?.mfTextFieldDelegate = delegateObject?.uiTextFieldDelegate as? MFTextFieldDelegate + dropDown?.uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate + dropDown?.setWithJSON(json?.optionalDictionaryForKey("dropDown"), delegateObject: delegateObject, additionalData: additionalData) + } + + public override func reset() { + super.reset() + bottomMarginPadding = 0 + bottomSeparatorView?.style = .none + } +} diff --git a/MVMCoreUI/Organisms/MoleculeStackView.swift b/MVMCoreUI/Organisms/MoleculeStackView.swift index cafe21b0..dc7cc81e 100644 --- a/MVMCoreUI/Organisms/MoleculeStackView.swift +++ b/MVMCoreUI/Organisms/MoleculeStackView.swift @@ -264,7 +264,7 @@ public class MoleculeStackView: ViewConstrainingView { } else if let previousView = items.last(where: { stackItem in return !stackItem.gone })?.view { - _ = NSLayoutConstraint(pinFirstView: previousView, toSecondView: view, withConstant: spacing, directionVertical: true) + view.topAnchor.constraint(equalTo: previousView.bottomAnchor, constant: spacing).isActive = true } pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: 0) pinView(contentView, toView: view, attribute: .trailing, relation: .equal, priority: .required, constant: 0) @@ -281,7 +281,7 @@ public class MoleculeStackView: ViewConstrainingView { } else if let previousView = items.last(where: { stackItem in return !stackItem.gone })?.view { - _ = NSLayoutConstraint(pinFirstView: previousView, toSecondView: view, withConstant: spacing, directionVertical: false) + view.leftAnchor.constraint(equalTo: previousView.rightAnchor, constant: spacing).isActive = true } pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: 0) pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0) diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 44bb0a56..a7b8e586 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -36,10 +36,11 @@ @"footer": StandardFooterView.class, @"caretView": CaretView.class, @"caretButton": CaretButton.class, - @"textField" : MFTextField.class, - @"digitTextField" : MFDigitTextField.class, - @"checkbox" : Checkbox.class, - @"checkboxWithLabel" : CheckboxWithLabelView.class, + @"textField": MFTextField.class, + @"dropDown": DropDown.class, + @"digitTextField": MFDigitTextField.class, + @"checkbox": Checkbox.class, + @"checkboxWithLabel": CheckboxWithLabelView.class, @"cornerLabels" : CornerLabels.class, @"progressbar": ProgressBar.class, @"circleProgress": GraphView.class, @@ -64,6 +65,7 @@ @"headlineBodyTextButton": HeadlineBodyTextButton.class, @"headlineBodyTextButtonSwitch": HeadlineBodyTextButtonSwitch.class, @"tabsListItem": TabsTableViewCell.class, + @"dropDownListItem": DropDownFilterTableViewCell.class, @"headlineBodyButton": HeadlineBodyButton.class, @"eyebrowHeadlineBodyLink": EyebrowHeadlineBodyLink.class } mutableCopy]; diff --git a/MVMCoreUI/Styles/MFStyler.h b/MVMCoreUI/Styles/MFStyler.h index 5b73c8e2..bdef57ba 100644 --- a/MVMCoreUI/Styles/MFStyler.h +++ b/MVMCoreUI/Styles/MFStyler.h @@ -210,6 +210,7 @@ B3 -> Legal /// Will style the label based on the string. Accepted values, H1, H2, H3, H32, B1, B2, B3, B20 + (void)styleLabel:(nonnull UILabel *)label withStyle:(nullable NSString *)style; ++ (void)styleLabel:(nonnull UILabel *)label withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling; + (void)styleLabelH1:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling; + (void)styleLabelH1:(nonnull UILabel *)label; @@ -258,6 +259,7 @@ B3 -> Legal /// Will style the string based on the string. Accepted values, H1, H2, H3, H32, B1, B2, B3, B20 + (nonnull NSAttributedString *)styleGetAttributedString:(nullable NSString *)string withStyle:(nullable NSString *)style; ++ (nonnull NSAttributedString *)styleGetAttributedString:(nullable NSString *)string withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling; + (nonnull NSAttributedString *)styleGetAttributedString:(nullable NSString *)string font:(nonnull UIFont *)font color:(nonnull UIColor *)color; + (nonnull NSAttributedString *)styleGetH1AttributedString:(nullable NSString *)string; @@ -266,6 +268,14 @@ B3 -> Legal + (nonnull NSAttributedString *)styleGetB1AttributedString:(nullable NSString *)string; + (nonnull NSAttributedString *)styleGetB2AttributedString:(nullable NSString *)string; + (nonnull NSAttributedString *)styleGetB3AttributedString:(nullable NSString *)string; ++ (nonnull NSAttributedString *)styleGetH1AttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; ++ (nonnull NSAttributedString *)styleGetH2AttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; ++ (nonnull NSAttributedString *)styleGetH3AttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; ++ (nonnull NSAttributedString *)styleGetH32AttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; ++ (nonnull NSAttributedString *)styleGetB1AttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; ++ (nonnull NSAttributedString *)styleGetB2AttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; ++ (nonnull NSAttributedString *)styleGetB3AttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; ++ (nonnull NSAttributedString *)styleGetB20AttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling; + (nonnull NSAttributedString *)styleGetDisabledB2AttributedString:(nullable NSString *)string; + (nonnull NSAttributedString *)styleGetDisabledB1AttributedString:(nullable NSString *)string; diff --git a/MVMCoreUI/Styles/MFStyler.m b/MVMCoreUI/Styles/MFStyler.m index 18246f7f..c3dc8946 100644 --- a/MVMCoreUI/Styles/MFStyler.m +++ b/MVMCoreUI/Styles/MFStyler.m @@ -516,26 +516,30 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; #pragma mark - 2.0 Styles -+ (void)styleLabel:(nonnull UILabel *)label withStyle:(nullable NSString *)style { ++ (void)styleLabel:(nonnull UILabel *)label withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling { if ([style isEqualToString:@"H1"]) { - [self styleLabelH1:label]; + [self styleLabelH1:label genericScaling:genericScaling]; } else if ([style isEqualToString:@"H2"]) { - [self styleLabelH2:label]; + [self styleLabelH2:label genericScaling:genericScaling]; } else if ([style isEqualToString:@"H3"]) { - [self styleLabelH3:label]; + [self styleLabelH3:label genericScaling:genericScaling]; } else if ([style isEqualToString:@"H32"]) { - [self styleLabelH32:label]; + [self styleLabelH32:label genericScaling:genericScaling]; } else if ([style isEqualToString:@"B1"]) { - [self styleLabelB1:label]; + [self styleLabelB1:label genericScaling:genericScaling]; } else if ([style isEqualToString:@"B3"]) { - [self styleLabelB3:label]; + [self styleLabelB3:label genericScaling:genericScaling]; } else if ([style isEqualToString:@"B20"]) { - [self styleLabelB20:label]; + [self styleLabelB20:label genericScaling:genericScaling]; } else { - [self styleLabelB2:label]; + [self styleLabelB2:label genericScaling:genericScaling]; } } ++ (void)styleLabel:(nonnull UILabel *)label withStyle:(nullable NSString *)style { + [self styleLabel:label withStyle:style genericScaling:YES]; +} + + (void)styleLabelH1:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling { label.font = [MFStyler fontH1:genericScaling]; label.textColor = [UIColor blackColor]; @@ -656,22 +660,26 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; #pragma mark - Attributed Strings + (nonnull NSAttributedString *)styleGetAttributedString:(nullable NSString *)string withStyle:(nullable NSString *)style { + return [self styleGetAttributedString:string withStyle:style genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetAttributedString:(nullable NSString *)string withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling { if ([style isEqualToString:@"H1"]) { - return [self styleGetH1AttributedString:string]; + return [self styleGetH1AttributedString:string genericScaling:genericScaling]; } else if ([style isEqualToString:@"H2"]) { - return [self styleGetH2AttributedString:string]; + return [self styleGetH2AttributedString:string genericScaling:genericScaling]; } else if ([style isEqualToString:@"H3"]) { - return [self styleGetH3AttributedString:string]; + return [self styleGetH3AttributedString:string genericScaling:genericScaling]; } else if ([style isEqualToString:@"H32"]) { - return [self styleGetH32AttributedString:string]; + return [self styleGetH32AttributedString:string genericScaling:genericScaling]; } else if ([style isEqualToString:@"B1"]) { - return [self styleGetB1AttributedString:string]; + return [self styleGetB1AttributedString:string genericScaling:genericScaling]; } else if ([style isEqualToString:@"B3"]) { - return [self styleGetB3AttributedString:string]; + return [self styleGetB3AttributedString:string genericScaling:genericScaling]; } else if ([style isEqualToString:@"B20"]) { - return [self styleGetB20AttributedString:string]; + return [self styleGetB20AttributedString:string genericScaling:genericScaling]; } else { - return [self styleGetB2AttributedString:string]; + return [self styleGetB2AttributedString:string genericScaling:genericScaling]; } } @@ -690,35 +698,67 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; } + (nonnull NSAttributedString *)styleGetH1AttributedString:(nullable NSString *)string { - return [MFStyler styleGetAttributedString:string font:[MFStyler fontH1] color:[UIColor blackColor]]; + return [MFStyler styleGetH1AttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetH1AttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontH1:genericScaling] color:[UIColor blackColor]]; } + (nonnull NSAttributedString *)styleGetH2AttributedString:(nullable NSString *)string { - return [MFStyler styleGetAttributedString:string font:[MFStyler fontH2] color:[UIColor blackColor]]; + return [MFStyler styleGetH2AttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetH2AttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontH2:genericScaling] color:[UIColor blackColor]]; } + (nonnull NSAttributedString *)styleGetH3AttributedString:(nullable NSString *)string { - return [MFStyler styleGetAttributedString:string font:[MFStyler fontH3] color:[UIColor blackColor]]; + return [MFStyler styleGetH3AttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetH3AttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontH3:genericScaling] color:[UIColor blackColor]]; } + (nonnull NSAttributedString *)styleGetH32AttributedString:(nullable NSString *)string { - return [MFStyler styleGetAttributedString:string font:[MFStyler fontH32] color:[UIColor blackColor]]; + return [MFStyler styleGetH32AttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetH32AttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontH32:genericScaling] color:[UIColor blackColor]]; } + (nonnull NSAttributedString *)styleGetB1AttributedString:(nullable NSString *)string { - return [MFStyler styleGetAttributedString:string font:[MFStyler fontB1] color:[UIColor blackColor]]; + return [MFStyler styleGetB1AttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetB1AttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontB1:genericScaling] color:[UIColor blackColor]]; } + (nonnull NSAttributedString *)styleGetB2AttributedString:(nullable NSString *)string { - return [MFStyler styleGetAttributedString:string font:[MFStyler fontB2] color:[UIColor blackColor]]; + return [MFStyler styleGetB2AttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetB2AttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontB2:genericScaling] color:[UIColor blackColor]]; } + (nonnull NSAttributedString *)styleGetB3AttributedString:(nullable NSString *)string { - return [MFStyler styleGetAttributedString:string font:[MFStyler fontB3] color:[UIColor mfBattleshipGrey]]; + return [MFStyler styleGetB3AttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetB3AttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontB3:genericScaling] color:[UIColor mfBattleshipGrey]]; } + (nonnull NSAttributedString *)styleGetB20AttributedString:(nullable NSString *)string { - return [MFStyler styleGetAttributedString:string font:[MFStyler fontB20] color:[UIColor blackColor]]; + return [MFStyler styleGetB20AttributedString:string genericScaling:YES]; +} + ++ (nonnull NSAttributedString *)styleGetB20AttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling { + return [MFStyler styleGetAttributedString:string font:[MFStyler fontB20:genericScaling] color:[UIColor blackColor]]; } + (nonnull NSAttributedString *)styleGetDisabledB1AttributedString:(nullable NSString *)string {