From e5ca7b5c9e2996091496750180a871843d3cbf97 Mon Sep 17 00:00:00 2001 From: "Murugan, Vimal" Date: Thu, 2 Jan 2020 21:33:31 +0530 Subject: [PATCH] bullet list molecule added --- MVMCoreUI.xcodeproj/project.pbxproj | 4 + MVMCoreUI/Molecules/BulletList.swift | 233 ++++++++++++++++++ .../MVMCoreUIMoleculeMappingObject.m | 3 +- 3 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 MVMCoreUI/Molecules/BulletList.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index e8c26f4c..14506f07 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -32,6 +32,7 @@ 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */; }; 9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */; }; 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948DB67D2326DCD90011F916 /* MultiProgress.swift */; }; + C63D632123BDC3A0008F3B1F /* BulletList.swift in Sources */ = {isa = PBXBuildFile; fileRef = C63D632023BDC3A0008F3B1F /* BulletList.swift */; }; D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; D224798A2314445E003FCCF9 /* LabelSwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22479892314445E003FCCF9 /* LabelSwitch.swift */; }; @@ -233,6 +234,7 @@ 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphViewAnimationHandler.swift; sourceTree = ""; }; 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MVMAnimationFramework.framework; path = ../SharedFrameworks/MVMAnimationFramework.framework; sourceTree = ""; }; 948DB67D2326DCD90011F916 /* MultiProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgress.swift; sourceTree = ""; }; + C63D632023BDC3A0008F3B1F /* BulletList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BulletList.swift; sourceTree = ""; }; D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = ""; }; D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; D22479892314445E003FCCF9 /* LabelSwitch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelSwitch.swift; sourceTree = ""; }; @@ -633,6 +635,7 @@ 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */, 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */, D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */, + C63D632023BDC3A0008F3B1F /* BulletList.swift */, ); path = Molecules; sourceTree = ""; @@ -1177,6 +1180,7 @@ 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */, D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */, D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */, + C63D632123BDC3A0008F3B1F /* BulletList.swift in Sources */, 0105618E224BBE7700E1557D /* FormValidator+TextFields.swift in Sources */, 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */, D2B18B922361E65A00A9AEDC /* CoreUIObject.swift in Sources */, diff --git a/MVMCoreUI/Molecules/BulletList.swift b/MVMCoreUI/Molecules/BulletList.swift new file mode 100644 index 00000000..f680b36a --- /dev/null +++ b/MVMCoreUI/Molecules/BulletList.swift @@ -0,0 +1,233 @@ +// +// BulletList.swift +// MVMCoreUI +// +// Created by Murugan, Vimal on 02/01/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +open class BulletList: Container { + + var contentView = MVMCoreUICommonViewsUtility.commonView() + var reusableViews: [LeftRightLabelView] = [] + var bulletChar: String? + + /// Restacks the existing items. + func restack() { + //setWithStackItems(items) + } + + /// Removes all stack items views from the view. + func removeAllItemInViews() { + reusableViews.forEach({ $0.removeFromSuperview() }) + } + + /// The spacing to use between each item in the stack. + var verticalSpacing: CGFloat = 8 { + didSet { + if verticalSpacing != oldValue { + restack() + } + } + } + + // MARK: - Inits + public override init() { + super.init() + } + + public override init(frame: CGRect) { + super.init(frame: frame) + } + + public init(withJSON json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + super.init(frame: CGRect.zero) + setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - Helpers + public func pinView(_ view: UIView, toView: UIView, attribute: NSLayoutConstraint.Attribute, relation: NSLayoutConstraint.Relation, priority: UILayoutPriority, constant: CGFloat) { + let constraint = NSLayoutConstraint(item: view, attribute: attribute, relatedBy: relation, toItem: toView, attribute: attribute, multiplier: 1.0, constant: constant) + constraint.priority = priority + constraint.isActive = true + } + + // MARK: - MFViewProtocol + public override func setupView() { + super.setupView() + guard contentView.superview == nil else { + return + } + MVMCoreUIUtility.setMarginsFor(contentView, leading: 0, top: 0, trailing: 0, bottom: 0) + translatesAutoresizingMaskIntoConstraints = false + backgroundColor = .clear + addSubview(contentView) + containerHelper.constrainView(contentView) + contentView.setContentHuggingPriority(.defaultHigh, for: .vertical) + contentView.setContentHuggingPriority(.defaultHigh, for: .horizontal) + } + + public override func updateView(_ size: CGFloat) { + super.updateView(size) + directionalLayoutMargins.leading = 0 + directionalLayoutMargins.trailing = 0 + } + + // MARK: - MVMCoreUIMoleculeViewProtocol + public override func reset() { + super.reset() + backgroundColor = .clear + } + + open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + // let previousJSON = self.json + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + removeAllItemInViews() + guard let list = json?.arrayForKey("list") as? [[String: Any]] else { + return + } + + bulletChar = json?.optionalStringForKey("bulletChar") + + var views = [LeftLabelRightContainer]() + // Adds the molecules and sets the json. + for (index, map) in list.enumerated() { + let view = LeftLabelRightContainer() + let moleculeMap = ["left": leftItem(bulletChar ?? String(index + 1)), "right": map] + view.setWithJSON(moleculeMap, delegateObject: delegateObject, additionalData: additionalData) + views.append(view) + } + let lastObj = views.last + MVMCoreUIStackableViewController.populateView(contentView, withUIArray: views) { (obj) -> UIEdgeInsets in + return UIEdgeInsets(top: 0, left: 0, bottom: lastObj?.isEqual(obj) ?? false ? 0 : 16, right: 0) + } + } + + public class func name(forReuse molecule: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? { + // This will aggregate names of molecules to make an id. + guard let molecules = molecule?.optionalArrayForKey("list") else { + return "stack<>" + } + var name = "stack<" + for case let item as [AnyHashable: Any] in molecules { + if let molecule = item.optionalDictionaryForKey(KeyMolecule), let moleculeName = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule)?.name?(forReuse: molecule, delegateObject: delegateObject) ?? molecule.optionalStringForKey(KeyMoleculeName) { + name.append(moleculeName + ",") + } + } + name.append(">") + return name + } + + public class func requiredModules(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + guard let items = json?.optionalArrayForKey("list") else { + return nil + } + var modules: [String] = [] + for case let item as [AnyHashable: AnyHashable] in items { + if let molecule = item.optionalDictionaryForKey(KeyMolecule), let modulesForMolecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule)?.requiredModules?(molecule, delegateObject: delegateObject, error: error) { + modules += modulesForMolecule + } + } + return modules.count > 0 ? modules : nil + } + + func leftItem(_ string: String) -> [String: Any] { + return ["moleculeName":"label","text":string, "fontStyle":"B2"] + } + +} + +class LeftLabelRightContainer: View { + + var label = Label.commonLabelB2(true) + var rightContainer = MVMCoreUICommonViewsUtility.commonView() + var leftContainer = MVMCoreUICommonViewsUtility.commonView() + var rightMoleculeName: String? + var rightMolecule: View? + let containerHelper = ContainerHelper() + + var constraintBtwViews: NSLayoutConstraint? + var spaceBtwViews: CGFloat = 8 { + didSet { + if spaceBtwViews != oldValue { + constraintBtwViews?.constant = spaceBtwViews + layoutIfNeeded() + } + } + } + + override func setupView() { + super.setupView() + + guard rightContainer.superview == nil else { + return + } + + translatesAutoresizingMaskIntoConstraints = false + addSubview(rightContainer) + addSubview(leftContainer) + leftContainer.addSubview(label) + NSLayoutConstraint.constraintPinSubview(toSuperview: label) + + NSLayoutConstraint.constraintPinSubview(leftContainer, pinTop: true, pinBottom: false, pinLeft: true, pinRight: false) + bottomAnchor.constraint(greaterThanOrEqualTo: leftContainer.bottomAnchor).isActive = true + + NSLayoutConstraint.constraintPinSubview(rightContainer, pinTop: true, pinBottom: true, pinLeft: false, pinRight: true) + constraintBtwViews = rightContainer.leftAnchor.constraint(equalTo: leftContainer.rightAnchor, constant: spaceBtwViews) + constraintBtwViews?.priority = .required + constraintBtwViews?.isActive = true + + //TODO: Need to get confirmation on this + leftContainer.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.05, constant: 0).isActive = true + setContentHuggingPriority(.defaultHigh, for: .vertical) + setContentHuggingPriority(.defaultHigh, for: .horizontal) + rightContainer.setContentHuggingPriority(.defaultHigh, for: .vertical) + rightContainer.setContentHuggingPriority(.defaultHigh, for: .horizontal) + + label.setContentHuggingPriority(.defaultHigh, for: .horizontal) + label.setContentHuggingPriority(.defaultHigh, for: .vertical) + + } + + override func updateView(_ size: CGFloat) { + super.updateView(size) + } + + override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + let previousMoleculeName = rightMoleculeName + guard let moleculeJSON = json?.optionalDictionaryForKey("right") else { + removeSubviewsInRightContainer() + return + } + + Label.setUILabel(label, withJSON: json?.optionalDictionaryForKey("left"), delegate: delegateObject, additionalData: additionalData) + rightMoleculeName = moleculeJSON.optionalStringForKey(KeyMoleculeName) + //For reuse purpose check that allready added molecule is same + if rightMolecule != nil && previousMoleculeName == rightMoleculeName { + rightMolecule?.setWithJSON(json?.optionalDictionaryForKey("right"), delegateObject: delegateObject, additionalData: additionalData) + } else { + removeSubviewsInRightContainer() + if let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject, constrainIfNeeded: false) { + addView(molecule) + } + } + } + + func removeSubviewsInRightContainer() { + rightContainer.subviews.forEach({ $0.removeFromSuperview() }) + } + + func addView(_ view: UIView) { + view.translatesAutoresizingMaskIntoConstraints = false + rightContainer.addSubview(view) + containerHelper.constrainView(view) + rightMolecule = view as? View + } +} diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 9db7822d..47bbac98 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -66,7 +66,8 @@ @"tabsListItem": TabsTableViewCell.class, @"dropDownListItem": DropDownFilterTableViewCell.class, @"headlineBodyButton": HeadlineBodyButton.class, - @"eyebrowHeadlineBodyLink": EyebrowHeadlineBodyLink.class + @"eyebrowHeadlineBodyLink": EyebrowHeadlineBodyLink.class, + @"bulletList": BulletList.class } mutableCopy]; }); return mapping;