From b4c53f838b2b1efed0ff312ca24ad256056a5559 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 9 Sep 2019 14:07:32 -0400 Subject: [PATCH 01/12] Tabs table cell --- MVMCoreUI.xcodeproj/project.pbxproj | 4 + .../Containers/TabBarController/TopTabbar.h | 3 + .../Containers/TabBarController/TopTabbar.m | 6 +- .../AccordionMoleculeTableViewCell.swift | 4 +- .../Items/MoleculeTableViewCell.swift | 2 +- .../Molecules/Items/TabsTableViewCell.swift | 81 +++++++++++++++++++ .../MVMCoreUIMoleculeMappingObject.m | 3 +- .../OtherHandlers/MoleculeDelegateProtocol.h | 4 +- .../Templates/MoleculeListTemplate.swift | 44 +++++----- 9 files changed, 125 insertions(+), 26 deletions(-) create mode 100644 MVMCoreUI/Molecules/Items/TabsTableViewCell.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 9768fcf8..59f736a5 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -40,6 +40,7 @@ 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, ); }; }; D274CA332236A78900B01B62 /* StandardFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D274CA322236A78900B01B62 /* StandardFooterView.swift */; }; + D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */; }; D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D282AAB3223FDDAE00C46919 /* MFLoadImageView.swift */; }; D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D282AAB9224131D100C46919 /* MFTransparentGIFView.swift */; }; D282AACB2243C61700C46919 /* ButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D282AACA2243C61700C46919 /* ButtonView.swift */; }; @@ -222,6 +223,7 @@ 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 = ""; }; D274CA322236A78900B01B62 /* StandardFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StandardFooterView.swift; sourceTree = ""; }; + D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsTableViewCell.swift; sourceTree = ""; }; D282AAB3223FDDAE00C46919 /* MFLoadImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MFLoadImageView.swift; sourceTree = ""; }; D282AAB9224131D100C46919 /* MFTransparentGIFView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MFTransparentGIFView.swift; sourceTree = ""; }; D282AACA2243C61700C46919 /* ButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonView.swift; sourceTree = ""; }; @@ -451,6 +453,7 @@ D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */, D2E1FADC2268B25E00AEFD8C /* MoleculeTableViewCell.swift */, D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */, + D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */, ); path = Items; sourceTree = ""; @@ -997,6 +1000,7 @@ DBC4391922442197001AB423 /* DashLine.swift in Sources */, D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */, + D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */, D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */, D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */, D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */, diff --git a/MVMCoreUI/Containers/TabBarController/TopTabbar.h b/MVMCoreUI/Containers/TabBarController/TopTabbar.h index e63911e7..d851294b 100644 --- a/MVMCoreUI/Containers/TabBarController/TopTabbar.h +++ b/MVMCoreUI/Containers/TabBarController/TopTabbar.h @@ -30,6 +30,9 @@ @property (nonatomic, readonly) NSInteger selectedIndex; +/// A flag for if there should be padding before the first item. +@property (nonatomic) BOOL paddingBeforeFirstTab; + //method to set the height - (void)pinHeight:(CGFloat)height; diff --git a/MVMCoreUI/Containers/TabBarController/TopTabbar.m b/MVMCoreUI/Containers/TabBarController/TopTabbar.m index c52e9d66..e9d77c77 100644 --- a/MVMCoreUI/Containers/TabBarController/TopTabbar.m +++ b/MVMCoreUI/Containers/TabBarController/TopTabbar.m @@ -75,6 +75,7 @@ static NSString * const COLLECTION_CELL_ID = @"cell"; } - (void)setupView { + self.paddingBeforeFirstTab = YES; self.maxHeight = BAR_HEIGHT; self.selectedIndex = 0; self.backgroundColor = [UIColor whiteColor]; @@ -229,6 +230,9 @@ static NSString * const COLLECTION_CELL_ID = @"cell"; } - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { + if (!self.paddingBeforeFirstTab && section == 0) { + return UIEdgeInsetsMake(SECTION_TOPPIN, 0,SECTION_BOTPIN, 0); + } return UIEdgeInsetsMake(SECTION_TOPPIN, SECTION_PADDING,SECTION_BOTPIN, 0); } @@ -341,7 +345,7 @@ static NSString * const COLLECTION_CELL_ID = @"cell"; } - (void)selectIndex:(NSInteger)index animated:(BOOL)animated { - if (self.collectionView) { + if (self.collectionView && [self.datasource numberOfTopTabbarItems:self] > 0) { [MVMCoreDispatchUtility performBlockOnMainThread:^{ NSInteger currentIndex = self.selectedIndex; self.selectedIndex = index; diff --git a/MVMCoreUI/Molecules/Items/AccordionMoleculeTableViewCell.swift b/MVMCoreUI/Molecules/Items/AccordionMoleculeTableViewCell.swift index b188d45b..075d33f1 100644 --- a/MVMCoreUI/Molecules/Items/AccordionMoleculeTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/AccordionMoleculeTableViewCell.swift @@ -34,9 +34,9 @@ import UIKit } if accordionButton.isSelected { - delegateObject?.moleculeDelegate?.addMolecules?(molecules, senderIndexPath: indexPath) + delegateObject?.moleculeDelegate?.addMolecules?(molecules, sender: self, animation: .automatic) } else { - delegateObject?.moleculeDelegate?.removeMolecules?(molecules, senderIndexPath: indexPath) + delegateObject?.moleculeDelegate?.removeMolecules?(molecules, sender: self, animation: .automatic) } if (json?.boolForKey("hideSeparatorWhenExpanded") ?? false) && (self.bottomSeparatorView?.shouldBeVisible() ?? false) { diff --git a/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift b/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift index 210eac6f..641b3721 100644 --- a/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/MoleculeTableViewCell.swift @@ -137,7 +137,7 @@ import UIKit if let useHorizontalMargins = json?.optionalBoolForKey("useHorizontalMargins") { updateViewHorizontalDefaults = useHorizontalMargins } - if json?.optionalBoolForKey("useVerticalMargins") ?? false { + if (json?.optionalBoolForKey("useVerticalMargins") ?? true) == false { topMarginPadding = 0 bottomMarginPadding = 0 } diff --git a/MVMCoreUI/Molecules/Items/TabsTableViewCell.swift b/MVMCoreUI/Molecules/Items/TabsTableViewCell.swift new file mode 100644 index 00000000..1c509a8f --- /dev/null +++ b/MVMCoreUI/Molecules/Items/TabsTableViewCell.swift @@ -0,0 +1,81 @@ +// +// TabsTableViewCell.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 9/6/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +@objcMembers public class TabsTableViewCell: MoleculeTableViewCell { + let tabs = TopTabbar(frame: .zero) + var delegateObject: MVMCoreUIDelegateObject? + var previousTabIndex = 0 + + // MARK: - MFViewProtocol + override public func setupView() { + super.setupView() + guard tabs.superview == nil else { + return + } + tabs.paddingBeforeFirstTab = false + topMarginPadding = 8 + bottomMarginPadding = 0 + + tabs.translatesAutoresizingMaskIntoConstraints = false + tabs.delegate = self + tabs.datasource = self + contentView.addSubview(tabs) + + NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: tabs, useMargins: true).values)) + tabs.reloadData() + } + + public override func updateView(_ size: CGFloat) { + super.updateView(size) + tabs.updateView(size) + } + + // MARK: - MoleculeDelegateProtocol + public override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + self.delegateObject = delegateObject + tabs.reloadData() + } + + public override func reset() { + super.reset() + topMarginPadding = 8 + bottomMarginPadding = 0 + } +} + +extension TabsTableViewCell: TopTabbarDelegate { + public func shouldSelectItem(at index: Int, topTabbar: TopTabbar) -> Bool { + if let moleculesArrays = json?.arrayForKey(KeyMolecules), let molecules = moleculesArrays[topTabbar.selectedIndex] as? [[AnyHashable: Any]] { + delegateObject?.moleculeDelegate?.removeMolecules?(molecules, sender: self, animation: index < tabs.selectedIndex ? .right : .left) + } + previousTabIndex = tabs.selectedIndex + return true + } + + public func topTabbar(_ topTabbar: TopTabbar, didSelectItemAt index: Int) { + if let moleculesArrays = json?.arrayForKey(KeyMolecules), let molecules = moleculesArrays[index] as? [[AnyHashable: Any]] { + delegateObject?.moleculeDelegate?.addMolecules?(molecules, sender: self, animation: index < previousTabIndex ? .left : .right) + } + } +} + +extension TabsTableViewCell: TopTabbarDataSource { + public func number(ofTopTabbarItems topTabbar: TopTabbar) -> Int { + return json?.optionalDictionaryForKey("tabs")?.optionalArrayForKey("tabs")?.count ?? 0 + } + + public func topTabbar(_ topTabbar: TopTabbar, titleForItemAt index: Int) -> String? { + guard let tabs = json?.optionalDictionaryForKey("tabs")?.arrayForKey("tabs"), let label = tabs[index] as? [AnyHashable: Any], let title = label.optionalStringForKey(KeyText) else { + return "Select" + } + return title + } +} diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 9175781b..d99641ea 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -58,7 +58,8 @@ @"labelSwitch": LabelSwitch.class, @"headlineBodySwitch": HeadlineBodySwitch.class, @"headlineBodyTextButton": HeadlineBodyTextButton.class, - @"headlineBodyTextButtonSwitch": HeadlineBodyTextButtonSwitch.class + @"headlineBodyTextButtonSwitch": HeadlineBodyTextButtonSwitch.class, + @"tabsListItem": TabsTableViewCell.class } mutableCopy]; }); return mapping; diff --git a/MVMCoreUI/OtherHandlers/MoleculeDelegateProtocol.h b/MVMCoreUI/OtherHandlers/MoleculeDelegateProtocol.h index cfa1504f..57eb63f5 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeDelegateProtocol.h +++ b/MVMCoreUI/OtherHandlers/MoleculeDelegateProtocol.h @@ -17,7 +17,7 @@ - (void)moleculeLayoutUpdated:(nonnull UIView *)molecule; /// Asks the delegate to add or remove molecules. -- (void)addMolecules:(nonnull NSArray *)molecules senderIndexPath:(nonnull NSIndexPath *)indexPath; -- (void)removeMolecules:(nonnull NSArray *)molecules senderIndexPath:(nonnull NSIndexPath *)indexPath; +- (void)addMolecules:(nonnull NSArray *)molecules sender:(nonnull UITableViewCell *)sender animation:(UITableViewRowAnimation)animation; +- (void)removeMolecules:(nonnull NSArray *)molecules sender:(nonnull UITableViewCell *)sender animation:(UITableViewRowAnimation)animation; @end diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 7ad011b3..0270cb63 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -117,34 +117,40 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { } } - open override func addMolecules(_ molecules: [[AnyHashable: Any]], senderIndexPath indexPath: IndexPath) { - var indexPaths: [IndexPath] = [] - var moleculeList: [(identifier: String, class: AnyClass, molecule: [AnyHashable: Any])] = [] - for (index, molecule) in molecules.enumerated() { - if let info = getMoleculeInfo(with: molecule) { - moleculeList.append(info) - indexPaths.append(IndexPath(row: indexPath.row + 1 + index, section: 0)) - tableView?.register(info.class, forCellReuseIdentifier: info.identifier) + open override func addMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { + // This dispatch is needed to fix a race condition that can occur if this function is called during the table setup. + DispatchQueue.main.async { + guard let cell = sender as? MoleculeTableViewCell, let indexPath = self.tableView?.indexPath(for: cell) else { + return } + var indexPaths: [IndexPath] = [] + for molecule in molecules { + if let info = self.getMoleculeInfo(with: molecule) { + self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier) + let index = indexPath.row + 1 + indexPaths.count + self.moleculesInfo?.insert(info, at: index) + indexPaths.append(IndexPath(row: index, section: 0)) + } + } + self.tableView?.insertRows(at: indexPaths, with: animation) + self.updateViewConstraints() + self.view.layoutIfNeeded() } - moleculesInfo?.insert(contentsOf: moleculeList, at: indexPath.row + 1) - tableView?.insertRows(at: indexPaths, with: .automatic) } - open override func removeMolecules(_ molecules: [[AnyHashable: Any]], senderIndexPath indexPath: IndexPath) { - guard let moleculesList = moleculesInfo else { - return - } + open override func removeMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { var indexPaths: [IndexPath] = [] - for (index, moleculeInfo) in moleculesList.enumerated() { - if molecules.contains(where: { (molecule) -> Bool in + for molecule in molecules { + if let removeIndex = moleculesInfo?.firstIndex(where: { (moleculeInfo) -> Bool in return NSDictionary(dictionary: molecule).isEqual(to: moleculeInfo.molecule) }) { - indexPaths.append(IndexPath(row: index, section: 0)) - moleculesInfo?.remove(at: index) + moleculesInfo?.remove(at: removeIndex) + indexPaths.append(IndexPath(row: removeIndex + indexPaths.count, section: 0)) } } - tableView?.deleteRows(at: indexPaths, with: .automatic) + self.tableView?.deleteRows(at: indexPaths, with: animation) + self.updateViewConstraints() + self.view.layoutIfNeeded() } // MARK: - Convenience From dcd87fb924928564f6289985c2b50b52119e7a00 Mon Sep 17 00:00:00 2001 From: panxi Date: Mon, 9 Sep 2019 16:42:38 -0400 Subject: [PATCH 02/12] add MultiProgress --- MVMCoreUI.xcodeproj/project.pbxproj | 4 ++ MVMCoreUI/Atoms/Views/MultiProgress.swift | 66 +++++++++++++++++++ .../MVMCoreUIMoleculeMappingObject.m | 1 + 3 files changed, 71 insertions(+) create mode 100644 MVMCoreUI/Atoms/Views/MultiProgress.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 9768fcf8..9f804c22 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -18,6 +18,7 @@ 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, ); }; }; 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */; }; + 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948DB67D2326DCD90011F916 /* MultiProgress.swift */; }; B8200E152280C4CF007245F4 /* ProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8200E142280C4CF007245F4 /* ProgressBar.swift */; }; B8200E192281DC1A007245F4 /* CornerLabels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8200E182281DC1A007245F4 /* CornerLabels.swift */; }; D206997721FB8A0B00CAE0DE /* MVMCoreUINavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = D206997521FB8A0B00CAE0DE /* MVMCoreUINavigationController.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -200,6 +201,7 @@ 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 = ""; }; 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionDetailWithImage.swift; sourceTree = ""; }; + 948DB67D2326DCD90011F916 /* MultiProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgress.swift; sourceTree = ""; }; B8200E142280C4CF007245F4 /* ProgressBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressBar.swift; sourceTree = ""; }; B8200E182281DC1A007245F4 /* CornerLabels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CornerLabels.swift; sourceTree = ""; }; D206997521FB8A0B00CAE0DE /* MVMCoreUINavigationController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUINavigationController.h; sourceTree = ""; }; @@ -681,6 +683,7 @@ D260D7B022D65BDD007E7233 /* MVMCoreUIPageControl.m */, D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */, B8200E142280C4CF007245F4 /* ProgressBar.swift */, + 948DB67D2326DCD90011F916 /* MultiProgress.swift */, DBC4391622442196001AB423 /* CaretView.swift */, DBC4391722442197001AB423 /* DashLine.swift */, DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */, @@ -1068,6 +1071,7 @@ D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */, D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */, D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */, + 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */, D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */, D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */, D29DF26C21E6AA0B003B2FB9 /* FLAnimatedImage.m in Sources */, diff --git a/MVMCoreUI/Atoms/Views/MultiProgress.swift b/MVMCoreUI/Atoms/Views/MultiProgress.swift new file mode 100644 index 00000000..eac13ce2 --- /dev/null +++ b/MVMCoreUI/Atoms/Views/MultiProgress.swift @@ -0,0 +1,66 @@ +// +// MultiProgress.swift +// MVMCoreUI +// +// Created by Ryan on 9/9/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +@objcMembers open class MultiProgress: MFView { + + var progressList = Array<[AnyHashable: Any]>() + var roundedRect : Bool = false + var thicknessConstraint : NSLayoutConstraint? + + let defaultHeight : CGFloat = 8 + + override open func setupView() { + super.setupView() + translatesAutoresizingMaskIntoConstraints = false + backgroundColor = .mfSilver() + clipsToBounds = true + } + + override open func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + + thicknessConstraint?.isActive = false + thicknessConstraint = nil + let height = json?.optionalCGFloatForKey("thickness") ?? defaultHeight + let constraint = heightAnchor.constraint(equalToConstant: height) + constraint.isActive = true + thicknessConstraint = constraint + + if let rounded = json?.optionalBoolForKey("roundedRect") { + self.roundedRect = rounded + self.layer.cornerRadius = (thicknessConstraint?.constant ?? defaultHeight)/2 + } + if let list = json?.optionalArrayForKey("progressList") as? [[AnyHashable: Any]] { + progressList = list + var previous : UIView? + for module in progressList { + let view = MFView(frame: .zero) + view.translatesAutoresizingMaskIntoConstraints = false + addSubview(view) + view.backgroundColor = UIColor.mfGet(forHex: module.optionalStringForKey("progressColor") ?? "#007bb8") + view.widthAnchor.constraint(equalTo: widthAnchor, multiplier: (module.optionalCGFloatForKey("progress") ?? 0)/100).isActive = true + if previous != nil { + view.leadingAnchor.constraint(equalTo: previous!.trailingAnchor).isActive = true + previous = view + } else { + let constraint = view.leadingAnchor.constraint(equalTo: leadingAnchor) + constraint.priority = UILayoutPriority(rawValue: 900) + constraint.isActive = true + previous = view + } + NSLayoutConstraint.constraintPinSubview(view, pinTop: true, pinBottom: true, pinLeft: false, pinRight: false) + } + guard previous != nil else {return} + let constraint = trailingAnchor.constraint(equalTo: previous!.trailingAnchor) + constraint.priority = UILayoutPriority(800) + constraint.isActive = true + } + } +} diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 9175781b..ca9c1e66 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -41,6 +41,7 @@ @"checkbox" : MVMCoreUICheckBox.class, @"cornerLabels" : CornerLabels.class, @"progressBar": ProgressBar.class, + @"multiProgress": MultiProgress.class, @"checkbox": MVMCoreUICheckBox.class, @"listItem": MoleculeTableViewCell.class, @"accordionListItem": AccordionMoleculeTableViewCell.class, From 595a3b1e38362f3b47f849a7db49ea664ef8e5c3 Mon Sep 17 00:00:00 2001 From: panxi Date: Mon, 9 Sep 2019 16:49:12 -0400 Subject: [PATCH 03/12] fix typo --- MVMCoreUI/Atoms/Views/MultiProgress.swift | 4 ++-- MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/MultiProgress.swift b/MVMCoreUI/Atoms/Views/MultiProgress.swift index eac13ce2..ac801ec7 100644 --- a/MVMCoreUI/Atoms/Views/MultiProgress.swift +++ b/MVMCoreUI/Atoms/Views/MultiProgress.swift @@ -33,8 +33,8 @@ import UIKit constraint.isActive = true thicknessConstraint = constraint - if let rounded = json?.optionalBoolForKey("roundedRect") { - self.roundedRect = rounded + self.roundedRect = json?.optionalBoolForKey("roundedRect") ?? false + if self.roundedRect { self.layer.cornerRadius = (thicknessConstraint?.constant ?? defaultHeight)/2 } if let list = json?.optionalArrayForKey("progressList") as? [[AnyHashable: Any]] { diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index ca9c1e66..31943a79 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -41,7 +41,7 @@ @"checkbox" : MVMCoreUICheckBox.class, @"cornerLabels" : CornerLabels.class, @"progressBar": ProgressBar.class, - @"multiProgress": MultiProgress.class, + @"multiProgressBar": MultiProgress.class, @"checkbox": MVMCoreUICheckBox.class, @"listItem": MoleculeTableViewCell.class, @"accordionListItem": AccordionMoleculeTableViewCell.class, From 4050b784ed295afec63ce79fc77be6c58c72e3fb Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 10 Sep 2019 14:11:09 -0400 Subject: [PATCH 04/12] alignment fix issues. --- MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h | 2 +- MVMCoreUI/Atoms/Views/MVMCoreUISwitch.h | 3 +- .../ImageHeadlineBody.swift | 29 +++++++++-------- .../SwitchMolecules/HeadlineBodySwitch.swift | 8 +++-- .../HeadlineBodyTextButtonSwitch.swift | 8 +++-- .../SwitchMolecules/LabelSwitch.swift | 8 +++-- .../HeadlineBody.swift | 32 ++++++++----------- .../HeadlineBodyTextButton.swift | 22 +++++++------ MVMCoreUI/Organisms/MoleculeStackView.swift | 8 +++-- 9 files changed, 69 insertions(+), 51 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h index fc76ed71..f1638f6a 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h @@ -12,7 +12,7 @@ @class Label; @class MFSizeObject; -@interface MVMCoreUICheckBox : UIControl +@interface MVMCoreUICheckBox : UIControl @property (nullable, weak, nonatomic) MVMCoreUICheckMarkView *checkMark; @property (readonly, nonatomic) BOOL isSelected; diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUISwitch.h b/MVMCoreUI/Atoms/Views/MVMCoreUISwitch.h index a21dd55f..32e98f2a 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUISwitch.h +++ b/MVMCoreUI/Atoms/Views/MVMCoreUISwitch.h @@ -9,10 +9,11 @@ #import #import +#import @import MVMCore.MVMCoreViewProtocol; typedef void(^ValueChangeBlock)(void); -@interface MVMCoreUISwitch : UIControl +@interface MVMCoreUISwitch : UIControl @property (assign, nonatomic, getter=isOn) BOOL on; @property (nullable, strong, nonatomic) UIColor *onTintColor; diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBody.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBody.swift index f1e295fe..aca450aa 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBody.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBody.swift @@ -20,27 +20,30 @@ import UIKit guard subviews.count == 0 else { return } - MVMCoreUIUtility.setMarginsFor(self, leading: 0, top: 0, trailing: 0, bottom: 0) headlineBody.headlineLabel.styleB1(true) headlineBody.spaceBetweenLabelsConstant = 0 - addSubview(headlineBody) - addSubview(imageView) - NSLayoutConstraint.pinViewTop(toSuperview: headlineBody, useMargins: true, constant: 0).isActive = true - NSLayoutConstraint.pinViewRight(toSuperview: headlineBody, useMargins: true, constant: 0).isActive = true - layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: headlineBody.bottomAnchor).isActive = true - var constraint = NSLayoutConstraint.pinViewBottom(toSuperview: headlineBody, useMargins: true, constant: 0) + let view = MVMCoreUICommonViewsUtility.commonView() + addSubview(view) + pinView(toSuperView: view) + view.addSubview(headlineBody) + view.addSubview(imageView) + + headlineBody.topAnchor.constraint(equalTo: view.topAnchor).isActive = true + view.rightAnchor.constraint(equalTo: headlineBody.rightAnchor).isActive = true + view.bottomAnchor.constraint(greaterThanOrEqualTo: headlineBody.bottomAnchor).isActive = true + var constraint = view.bottomAnchor.constraint(equalTo: headlineBody.bottomAnchor) constraint.priority = .defaultLow constraint.isActive = true - imageView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true - NSLayoutConstraint.pinViewLeft(toSuperview: imageView, useMargins: true, constant: 0).isActive = true - imageView.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor).isActive = true - layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: imageView.bottomAnchor).isActive = true - constraint = NSLayoutConstraint.pinViewBottom(toSuperview: imageView, useMargins: true, constant: 0) + imageView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true + imageView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true + imageView.topAnchor.constraint(greaterThanOrEqualTo: view.topAnchor).isActive = true + view.bottomAnchor.constraint(greaterThanOrEqualTo: imageView.bottomAnchor).isActive = true + constraint = view.bottomAnchor.constraint(equalTo: imageView.bottomAnchor) constraint.priority = UILayoutPriority(rawValue: 200) constraint.isActive = true - constraint = NSLayoutConstraint.pinViewTop(toSuperview: imageView, useMargins: true, constant: 0) + constraint = imageView.topAnchor.constraint(equalTo: view.topAnchor) constraint.priority = UILayoutPriority(rawValue: 200) constraint.isActive = true diff --git a/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/HeadlineBodySwitch.swift b/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/HeadlineBodySwitch.swift index ffab9920..d373ce87 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/HeadlineBodySwitch.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/HeadlineBodySwitch.swift @@ -25,8 +25,12 @@ import UIKit return } headlineBody.styleListItem() - addSubview(headlineBody) - addSubview(mvmSwitch) + let view = MVMCoreUICommonViewsUtility.commonView() + addSubview(view) + pinView(toSuperView: view) + + view.addSubview(headlineBody) + view.addSubview(mvmSwitch) NSLayoutConstraint.pinSubviewsCenter(leftView: headlineBody, rightView: mvmSwitch) } diff --git a/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/HeadlineBodyTextButtonSwitch.swift b/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/HeadlineBodyTextButtonSwitch.swift index 754f508b..0f184544 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/HeadlineBodyTextButtonSwitch.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/HeadlineBodyTextButtonSwitch.swift @@ -24,9 +24,13 @@ import UIKit guard mvmSwitch.superview == nil else { return } + let view = MVMCoreUICommonViewsUtility.commonView() + addSubview(view) + pinView(toSuperView: view) + headlineBodyTextButton.headlineBody.styleListItem() - addSubview(headlineBodyTextButton) - addSubview(mvmSwitch) + view.addSubview(headlineBodyTextButton) + view.addSubview(mvmSwitch) NSLayoutConstraint.pinSubviewsCenter(leftView: headlineBodyTextButton, rightView: mvmSwitch) } diff --git a/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/LabelSwitch.swift b/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/LabelSwitch.swift index 017eee99..d47cf44c 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/LabelSwitch.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/LabelSwitch.swift @@ -24,8 +24,12 @@ import UIKit guard mvmSwitch.superview == nil else { return } - addSubview(label) - addSubview(mvmSwitch) + let view = MVMCoreUICommonViewsUtility.commonView() + addSubview(view) + pinView(toSuperView: view) + + view.addSubview(label) + view.addSubview(mvmSwitch) label.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) NSLayoutConstraint.pinSubviewsCenter(leftView: label, rightView: mvmSwitch) } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBody.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBody.swift index 1077ac0e..db30c8d6 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBody.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBody.swift @@ -70,33 +70,37 @@ open class HeadlineBody: ViewConstrainingView { translatesAutoresizingMaskIntoConstraints = false backgroundColor = .clear clipsToBounds = true - - addSubview(headlineLabel) - addSubview(messageLabel) + + let view = MVMCoreUICommonViewsUtility.commonView() + addSubview(view) + pinView(toSuperView: view) + + view.addSubview(headlineLabel) + view.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: 0) + topPin = headlineLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 0) topPin?.isActive = true spaceBetweenLabels = messageLabel.topAnchor.constraint(equalTo: headlineLabel.bottomAnchor, constant: spaceBetweenLabelsConstant) spaceBetweenLabels?.isActive = true - leftConstraintTitle = headlineLabel.leftAnchor.constraint(equalTo: leftAnchor) + leftConstraintTitle = headlineLabel.leftAnchor.constraint(equalTo: view.leftAnchor) leftConstraintTitle?.isActive = true - rightConstraintTitle = rightAnchor.constraint(equalTo: headlineLabel.rightAnchor) + rightConstraintTitle = view.rightAnchor.constraint(equalTo: headlineLabel.rightAnchor) rightConstraintTitle?.isActive = true - leftConstraintMessage = messageLabel.leftAnchor.constraint(equalTo: leftAnchor) + leftConstraintMessage = messageLabel.leftAnchor.constraint(equalTo: view.leftAnchor) leftConstraintMessage?.isActive = true - rightConstraintMessage = rightAnchor.constraint(equalTo: messageLabel.rightAnchor) + rightConstraintMessage = view.rightAnchor.constraint(equalTo: messageLabel.rightAnchor) rightConstraintMessage?.isActive = true - bottomPin = bottomAnchor.constraint(equalTo: messageLabel.bottomAnchor, constant: 0) + bottomPin = view.bottomAnchor.constraint(equalTo: messageLabel.bottomAnchor, constant: 0) bottomPin?.isActive = true } @@ -109,16 +113,6 @@ open class HeadlineBody: ViewConstrainingView { } } - open override func setLeftPinConstant(_ constant: CGFloat) { - leftConstraintTitle?.constant = constant - leftConstraintMessage?.constant = constant - } - - open override func setRightPinConstant(_ constant: CGFloat) { - rightConstraintTitle?.constant = constant - rightConstraintMessage?.constant = constant - } - // MARK: - MVMCoreUIMoleculeViewProtocol open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyTextButton.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyTextButton.swift index bb638624..009189cb 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyTextButton.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyTextButton.swift @@ -28,23 +28,27 @@ import UIKit guard subviews.count == 0 else { return } - addSubview(headlineBody) - addSubview(textButton) + let view = MVMCoreUICommonViewsUtility.commonView() + addSubview(view) + pinView(toSuperView: view) + + view.addSubview(headlineBody) + view.addSubview(textButton) headlineBody.styleListItem() - headlineBody.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor, constant: 0).isActive = true - headlineBody.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor).isActive = true - var constraint = layoutMarginsGuide.rightAnchor.constraint(equalTo: headlineBody.rightAnchor) + headlineBody.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true + headlineBody.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true + var constraint = view.rightAnchor.constraint(equalTo: headlineBody.rightAnchor) constraint.priority = .defaultHigh constraint.isActive = true spaceBetween = textButton.topAnchor.constraint(equalTo: headlineBody.bottomAnchor, constant: spaceBetweenConstant) spaceBetween?.isActive = true - textButton.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor).isActive = true - layoutMarginsGuide.bottomAnchor.constraint(equalTo: textButton.bottomAnchor).isActive = true - layoutMarginsGuide.rightAnchor.constraint(greaterThanOrEqualTo: textButton.rightAnchor).isActive = true - constraint = layoutMarginsGuide.rightAnchor.constraint(equalTo: textButton.rightAnchor) + textButton.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true + view.bottomAnchor.constraint(equalTo: textButton.bottomAnchor).isActive = true + view.rightAnchor.constraint(greaterThanOrEqualTo: textButton.rightAnchor).isActive = true + constraint = view.rightAnchor.constraint(equalTo: textButton.rightAnchor) constraint.priority = .defaultHigh constraint.isActive = true } diff --git a/MVMCoreUI/Organisms/MoleculeStackView.swift b/MVMCoreUI/Organisms/MoleculeStackView.swift index ad395eec..b2f70e6d 100644 --- a/MVMCoreUI/Organisms/MoleculeStackView.swift +++ b/MVMCoreUI/Organisms/MoleculeStackView.swift @@ -27,11 +27,15 @@ public class StackItem { func update(with json: [AnyHashable: Any]) { spacing = json.optionalCGFloatForKey("spacing") percentage = json["percent"] as? Int - if let alignment = json.optionalStringForKey("verticalAlignment") { + if let alignment = json.stringOptionalWithChainOfKeysOrIndexes([KeyMolecule,"verticalAlignment"]) { verticalAlignment = ViewConstrainingView.getAlignmentFor(alignment, defaultAlignment: .fill) + } else { + verticalAlignment = nil } - if let alignment = json.optionalStringForKey("horizontalAlignment") { + if let alignment = json.stringOptionalWithChainOfKeysOrIndexes([KeyMolecule,"horizontalAlignment"]) { horizontalAlignment = ViewConstrainingView.getAlignmentFor(alignment, defaultAlignment: .fill) + } else { + horizontalAlignment = nil } } } From d52e2047218f6c4fb518b0203348037730ff1a43 Mon Sep 17 00:00:00 2001 From: panxi Date: Tue, 10 Sep 2019 15:57:00 -0400 Subject: [PATCH 05/12] update multiprogressbar --- MVMCoreUI/Atoms/Views/MultiProgress.swift | 101 +++++++++++++--------- 1 file changed, 61 insertions(+), 40 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/MultiProgress.swift b/MVMCoreUI/Atoms/Views/MultiProgress.swift index ac801ec7..05aedcc1 100644 --- a/MVMCoreUI/Atoms/Views/MultiProgress.swift +++ b/MVMCoreUI/Atoms/Views/MultiProgress.swift @@ -10,57 +10,78 @@ import UIKit @objcMembers open class MultiProgress: MFView { - var progressList = Array<[AnyHashable: Any]>() - var roundedRect : Bool = false - var thicknessConstraint : NSLayoutConstraint? - - let defaultHeight : CGFloat = 8 + var progressList: Array? + var roundedRect: Bool = false { + didSet { + if roundedRect { + layer.cornerRadius = (thicknessConstraint?.constant ?? defaultHeight)/2 + } else { + layer.cornerRadius = 0 + } + } + } + var thicknessConstraint: NSLayoutConstraint? + let defaultHeight: CGFloat = 8 override open func setupView() { super.setupView() translatesAutoresizingMaskIntoConstraints = false backgroundColor = .mfSilver() clipsToBounds = true + if thicknessConstraint == nil { + thicknessConstraint = heightAnchor.constraint(equalToConstant: defaultHeight) + thicknessConstraint?.isActive = true + } } - override open func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - - thicknessConstraint?.isActive = false - thicknessConstraint = nil - let height = json?.optionalCGFloatForKey("thickness") ?? defaultHeight - let constraint = heightAnchor.constraint(equalToConstant: height) - constraint.isActive = true - thicknessConstraint = constraint - - self.roundedRect = json?.optionalBoolForKey("roundedRect") ?? false - if self.roundedRect { - self.layer.cornerRadius = (thicknessConstraint?.constant ?? defaultHeight)/2 + thicknessConstraint?.constant = json?.optionalCGFloatForKey("thickness") ?? defaultHeight + roundedRect = json?.optionalBoolForKey("roundedRect") ?? false + guard let list = json?.optionalArrayForKey("progressList") as? [[AnyHashable: Any]], let progressObjectList = ProgressBarObject.getProgressBarObjectList(list), progressObjectList.count > 0 else { + return } - if let list = json?.optionalArrayForKey("progressList") as? [[AnyHashable: Any]] { - progressList = list - var previous : UIView? - for module in progressList { - let view = MFView(frame: .zero) - view.translatesAutoresizingMaskIntoConstraints = false - addSubview(view) - view.backgroundColor = UIColor.mfGet(forHex: module.optionalStringForKey("progressColor") ?? "#007bb8") - view.widthAnchor.constraint(equalTo: widthAnchor, multiplier: (module.optionalCGFloatForKey("progress") ?? 0)/100).isActive = true - if previous != nil { - view.leadingAnchor.constraint(equalTo: previous!.trailingAnchor).isActive = true - previous = view - } else { - let constraint = view.leadingAnchor.constraint(equalTo: leadingAnchor) - constraint.priority = UILayoutPriority(rawValue: 900) - constraint.isActive = true - previous = view - } - NSLayoutConstraint.constraintPinSubview(view, pinTop: true, pinBottom: true, pinLeft: false, pinRight: false) + progressList = progressObjectList + var previous: UIView? + for progressObject in progressList! { + guard progressObject.progress > 0.0 else { + continue } - guard previous != nil else {return} - let constraint = trailingAnchor.constraint(equalTo: previous!.trailingAnchor) - constraint.priority = UILayoutPriority(800) - constraint.isActive = true + let view = MFView(frame: .zero) + view.translatesAutoresizingMaskIntoConstraints = false + addSubview(view) + view.backgroundColor = progressObject.color + view.widthAnchor.constraint(equalTo: widthAnchor, multiplier: progressObject.progress).isActive = true + view.leadingAnchor.constraint(equalTo: previous?.trailingAnchor ?? leadingAnchor).isActive = true + previous = view + NSLayoutConstraint.constraintPinSubview(view, pinTop: true, pinBottom: true, pinLeft: false, pinRight: false) } } } + + +@objcMembers open class ProgressBarObject { + ///form 0.0 to 1.0. input progress should be [0 100] + var progress: CGFloat = 0.0 + ///default color is cerulean + var color: UIColor = UIColor.mfCerulean() + + init(_ module: [AnyHashable: Any]?) { + progress = (module?.optionalCGFloatForKey("progress") ?? 0.0)/100 + if let colorString = module?.optionalStringForKey("progressColor") { + color = UIColor.mfGet(forHex: colorString) + } + } + + static func getProgressBarObjectList(_ list: [[AnyHashable: Any]]?) -> [ProgressBarObject]? { + guard list?.count ?? 0 > 0 else { + return nil + } + var progressList = [ProgressBarObject]() + for module in list! { + let progressObject = ProgressBarObject(module) + progressList.append(progressObject) + } + return progressList + } +} From 358842e43363dfb89000fad480e92a5c644846f6 Mon Sep 17 00:00:00 2001 From: panxi Date: Wed, 11 Sep 2019 10:04:19 -0400 Subject: [PATCH 06/12] update based on Scott's comment --- MVMCoreUI/Atoms/Views/MultiProgress.swift | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/MultiProgress.swift b/MVMCoreUI/Atoms/Views/MultiProgress.swift index 05aedcc1..de40a6b1 100644 --- a/MVMCoreUI/Atoms/Views/MultiProgress.swift +++ b/MVMCoreUI/Atoms/Views/MultiProgress.swift @@ -38,10 +38,18 @@ import UIKit super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) thicknessConstraint?.constant = json?.optionalCGFloatForKey("thickness") ?? defaultHeight roundedRect = json?.optionalBoolForKey("roundedRect") ?? false - guard let list = json?.optionalArrayForKey("progressList") as? [[AnyHashable: Any]], let progressObjectList = ProgressBarObject.getProgressBarObjectList(list), progressObjectList.count > 0 else { + setupProgressList(json?.optionalArrayForKey("progressList") as? [[AnyHashable: Any]]) + } + + func setupProgressList(_ list: [[AnyHashable: Any]]?) { + for subview in subviews { + subview.removeFromSuperview() + } + let progressObjectList = ProgressBarObject.getProgressBarObjectList(list) + progressList = progressObjectList + guard (progressList?.count ?? 0) > 0 else { return } - progressList = progressObjectList var previous: UIView? for progressObject in progressList! { guard progressObject.progress > 0.0 else { @@ -61,7 +69,7 @@ import UIKit @objcMembers open class ProgressBarObject { - ///form 0.0 to 1.0. input progress should be [0 100] + ///from 0.0 to 1.0. input progress should be [0 100] var progress: CGFloat = 0.0 ///default color is cerulean var color: UIColor = UIColor.mfCerulean() From f69fe85d8334fc17aa40d2f82f6a289121f7a6ff Mon Sep 17 00:00:00 2001 From: panxi Date: Wed, 11 Sep 2019 10:19:03 -0400 Subject: [PATCH 07/12] update based on Scott's comment --- MVMCoreUI/Atoms/Views/MultiProgress.swift | 108 +++++++++++----------- 1 file changed, 53 insertions(+), 55 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/MultiProgress.swift b/MVMCoreUI/Atoms/Views/MultiProgress.swift index de40a6b1..619e31e7 100644 --- a/MVMCoreUI/Atoms/Views/MultiProgress.swift +++ b/MVMCoreUI/Atoms/Views/MultiProgress.swift @@ -8,9 +8,59 @@ import UIKit -@objcMembers open class MultiProgress: MFView { +@objcMembers open class ProgressBarObject { + ///from 0.0 to 1.0. input progress should be [0 100] + var progress: CGFloat = 0.0 + ///default color is cerulean + var color: UIColor = UIColor.mfCerulean() + + init(_ module: [AnyHashable: Any]?) { + progress = (module?.optionalCGFloatForKey("progress") ?? 0.0)/100 + if let colorString = module?.optionalStringForKey("progressColor") { + color = UIColor.mfGet(forHex: colorString) + } + } + + static func getProgressBarObjectList(_ list: [[AnyHashable: Any]]?) -> [ProgressBarObject]? { + guard list?.count ?? 0 > 0 else { + return nil + } + var progressList = [ProgressBarObject]() + for module in list! { + let progressObject = ProgressBarObject(module) + progressList.append(progressObject) + } + return progressList + } +} - var progressList: Array? +@objcMembers open class MultiProgress: MFView { + ///passing value to progressList creates corresponding progress bars + var progressList: Array? { + didSet { + for subview in subviews { + subview.removeFromSuperview() + } + guard (progressList?.count ?? 0) > 0 else { + return + } + var previous: UIView? + for progressObject in progressList! { + guard progressObject.progress > 0.0 else { + continue + } + let view = MFView(frame: .zero) + view.translatesAutoresizingMaskIntoConstraints = false + addSubview(view) + view.backgroundColor = progressObject.color + view.widthAnchor.constraint(equalTo: widthAnchor, multiplier: progressObject.progress).isActive = true + view.leadingAnchor.constraint(equalTo: previous?.trailingAnchor ?? leadingAnchor).isActive = true + previous = view + NSLayoutConstraint.constraintPinSubview(view, pinTop: true, pinBottom: true, pinLeft: false, pinRight: false) + } + } + } + var roundedRect: Bool = false { didSet { if roundedRect { @@ -38,58 +88,6 @@ import UIKit super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) thicknessConstraint?.constant = json?.optionalCGFloatForKey("thickness") ?? defaultHeight roundedRect = json?.optionalBoolForKey("roundedRect") ?? false - setupProgressList(json?.optionalArrayForKey("progressList") as? [[AnyHashable: Any]]) - } - - func setupProgressList(_ list: [[AnyHashable: Any]]?) { - for subview in subviews { - subview.removeFromSuperview() - } - let progressObjectList = ProgressBarObject.getProgressBarObjectList(list) - progressList = progressObjectList - guard (progressList?.count ?? 0) > 0 else { - return - } - var previous: UIView? - for progressObject in progressList! { - guard progressObject.progress > 0.0 else { - continue - } - let view = MFView(frame: .zero) - view.translatesAutoresizingMaskIntoConstraints = false - addSubview(view) - view.backgroundColor = progressObject.color - view.widthAnchor.constraint(equalTo: widthAnchor, multiplier: progressObject.progress).isActive = true - view.leadingAnchor.constraint(equalTo: previous?.trailingAnchor ?? leadingAnchor).isActive = true - previous = view - NSLayoutConstraint.constraintPinSubview(view, pinTop: true, pinBottom: true, pinLeft: false, pinRight: false) - } - } -} - - -@objcMembers open class ProgressBarObject { - ///from 0.0 to 1.0. input progress should be [0 100] - var progress: CGFloat = 0.0 - ///default color is cerulean - var color: UIColor = UIColor.mfCerulean() - - init(_ module: [AnyHashable: Any]?) { - progress = (module?.optionalCGFloatForKey("progress") ?? 0.0)/100 - if let colorString = module?.optionalStringForKey("progressColor") { - color = UIColor.mfGet(forHex: colorString) - } - } - - static func getProgressBarObjectList(_ list: [[AnyHashable: Any]]?) -> [ProgressBarObject]? { - guard list?.count ?? 0 > 0 else { - return nil - } - var progressList = [ProgressBarObject]() - for module in list! { - let progressObject = ProgressBarObject(module) - progressList.append(progressObject) - } - return progressList + progressList = ProgressBarObject.getProgressBarObjectList(json?.optionalArrayForKey("progressList") as? [[AnyHashable: Any]]) } } From 44ebfb92943b6e4e5dc87924efa3a7e93b362d4b Mon Sep 17 00:00:00 2001 From: "Murugan, Vimal" Date: Tue, 17 Sep 2019 16:25:00 +0530 Subject: [PATCH 08/12] fix for cxtdt_28106 --- MVMCoreUI/Atoms/Views/LabelWithInternalButton.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atoms/Views/LabelWithInternalButton.swift b/MVMCoreUI/Atoms/Views/LabelWithInternalButton.swift index bc1c2219..ff2e751d 100644 --- a/MVMCoreUI/Atoms/Views/LabelWithInternalButton.swift +++ b/MVMCoreUI/Atoms/Views/LabelWithInternalButton.swift @@ -174,7 +174,7 @@ public typealias CoreObjectActionLoadPresentDelegate = MVMCoreActionDelegateProt super.init(frame: .zero) setText(fullText, startTag: startTag, endTag: endTag) - actionBlock = label?.createActionBlockFrom(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject) + setActionMap(actionMap, additionalData: additionalData, delegateObject: delegateObject) } //------------------------------------------------------ From 6cdde756e5c4d8680830c9691777f1aef1178d0c Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 19 Sep 2019 09:06:14 -0400 Subject: [PATCH 09/12] bug fixes --- MVMCoreUI/Atoms/Views/MultiProgress.swift | 8 +++++++- MVMCoreUI/Atoms/Views/ProgressBar.swift | 2 +- MVMCoreUI/Atoms/Views/ViewConstrainingView.h | 3 +++ MVMCoreUI/Atoms/Views/ViewConstrainingView.m | 19 ++++++++++--------- MVMCoreUI/Molecules/Scroller.swift | 3 ++- MVMCoreUI/Molecules/StandardFooterView.swift | 2 ++ MVMCoreUI/Molecules/StandardHeaderView.swift | 4 ++++ .../HeadlineBody.swift | 16 +++++++++++----- 8 files changed, 40 insertions(+), 17 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/MultiProgress.swift b/MVMCoreUI/Atoms/Views/MultiProgress.swift index 619e31e7..fe902d9f 100644 --- a/MVMCoreUI/Atoms/Views/MultiProgress.swift +++ b/MVMCoreUI/Atoms/Views/MultiProgress.swift @@ -76,7 +76,7 @@ import UIKit override open func setupView() { super.setupView() translatesAutoresizingMaskIntoConstraints = false - backgroundColor = .mfSilver() + backgroundColor = .mfLightSilver() clipsToBounds = true if thicknessConstraint == nil { thicknessConstraint = heightAnchor.constraint(equalToConstant: defaultHeight) @@ -84,6 +84,12 @@ import UIKit } } + open override func reset() { + super.reset() + backgroundColor = .mfLightSilver() + progressList = nil + } + override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) thicknessConstraint?.constant = json?.optionalCGFloatForKey("thickness") ?? defaultHeight diff --git a/MVMCoreUI/Atoms/Views/ProgressBar.swift b/MVMCoreUI/Atoms/Views/ProgressBar.swift index 5416f0a7..a9333966 100644 --- a/MVMCoreUI/Atoms/Views/ProgressBar.swift +++ b/MVMCoreUI/Atoms/Views/ProgressBar.swift @@ -70,7 +70,7 @@ import Foundation thickness = 8 progress = 0 progressTintColor = UIColor.mfCerulean() - trackTintColor = UIColor.mfSilver() + trackTintColor = UIColor.mfLightSilver() } public static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.h b/MVMCoreUI/Atoms/Views/ViewConstrainingView.h index a5e359d0..df443afd 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.h +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.h @@ -34,6 +34,9 @@ @property (nonatomic) BOOL updateViewHorizontalDefaults; @property (nonatomic) BOOL updateViewVerticalDefaults; +@property (nonatomic) CGFloat topMarginPadding; +@property (nonatomic) CGFloat bottomMarginPadding; + /// A molecule if we constrain one. @property (weak, nullable, nonatomic) UIView *molecule; diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m index ba5f1bd0..66a3a83d 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m @@ -304,18 +304,15 @@ [super setupView]; self.translatesAutoresizingMaskIntoConstraints = NO; self.backgroundColor = [UIColor clearColor]; + self.topMarginPadding = PaddingDefaultVerticalSpacing3; + self.bottomMarginPadding = PaddingDefaultVerticalSpacing3; [MVMCoreUIUtility setMarginsForView:self leading:0 top:0 trailing:0 bottom:0]; } - (void)updateView:(CGFloat)size { [super updateView:size]; - if ([self.constrainedView respondsToSelector:@selector(updateView:)]) { - [((id)self.constrainedView) updateView:size]; - } - if (self.molecule != self.constrainedView) { - [self.molecule updateView:size]; - } - [MFStyler setDefaultMarginsForView:self size:size horizontal:self.updateViewHorizontalDefaults vertical:self.updateViewVerticalDefaults]; + [self.molecule updateView:size]; + [MFStyler setMarginsForView:self size:size defaultHorizontal:self.updateViewHorizontalDefaults top:(self.updateViewVerticalDefaults ? self.topMarginPadding : 0) bottom:(self.updateViewVerticalDefaults ? self.bottomMarginPadding : 0)]; UIEdgeInsets margins = [MVMCoreUIUtility getMarginsForView:self]; if (self.updateViewHorizontalDefaults) { [self setLeftPinConstant:margins.left]; @@ -344,6 +341,8 @@ [super reset]; self.updateViewHorizontalDefaults = NO; self.updateViewVerticalDefaults = NO; + self.topMarginPadding = PaddingDefaultVerticalSpacing3; + self.bottomMarginPadding = PaddingDefaultVerticalSpacing3; if ([self.molecule respondsToSelector:@selector(alignment)]) { [self alignHorizontal:[(UIView *)self.molecule alignment]]; } @@ -354,8 +353,10 @@ } - (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { - [super setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; - + // Only treated as a container if we are constraining a molecule. + 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]; diff --git a/MVMCoreUI/Molecules/Scroller.swift b/MVMCoreUI/Molecules/Scroller.swift index cd2949d8..e4289bc3 100644 --- a/MVMCoreUI/Molecules/Scroller.swift +++ b/MVMCoreUI/Molecules/Scroller.swift @@ -19,7 +19,8 @@ import UIKit } translatesAutoresizingMaskIntoConstraints = false scrollView.translatesAutoresizingMaskIntoConstraints = false - addConstrainedView(scrollView) + addSubview(scrollView) + pinView(toSuperView: scrollView) scrollView.addSubview(contentView) NSLayoutConstraint.constraintPinSubview(toSuperview: contentView) let constraint = contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor, multiplier: 1.0) diff --git a/MVMCoreUI/Molecules/StandardFooterView.swift b/MVMCoreUI/Molecules/StandardFooterView.swift index f00af028..7734883e 100644 --- a/MVMCoreUI/Molecules/StandardFooterView.swift +++ b/MVMCoreUI/Molecules/StandardFooterView.swift @@ -11,6 +11,8 @@ import UIKit open class StandardFooterView: ViewConstrainingView { open override func setupView() { super.setupView() + topMarginPadding = PaddingDefaultVerticalSpacing + bottomMarginPadding = PaddingDefaultVerticalSpacing shouldSetupMoleculeFromJSON = true updateViewVerticalDefaults = true updateViewHorizontalDefaults = true diff --git a/MVMCoreUI/Molecules/StandardHeaderView.swift b/MVMCoreUI/Molecules/StandardHeaderView.swift index 093a2e31..12819313 100644 --- a/MVMCoreUI/Molecules/StandardHeaderView.swift +++ b/MVMCoreUI/Molecules/StandardHeaderView.swift @@ -22,6 +22,8 @@ public class StandardHeaderView: ViewConstrainingView { shouldSetupMoleculeFromJSON = true updateViewVerticalDefaults = true updateViewHorizontalDefaults = true + topMarginPadding = PaddingDefaultVerticalSpacing + bottomMarginPadding = PaddingDefaultVerticalSpacing if separatorView == nil, let separatorView = SeparatorView.separatorAdd(to: self, position: SeparatorPositionBot, withHorizontalPadding: 0) { separatorView.setAsHeavy() addSubview(separatorView) @@ -54,6 +56,8 @@ public class StandardHeaderView: ViewConstrainingView { open override func reset() { super.reset() + topMarginPadding = PaddingDefaultVerticalSpacing + bottomMarginPadding = PaddingDefaultVerticalSpacing separatorView?.setAsHeavy() separatorView?.show() } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBody.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBody.swift index db30c8d6..e63eb2ba 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBody.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBody.swift @@ -32,6 +32,8 @@ open class HeadlineBody: ViewConstrainingView { stylePageHeader() case "item": styleListItem() + case "itemHeader": + styleListItemDivider() default: break } } @@ -53,6 +55,12 @@ open class HeadlineBody: ViewConstrainingView { messageLabel.styleB2(true) spaceBetweenLabelsConstant = 0 } + + func styleListItemDivider() { + headlineLabel.styleH3(true) + messageLabel.styleB2(true) + spaceBetweenLabelsConstant = 0 + } // MARK: - MVMCoreViewProtocol open override func updateView(_ size: CGFloat) { @@ -80,10 +88,9 @@ open class HeadlineBody: ViewConstrainingView { headlineLabel.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) messageLabel.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) - setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) + view.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) - topPin = headlineLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 0) - topPin?.isActive = true + headlineLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true spaceBetweenLabels = messageLabel.topAnchor.constraint(equalTo: headlineLabel.bottomAnchor, constant: spaceBetweenLabelsConstant) spaceBetweenLabels?.isActive = true @@ -100,8 +107,7 @@ open class HeadlineBody: ViewConstrainingView { rightConstraintMessage = view.rightAnchor.constraint(equalTo: messageLabel.rightAnchor) rightConstraintMessage?.isActive = true - bottomPin = view.bottomAnchor.constraint(equalTo: messageLabel.bottomAnchor, constant: 0) - bottomPin?.isActive = true + view.bottomAnchor.constraint(equalTo: messageLabel.bottomAnchor, constant: 0).isActive = true } // MARK: - Constraining From 0bb3c8a71932d8b9e5adde826b3cd206ad7cc464 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 23 Sep 2019 12:21:59 -0400 Subject: [PATCH 10/12] new molecule and gone state of stack. --- MVMCoreUI.xcodeproj/project.pbxproj | 4 ++ .../EyebrowHeadlineBodyLink.swift | 70 +++++++++++++++++++ MVMCoreUI/Organisms/MoleculeStackView.swift | 63 ++++++++++++----- .../MVMCoreUIMoleculeMappingObject.m | 3 +- 4 files changed, 123 insertions(+), 17 deletions(-) create mode 100644 MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index c1f4a798..17fc19f7 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -42,6 +42,7 @@ D260D7B622D68514007E7233 /* MVMCoreUIPagingProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D274CA332236A78900B01B62 /* StandardFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D274CA322236A78900B01B62 /* StandardFooterView.swift */; }; D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */; }; + D27CD4102339057800C1DC07 /* EyebrowHeadlineBodyLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27CD40F2339057800C1DC07 /* EyebrowHeadlineBodyLink.swift */; }; D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D282AAB3223FDDAE00C46919 /* MFLoadImageView.swift */; }; D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D282AAB9224131D100C46919 /* MFTransparentGIFView.swift */; }; D282AACB2243C61700C46919 /* ButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D282AACA2243C61700C46919 /* ButtonView.swift */; }; @@ -226,6 +227,7 @@ D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIPagingProtocol.h; sourceTree = ""; }; D274CA322236A78900B01B62 /* StandardFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StandardFooterView.swift; sourceTree = ""; }; D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsTableViewCell.swift; sourceTree = ""; }; + D27CD40F2339057800C1DC07 /* EyebrowHeadlineBodyLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EyebrowHeadlineBodyLink.swift; sourceTree = ""; }; D282AAB3223FDDAE00C46919 /* MFLoadImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MFLoadImageView.swift; sourceTree = ""; }; D282AAB9224131D100C46919 /* MFTransparentGIFView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MFTransparentGIFView.swift; sourceTree = ""; }; D282AACA2243C61700C46919 /* ButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonView.swift; sourceTree = ""; }; @@ -418,6 +420,7 @@ children = ( D2A638FC22CA98280052ED1F /* HeadlineBody.swift */, D22479952316AF6D003FCCF9 /* HeadlineBodyTextButton.swift */, + D27CD40F2339057800C1DC07 /* EyebrowHeadlineBodyLink.swift */, ); path = VerticalCombinationViews; sourceTree = ""; @@ -1067,6 +1070,7 @@ D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */, D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */, D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */, + D27CD4102339057800C1DC07 /* EyebrowHeadlineBodyLink.swift in Sources */, D29DF11D21E684A9003B2FB9 /* MVMCoreUISplitViewController.m in Sources */, 0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */, D29DF29821E7ADB8003B2FB9 /* MFScrollingViewController.m in Sources */, diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift new file mode 100644 index 00000000..306cf690 --- /dev/null +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift @@ -0,0 +1,70 @@ +// +// EyebrowHeadlineBodyLink.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 9/23/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +@objcMembers open class EyebrowHeadlineBodyLink: ViewConstrainingView { + let stack = MoleculeStackView(frame: .zero) + let eyebrow = Label.commonLabelB3(true) + let headline = Label.commonLabelB1(true) + let body = Label.commonLabelB2(true) + let link = MFTextButton(nil, constrainHeight: false, forWidth: MVMCoreUIUtility.getWidth()) + + // MARK: - MFViewProtocol + open override func setupView() { + super.setupView() + guard stack.superview == nil else { + return + } + stack.spacing = 0 + stack.updateViewHorizontalDefaults = false + addSubview(stack) + pinView(toSuperView: stack) + stack.addStackItem(StackItem(with: eyebrow), lastItem: false) + stack.addStackItem(StackItem(with: headline), lastItem: false) + stack.addStackItem(StackItem(with: body), lastItem: false) + + // To visually take into account the extra padding in the intrinsic content of a button. + let stackItem = StackItem(with: link) + stackItem.spacing = -6 + stack.addStackItem(stackItem, lastItem: true) + } + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + stack.updateView(size) + } + + // MARK: - MVMCoreUIMoleculeViewProtocol + open override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + eyebrow.setWithJSON(json?.optionalDictionaryForKey("eyebrow"), delegateObject: delegateObject, additionalData: additionalData) + stack.items[0].gone = !eyebrow.hasText + headline.setWithJSON(json?.optionalDictionaryForKey("headline"), delegateObject: delegateObject, additionalData: additionalData) + stack.items[1].gone = !headline.hasText + body.setWithJSON(json?.optionalDictionaryForKey("body"), delegateObject: delegateObject, additionalData: additionalData) + stack.items[2].gone = !body.hasText + link.setWithJSON(json?.optionalDictionaryForKey("link"), delegateObject: delegateObject, additionalData: additionalData) + stack.items[3].gone = link.titleLabel?.text?.count ?? 0 == 0 + stack.restack() + } + + open override func reset() { + super.reset() + stack.reset() + stack.spacing = 0 + stack.updateViewHorizontalDefaults = false + eyebrow.styleB3(true) + headline.styleB1(true) + body.styleB2(true) + } + + public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + return 65 + } +} diff --git a/MVMCoreUI/Organisms/MoleculeStackView.swift b/MVMCoreUI/Organisms/MoleculeStackView.swift index b2f70e6d..b8cd0baf 100644 --- a/MVMCoreUI/Organisms/MoleculeStackView.swift +++ b/MVMCoreUI/Organisms/MoleculeStackView.swift @@ -14,25 +14,27 @@ public class StackItem { var percentage: Int? var verticalAlignment: UIStackView.Alignment? var horizontalAlignment: UIStackView.Alignment? + var gone = false init(with view: UIView) { self.view = view } - init(with view: UIView, json: [AnyHashable: Any]) { + init(with view: UIView, json: [AnyHashable: Any]?) { self.view = view update(with: json) } - func update(with json: [AnyHashable: Any]) { - spacing = json.optionalCGFloatForKey("spacing") - percentage = json["percent"] as? Int - if let alignment = json.stringOptionalWithChainOfKeysOrIndexes([KeyMolecule,"verticalAlignment"]) { + func update(with json: [AnyHashable: Any]?) { + gone = (json == nil) + spacing = json?.optionalCGFloatForKey("spacing") + percentage = json?["percent"] as? Int + if let alignment = json?.stringOptionalWithChainOfKeysOrIndexes([KeyMolecule,"verticalAlignment"]) { verticalAlignment = ViewConstrainingView.getAlignmentFor(alignment, defaultAlignment: .fill) } else { verticalAlignment = nil } - if let alignment = json.stringOptionalWithChainOfKeysOrIndexes([KeyMolecule,"horizontalAlignment"]) { + if let alignment = json?.stringOptionalWithChainOfKeysOrIndexes([KeyMolecule,"horizontalAlignment"]) { horizontalAlignment = ViewConstrainingView.getAlignmentFor(alignment, defaultAlignment: .fill) } else { horizontalAlignment = nil @@ -84,11 +86,13 @@ public class MoleculeStackView: ViewConstrainingView { /// Restacks the existing items. func restack() { - MVMCoreUIStackableViewController.remove(contentView.subviews) - let stackItems = items - items.removeAll() - for (index, item) in stackItems.enumerated() { - addStackItem(item, lastItem: index == stackItems.count - 1) + setWithStackItems(items) + } + + /// Removes all stack items views from the view. + func removeAllItemViews() { + for item in items { + item.view.removeFromSuperview() } } @@ -144,7 +148,7 @@ public class MoleculeStackView: ViewConstrainingView { open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { let previousJSON = self.json super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - MVMCoreUIStackableViewController.remove(contentView.subviews) + removeAllItemViews() // If the items in the stack are the same, just update previous items instead of re-allocating. var items: [StackItem]? @@ -238,6 +242,10 @@ public class MoleculeStackView: ViewConstrainingView { /// Adds the stack item to the stack. func addStackItem(_ stackItem: StackItem, lastItem: Bool) { + guard !stackItem.gone else { + items.append(stackItem) + return + } let view = stackItem.view contentView.addSubview(view) view.translatesAutoresizingMaskIntoConstraints = false @@ -249,10 +257,15 @@ public class MoleculeStackView: ViewConstrainingView { view.alignHorizontal?(horizontalAlignment) view.alignVertical?(verticalAlignment) } + let first = items.first(where: { (stackItem) -> Bool in + return !stackItem.gone + }) == nil if axis == .vertical { - if items.count == 0 { + if first { pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: useStackSpacingBeforeFirstItem ? spacing : stackItem.spacing ?? 0) - } else if let previousView = items.last?.view { + } else if let previousView = items.last(where: { (stackItem) -> Bool in + return !stackItem.gone + })?.view { _ = NSLayoutConstraint(pinFirstView: previousView, toSecondView: view, withConstant: spacing, directionVertical: true) } pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: 0) @@ -264,10 +277,12 @@ public class MoleculeStackView: ViewConstrainingView { pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0) } } else { - if items.count == 0 { + if first { // First horizontal item has no spacing by default unless told otherwise. pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: useStackSpacingBeforeFirstItem ? spacing : stackItem.spacing ?? 0) - } else if let previousView = items.last?.view { + } else if let previousView = items.last(where: { (stackItem) -> Bool in + return !stackItem.gone + })?.view { _ = NSLayoutConstraint(pinFirstView: previousView, toSecondView: view, withConstant: spacing, directionVertical: false) } pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: 0) @@ -281,4 +296,20 @@ public class MoleculeStackView: ViewConstrainingView { } items.append(stackItem) } + + func setWithStackItems(_ items: [StackItem]) { + removeAllItemViews() + self.items.removeAll() + var previousPresentItem: StackItem? = nil + for item in items { + if !item.gone { + previousPresentItem = item + } + addStackItem(item, lastItem: false) + } + if let lastView = previousPresentItem?.view { + let attribute: NSLayoutConstraint.Attribute = axis == .vertical ? .bottom : .right + pinView(contentView, toView: lastView, attribute: attribute, relation: .equal, priority: .required, constant: 0) + } + } } diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 86267332..945eb7bf 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -60,7 +60,8 @@ @"headlineBodySwitch": HeadlineBodySwitch.class, @"headlineBodyTextButton": HeadlineBodyTextButton.class, @"headlineBodyTextButtonSwitch": HeadlineBodyTextButtonSwitch.class, - @"tabsListItem": TabsTableViewCell.class + @"tabsListItem": TabsTableViewCell.class, + @"eyebrowHeadlineBodyLink": EyebrowHeadlineBodyLink.class } mutableCopy]; }); return mapping; From a0f9470c27b7ac83ea2dcfc672854cf427c62c4b Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 23 Sep 2019 12:25:49 -0400 Subject: [PATCH 11/12] model driven gone --- MVMCoreUI/Organisms/MoleculeStackView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Organisms/MoleculeStackView.swift b/MVMCoreUI/Organisms/MoleculeStackView.swift index b8cd0baf..c8654fb5 100644 --- a/MVMCoreUI/Organisms/MoleculeStackView.swift +++ b/MVMCoreUI/Organisms/MoleculeStackView.swift @@ -26,7 +26,7 @@ public class StackItem { } func update(with json: [AnyHashable: Any]?) { - gone = (json == nil) + gone = json?.boolForKey("gone") ?? (json == nil) spacing = json?.optionalCGFloatForKey("spacing") percentage = json?["percent"] as? Int if let alignment = json?.stringOptionalWithChainOfKeysOrIndexes([KeyMolecule,"verticalAlignment"]) { From 5b5a03b869deea9358846419596f1ea1f18c6069 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 23 Sep 2019 13:30:35 -0400 Subject: [PATCH 12/12] condensing --- MVMCoreUI/Organisms/MoleculeStackView.swift | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Organisms/MoleculeStackView.swift b/MVMCoreUI/Organisms/MoleculeStackView.swift index c8654fb5..14ad9e70 100644 --- a/MVMCoreUI/Organisms/MoleculeStackView.swift +++ b/MVMCoreUI/Organisms/MoleculeStackView.swift @@ -257,13 +257,11 @@ public class MoleculeStackView: ViewConstrainingView { view.alignHorizontal?(horizontalAlignment) view.alignVertical?(verticalAlignment) } - let first = items.first(where: { (stackItem) -> Bool in - return !stackItem.gone - }) == nil + let first = items.first { !$0.gone } == nil if axis == .vertical { if first { pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: useStackSpacingBeforeFirstItem ? spacing : stackItem.spacing ?? 0) - } else if let previousView = items.last(where: { (stackItem) -> Bool in + } else if let previousView = items.last(where: { stackItem in return !stackItem.gone })?.view { _ = NSLayoutConstraint(pinFirstView: previousView, toSecondView: view, withConstant: spacing, directionVertical: true) @@ -280,7 +278,7 @@ public class MoleculeStackView: ViewConstrainingView { if first { // First horizontal item has no spacing by default unless told otherwise. pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: useStackSpacingBeforeFirstItem ? spacing : stackItem.spacing ?? 0) - } else if let previousView = items.last(where: { (stackItem) -> Bool in + } else if let previousView = items.last(where: { stackItem in return !stackItem.gone })?.view { _ = NSLayoutConstraint(pinFirstView: previousView, toSecondView: view, withConstant: spacing, directionVertical: false)