From 7373667f599e328b37adb4fe2070453a54ed6abd Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 12 Feb 2019 19:22:34 -0500 Subject: [PATCH] Stack view commit --- MVMCoreUI.xcodeproj/project.pbxproj | 28 +++++ .../MVMCoreUIThreeLayerViewController.m | 22 ++-- MVMCoreUI/MVMCoreUI.h | 11 +- MVMCoreUI/Molecules/MVMCoreUIHeaderView.swift | 109 ++++++++++++++++++ .../MVMCoreUIMoleculeStackView.swift | 65 +++++++++++ .../Molecules/MVMCoreUIMoleculeViewProtocol.h | 18 +++ .../MVMCoreUIMoleculeMappingObject.h | 24 ++++ .../MVMCoreUIMoleculeMappingObject.m | 54 +++++++++ MVMCoreUI/OtherHandlers/MVMCoreUIObject.h | 3 + MVMCoreUI/OtherHandlers/MVMCoreUIObject.m | 1 + .../MVMCoreUIViewControllerMappingObject.m | 4 +- ...MCoreUIMoleculeStackCenteredTemplate.swift | 44 +++++++ .../MVMCoreUIMoleculeStackTemplate.swift | 42 +++++++ 13 files changed, 411 insertions(+), 14 deletions(-) create mode 100644 MVMCoreUI/Molecules/MVMCoreUIHeaderView.swift create mode 100644 MVMCoreUI/Molecules/MVMCoreUIMoleculeStackView.swift create mode 100644 MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h create mode 100644 MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.h create mode 100644 MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m create mode 100644 MVMCoreUI/Templates/MVMCoreUIMoleculeStackCenteredTemplate.swift create mode 100644 MVMCoreUI/Templates/MVMCoreUIMoleculeStackTemplate.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index aed43ac1..0d553fdb 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -151,6 +151,13 @@ D29DF32521ED0DA2003B2FB9 /* TextButtonView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF32321ED0DA2003B2FB9 /* TextButtonView.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF32C21EE8736003B2FB9 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D29DF32821EE8736003B2FB9 /* Localizable.strings */; }; D29DF32E21EE8C3D003B2FB9 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D29DF32D21EE8C3D003B2FB9 /* Media.xcassets */; }; + D2A514582211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2A514562211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D2A514592211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2A514572211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m */; }; + D2A5145D2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D2A5145F2211DDC100345BFB /* MVMCoreUIMoleculeStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A5145E2211DDC100345BFB /* MVMCoreUIMoleculeStackView.swift */; }; + D2A5146122121FBF00345BFB /* MVMCoreUIMoleculeStackTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A5146022121FBF00345BFB /* MVMCoreUIMoleculeStackTemplate.swift */; }; + D2A514632213643100345BFB /* MVMCoreUIMoleculeStackCenteredTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514622213643100345BFB /* MVMCoreUIMoleculeStackCenteredTemplate.swift */; }; + D2A514672213885800345BFB /* MVMCoreUIHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514662213885800345BFB /* MVMCoreUIHeaderView.swift */; }; D2C5001821F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */; }; D2C5001D21F8EE67001DA659 /* LabelWithInternalButton.h in Headers */ = {isa = PBXBuildFile; fileRef = D2C5001B21F8EE66001DA659 /* LabelWithInternalButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -306,6 +313,13 @@ D29DF32A21EE8736003B2FB9 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; D29DF32B21EE8736003B2FB9 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/Localizable.strings"; sourceTree = ""; }; D29DF32D21EE8C3D003B2FB9 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = ""; }; + D2A514562211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIMoleculeMappingObject.h; sourceTree = ""; }; + D2A514572211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIMoleculeMappingObject.m; sourceTree = ""; }; + D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIMoleculeViewProtocol.h; sourceTree = ""; }; + D2A5145E2211DDC100345BFB /* MVMCoreUIMoleculeStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIMoleculeStackView.swift; sourceTree = ""; }; + D2A5146022121FBF00345BFB /* MVMCoreUIMoleculeStackTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIMoleculeStackTemplate.swift; sourceTree = ""; }; + D2A514622213643100345BFB /* MVMCoreUIMoleculeStackCenteredTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIMoleculeStackCenteredTemplate.swift; sourceTree = ""; }; + D2A514662213885800345BFB /* MVMCoreUIHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIHeaderView.swift; sourceTree = ""; }; D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewControllerMappingObject.h; sourceTree = ""; }; D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIViewControllerMappingObject.m; sourceTree = ""; }; D2C5001B21F8EE66001DA659 /* LabelWithInternalButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LabelWithInternalButton.h; sourceTree = ""; }; @@ -382,6 +396,8 @@ 01DF566F21FA5AB300CC099B /* MVMCoreUITextFieldListFormViewController.swift */, D29DF0E021E4F3B6003B2FB9 /* MVMCoreUILargeHeaderSingleLabelTemplate.h */, D29DF0E121E4F3B6003B2FB9 /* MVMCoreUILargeHeaderSingleLabelTemplate.m */, + D2A5146022121FBF00345BFB /* MVMCoreUIMoleculeStackTemplate.swift */, + D2A514622213643100345BFB /* MVMCoreUIMoleculeStackCenteredTemplate.swift */, ); path = Templates; sourceTree = ""; @@ -413,6 +429,9 @@ D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */, D29770F621F7C73800B2F0D0 /* PrimaryButtonView.h */, D29770F721F7C73800B2F0D0 /* PrimaryButtonView.m */, + D2A514662213885800345BFB /* MVMCoreUIHeaderView.swift */, + D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */, + D2A5145E2211DDC100345BFB /* MVMCoreUIMoleculeStackView.swift */, ); path = Molecules; sourceTree = ""; @@ -620,6 +639,8 @@ D29DF27421E79E81003B2FB9 /* MVMCoreUILoggingHandler.m */, D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */, D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */, + D2A514562211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h */, + D2A514572211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m */, ); path = OtherHandlers; sourceTree = ""; @@ -703,6 +724,7 @@ D29DF29B21E7ADB9003B2FB9 /* StackableViewController.h in Headers */, D29770F421F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.h in Headers */, D29DF15421E69760003B2FB9 /* MVMCoreUIPanelButtonProtocol.h in Headers */, + D2A514582211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h in Headers */, D29DF0D121E404D4003B2FB9 /* MVMCoreUI.h in Headers */, D29DF29A21E7ADB8003B2FB9 /* MFProgrammaticTableViewController.h in Headers */, D29DF25621E6A177003B2FB9 /* MFTextFieldSubclassExtension.h in Headers */, @@ -736,6 +758,7 @@ D29DF16221E69996003B2FB9 /* MFViewController.h in Headers */, D29DF13121E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.h in Headers */, D29DF2C421E7BF57003B2FB9 /* MFTabBarSwipeAnimator.h in Headers */, + D2A5145D2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h in Headers */, D28B4F8A21FF967C00712C7A /* MVMCoreUIObject.h in Headers */, D29DF2CA21E7BFC8003B2FB9 /* MFSizeThreshold.h in Headers */, D29770F821F7C73800B2F0D0 /* PrimaryButtonView.h in Headers */, @@ -857,12 +880,14 @@ D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */, D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */, 01DF567021FA5AB300CC099B /* MVMCoreUITextFieldListFormViewController.swift in Sources */, + D2A5145F2211DDC100345BFB /* MVMCoreUIMoleculeStackView.swift in Sources */, D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */, D29DF24D21E6A177003B2FB9 /* MFTextField.m in Sources */, D29DF2A221E7AF4E003B2FB9 /* MVMCoreUIUtility.m in Sources */, D29DF12B21E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m in Sources */, D29DF25421E6A177003B2FB9 /* MFMdnTextField.m in Sources */, D29DF26521E6A9D9003B2FB9 /* MFTransparentGIFView.m in Sources */, + D2A514672213885800345BFB /* MVMCoreUIHeaderView.swift in Sources */, D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */, D28B4F8B21FF967C00712C7A /* MVMCoreUIObject.m in Sources */, D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */, @@ -892,6 +917,7 @@ D29DF29821E7ADB8003B2FB9 /* MFScrollingViewController.m in Sources */, D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */, D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */, + D2A5146122121FBF00345BFB /* MVMCoreUIMoleculeStackTemplate.swift in Sources */, D29DF17821E69E1F003B2FB9 /* MFCaretButton.m in Sources */, D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */, D29DF26C21E6AA0B003B2FB9 /* FLAnimatedImage.m in Sources */, @@ -902,8 +928,10 @@ D2C5001E21F8EE67001DA659 /* LabelWithInternalButton.m in Sources */, D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */, D29DF2BE21E7BEA4003B2FB9 /* TopTabbar.m in Sources */, + D2A514632213643100345BFB /* MVMCoreUIMoleculeStackCenteredTemplate.swift in Sources */, D29DF32421ED0DA2003B2FB9 /* TextButtonView.m in Sources */, D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */, + D2A514592211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m in Sources */, D22D1F1B220341F60077CEC0 /* MVMCoreUICheckBox.m in Sources */, D29DF2CB21E7BFCC003B2FB9 /* MFSizeThreshold.m in Sources */, D29770F521F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m in Sources */, diff --git a/MVMCoreUI/BaseControllers/MVMCoreUIThreeLayerViewController.m b/MVMCoreUI/BaseControllers/MVMCoreUIThreeLayerViewController.m index 532515ad..7b9e3398 100644 --- a/MVMCoreUI/BaseControllers/MVMCoreUIThreeLayerViewController.m +++ b/MVMCoreUI/BaseControllers/MVMCoreUIThreeLayerViewController.m @@ -52,7 +52,6 @@ [self updateBottomButtonsPadding:width]; [self.bottomAccessoryView updateView:width]; [self.bottomAccessoryView setPinConstantsWithInsets:[self spaceAroundUIObject:self.bottomAccessoryView size:width]]; - } - (void)updateTopLabelsPadding:(CGFloat)size { @@ -95,13 +94,20 @@ UIView *topView = [self useCustomViewInsteadOfLabels]; self.topView = topView; if (!topView) { - // Sets up the labels toward the top of the screen. - TopLabelsView *topLabelsView = [[TopLabelsView alloc] initWithFrame:CGRectZero]; - topLabelsView.separatorView.hidden = NO; - self.topLabelsView = topLabelsView; - topView = topLabelsView; - self.topView = topView; - [topLabelsView setWithJSON:[self mapForTopLabels]]; + NSDictionary *mapForTopLabels = [self mapForTopLabels]; + if (mapForTopLabels) { + // Sets up the labels toward the top of the screen. + TopLabelsView *topLabelsView = [[TopLabelsView alloc] initWithFrame:CGRectZero]; + topLabelsView.separatorView.hidden = NO; + self.topLabelsView = topLabelsView; + topView = topLabelsView; + self.topView = topView; + [topLabelsView setWithJSON:[self mapForTopLabels]]; + } else { + topView = [MVMCoreUICommonViewsUtility commonView]; + [topView.heightAnchor constraintEqualToConstant:0].active = YES; + self.topView = topView; + } } [self.contentView addSubview:topView]; [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[topView]-0-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(topView)]]; diff --git a/MVMCoreUI/MVMCoreUI.h b/MVMCoreUI/MVMCoreUI.h index 3ec411ae..aade78f2 100644 --- a/MVMCoreUI/MVMCoreUI.h +++ b/MVMCoreUI/MVMCoreUI.h @@ -15,7 +15,12 @@ FOUNDATION_EXPORT double MVMCoreUIVersionNumber; FOUNDATION_EXPORT const unsigned char MVMCoreUIVersionString[]; // In this header, you should import all the public headers of your framework using statements like #import +#pragma mark - OtherHandlers +#import #import +#import +#import +#import #pragma mark - TopAlert #import @@ -24,11 +29,6 @@ FOUNDATION_EXPORT const unsigned char MVMCoreUIVersionString[]; #import #import -#pragma mark - OtherHandlers -#import -#import -#import - #pragma mark - Categories #import #import @@ -109,6 +109,7 @@ FOUNDATION_EXPORT const unsigned char MVMCoreUIVersionString[]; #pragma mark - Molecules #import #import +#import #pragma mark - Templates #import diff --git a/MVMCoreUI/Molecules/MVMCoreUIHeaderView.swift b/MVMCoreUI/Molecules/MVMCoreUIHeaderView.swift new file mode 100644 index 00000000..b5d9629d --- /dev/null +++ b/MVMCoreUI/Molecules/MVMCoreUIHeaderView.swift @@ -0,0 +1,109 @@ +// +// MVMCoreUIHeaderView.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 2/12/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +public class MVMCoreUIHeaderView: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol { + let headlineLabel = MFLabel.commonLabelH2(true) + let messageLabel = MFLabel.commonLabelB2(true) + var separatorView: SeparatorView? + var spaceBetweenLabels: NSLayoutConstraint? + var leftConstraintTitle: NSLayoutConstraint? + var rightConstraintTitle: NSLayoutConstraint? + var leftConstraintMessage: NSLayoutConstraint? + var rightConstraintMessage: NSLayoutConstraint? + private var heightConstraint: NSLayoutConstraint? + + public override func updateView(_ size: CGFloat) { + super.updateView(size) + headlineLabel.updateView(size) + messageLabel.updateView(size) + separatorView?.updateView(size) + } + + public override func setupView() { + super.setupView() + if separatorView == nil { + translatesAutoresizingMaskIntoConstraints = false + backgroundColor = .clear + clipsToBounds = true + updateViewHorizontalDefaults = true + + addSubview(headlineLabel) + addSubview(messageLabel) + + headlineLabel.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) + messageLabel.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) + setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) + + topPin = headlineLabel.topAnchor.constraint(equalTo: topAnchor, constant: PaddingFive) + topPin?.isActive = true + + spaceBetweenLabels = messageLabel.topAnchor.constraint(equalTo: headlineLabel.bottomAnchor, constant: PaddingTwo) + spaceBetweenLabels?.isActive = true + + leftConstraintTitle = headlineLabel.leftAnchor.constraint(equalTo: leftAnchor) + leftConstraintTitle?.isActive = true + + rightConstraintTitle = rightAnchor.constraint(equalTo: headlineLabel.rightAnchor) + rightConstraintTitle?.isActive = true + + leftConstraintMessage = messageLabel.leftAnchor.constraint(equalTo: leftAnchor) + leftConstraintMessage?.isActive = true + + rightConstraintMessage = rightAnchor.constraint(equalTo: messageLabel.rightAnchor) + rightConstraintMessage?.isActive = true + + bottomPin = bottomAnchor.constraint(equalTo: messageLabel.bottomAnchor, constant: PaddingDefaultVerticalSpacing) + bottomPin?.isActive = true + + heightConstraint = heightAnchor.constraint(equalToConstant: 0) + heightConstraint?.priority = UILayoutPriority(rawValue: 950) + + if let separatorView = SeparatorView.separatorAdd(to: self, position: SeparatorPositionBot, withHorizontalPadding: 0) { + separatorView.setAsHeavy() + separatorView.isHidden = true + addSubview(separatorView) + self.separatorView = separatorView + } + } + } + + public override func setLeftPinConstant(_ constant: CGFloat) { + leftConstraintTitle?.constant = constant + leftConstraintMessage?.constant = constant + separatorView?.leftPin?.constant = constant + } + + public override func setRightPinConstant(_ constant: CGFloat) { + rightConstraintTitle?.constant = constant + rightConstraintMessage?.constant = constant + separatorView?.rightPin?.constant = constant + } + + public func setWithJSON(_ json: [AnyHashable : Any]?) { + headlineLabel.text = json?.optionalStringForKey(KeyTitle) + messageLabel.text = json?.optionalStringForKey(KeyMessage) + separatorView?.isHidden = !(json?.boolForKey("showSeparator") ?? false) + if let colorString = json?.optionalStringForKey("backgroundColor") { + backgroundColor = .mfGet(forHex: colorString) + } + if let colorString = json?.optionalStringForKey("contentColor") { + let color = UIColor.mfGet(forHex: colorString) + headlineLabel.textColor = color + messageLabel.textColor = color + separatorView?.backgroundColor = color + } + + if separatorView?.isHidden ?? true { + bottomPin?.constant = 0 + } else { + bottomPin?.constant = PaddingDefaultVerticalSpacing + } + } +} diff --git a/MVMCoreUI/Molecules/MVMCoreUIMoleculeStackView.swift b/MVMCoreUI/Molecules/MVMCoreUIMoleculeStackView.swift new file mode 100644 index 00000000..e1db3c68 --- /dev/null +++ b/MVMCoreUI/Molecules/MVMCoreUIMoleculeStackView.swift @@ -0,0 +1,65 @@ +// +// MVMCoreUIMoleculeStackView.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 2/11/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +public class MVMCoreUIMoleculeStackView: MFView, MVMCoreUIMoleculeViewProtocol { + + init(withJSON json: [AnyHashable : Any]?) { + super.init(frame: CGRect.zero) + setWithJSON(json) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public override func setupView() { + super.setupView() + translatesAutoresizingMaskIntoConstraints = false + backgroundColor = .clear + self.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) + self.setContentCompressionResistancePriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) + } + + public override func updateView(_ size: CGFloat) { + super.updateView(size) + for view in subviews { + if let mvmView = view as? MVMCoreViewProtocol { + mvmView.updateView(size) + } + } + } + + public func setWithJSON(_ json: [AnyHashable : Any]?) { + guard let molecules = json?.arrayForKey("molecules") as? [[String: Any]] else { + return + } + + // Create the molecules and set the json. + var moleculesArray = [] as [UIView] + for moleculeJSON in molecules { + if let name = moleculeJSON.optionalStringForKey("moleculeName"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForName(name) { + molecule.setWithJSON(moleculeJSON) + moleculesArray.append(molecule) + } + } + + guard moleculesArray.count > 0 else { + return + } + + MVMCoreUIStackableViewController.populateView(self, withUIArray: moleculesArray) { (object) -> UIEdgeInsets in + if object as AnyObject? === moleculesArray.first { + return UIEdgeInsets.zero + } else { + return UIEdgeInsets.init(top: PaddingTwo, left: 0, bottom: 0, right: 0) + } + } + } +} diff --git a/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h b/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h new file mode 100644 index 00000000..02533dc3 --- /dev/null +++ b/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h @@ -0,0 +1,18 @@ +// +// MVMCoreUIMoleculeViewProtocol.h +// MVMCoreUI +// +// Created by Scott Pfeil on 2/11/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +#import + +@protocol MVMCoreUIMoleculeViewProtocol + +// Sets up the ui based on the json +- (void)setWithJSON:(nullable NSDictionary *)json; + +@end + + diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.h b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.h new file mode 100644 index 00000000..541c3ce8 --- /dev/null +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.h @@ -0,0 +1,24 @@ +// +// MVMCoreUIMoleculeMappingObject.h +// MVMCoreUI +// +// Created by Scott Pfeil on 2/11/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +#import +#import + +@interface MVMCoreUIMoleculeMappingObject : NSObject + +// Maps molecule name to class. +@property (nullable, strong, nonatomic) NSMutableDictionary *moleculeMapping; + +// Returns the shared instance ++ (nullable instancetype)sharedMappingObject; + +// Returns the molecule for the given name. +- (nullable UIView *)getMoleculeForName:(nonnull NSString *)name; +- (nullable UIView *)getMoleculeForJSON:(nonnull NSDictionary *)json; + +@end diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m new file mode 100644 index 00000000..8c8352e6 --- /dev/null +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -0,0 +1,54 @@ +// +// MVMCoreUIMoleculeMappingObject.m +// MVMCoreUI +// +// Created by Scott Pfeil on 2/11/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +#import "MVMCoreUIMoleculeMappingObject.h" +@import MVMCore.MVMCoreActionUtility; +@import MVMCore.NSDictionary_MFConvenience; +#import "MVMCoreUIObject.h" +#import + +@implementation MVMCoreUIMoleculeMappingObject + +- (NSMutableDictionary *)moleculeMapping { + + // Keeps a mapping of the given page type + static dispatch_once_t onceToken; + static NSMutableDictionary *mapping; + dispatch_once(&onceToken, ^{ + mapping = [@{ + @"StandardHeader": MVMCoreUIHeaderView.class, + @"MoleculeStack": MVMCoreUIMoleculeStackView.class, + } mutableCopy]; + }); + return mapping; +} + + ++ (nullable instancetype)sharedMappingObject { + return [MVMCoreActionUtility initializerClassCheck:[MVMCoreUIObject sharedInstance].moleculeMap classToVerify:self]; +} + +- (nullable UIView *)getMoleculeForName:(nonnull NSString *)name { + Class class = [self.moleculeMapping objectForKey:name]; + if (class) { + return [[class alloc] init]; + } + return nil; +} + +- (nullable UIView *)getMoleculeForJSON:(nonnull NSDictionary *)json { + NSString *moleculeName = [json string:@"moleculeName"]; + if (!moleculeName) { + return nil; + } + UIView *molecule = [self getMoleculeForName:moleculeName]; + [molecule setWithJSON:json]; + return molecule; +} + +@end diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIObject.h b/MVMCoreUI/OtherHandlers/MVMCoreUIObject.h index f9a3510d..080bd457 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIObject.h +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIObject.h @@ -7,11 +7,14 @@ // #import +#import NS_ASSUME_NONNULL_BEGIN @interface MVMCoreUIObject : MVMCoreObject +@property (nullable, nonatomic, strong) MVMCoreUIMoleculeMappingObject *moleculeMap; + @end NS_ASSUME_NONNULL_END diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIObject.m index 4c601e46..cea769d1 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIObject.m @@ -21,6 +21,7 @@ self.session = [[MVMCoreUISession alloc] init]; self.viewControllerMapping = [[MVMCoreUIViewControllerMappingObject alloc] init]; self.loggingDelegate = [[MVMCoreUILoggingHandler alloc] init]; + self.moleculeMap = [[MVMCoreUIMoleculeMappingObject alloc] init]; } @end diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m index 255cade5..68fc1cd5 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m @@ -21,7 +21,9 @@ dispatch_once(&onceToken, ^{ viewControllerMapping = [@{ @"LargeHeaderSingleLabel": [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MVMCoreUILargeHeaderSingleLabelTemplate class]], - @"TextFieldListForm" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MVMCoreUITextFieldListFormViewController class]] + @"TextFieldListForm" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MVMCoreUITextFieldListFormViewController class]], + @"MoleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MVMCoreUIMoleculeStackTemplate class]], + @"CenterMoleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MVMCoreUIMoleculeStackCenteredTemplate class]] } mutableCopy]; }); return viewControllerMapping; diff --git a/MVMCoreUI/Templates/MVMCoreUIMoleculeStackCenteredTemplate.swift b/MVMCoreUI/Templates/MVMCoreUIMoleculeStackCenteredTemplate.swift new file mode 100644 index 00000000..86bcbc12 --- /dev/null +++ b/MVMCoreUI/Templates/MVMCoreUIMoleculeStackCenteredTemplate.swift @@ -0,0 +1,44 @@ +// +// MVMCoreUIMoleculeStackCenteredTemplate.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 2/12/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +public class MVMCoreUIMoleculeStackCenteredTemplate: MVMCoreUIThreeLayerViewController { + + override public func mapForTopLabels() -> [AnyHashable : Any]? { + return nil + } + + public override func primaryButtonMap() -> [AnyHashable : Any]? { + return nil + } + + public override func secondaryButtonMap() -> [AnyHashable : Any]? { + return nil + } + + override public func buildViewsBetweenLabelsAndButtons() -> [UIView]? { + let molecule = loadObject?.pageJSON?.optionalDictionaryForKey("MoleculeStack") + let moleculeStack = MVMCoreUIMoleculeStackView(withJSON: molecule) + return [moleculeStack] + } + + public override func useCustomViewInsteadOfLabels() -> UIView? { + guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("Header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON) else { + return nil + } + return molecule + } + + override public func useCustomViewInsteadOfButtons() -> UIView? { + guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("Footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON) else { + return nil + } + return molecule + } +} diff --git a/MVMCoreUI/Templates/MVMCoreUIMoleculeStackTemplate.swift b/MVMCoreUI/Templates/MVMCoreUIMoleculeStackTemplate.swift new file mode 100644 index 00000000..37bdc573 --- /dev/null +++ b/MVMCoreUI/Templates/MVMCoreUIMoleculeStackTemplate.swift @@ -0,0 +1,42 @@ +// +// MVMCoreUIMoleculeStackTemplate.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 2/11/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +public class MVMCoreUIMoleculeStackTemplate: MVMCoreUIThreeLayerViewController { + + override public func spaceAboveBetweenView() -> NSNumber? { + return 0 + } + + override public func mapForTopLabels() -> [AnyHashable : Any]? { + return nil + } + + public override func primaryButtonMap() -> [AnyHashable : Any]? { + return nil + } + + public override func secondaryButtonMap() -> [AnyHashable : Any]? { + return nil + } + + public override func useCustomViewInsteadOfLabels() -> UIView? { + guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("MoleculeStack") else { + return nil + } + return MVMCoreUIMoleculeStackView(withJSON: moleculeJSON) + } + + override public func useCustomViewInsteadOfButtons() -> UIView? { + guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("Footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON) else { + return nil + } + return molecule + } +}