From a7f9104bd8e96e3681580f00ae1fae1200f0507d Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 20 Jun 2019 16:04:59 -0400 Subject: [PATCH 01/20] re-molecule image view --- MVMCoreUI/Atoms/Views/MFLoadImageView.swift | 120 +++++++++--------- MVMCoreUI/Molecules/MoleculeStackView.swift | 2 +- .../Molecules/MoleculeTableViewCell.swift | 5 + .../MVMCoreUIMoleculeMappingObject.m | 3 +- 4 files changed, 66 insertions(+), 64 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift index 2a72481e..c11ffffe 100644 --- a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift +++ b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift @@ -22,6 +22,7 @@ import UIKit var edges: UIRectEdge? var spinnerHeight: CGFloat? var width: CGFloat? + var height: CGFloat? var loadingImageName: String? var isFallbackImage: Bool = false @@ -50,62 +51,24 @@ import UIKit imageView.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: NSLayoutConstraint.Axis.vertical) } - if let topPin = topPin { - removeConstraint(topPin) - } - if edge.contains(UIRectEdge.top) { - topPin = imageView.topAnchor.constraint(equalTo: topAnchor) + if edge.contains(UIRectEdge.top) && edge.contains(UIRectEdge.bottom) { + alignFillVertical() + } else if edge.contains(UIRectEdge.top) { + alignTop() + } else if edge.contains(UIRectEdge.bottom) { + alignBottom() } else { - topPin = imageView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor) + alignCenterVertical() } - topPin?.isActive = true - if let bottomPin = bottomPin { - removeConstraint(bottomPin) - } - if edge.contains(UIRectEdge.bottom) { - bottomPin = bottomAnchor.constraint(equalTo: imageView.bottomAnchor) + if edge.contains(UIRectEdge.left) && edge.contains(UIRectEdge.right) { + alignFillHorizontal() + } else if edge.contains(UIRectEdge.left) { + alignLeft() + } else if edge.contains(UIRectEdge.right) { + alignRight() } else { - bottomPin = bottomAnchor.constraint(greaterThanOrEqualTo: imageView.bottomAnchor) - } - bottomPin?.isActive = true - - if let leftPin = leftPin { - removeConstraint(leftPin) - } - if edge.contains(UIRectEdge.left) { - leftPin = imageView.leftAnchor.constraint(equalTo: leftAnchor) - } else { - leftPin = imageView.leftAnchor.constraint(greaterThanOrEqualTo: leftAnchor) - } - leftPin?.isActive = true - - if let rightPin = rightPin { - removeConstraint(rightPin) - } - if edge.contains(UIRectEdge.right) { - rightPin = rightAnchor.constraint(equalTo: imageView.rightAnchor) - } else { - rightPin = rightAnchor.constraint(greaterThanOrEqualTo: imageView.rightAnchor) - } - rightPin?.isActive = true - - // If neither the top or the bottom are pinned, center it. - if let centerY = centerY { - removeConstraint(centerY) - } - if !edge.contains(UIRectEdge.top) && !edge.contains(UIRectEdge.bottom) { - centerY = imageView.centerYAnchor.constraint(equalTo: centerYAnchor) - centerY?.isActive = true - } - - // If neither the left or the right are pinned, center it. - if let centerX = centerX { - removeConstraint(centerX) - } - if !edge.contains(UIRectEdge.left) && !edge.contains(UIRectEdge.right) { - centerX = imageView.centerXAnchor.constraint(equalTo: centerXAnchor) - centerX?.isActive = true + alignCenterHorizontal() } } @@ -121,6 +84,7 @@ import UIKit // Setup image. imageView.translatesAutoresizingMaskIntoConstraints = false; addSubview(imageView) + pinView(toSuperView: imageView) // Setup edges constraints if edges == nil { @@ -162,7 +126,27 @@ import UIKit guard let currentWidth = self.width else { return true } - return (imageView.image == nil && imageView.animatedImage == nil) || imageName != loadingImageName || !MVMCoreGetterUtility.cgfequal(width, currentWidth) || self.isFallbackImage + return (imageView.image == nil && imageView.animatedImage == nil) || imageName != loadingImageName || !MVMCoreGetterUtility.cgfequal(width, currentWidth) || isFallbackImage + } + + open func shouldLoadImage(withName imageName: String?, width: CGFloat?, height: CGFloat?) -> Bool { + // We should load a new image if there is no current image, the image names are different, or we are using a fallback image. + if ((imageView.image == nil && imageView.animatedImage == nil) || imageName != loadingImageName || isFallbackImage) { + return true + } + // load new image if the width is different + if let oldWidth = self.width, let newWidth = width, !MVMCoreGetterUtility.cgfequal(oldWidth, newWidth) { + return true + } else if (self.width != nil && width == nil) || (self.width == nil && width != nil) { + return true + } + // load new image if the height is different + if let oldHeight = self.height, let newHeight = height, !MVMCoreGetterUtility.cgfequal(oldHeight, newHeight) { + return true + } else if (self.height != nil && height == nil) || (self.height == nil && height != nil) { + return true + } + return false } // Constrains the image view to be the size provided. Used to size it to the image to fix aspect fit defect. @@ -191,17 +175,11 @@ import UIKit imageView.setContentHuggingPriority(UILayoutPriority.defaultLow, for: NSLayoutConstraint.Axis.vertical) } - open override func updateView(_ size: CGFloat) { - super.updateView(size) - let width = size.rounded() - if let imageName = json?.optionalStringForKey("image"), shouldLoadImage(withName: imageName, width: width) { - imageView.image = nil - imageView.animatedImage = nil - loadImage(withName: imageName, format: json?.optionalStringForKey("imageFormat"), width: NSNumber(value: Double(width)), height: nil, customFallbackImage: json?.optionalStringForKey("fallbackImage")) - } + // MARK: - MVMCoreUIMoleculeViewProtocol functions + open override func setAsMolecule() { + addSizeConstraintsForAspectRatio = true } - // MARK: - MVMCoreUIMoleculeViewProtocol functions open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) if let backgroundColorString = json?.optionalStringForKey(KeyBackgroundColor) { @@ -212,6 +190,21 @@ import UIKit imageView.accessibilityTraits = .staticText imageView.isAccessibilityElement = true } + let width = json?.optionalCGFloatForKey("width") + let height = json?.optionalCGFloatForKey("height") + if let imageName = json?.optionalStringForKey("image"), shouldLoadImage(withName: imageName, width: width, height: height) { + imageView.image = nil + imageView.animatedImage = nil + var widthNumber: NSNumber? + if let width = width { + widthNumber = NSNumber(value: Double(width)) + } + var heightNumber: NSNumber? + if let height = height { + heightNumber = NSNumber(value: Double(height)) + } + loadImage(withName: imageName, format: json?.optionalStringForKey("imageFormat"), width: widthNumber, height: heightNumber, customFallbackImage: json?.optionalStringForKey("fallbackImage")) + } } // MARK: - load functions @@ -221,6 +214,9 @@ import UIKit if let width = width { self.width = width.cgfloat() } + if let height = height { + self.height = height.cgfloat() + } self.loadingSpinner.resumeSpinnerAfterDelay() if let height = self.spinnerHeight { self.loadingSpinnerHeightConstraint?.constant = height diff --git a/MVMCoreUI/Molecules/MoleculeStackView.swift b/MVMCoreUI/Molecules/MoleculeStackView.swift index 7c72cf09..d2a70402 100644 --- a/MVMCoreUI/Molecules/MoleculeStackView.swift +++ b/MVMCoreUI/Molecules/MoleculeStackView.swift @@ -163,7 +163,7 @@ public class MoleculeStackView: ViewConstrainingView { alignVertical(ViewConstrainingView.getAlignmentFor(json?.optionalStringForKey("alignment"), defaultAlignment: .fill)) } else { alignHorizontal(ViewConstrainingView.getAlignmentFor(json?.optionalStringForKey("alignment"), defaultAlignment: .fill)) - alignVertical(.leading) + alignVertical(.fill) } // Adds the molecules and sets the json. diff --git a/MVMCoreUI/Molecules/MoleculeTableViewCell.swift b/MVMCoreUI/Molecules/MoleculeTableViewCell.swift index 695b5849..be6f1a71 100644 --- a/MVMCoreUI/Molecules/MoleculeTableViewCell.swift +++ b/MVMCoreUI/Molecules/MoleculeTableViewCell.swift @@ -105,6 +105,11 @@ import UIKit } } else { molecule?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData) + if let castView = molecule as? MVMCoreUIViewConstrainingProtocol { + let standardConstraints = castView.useStandardConstraints?() ?? true + castView.shouldSetHorizontalMargins?(!standardConstraints) + castView.shouldSetVerticalMargins?(!standardConstraints) + } } backgroundColor = molecule?.backgroundColor diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 309491bf..07d3e548 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -42,7 +42,8 @@ @"checkbox": MVMCoreUICheckBox.class, @"listItem": MoleculeTableViewCell.class, @"switchLineItem": SwitchLineItem.class, - @"switch": Switch.class + @"switch": Switch.class, + @"image": MFLoadImageView.class } mutableCopy]; }); return mapping; From 086378608d7882e10c898320603366eeb46d01be Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 21 Jun 2019 08:56:57 -0400 Subject: [PATCH 02/20] small logic cleaning --- MVMCoreUI/Atoms/Views/MFLoadImageView.swift | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift index c11ffffe..9d101646 100644 --- a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift +++ b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift @@ -137,13 +137,13 @@ import UIKit // load new image if the width is different if let oldWidth = self.width, let newWidth = width, !MVMCoreGetterUtility.cgfequal(oldWidth, newWidth) { return true - } else if (self.width != nil && width == nil) || (self.width == nil && width != nil) { + } else if (self.width == nil) != (width == nil) { return true } // load new image if the height is different if let oldHeight = self.height, let newHeight = height, !MVMCoreGetterUtility.cgfequal(oldHeight, newHeight) { return true - } else if (self.height != nil && height == nil) || (self.height == nil && height != nil) { + } else if (self.height == nil) || (height == nil) { return true } return false @@ -195,15 +195,7 @@ import UIKit if let imageName = json?.optionalStringForKey("image"), shouldLoadImage(withName: imageName, width: width, height: height) { imageView.image = nil imageView.animatedImage = nil - var widthNumber: NSNumber? - if let width = width { - widthNumber = NSNumber(value: Double(width)) - } - var heightNumber: NSNumber? - if let height = height { - heightNumber = NSNumber(value: Double(height)) - } - loadImage(withName: imageName, format: json?.optionalStringForKey("imageFormat"), width: widthNumber, height: heightNumber, customFallbackImage: json?.optionalStringForKey("fallbackImage")) + loadImage(withName: imageName, format: json?.optionalStringForKey("imageFormat"), width: width as NSNumber?, height: height as NSNumber?, customFallbackImage: json?.optionalStringForKey("fallbackImage")) } } From dc62e16c074ddcdd3cefd0e139f868d31bad8994 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 21 Jun 2019 09:28:51 -0400 Subject: [PATCH 03/20] image view name change, allow view override of width and height --- MVMCoreUI/Atoms/Views/MFLoadImageView.swift | 50 ++++++++++----------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift index 9d101646..9bd22c19 100644 --- a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift +++ b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift @@ -18,13 +18,17 @@ import UIKit var heightConstraint: NSLayoutConstraint? var loadingSpinnerHeightConstraint: NSLayoutConstraint? + // Allows for a view to hardcode which height to use if there is none in the json. + var imageWidth: CGFloat? + var imageHeight: CGFloat? + // For keeping track of current state. - var edges: UIRectEdge? - var spinnerHeight: CGFloat? - var width: CGFloat? - var height: CGFloat? - var loadingImageName: String? - var isFallbackImage: Bool = false + private var edges: UIRectEdge? + private var spinnerHeight: CGFloat? + private var currentImageWidth: CGFloat? + private var currentImageHeight: CGFloat? + private var currentImageName: String? + private var isFallbackImage: Bool = false public init(pinnedEdges edge: UIRectEdge) { edges = edge @@ -123,27 +127,27 @@ import UIKit open func shouldLoadImage(withName imageName: String?, width: CGFloat) -> Bool { // We should load a new image if there is no current image, the image names are different, the width is different, or we are using a fallback image. - guard let currentWidth = self.width else { + guard let currentWidth = self.currentImageWidth else { return true } - return (imageView.image == nil && imageView.animatedImage == nil) || imageName != loadingImageName || !MVMCoreGetterUtility.cgfequal(width, currentWidth) || isFallbackImage + return (imageView.image == nil && imageView.animatedImage == nil) || imageName != currentImageName || !MVMCoreGetterUtility.cgfequal(width, currentWidth) || isFallbackImage } open func shouldLoadImage(withName imageName: String?, width: CGFloat?, height: CGFloat?) -> Bool { // We should load a new image if there is no current image, the image names are different, or we are using a fallback image. - if ((imageView.image == nil && imageView.animatedImage == nil) || imageName != loadingImageName || isFallbackImage) { + if ((imageView.image == nil && imageView.animatedImage == nil) || imageName != currentImageName || isFallbackImage) { return true } // load new image if the width is different - if let oldWidth = self.width, let newWidth = width, !MVMCoreGetterUtility.cgfequal(oldWidth, newWidth) { + if let oldWidth = self.currentImageWidth, let newWidth = width, !MVMCoreGetterUtility.cgfequal(oldWidth, newWidth) { return true - } else if (self.width == nil) != (width == nil) { + } else if (self.currentImageWidth == nil) != (width == nil) { return true } // load new image if the height is different - if let oldHeight = self.height, let newHeight = height, !MVMCoreGetterUtility.cgfequal(oldHeight, newHeight) { + if let oldHeight = self.currentImageHeight, let newHeight = height, !MVMCoreGetterUtility.cgfequal(oldHeight, newHeight) { return true - } else if (self.height == nil) || (height == nil) { + } else if (self.currentImageHeight == nil) || (height == nil) { return true } return false @@ -190,8 +194,8 @@ import UIKit imageView.accessibilityTraits = .staticText imageView.isAccessibilityElement = true } - let width = json?.optionalCGFloatForKey("width") - let height = json?.optionalCGFloatForKey("height") + let width = json?.optionalCGFloatForKey("width") ?? imageWidth + let height = json?.optionalCGFloatForKey("height") ?? imageHeight if let imageName = json?.optionalStringForKey("image"), shouldLoadImage(withName: imageName, width: width, height: height) { imageView.image = nil imageView.animatedImage = nil @@ -202,20 +206,16 @@ import UIKit // MARK: - load functions public func loadImage(withName imageName: String?, format: String?, width: NSNumber?, height: NSNumber?, customFallbackImage: String?, completionHandler: @escaping MVMCoreGetImageBlock) { MVMCoreDispatchUtility.performBlock(onMainThread: { [unowned self] in - self.loadingImageName = imageName - if let width = width { - self.width = width.cgfloat() - } - if let height = height { - self.height = height.cgfloat() - } + self.currentImageName = imageName + self.currentImageWidth = width?.cgfloat() + self.currentImageHeight = height?.cgfloat() self.loadingSpinner.resumeSpinnerAfterDelay() if let height = self.spinnerHeight { self.loadingSpinnerHeightConstraint?.constant = height } let finishedLoadingBlock: MVMCoreGetImageBlock = {[weak self] (image, data, isFallbackImage) in MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in - guard let loadingImageName = self?.loadingImageName, loadingImageName == imageName else { + guard let loadingImageName = self?.currentImageName, loadingImageName == imageName else { return } self?.isFallbackImage = isFallbackImage @@ -238,14 +238,14 @@ import UIKit public func loadCroppedImage(withName imageName: String?, width: NSNumber?, height: NSNumber?, cropRect: CGRect, flipImage: Bool, customFallbackImage: String?) { MVMCoreDispatchUtility.performBlock(onMainThread: { [unowned self] in - self.loadingImageName = imageName + self.currentImageName = imageName self.loadingSpinner.resumeSpinnerAfterDelay() if let height = self.spinnerHeight { self.loadingSpinnerHeightConstraint?.constant = height } MVMCoreCache.shared()?.getCroppedImage(imageName, useWidth: width != nil, widthForS7: width?.intValue ?? 0, useHeight: height != nil, heightForS7: height?.intValue ?? 0, finalRect: cropRect, flipImage: flipImage, localFallbackImageName: customFallbackImage ?? MVMCoreUIUtility.localizedImageName("fallback"), completionHandler: { [weak self] (image, data, isFallBackImage) in MVMCoreDispatchUtility.performBlock(onMainThread: { - guard let image = image, let loadingImageName = self?.loadingImageName, loadingImageName == imageName else { + guard let image = image, let loadingImageName = self?.currentImageName, loadingImageName == imageName else { return } self?.loadingSpinnerHeightConstraint?.constant = 0 From ed87bd2cfcf3ae5691022f876f87d8548a3d2e0d Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 21 Jun 2019 12:52:30 -0400 Subject: [PATCH 04/20] Button json to have style and size. Separator alone in stack fix. remove view constraining view auto background color fix padding for stack in stack --- MVMCoreUI/Atoms/Buttons/PrimaryButton.m | 16 ++++++++++- MVMCoreUI/Atoms/Views/SeparatorView.h | 3 ++- MVMCoreUI/Atoms/Views/SeparatorView.m | 6 +++++ MVMCoreUI/Atoms/Views/ViewConstrainingView.m | 4 ++- MVMCoreUI/Molecules/MoleculeStackView.swift | 27 ++++++++++++++----- .../Molecules/MoleculeTableViewCell.swift | 21 ++++++--------- .../MVMCoreUIMoleculeMappingObject.m | 1 - .../Templates/MoleculeListTemplate.swift | 2 ++ .../Templates/MoleculeStackTemplate.swift | 7 ++++- 9 files changed, 62 insertions(+), 25 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/PrimaryButton.m b/MVMCoreUI/Atoms/Buttons/PrimaryButton.m index 74a1e41a..57470bf9 100644 --- a/MVMCoreUI/Atoms/Buttons/PrimaryButton.m +++ b/MVMCoreUI/Atoms/Buttons/PrimaryButton.m @@ -669,6 +669,13 @@ [FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol]; self.primaryButtonType = PrimaryButtonTypeCustom; + NSString *style = [json string:@"style"]; + if ([style isEqualToString:@"primary"]) { + [self setAsStandardCustom]; + } else if ([style isEqualToString:@"secondary"]) { + [self setAsSecondaryCustom]; + } + NSString *color = [json string:@"fillColor"]; if (color) { self.fillColor = [UIColor mfGetColorForHex:color]; @@ -691,7 +698,14 @@ } self.validationRequired = [json boolForKey:@"validationRequired"]; - [self setAsSmallButton:[json boolForKey:@"small"]]; + NSString *size = [json string:@"size"]; + if ([size isEqualToString:@"small"]) { + [self setAsSmallButton:YES]; + } else if ([size isEqualToString:@"tiny"]) { + [self setAsTiny:YES]; + } else { + [self setAsSmallButton:NO]; + } [self setWithActionMap:json delegateObject:delegateObject additionalData:additionalData]; } diff --git a/MVMCoreUI/Atoms/Views/SeparatorView.h b/MVMCoreUI/Atoms/Views/SeparatorView.h index 78fe65e8..89a9197d 100644 --- a/MVMCoreUI/Atoms/Views/SeparatorView.h +++ b/MVMCoreUI/Atoms/Views/SeparatorView.h @@ -8,6 +8,7 @@ #import #import +#import @class MFSizeObject; typedef enum : NSUInteger { @@ -15,7 +16,7 @@ typedef enum : NSUInteger { SeparatorPositionBot } SeparatorPosition; -@interface SeparatorView : MFView +@interface SeparatorView : MFView @property (nullable, weak, nonatomic) NSLayoutConstraint *height; @property (nullable, weak, nonatomic) NSLayoutConstraint *leftPin; diff --git a/MVMCoreUI/Atoms/Views/SeparatorView.m b/MVMCoreUI/Atoms/Views/SeparatorView.m index 2734bc94..44e95d3c 100644 --- a/MVMCoreUI/Atoms/Views/SeparatorView.m +++ b/MVMCoreUI/Atoms/Views/SeparatorView.m @@ -165,5 +165,11 @@ [self setNeedsLayout]; [self layoutIfNeeded]; } + +#pragma mark - Molecule + +- (BOOL)needsToBeConstrained { + return YES; +} @end diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m index a7412b93..44445a3e 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m @@ -267,6 +267,9 @@ - (void)shouldSetHorizontalMargins:(BOOL)shouldSet { self.updateViewHorizontalDefaults = shouldSet; } + +- (void)shouldSetVerticalMargins:(BOOL)shouldSet { +} #pragma mark - MVMCoreViewProtocol @@ -307,7 +310,6 @@ [super setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; if (self.molecule) { [self.molecule setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; - self.backgroundColor = self.molecule.backgroundColor; } } diff --git a/MVMCoreUI/Molecules/MoleculeStackView.swift b/MVMCoreUI/Molecules/MoleculeStackView.swift index d2a70402..8c6e76bf 100644 --- a/MVMCoreUI/Molecules/MoleculeStackView.swift +++ b/MVMCoreUI/Molecules/MoleculeStackView.swift @@ -39,11 +39,14 @@ public class StackItem { public class MoleculeStackView: ViewConstrainingView { var contentView: UIView = MVMCoreUICommonViewsUtility.commonView() var items: [StackItem] = [] + var useStackSpacingBeforeFirstItem = false + private var moleculesShouldSetHorizontalMargins = true + private var moleculesShouldSetVerticalMargins = false + /// For setting the direction of the stack var axis: NSLayoutConstraint.Axis = .vertical { didSet { - updateViewHorizontalDefaults = axis == .horizontal if axis != oldValue { restack() } @@ -133,6 +136,17 @@ public class MoleculeStackView: ViewConstrainingView { } } + // If this item is in another container, do have the child molecules not use alignment. + public override func shouldSetHorizontalMargins(_ shouldSet: Bool) { + super.shouldSetHorizontalMargins(shouldSet) + moleculesShouldSetHorizontalMargins = false + } + + public override func shouldSetVerticalMargins(_ shouldSet: Bool) { + super.shouldSetVerticalMargins(shouldSet) + moleculesShouldSetVerticalMargins = false + } + open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { let previousJSON = self.json super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) @@ -171,7 +185,6 @@ public class MoleculeStackView: ViewConstrainingView { if let moleculeJSON = map.optionalDictionaryForKey(KeyMolecule) { var view: UIView? if let item = items?[index] { - (item.view as? MVMCoreUIMoleculeViewProtocol)?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData) item.update(with: moleculeJSON) view = item.view addStackItem(item, lastItem: index == molecules.count - 1) @@ -179,9 +192,9 @@ public class MoleculeStackView: ViewConstrainingView { view = molecule addStackItem(StackItem(with: molecule, json: map), lastItem: index == molecules.count - 1) } - - (view as? MVMCoreUIViewConstrainingProtocol)?.shouldSetHorizontalMargins?(axis == .vertical) - (view as? MVMCoreUIViewConstrainingProtocol)?.shouldSetVerticalMargins?(false) + (view as? MVMCoreUIViewConstrainingProtocol)?.shouldSetHorizontalMargins?(moleculesShouldSetHorizontalMargins && axis == .vertical) + (view as? MVMCoreUIViewConstrainingProtocol)?.shouldSetVerticalMargins?(moleculesShouldSetVerticalMargins) + (view as? MVMCoreUIMoleculeViewProtocol)?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: nil) } } } @@ -221,7 +234,7 @@ public class MoleculeStackView: ViewConstrainingView { } if axis == .vertical { if items.count == 0 { - pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: spacing) + pinView(view, toView: contentView, attribute: .top, relation: .equal, priority: .required, constant: useStackSpacingBeforeFirstItem ? spacing : stackItem.spacing ?? 0) } else if let previousView = items.last?.view { _ = NSLayoutConstraint(pinFirstView: previousView, toSecondView: view, withConstant: spacing, directionVertical: true) } @@ -236,7 +249,7 @@ public class MoleculeStackView: ViewConstrainingView { } else { if items.count == 0 { // First horizontal item has no spacing by default unless told otherwise. - pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: stackItem.spacing ?? 0) + pinView(view, toView: contentView, attribute: .leading, relation: .equal, priority: .required, constant: useStackSpacingBeforeFirstItem ? spacing : stackItem.spacing ?? 0) } else if let previousView = items.last?.view { _ = NSLayoutConstraint(pinFirstView: previousView, toSecondView: view, withConstant: spacing, directionVertical: false) } diff --git a/MVMCoreUI/Molecules/MoleculeTableViewCell.swift b/MVMCoreUI/Molecules/MoleculeTableViewCell.swift index be6f1a71..ed5bf1fc 100644 --- a/MVMCoreUI/Molecules/MoleculeTableViewCell.swift +++ b/MVMCoreUI/Molecules/MoleculeTableViewCell.swift @@ -89,12 +89,7 @@ import UIKit if molecule == nil { if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject, constrainIfNeeded: true) { contentView.addSubview(moleculeView) - var standardConstraints = true - if let castView = moleculeView as? MVMCoreUIViewConstrainingProtocol { - standardConstraints = castView.useStandardConstraints?() ?? true - castView.shouldSetHorizontalMargins?(!standardConstraints) - castView.shouldSetVerticalMargins?(!standardConstraints) - } + let standardConstraints = (moleculeView as? MVMCoreUIViewConstrainingProtocol)?.useStandardConstraints?() ?? true NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: moleculeView, useMargins: standardConstraints).values)) if standardConstraints { let constraint = contentView.heightAnchor.constraint(equalToConstant: 80) @@ -103,14 +98,14 @@ import UIKit } molecule = moleculeView } - } else { - molecule?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData) - if let castView = molecule as? MVMCoreUIViewConstrainingProtocol { - let standardConstraints = castView.useStandardConstraints?() ?? true - castView.shouldSetHorizontalMargins?(!standardConstraints) - castView.shouldSetVerticalMargins?(!standardConstraints) - } } + if let castView = molecule as? MVMCoreUIViewConstrainingProtocol { + let standardConstraints = castView.useStandardConstraints?() ?? true + castView.shouldSetHorizontalMargins?(!standardConstraints) + castView.shouldSetVerticalMargins?(!standardConstraints) + } + molecule?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData) + backgroundColor = molecule?.backgroundColor // Add the caret if there is an action and it's not declared hidden. diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 07d3e548..7ffc2959 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -94,7 +94,6 @@ if (constrainIfNeeded && [castMolecule respondsToSelector:@selector(needsToBeConstrained)] && [castMolecule needsToBeConstrained]) { molecule = [[ViewConstrainingView alloc] initWithMolecule:molecule alignment:[castMolecule respondsToSelector:@selector(alignment)] ? [castMolecule alignment] : UIStackViewAlignmentFill]; } - [molecule setWithJSON:moleculeJSON delegateObject:delegateObject additionalData:nil]; return molecule; } diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index ea3f94b4..9a3fd952 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -30,6 +30,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { return super.viewForTop() } + molecule.setWithJSON(moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) return molecule } @@ -38,6 +39,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { return super.viewForBottom() } + molecule.setWithJSON(moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) return molecule } diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index 3f5e04da..3d6d76d8 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -28,6 +28,7 @@ public class MoleculeStackTemplate: ThreeLayerViewController { guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { return nil } + molecule.setWithJSON(moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) return molecule } @@ -35,13 +36,17 @@ public class MoleculeStackTemplate: ThreeLayerViewController { guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("moleculeStack") else { return nil } - return MoleculeStackView(withJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) + let stack = MoleculeStackView(frame: .zero) + stack.useStackSpacingBeforeFirstItem = true + stack.setWithJSON(moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) + return stack } override public func viewForBottom() -> UIView? { guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { return nil } + molecule.setWithJSON(moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) return molecule } From cb03232a13394b95164a1d309d7cfd1f54d36f75 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 21 Jun 2019 13:04:39 -0400 Subject: [PATCH 05/20] missing comma --- MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index f87d6715..9da408cb 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -43,7 +43,7 @@ @"listItem": MoleculeTableViewCell.class, @"switchLineItem": SwitchLineItem.class, @"switch": Switch.class, - @"image": MFLoadImageView.class + @"image": MFLoadImageView.class, @"leftRightLabelView": LeftRightLabelView.class } mutableCopy]; }); From 9f038467a9e894e0f1a9f76c1e8f253c9e55bde0 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 21 Jun 2019 13:14:25 -0400 Subject: [PATCH 06/20] key fix --- MVMCoreUI/Molecules/TwoButtonView.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Molecules/TwoButtonView.swift b/MVMCoreUI/Molecules/TwoButtonView.swift index f2a8bc44..c5085cce 100644 --- a/MVMCoreUI/Molecules/TwoButtonView.swift +++ b/MVMCoreUI/Molecules/TwoButtonView.swift @@ -44,8 +44,8 @@ import UIKit if let backgroundColorString = json?.optionalStringForKey(KeyBackgroundColor) { backgroundColor = UIColor.mfGet(forHex: backgroundColorString) } - let primaryButtonMap = json?.optionalDictionaryForKey(KeyPrimaryButton) - let secondaryButtonMap = json?.optionalDictionaryForKey(KeySecondaryButton) + let primaryButtonMap = json?.optionalDictionaryForKey("primaryButton") + let secondaryButtonMap = json?.optionalDictionaryForKey("secondaryButton") set(primaryButtonJSON: primaryButtonMap, secondaryButtonJSON: secondaryButtonMap, delegateObject: delegateObject, additionalData: additionalData) } From cb8ad83149fa7fea5cc1c33683544bb5938e06e2 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 21 Jun 2019 13:34:02 -0400 Subject: [PATCH 07/20] fix label overriding itself --- MVMCoreUI/Atoms/Views/Label.swift | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label.swift b/MVMCoreUI/Atoms/Views/Label.swift index a0733521..4fa300a2 100644 --- a/MVMCoreUI/Atoms/Views/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label.swift @@ -247,10 +247,11 @@ public typealias ActionBlock = () -> Void case "action": guard let actionLabel = label as? Label else { continue } - actionLabel.addTappableLinkAttribute(range: range, - actionMap: json, - additionalData: additionalData, - delegateObject: delegate) + actionLabel.addDefaultAttributes(range: range, string: attributedString) + actionLabel.clauses.append(ActionableClause(range: range, + actionBlock: actionLabel.createActionBlockFrom(actionMap: json, + additionalData: additionalData, + delegateObject: delegate))) default: continue } @@ -397,6 +398,13 @@ extension Label { } } + func addDefaultAttributes(range: NSRange, string: NSAttributedString?) { + + guard let string = string else { return } + let mutableAttributedString = NSMutableAttributedString(attributedString: string) + mutableAttributedString.addAttributes([NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue], range: range) + } + fileprivate func setDefaultAttributes(range: NSRange) { guard let attributedText = attributedText else { return } From fe09ce04dc98067620986d138e60871eb7196ae9 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 21 Jun 2019 13:48:29 -0400 Subject: [PATCH 08/20] add setter to label --- MVMCoreUI/Atoms/Views/Label.swift | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label.swift b/MVMCoreUI/Atoms/Views/Label.swift index 4fa300a2..f7a70381 100644 --- a/MVMCoreUI/Atoms/Views/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label.swift @@ -398,11 +398,10 @@ extension Label { } } - func addDefaultAttributes(range: NSRange, string: NSAttributedString?) { + func addDefaultAttributes(range: NSRange, string: NSMutableAttributedString?) { guard let string = string else { return } - let mutableAttributedString = NSMutableAttributedString(attributedString: string) - mutableAttributedString.addAttributes([NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue], range: range) + string.addAttributes([NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue], range: range) } fileprivate func setDefaultAttributes(range: NSRange) { @@ -410,8 +409,7 @@ extension Label { guard let attributedText = attributedText else { return } let mutableAttributedString = NSMutableAttributedString(attributedString: attributedText) - mutableAttributedString.addAttributes([NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue], range: range) - + addDefaultAttributes(range: range, string: mutableAttributedString) self.attributedText = mutableAttributedString } From ab33ceebde7f645ec619e01bb45e2a7ce1debee4 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 24 Jun 2019 10:55:07 -0400 Subject: [PATCH 09/20] name change --- MVMCoreUI/Atoms/Views/Label.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label.swift b/MVMCoreUI/Atoms/Views/Label.swift index f7a70381..35f8ab71 100644 --- a/MVMCoreUI/Atoms/Views/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label.swift @@ -247,7 +247,7 @@ public typealias ActionBlock = () -> Void case "action": guard let actionLabel = label as? Label else { continue } - actionLabel.addDefaultAttributes(range: range, string: attributedString) + actionLabel.addActionAttributes(range: range, string: attributedString) actionLabel.clauses.append(ActionableClause(range: range, actionBlock: actionLabel.createActionBlockFrom(actionMap: json, additionalData: additionalData, @@ -398,18 +398,18 @@ extension Label { } } - func addDefaultAttributes(range: NSRange, string: NSMutableAttributedString?) { + func addActionAttributes(range: NSRange, string: NSMutableAttributedString?) { guard let string = string else { return } string.addAttributes([NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue], range: range) } - fileprivate func setDefaultAttributes(range: NSRange) { + fileprivate func setActionAttributes(range: NSRange) { guard let attributedText = attributedText else { return } let mutableAttributedString = NSMutableAttributedString(attributedString: attributedText) - addDefaultAttributes(range: range, string: mutableAttributedString) + addActionAttributes(range: range, string: mutableAttributedString) self.attributedText = mutableAttributedString } @@ -423,7 +423,7 @@ extension Label { */ @objc public func addTappableLinkAttribute(range: NSRange, actionBlock: @escaping ActionBlock) { - setDefaultAttributes(range: range) + setActionAttributes(range: range) clauses.append(ActionableClause(range: range, actionBlock: actionBlock)) } @@ -439,7 +439,7 @@ extension Label { */ @objc public func addTappableLinkAttribute(range: NSRange, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) { - setDefaultAttributes(range: range) + setActionAttributes(range: range) clauses.append(ActionableClause(range: range, actionBlock: createActionBlockFrom(actionMap: actionMap, additionalData: additionalData, From 0db0f91b3b3a347b4500e86a6d464488869b32ba Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 26 Jun 2019 12:01:47 -0400 Subject: [PATCH 10/20] ModuleMolecule is now a self contained view. Fixed priority defect in view constraining view. Change the way names are set for reuse improve current margin logic --- MVMCoreUI.xcodeproj/project.pbxproj | 8 +- MVMCoreUI/Atoms/Views/ViewConstrainingView.m | 20 ++- MVMCoreUI/Molecules/ButtonView.swift | 2 +- .../Molecules/MVMCoreUIMoleculeViewProtocol.h | 6 +- MVMCoreUI/Molecules/ModuleMolecule.swift | 98 ++++++++++++++ MVMCoreUI/Molecules/MoleculeStackView.swift | 41 ++++-- .../Molecules/MoleculeTableViewCell.swift | 30 +++-- .../MVMCoreUIMoleculeMappingObject.h | 15 +-- .../MVMCoreUIMoleculeMappingObject.m | 41 +++--- .../MoleculeMappingObject+Extension.swift | 47 ------- .../Templates/MoleculeListTemplate.swift | 120 +++++++----------- .../Templates/MoleculeStackTemplate.swift | 31 ++--- 12 files changed, 260 insertions(+), 199 deletions(-) create mode 100644 MVMCoreUI/Molecules/ModuleMolecule.swift delete mode 100644 MVMCoreUI/OtherHandlers/MoleculeMappingObject+Extension.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index d45f3185..7ea64bcf 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -39,7 +39,6 @@ D28B4F8B21FF967C00712C7A /* MVMCoreUIObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D28B4F8921FF967C00712C7A /* MVMCoreUIObject.m */; }; D296E13C229598BF0051EBE7 /* MoleculeListCellProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D296E13B2295969C0051EBE7 /* MoleculeListCellProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D296E1412295EBBA0051EBE7 /* MoleculeDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D296E1402295EBBA0051EBE7 /* MoleculeDelegateProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D296E143229729C30051EBE7 /* MoleculeMappingObject+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D296E142229729C30051EBE7 /* MoleculeMappingObject+Extension.swift */; }; D296E14722A5984C0051EBE7 /* MVMCoreUIViewConstrainingProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */; }; D29770C921F7C4AE00B2F0D0 /* TopLabelsView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -49,6 +48,7 @@ D29770F521F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29770F121F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m */; }; D29770FC21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29770FA21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m */; }; D29770FD21F7C77400B2F0D0 /* MVMCoreUITextFieldView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29770FB21F7C77400B2F0D0 /* MVMCoreUITextFieldView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */; }; D29DF0D121E404D4003B2FB9 /* MVMCoreUI.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF0CF21E404D4003B2FB9 /* MVMCoreUI.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF0E621E4F3C7003B2FB9 /* MVMCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D29DF0E521E4F3C7003B2FB9 /* MVMCore.framework */; }; D29DF11521E6805F003B2FB9 /* UIColor+MFConvenience.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF11121E6805F003B2FB9 /* UIColor+MFConvenience.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -207,7 +207,6 @@ D28B4F8921FF967C00712C7A /* MVMCoreUIObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIObject.m; sourceTree = ""; }; D296E13B2295969C0051EBE7 /* MoleculeListCellProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MoleculeListCellProtocol.h; sourceTree = ""; }; D296E1402295EBBA0051EBE7 /* MoleculeDelegateProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MoleculeDelegateProtocol.h; sourceTree = ""; }; - D296E142229729C30051EBE7 /* MoleculeMappingObject+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MoleculeMappingObject+Extension.swift"; sourceTree = ""; }; D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewConstrainingProtocol.h; sourceTree = ""; }; D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TopLabelsView.m; sourceTree = ""; }; D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TopLabelsView.h; sourceTree = ""; }; @@ -217,6 +216,7 @@ D29770F121F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TopLabelsAndBottomButtonsViewController.m; sourceTree = ""; }; D29770FA21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITextFieldView.m; sourceTree = ""; }; D29770FB21F7C77400B2F0D0 /* MVMCoreUITextFieldView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITextFieldView.h; sourceTree = ""; }; + D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModuleMolecule.swift; sourceTree = ""; }; D29DF0CC21E404D4003B2FB9 /* MVMCoreUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MVMCoreUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D29DF0CF21E404D4003B2FB9 /* MVMCoreUI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUI.h; sourceTree = ""; }; D29DF0D021E404D4003B2FB9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -471,6 +471,7 @@ D2E1FADC2268B25E00AEFD8C /* MoleculeTableViewCell.swift */, B8200E142280C4CF007245F4 /* ProgressBar.swift */, B8200E182281DC1A007245F4 /* ProgressBarWithLabel.swift */, + D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */, ); path = Molecules; sourceTree = ""; @@ -679,7 +680,6 @@ D296E1402295EBBA0051EBE7 /* MoleculeDelegateProtocol.h */, D2A514562211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h */, D2A514572211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m */, - D296E142229729C30051EBE7 /* MoleculeMappingObject+Extension.swift */, ); path = OtherHandlers; sourceTree = ""; @@ -901,6 +901,7 @@ D29DF32121ED0CBA003B2FB9 /* LabelView.m in Sources */, DBC4391822442197001AB423 /* CaretView.swift in Sources */, D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */, + D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */, DBC4391922442197001AB423 /* DashLine.swift in Sources */, D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */, @@ -944,7 +945,6 @@ D29DF28321E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.m in Sources */, D206997821FB8A0B00CAE0DE /* MVMCoreUINavigationController.m in Sources */, D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */, - D296E143229729C30051EBE7 /* MoleculeMappingObject+Extension.swift in Sources */, 01DF55E021F8FAA800CC099B /* MFTextFieldListView.swift in Sources */, D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */, D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */, diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m index b2b6fea8..2f97c09a 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m @@ -48,11 +48,21 @@ #pragma mark - Constraining - (void)pinViewToSuperView:(nonnull UIView *)view { - NSDictionary *dictionary = [NSLayoutConstraint constraintPinSubviewToSuperview:view]; - self.leftPin = dictionary[ConstraintLeading]; - self.topPin = dictionary[ConstraintTop]; - self.bottomPin = dictionary[ConstraintBot]; - self.rightPin = dictionary[ConstraintTrailing]; + NSLayoutConstraint *constraint = [view.leftAnchor constraintEqualToAnchor:view.superview.leftAnchor]; + constraint.active = YES; + self.leftPin = constraint; + + constraint = [view.topAnchor constraintEqualToAnchor:view.superview.topAnchor]; + constraint.active = YES; + self.topPin = constraint; + + constraint = [view.superview.rightAnchor constraintEqualToAnchor:view.rightAnchor]; + constraint.active = YES; + self.rightPin = constraint; + + constraint = [view.superview.bottomAnchor constraintEqualToAnchor:view.bottomAnchor]; + constraint.active = YES; + self.bottomPin = constraint; self.alignCenterPin = [view.centerXAnchor constraintEqualToAnchor:view.superview.centerXAnchor]; self.alignCenterLeftPin = [view.leftAnchor constraintGreaterThanOrEqualToAnchor:view.superview.leftAnchor]; diff --git a/MVMCoreUI/Molecules/ButtonView.swift b/MVMCoreUI/Molecules/ButtonView.swift index 4596164c..d9163ae4 100644 --- a/MVMCoreUI/Molecules/ButtonView.swift +++ b/MVMCoreUI/Molecules/ButtonView.swift @@ -64,7 +64,7 @@ import UIKit primaryButton?.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) } - public override static func estimatedHeight(forRow json: [AnyHashable : Any]?) -> CGFloat { + public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { return 42 } diff --git a/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h b/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h index 9140245e..4c69b1f7 100644 --- a/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h +++ b/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h @@ -9,6 +9,7 @@ #import @import MVMCore.MVMCoreViewProtocol; @class MVMCoreUIDelegateObject; +@class MVMCoreErrorObject; @protocol MVMCoreUIMoleculeViewProtocol @@ -25,11 +26,14 @@ /// For the molecule list to load more efficiently. -+ (CGFloat)estimatedHeightForRow:(nullable NSDictionary *)json; ++ (CGFloat)estimatedHeightForRow:(nullable NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject; /// Allows the molecule to set its name for reuse. Default could be moleculeName. + (nullable NSString *)nameForReuse:(nullable NSDictionary *)molecule delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject; +/// Can return the required modules ++ (nullable NSArray *)requiredModules:(nullable NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject error:(MVMCoreErrorObject *_Nullable *_Nullable)error; + @end diff --git a/MVMCoreUI/Molecules/ModuleMolecule.swift b/MVMCoreUI/Molecules/ModuleMolecule.swift new file mode 100644 index 00000000..316f3f2a --- /dev/null +++ b/MVMCoreUI/Molecules/ModuleMolecule.swift @@ -0,0 +1,98 @@ +// +// ModuleMolecule.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 6/25/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +open class ModuleMolecule: ViewConstrainingView { + + open var molecule: (UIView & MVMCoreUIMoleculeViewProtocol)? + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + molecule?.updateView(size) + } + + // MARK: - MVMCoreUIMoleculeViewProtocol + open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + + guard let moduleName = json?.optionalStringForKey("moduleName"), let module = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else { + // Critical error + return + } + + if molecule == nil { + if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: module, delegateObject: delegateObject, constrainIfNeeded: true) { + addSubview(moleculeView) + NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: moleculeView, useMargins: false).values)) + molecule = moleculeView + } + } else { + molecule?.setWithJSON(module, delegateObject: delegateObject, additionalData: additionalData) + } + } + + open override func setAsMolecule() { + super.setAsMolecule() + updateViewHorizontalDefaults = false + molecule?.setAsMolecule?() + } + + open override func reset() { + super.reset() + molecule?.reset?() + } + + public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + guard let moduleName = json?.optionalStringForKey("moduleName"), let module = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else { + // Critical error + return 0 + } + return MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: module)?.estimatedHeight?(forRow: module, delegateObject: delegateObject) ?? 80 + } + + public override static func name(forReuse molecule: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? { + guard let moduleName = molecule?.optionalStringForKey("moduleName"), let module = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else { + // Critical error + return "moduleMolecule<>" + } + return "moduleMolecule<" + (MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: module)?.name?(forReuse: module, delegateObject: delegateObject) ?? module.stringForkey(KeyMoleculeName)) + ">" + } + + public override static func requiredModules(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + guard let moduleName = json?.optionalStringForKey("moduleName"), let _ = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else { + if let errorObject = MVMCoreErrorObject(title: nil, message: MVMCoreGetterUtility.hardcodedString(withKey: HardcodedErrorUnableToProcess), code: CoreUIErrorCode.ErrorCodeModuleMolecule.rawValue, domain: ErrorDomainNative, location: String(describing: self)) { + error?.pointee = errorObject + MVMCoreUILoggingHandler.shared()?.addError(toLog: errorObject) + } + return nil + } + return [moduleName] + } + + // MARK: - MVMCoreUIViewConstrainingProtocol + open override func useStandardConstraints() -> Bool { + return (molecule as? MVMCoreUIViewConstrainingProtocol)?.useStandardConstraints?() ?? true + } + + open override func alignHorizontal(_ alignment: UIStackView.Alignment) { + (molecule as? MVMCoreUIViewConstrainingProtocol)?.alignHorizontal?(alignment) + } + + open override func alignVertical(_ alignment: UIStackView.Alignment) { + (molecule as? MVMCoreUIViewConstrainingProtocol)?.alignVertical?(alignment) + } + + open override func shouldSetHorizontalMargins(_ shouldSet: Bool) { + (molecule as? MVMCoreUIViewConstrainingProtocol)?.shouldSetHorizontalMargins?(shouldSet) + } + + open override func shouldSetVerticalMargins(_ shouldSet: Bool) { + (molecule as? MVMCoreUIViewConstrainingProtocol)?.shouldSetVerticalMargins?(shouldSet) + } +} diff --git a/MVMCoreUI/Molecules/MoleculeStackView.swift b/MVMCoreUI/Molecules/MoleculeStackView.swift index 8c6e76bf..ad667d16 100644 --- a/MVMCoreUI/Molecules/MoleculeStackView.swift +++ b/MVMCoreUI/Molecules/MoleculeStackView.swift @@ -47,6 +47,7 @@ public class MoleculeStackView: ViewConstrainingView { /// For setting the direction of the stack var axis: NSLayoutConstraint.Axis = .vertical { didSet { + moleculesShouldSetHorizontalMargins = (moleculesShouldSetHorizontalMargins && axis == .vertical) if axis != oldValue { restack() } @@ -136,15 +137,20 @@ public class MoleculeStackView: ViewConstrainingView { } } - // If this item is in another container, do have the child molecules not use alignment. public override func shouldSetHorizontalMargins(_ shouldSet: Bool) { super.shouldSetHorizontalMargins(shouldSet) - moleculesShouldSetHorizontalMargins = false + moleculesShouldSetHorizontalMargins = (shouldSet && axis == .vertical) + for item in items { + (item.view as? MVMCoreUIViewConstrainingProtocol)?.shouldSetHorizontalMargins?(moleculesShouldSetHorizontalMargins) + } } public override func shouldSetVerticalMargins(_ shouldSet: Bool) { super.shouldSetVerticalMargins(shouldSet) moleculesShouldSetVerticalMargins = false + for item in items { + (item.view as? MVMCoreUIViewConstrainingProtocol)?.shouldSetVerticalMargins?(moleculesShouldSetVerticalMargins) + } } open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { @@ -187,32 +193,51 @@ public class MoleculeStackView: ViewConstrainingView { if let item = items?[index] { item.update(with: moleculeJSON) view = item.view + (view as? MVMCoreUIMoleculeViewProtocol)?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: nil) addStackItem(item, lastItem: index == molecules.count - 1) } else if let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject, constrainIfNeeded: true) { view = molecule addStackItem(StackItem(with: molecule, json: map), lastItem: index == molecules.count - 1) } - (view as? MVMCoreUIViewConstrainingProtocol)?.shouldSetHorizontalMargins?(moleculesShouldSetHorizontalMargins && axis == .vertical) + (view as? MVMCoreUIViewConstrainingProtocol)?.shouldSetHorizontalMargins?(moleculesShouldSetHorizontalMargins) (view as? MVMCoreUIViewConstrainingProtocol)?.shouldSetVerticalMargins?(moleculesShouldSetVerticalMargins) - (view as? MVMCoreUIMoleculeViewProtocol)?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: nil) } } } public override static func name(forReuse molecule: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? { // This will aggregate names of molecules to make an id. - var name = "" guard let molecules = molecule?.optionalArrayForKey(KeyMolecules) else { - return name + return "stack<>" } + var name = "stack<" for case let item as [AnyHashable: AnyHashable] in molecules { - if let moleculeName = item.stringOptionalWithChainOfKeysOrIndexes([KeyMolecule, KeyMoleculeName]) { - name.append(moleculeName) + 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 override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + // if horizontal, max, if vertical, append. + return 100 + } + + public override static func requiredModules(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + guard let items = json?.optionalArrayForKey(KeyMolecules) 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 + } + // MARK: - Adding to stack /// Adds the view to the stack. func addView(_ view: UIView, lastItem: Bool) { diff --git a/MVMCoreUI/Molecules/MoleculeTableViewCell.swift b/MVMCoreUI/Molecules/MoleculeTableViewCell.swift index ed5bf1fc..f8fc00fa 100644 --- a/MVMCoreUI/Molecules/MoleculeTableViewCell.swift +++ b/MVMCoreUI/Molecules/MoleculeTableViewCell.swift @@ -98,13 +98,14 @@ import UIKit } molecule = moleculeView } + } else { + molecule?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData) } if let castView = molecule as? MVMCoreUIViewConstrainingProtocol { let standardConstraints = castView.useStandardConstraints?() ?? true castView.shouldSetHorizontalMargins?(!standardConstraints) castView.shouldSetVerticalMargins?(!standardConstraints) } - molecule?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData) backgroundColor = molecule?.backgroundColor @@ -126,25 +127,26 @@ import UIKit molecule?.reset?() } - public static func estimatedHeight(forRow json: [AnyHashable: Any]?) -> CGFloat { - guard let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule), - let theClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON, delegateObject: nil), - let estimatedHeightFor = theClass.estimatedHeight else { + public static func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + guard let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule), let height = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON)?.estimatedHeight?(forRow: moleculeJSON, delegateObject: delegateObject) else { return 80 } - return estimatedHeightFor(moleculeJSON) + return height } public static func name(forReuse molecule: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? { - if let molecule = molecule?.optionalDictionaryForKey(KeyMolecule), - let moleculeName = molecule.optionalStringForKey(KeyMoleculeName), - let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping[moleculeName] as? AnyClass, - let castClass = moleculeClass as? MVMCoreUIMoleculeViewProtocol.Type, - let nameFunc = castClass.name { - return nameFunc(molecule, delegateObject) - } else { - return molecule?.optionalDictionaryForKey(KeyMolecule)?.optionalStringForKey(KeyMoleculeName) + guard let molecule = molecule?.optionalDictionaryForKey(KeyMolecule) else { + return nil } + return MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule)?.name?(forReuse: molecule, delegateObject: delegateObject) ?? molecule.optionalStringForKey(KeyMoleculeName) + } + + public static func requiredModules(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + guard let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule), + let theClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON) else { + return nil + } + return theClass.requiredModules?(moleculeJSON, delegateObject: delegateObject, error: error) } // MARK: - Arrow diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.h b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.h index 4e7dd8db..7d85a2ea 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.h +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.h @@ -21,22 +21,19 @@ + (nullable instancetype)sharedMappingObject; /// Returns the molecule class. -- (nullable Class)getMoleculeClassWithJSON:(nonnull NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject; +- (nullable Class)getMoleculeClassWithJSON:(nonnull NSDictionary *)json; #pragma mark - Molecule Creation -/// Creates the molecule for the given name. -- (nullable UIView *)createMoleculeForName:(nonnull NSString *)name; - -/// Creates the molecule for the molecule json. Takes into account moduleMolecule as well. +/// Creates the molecule for the molecule json. - (nullable UIView *)createMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject; -/// Creates the molecule for the molecule json. Takes into account moduleMolecule as well. Also checks if the molecule needs to be constrained for a stack/list style situation. +/// Creates the molecule for the molecule json. Also checks if the molecule needs to be constrained for a stack/list style situation. - (nullable UIView *)createMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject constrainIfNeeded:(BOOL)constrainIfNeeded; -#pragma mark - ModuleMolecule Helpers +#pragma mark - Convenience -/// If the molecule is a module molecule, will get the map for the molecule to load from a module. Otherwise nil. -+ (nullable NSDictionary *)getMoleculeMapForModuleMolecule:(nullable NSDictionary *)moduleMolecule delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject error:(MVMCoreErrorObject *_Nullable *_Nullable)error; ++ (nullable NSArray *)getRequiredModulesForJSON:(nullable NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject error:(MVMCoreErrorObject *_Nullable *_Nullable)error; ++ (void)addRequiredModulesForJSON:(nullable NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject moduleList:(nullable NSMutableArray *)moduleList errorList:(nullable NSMutableArray *)errorList; @end diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 9da408cb..148932bb 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -10,6 +10,7 @@ @import MVMCore.MVMCoreActionUtility; @import MVMCore.NSDictionary_MFConvenience; @import MVMCore.MVMCoreLoadObject; +@import MVMCore.MVMCoreErrorObject; #import "MVMCoreUIObject.h" #import #import "MFTextField.h" @@ -44,7 +45,8 @@ @"switchLineItem": SwitchLineItem.class, @"switch": Switch.class, @"image": MFLoadImageView.class, - @"leftRightLabelView": LeftRightLabelView.class + @"leftRightLabelView": LeftRightLabelView.class, + @"moduleMolecule": ModuleMolecule.class } mutableCopy]; }); return mapping; @@ -55,9 +57,8 @@ return [MVMCoreActionUtility initializerClassCheck:[MVMCoreUIObject sharedInstance].moleculeMap classToVerify:self]; } -- (nullable Class)getMoleculeClassWithJSON:(nonnull NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject { - NSDictionary *moleculeJSON = [MVMCoreUIMoleculeMappingObject getMoleculeMapForModuleMolecule:json delegateObject:delegateObject error:nil] ?: json; - NSString *moleculeName = [moleculeJSON string:KeyMoleculeName]; +- (nullable Class)getMoleculeClassWithJSON:(nonnull NSDictionary *)json { + NSString *moleculeName = [json string:KeyMoleculeName]; if (moleculeName) { return [self.moleculeMapping objectForKey:moleculeName]; } @@ -83,13 +84,13 @@ } - (nullable UIView *)createMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject constrainIfNeeded:(BOOL)constrainIfNeeded { - NSDictionary *moleculeJSON = [MVMCoreUIMoleculeMappingObject getMoleculeMapForModuleMolecule:json delegateObject:delegateObject error:nil] ?: json; - NSString *moleculeName = [moleculeJSON string:KeyMoleculeName]; + NSString *moleculeName = [json string:KeyMoleculeName]; if (!moleculeName) { return nil; } UIView *molecule = [self createMoleculeForName:moleculeName]; - + [molecule setWithJSON:json delegateObject:delegateObject additionalData:nil]; + // Check if we need to constrain this view. UIView *castMolecule = [molecule conformsToProtocol:@protocol(MVMCoreUIViewConstrainingProtocol)] ? (UIView *)molecule : nil; if (constrainIfNeeded && [castMolecule respondsToSelector:@selector(needsToBeConstrained)] && [castMolecule needsToBeConstrained]) { @@ -98,20 +99,26 @@ return molecule; } -#pragma mark - ModuleMolecule Helpers +#pragma mark - Convenience -+ (nullable NSDictionary *)getMoleculeMapForModuleMolecule:(nullable NSDictionary *)moduleMolecule delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject error:(MVMCoreErrorObject *_Nullable *_Nullable)error { - NSString *moleculeName = [moduleMolecule string:KeyMoleculeName]; - if ([moleculeName isEqualToString:@"moduleMolecule"]) { - NSString *moduleName = [moduleMolecule string:@"moduleName"]; - NSDictionary *module = moduleName ? [delegateObject.moleculeDelegate getModuleWithName:moduleName] : nil; - if (!module && error) { - *error = [[MVMCoreErrorObject alloc] initWithTitle:nil message:[MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorUnableToProcess] code:ErrorCodeModuleMolecule domain:ErrorDomainNative location:NSStringFromClass(self)]; - } - return module; ++ (nullable NSArray *)getRequiredModulesForJSON:(nullable NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject error:(MVMCoreErrorObject *_Nullable *_Nullable)error { + Class theClass = [[MVMCoreUIMoleculeMappingObject sharedMappingObject] getMoleculeClassWithJSON:json]; + if ([theClass respondsToSelector:@selector(requiredModules:delegateObject:error:)]) { + return [theClass requiredModules:json delegateObject:delegateObject error:error]; } else { return nil; } } ++ (void)addRequiredModulesForJSON:(nullable NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject moduleList:(nullable NSMutableArray *)moduleList errorList:(nullable NSMutableArray *)errorList { + MVMCoreErrorObject *error = nil; + NSArray *modules = [self getRequiredModulesForJSON:json delegateObject:delegateObject error:&error]; + if (modules) { + [moduleList addObjectsFromArray:modules]; + } + if (error) { + [errorList addObject:error]; + } +} + @end diff --git a/MVMCoreUI/OtherHandlers/MoleculeMappingObject+Extension.swift b/MVMCoreUI/OtherHandlers/MoleculeMappingObject+Extension.swift deleted file mode 100644 index 3c88a743..00000000 --- a/MVMCoreUI/OtherHandlers/MoleculeMappingObject+Extension.swift +++ /dev/null @@ -1,47 +0,0 @@ -// -// MoleculeMappingObject+Extension.swift -// MVMCoreUI -// -// Created by Scott Pfeil on 5/23/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import Foundation - -public extension MVMCoreUIMoleculeMappingObject { - - /// Gets the molecule, and if it belonged to a moduleMolecule, the module name or error. - static func getMoleculeJSON(for map: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> (molecule: [AnyHashable: Any]?, moduleName: String?, error: MVMCoreErrorObject?)? { - guard let map = map, let moleculeName = map.optionalStringForKey(KeyMoleculeName) else { - return nil - } - guard moleculeName == "moduleMolecule" else { - // Not a module molecule. - return (map, nil, nil) - } - - guard let moduleName = map.optionalStringForKey("moduleName"), - let module = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else { - guard let error = MVMCoreErrorObject(title: nil, message: MVMCoreGetterUtility.hardcodedString(withKey: HardcodedErrorUnableToProcess), code: CoreUIErrorCode.ErrorCodeModuleMolecule.rawValue, domain: ErrorDomainNative, location: String(describing: self)) else { - return nil - } - MVMCoreUILoggingHandler.shared()?.addError(toLog: error) - return (nil, nil, error) - } - return (module, moduleName, nil) - } - - /// Gets the molecule, and if it belonged to a moduleMolecule adds the module name or error to the passed lists. - static func getMoleculeJSON(for map: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, moduleNames: inout [String]?, errors: inout [MVMCoreErrorObject]?) -> [AnyHashable: Any]? { - guard let molecule = getMoleculeJSON(for: map, delegateObject: delegateObject) else { - return nil - } - if let moduleName = molecule.moduleName { - moduleNames?.append(moduleName) - } - if let error = molecule.error { - errors?.append(error) - } - return molecule.molecule - } -} diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 9a3fd952..93e9dab4 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -9,15 +9,16 @@ import UIKit open class MoleculeListTemplate: ThreeLayerTableViewController { - var molecules: [(molecule: [AnyHashable: Any]?, moduleName: String?, error: MVMCoreErrorObject?)]? - + var moleculesInfo: [(identifier: String, class: AnyClass, molecule: [AnyHashable: Any])]? + var modulesRequired: NSMutableArray? + open override func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer) -> Bool { var shouldFinish = super.shouldFinishProcessingLoad(loadObject, error: error) guard shouldFinish else { return shouldFinish } - if let firstError = setup()?.first { + if let firstError = setup()?.firstObject as? MVMCoreErrorObject { // Don't continue if there was an error loading needed modules. error.pointee = firstError shouldFinish = false @@ -30,7 +31,6 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { return super.viewForTop() } - molecule.setWithJSON(moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) return molecule } @@ -39,47 +39,43 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { return super.viewForBottom() } - molecule.setWithJSON(moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) return molecule } open override func newDataBuildScreen() { super.newDataBuildScreen() - _ = setupMoleculeList() + _ = setup() registerWithTable() } // MARK: - table open override func registerWithTable() { super.registerWithTable() - guard let molecules = molecules else { + guard let moleculesInfo = moleculesInfo else { return } - for molecule in molecules { - if let moleculeInfo = getMoleculeInfo(with: molecule), let moleculeToRegister = moleculeInfo.name { - tableView?.register(moleculeInfo.class, forCellReuseIdentifier: moleculeToRegister) - } + for moleculeInfo in moleculesInfo { + print(moleculeInfo.identifier) + tableView?.register(moleculeInfo.class, forCellReuseIdentifier: moleculeInfo.identifier) } } open override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { - guard let molecule = molecules?[indexPath.row], - let moleculeInfo = getMoleculeInfo(with: molecule), - let estimatedHeight = moleculeInfo.class.estimatedHeight else { + guard let moleculeInfo = moleculesInfo?[indexPath.row], + let estimatedHeight = moleculeInfo.class.estimatedHeight?(forRow: moleculeInfo.molecule, delegateObject: delegateObject() as? MVMCoreUIDelegateObject) else { return 0 } - return estimatedHeight(molecule.molecule) + print("height :" + moleculeInfo.class.description() + " :" + estimatedHeight.description) + return estimatedHeight } open override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return molecules?.count ?? 0 + return moleculesInfo?.count ?? 0 } open override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - guard let molecule = molecules?[indexPath.row], - let moleculeInfo = getMoleculeInfo(with: molecule), - let moleculeName = moleculeInfo.name, - let cell = tableView.dequeueReusableCell(withIdentifier: moleculeName) else { + guard let moleculeInfo = moleculesInfo?[indexPath.row], + let cell = tableView.dequeueReusableCell(withIdentifier: moleculeInfo.identifier) else { return UITableViewCell() } let delegate = delegateObject() as? MVMCoreUIDelegateObject @@ -88,7 +84,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { } if let protocolCell = cell as? MVMCoreUIMoleculeViewProtocol { protocolCell.reset?() - protocolCell.setWithJSON(molecule.molecule, delegateObject: delegate, additionalData: nil) + protocolCell.setWithJSON(moleculeInfo.molecule, delegateObject: delegate, additionalData: nil) protocolCell.updateView(tableView.bounds.width) } return cell @@ -110,78 +106,52 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { open override func modulesToListenFor() -> [Any]? { // Get all of the molecules that need modules. - return modulesNeeded() + return modulesRequired as? [Any] } - // MARK: - Module Molecule Handling - /// Returns the (name, class) of the molecule for the given map. - func getMoleculeInfo(with molecule: (molecule: [AnyHashable: Any]?, moduleName: String?, error: MVMCoreErrorObject?)) -> (name: String?, class: AnyClass)? { - guard let map = molecule.molecule, let moleculeName = map.optionalStringForKey(KeyMoleculeName), let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping[moleculeName] as? AnyClass else { + // MARK: - Convenience + /// Returns the (identifier, class) of the molecule for the given map. + func getMoleculeInfo(with molecule: [AnyHashable: Any]?) -> (identifier: String, class: AnyClass, molecule: [AnyHashable: Any])? { + guard let molecule = molecule, + let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule), + let moleculeName = moleculeClass.name?(forReuse: molecule, delegateObject: delegateObject() as? MVMCoreUIDelegateObject) ?? molecule.optionalStringForKey(KeyMoleculeName) else { return nil } - if let moleculeClass = moleculeClass as? MVMCoreUIMoleculeViewProtocol.Type, let moleculeNameFunc = moleculeClass.name { - return (moleculeNameFunc(map, delegateObject() as? MVMCoreUIDelegateObject), moleculeClass) - } else { - return (moleculeName, moleculeClass) - } + return (moleculeName, moleculeClass, molecule) } /// Sets up the molecule list and ensures no errors loading all content. - func setupMoleculeList() -> [MVMCoreErrorObject]? { - var errors: [MVMCoreErrorObject] = [] - let delegate = delegateObject() as? MVMCoreUIDelegateObject - var moleculeList: [(molecule: [AnyHashable: Any]?, moduleName: String?, error: MVMCoreErrorObject?)] = [] + func getMoleculeInfoList() -> [(identifier: String, class: AnyClass, molecule: [AnyHashable: Any])]? { + var moleculeList: [(identifier: String, class: AnyClass, molecule: [AnyHashable: Any])] = [] if let molecules = loadObject?.pageJSON?.optionalArrayForKey(KeyMolecules) as? [[AnyHashable: Any]] { for molecule in molecules { - if let object = MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: molecule, delegateObject: delegate) { - if let error = object.error { - errors.append(error) - } else { - moleculeList.append(object) - } + if let info = getMoleculeInfo(with: molecule) { + moleculeList.append(info) } } } - molecules = moleculeList - return errors.count > 0 ? errors : nil + return moleculeList.count > 0 ? moleculeList : nil } /// Sets up the header, footer, molecule list and ensures no errors loading all content. - func setup() -> [MVMCoreErrorObject]? { - var errors: [MVMCoreErrorObject] = [] + func setup() -> NSMutableArray? { + let modules: NSMutableArray = [] + let errors: NSMutableArray = [] let delegate = delegateObject() as? MVMCoreUIDelegateObject - MoleculeListTemplate.addToErrorList(with: MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate), errors: &errors) - MoleculeListTemplate.addToErrorList(with: MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate), errors: &errors) - if let newErrors = setupMoleculeList() { - errors.append(contentsOf: newErrors) - } - return errors.count > 0 ? errors : nil - } - - static func addToErrorList(with moleculeObject: (molecule: [AnyHashable: Any]?, moduleName: String?, error: MVMCoreErrorObject?)?, errors: inout [MVMCoreErrorObject]) { - if let error = moleculeObject?.error { - errors.append(error) - } - } - - static func addToModuleList(with moleculeObject: (molecule: [AnyHashable: Any]?, moduleName: String?, error: MVMCoreErrorObject?)?, moduleNames: inout [String]) { - if let moduleName = moleculeObject?.moduleName { - moduleNames.append(moduleName) - } - } - - /// Gets a list of required modules - func modulesNeeded() -> [String]? { - var modules: [String] = [] - let delegate = delegateObject() as? MVMCoreUIDelegateObject - - MoleculeListTemplate.addToModuleList(with: MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate), moduleNames: &modules) - MoleculeListTemplate.addToModuleList(with: MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate), moduleNames: &modules) - if let molecules = molecules { + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate, moduleList: modules, errorList: errors) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate, moduleList: modules, errorList: errors) + + var moleculeList: [(identifier: String, class: AnyClass, molecule: [AnyHashable: Any])] = [] + if let molecules = loadObject?.pageJSON?.optionalArrayForKey(KeyMolecules) as? [[AnyHashable: Any]] { for molecule in molecules { - MoleculeListTemplate.addToModuleList(with: molecule, moduleNames: &modules) + if let info = getMoleculeInfo(with: molecule) { + moleculeList.append(info) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: molecule, delegateObject: delegate, moduleList: modules, errorList: errors) + } } } - return (modules.count > 0 ? modules : nil) + moleculesInfo = moleculeList + modulesRequired = modules + return errors.count > 0 ? errors : nil } } diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index 3d6d76d8..7bf2a1ed 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -9,10 +9,11 @@ import UIKit public class MoleculeStackTemplate: ThreeLayerViewController { - + var modulesRequired: NSMutableArray? + public override func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer) -> Bool { var shouldFinish = super.shouldFinishProcessingLoad(loadObject, error: error) - if shouldFinish, let firstError = modulesNeeded().errors?.first { + if shouldFinish, let firstError = modulesNeeded().errors?.firstObject as? MVMCoreErrorObject { // Don't continue if there was an error loading needed modules. error.pointee = firstError shouldFinish = false @@ -28,7 +29,6 @@ public class MoleculeStackTemplate: ThreeLayerViewController { guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { return nil } - molecule.setWithJSON(moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) return molecule } @@ -46,7 +46,6 @@ public class MoleculeStackTemplate: ThreeLayerViewController { guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { return nil } - molecule.setWithJSON(moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) return molecule } @@ -60,22 +59,18 @@ public class MoleculeStackTemplate: ThreeLayerViewController { public override func modulesToListenFor() -> [Any]? { // Get all of the molecules that need modules. - return modulesNeeded().modules + return modulesNeeded().modules as? [Any] } - // MARK: - Module Molecule Handling - func modulesNeeded() -> (modules: [String]?, errors: [MVMCoreErrorObject]?) { - var modules: [String]? = [] - var errors: [MVMCoreErrorObject]? = [] + /// Gets the modules needed. + func modulesNeeded() -> (modules: NSMutableArray?, errors: NSMutableArray?) { + let modules: NSMutableArray = [] + let errors: NSMutableArray = [] let delegate = delegateObject() as? MVMCoreUIDelegateObject - - let _ = MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate, moduleNames: &modules, errors: &errors) - let _ = MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate, moduleNames: &modules, errors: &errors) - if let molecules = loadObject?.pageJSON?.optionalArrayForChainOfKeysOrIndexes(["moleculeStack",KeyMolecules]) as? [[AnyHashable: Any]] { - for molecule in molecules { - let _ = MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: molecule, delegateObject: delegate, moduleNames: &modules, errors: &errors) - } - } - return (modules?.count ?? 0 > 0 ? modules : nil, errors?.count ?? 0 > 0 ? errors : nil) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate, moduleList: modules, errorList: errors) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate, moduleList: modules, errorList: errors) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("moleculeStack"), delegateObject: delegate, moduleList: modules, errorList: errors) + modulesRequired = modules + return (modules.count > 0 ? modules : nil, errors.count > 0 ? errors : nil) } } From 01803e90d628d6cf8e17101ffcf5fa360383779f Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 26 Jun 2019 12:58:43 -0400 Subject: [PATCH 11/20] background color consolidation --- MVMCoreUI/Atoms/Views/CaretView.swift | 4 ---- MVMCoreUI/Atoms/Views/DashLine.swift | 4 ---- MVMCoreUI/Atoms/Views/LeftRightLabelView.swift | 4 ---- MVMCoreUI/Atoms/Views/MFLoadImageView.swift | 3 --- MVMCoreUI/Atoms/Views/MFView.m | 8 ++++++++ MVMCoreUI/Atoms/Views/SeparatorView.m | 5 +---- MVMCoreUI/Atoms/Views/ViewConstrainingView.m | 3 +++ MVMCoreUI/Molecules/MoleculeStackView.swift | 7 ++----- MVMCoreUI/Molecules/StandardFooterView.swift | 3 --- MVMCoreUI/Molecules/StandardHeaderView.swift | 3 --- MVMCoreUI/Molecules/TwoButtonView.swift | 3 --- MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m | 2 +- 12 files changed, 15 insertions(+), 34 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/CaretView.swift b/MVMCoreUI/Atoms/Views/CaretView.swift index 62b82b90..ec4457c2 100644 --- a/MVMCoreUI/Atoms/Views/CaretView.swift +++ b/MVMCoreUI/Atoms/Views/CaretView.swift @@ -108,10 +108,6 @@ open class CaretView: MFView { // Configure class properties with JSON values guard let dictionary = json else { return } - if let backgroundColorHex = dictionary[KeyBackgroundColor] as? String { - backgroundColor = UIColor.mfGet(forHex: backgroundColorHex) - } - if let strokeColorHex = dictionary["strokeColor"] as? String { strokeColor = UIColor.mfGet(forHex: strokeColorHex) } diff --git a/MVMCoreUI/Atoms/Views/DashLine.swift b/MVMCoreUI/Atoms/Views/DashLine.swift index e9ca4a78..512b48cd 100644 --- a/MVMCoreUI/Atoms/Views/DashLine.swift +++ b/MVMCoreUI/Atoms/Views/DashLine.swift @@ -74,10 +74,6 @@ open class DashLine: MFView { // Configure class properties with JSON values guard let jsonDictionary = json else { return } - if let backgroundColorHex = jsonDictionary[KeyBackgroundColor] as? String { - backgroundColor = UIColor.mfGet(forHex: backgroundColorHex) - } - if let isHiddenValue = jsonDictionary[KeyIsHidden] as? Bool { isHidden = isHiddenValue } diff --git a/MVMCoreUI/Atoms/Views/LeftRightLabelView.swift b/MVMCoreUI/Atoms/Views/LeftRightLabelView.swift index 1ca1402a..a059aef5 100644 --- a/MVMCoreUI/Atoms/Views/LeftRightLabelView.swift +++ b/MVMCoreUI/Atoms/Views/LeftRightLabelView.swift @@ -170,10 +170,6 @@ import Foundation leftTextLabel.setWithJSON(dictionary.optionalDictionaryForKey("leftText"), delegateObject: delegateObject as? MVMCoreUIDelegateObject, additionalData: additionalData) rightTextLabel.setWithJSON(dictionary.optionalDictionaryForKey("rightText"), delegateObject: delegateObject as? MVMCoreUIDelegateObject, additionalData: additionalData) - if let backgroundColorHex = dictionary[KeyBackgroundColor] as? String { - backgroundColor = UIColor.mfGet(forHex: backgroundColorHex) - } - if !leftTextLabel.hasText { constrainRightLabel() } else if !rightTextLabel.hasText { diff --git a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift index 9bd22c19..795dea86 100644 --- a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift +++ b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift @@ -186,9 +186,6 @@ import UIKit open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - if let backgroundColorString = json?.optionalStringForKey(KeyBackgroundColor) { - backgroundColor = UIColor.mfGet(forHex: backgroundColorString) - } if let accessibilityString = json?.optionalStringForKey("accessibilityText") { imageView.accessibilityLabel = accessibilityString imageView.accessibilityTraits = .staticText diff --git a/MVMCoreUI/Atoms/Views/MFView.m b/MVMCoreUI/Atoms/Views/MFView.m index 029c6ce2..a5754b2a 100644 --- a/MVMCoreUI/Atoms/Views/MFView.m +++ b/MVMCoreUI/Atoms/Views/MFView.m @@ -8,6 +8,9 @@ #import "MFView.h" @import MVMCore.Swift; +@import MVMCore.NSDictionary_MFConvenience; +#import "MVMCoreUIConstants.h" +#import "UIColor+MFConvenience.h" @implementation MFView @@ -46,6 +49,11 @@ - (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { self.json = json; + + NSString *colorString = [json string:KeyBackgroundColor]; + if (colorString) { + self.backgroundColor = [UIColor mfGetColorForHex:colorString]; + } } @end diff --git a/MVMCoreUI/Atoms/Views/SeparatorView.m b/MVMCoreUI/Atoms/Views/SeparatorView.m index 44e95d3c..9abaeaab 100644 --- a/MVMCoreUI/Atoms/Views/SeparatorView.m +++ b/MVMCoreUI/Atoms/Views/SeparatorView.m @@ -115,10 +115,7 @@ [self setAsLight]; } } - NSString *backgroundColor = [json string:KeyBackgroundColor]; - if (backgroundColor) { - self.backgroundColor = [UIColor mfGetColorForHex:backgroundColor]; - } + } else { self.hidden = YES; } diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m index 2f97c09a..7166efee 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m @@ -326,6 +326,9 @@ if (self.molecule) { [self.molecule setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; } + if (self.constrainedView) { + self.backgroundColor = self.constrainedView.backgroundColor; + } } @end diff --git a/MVMCoreUI/Molecules/MoleculeStackView.swift b/MVMCoreUI/Molecules/MoleculeStackView.swift index ad667d16..59c8280d 100644 --- a/MVMCoreUI/Molecules/MoleculeStackView.swift +++ b/MVMCoreUI/Molecules/MoleculeStackView.swift @@ -111,7 +111,8 @@ public class MoleculeStackView: ViewConstrainingView { } translatesAutoresizingMaskIntoConstraints = false backgroundColor = .clear - addConstrainedView(contentView) + addSubview(contentView) + pinView(toSuperView: contentView) contentView.setContentHuggingPriority(.defaultHigh, for: .vertical) contentView.setContentHuggingPriority(.defaultHigh, for: .horizontal) } @@ -164,10 +165,6 @@ public class MoleculeStackView: ViewConstrainingView { items = self.items } self.items = [] - - if let colorString = json?.optionalStringForKey(KeyBackgroundColor) { - backgroundColor = .mfGet(forHex: colorString) - } guard let molecules = json?.arrayForKey(KeyMolecules) as? [[String: Any]] else { return diff --git a/MVMCoreUI/Molecules/StandardFooterView.swift b/MVMCoreUI/Molecules/StandardFooterView.swift index 73088b2e..b99ad5d0 100644 --- a/MVMCoreUI/Molecules/StandardFooterView.swift +++ b/MVMCoreUI/Molecules/StandardFooterView.swift @@ -95,9 +95,6 @@ public class StandardFooterView: ViewConstrainingView { open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - if let colorString = json?.optionalStringForKey(KeyBackgroundColor) { - backgroundColor = .mfGet(forHex: colorString) - } twoButtonView.setWithJSON(json?.optionalDictionaryForKey("twoButtonView"), delegateObject: delegateObject, additionalData: additionalData) textButton.setWithJSON(json?.optionalDictionaryForKey("textButton"), delegateObject: delegateObject, additionalData: additionalData) } diff --git a/MVMCoreUI/Molecules/StandardHeaderView.swift b/MVMCoreUI/Molecules/StandardHeaderView.swift index 2391f062..b9639f07 100644 --- a/MVMCoreUI/Molecules/StandardHeaderView.swift +++ b/MVMCoreUI/Molecules/StandardHeaderView.swift @@ -122,9 +122,6 @@ public class StandardHeaderView: ViewConstrainingView { // MARK: - MVMCoreUIMoleculeViewProtocol open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - if let colorString = json?.optionalStringForKey(KeyBackgroundColor) { - backgroundColor = .mfGet(forHex: colorString) - } if let colorString = json?.optionalStringForKey("contentColor") { let color = UIColor.mfGet(forHex: colorString) headlineLabel.textColor = color diff --git a/MVMCoreUI/Molecules/TwoButtonView.swift b/MVMCoreUI/Molecules/TwoButtonView.swift index c5085cce..4b4f64d9 100644 --- a/MVMCoreUI/Molecules/TwoButtonView.swift +++ b/MVMCoreUI/Molecules/TwoButtonView.swift @@ -41,9 +41,6 @@ import UIKit // MARK: - MVMCoreUIMoleculeViewProtocol open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - if let backgroundColorString = json?.optionalStringForKey(KeyBackgroundColor) { - backgroundColor = UIColor.mfGet(forHex: backgroundColorString) - } let primaryButtonMap = json?.optionalDictionaryForKey("primaryButton") let secondaryButtonMap = json?.optionalDictionaryForKey("secondaryButton") set(primaryButtonJSON: primaryButtonMap, secondaryButtonJSON: secondaryButtonMap, delegateObject: delegateObject, additionalData: additionalData) diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 148932bb..b9177192 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -89,13 +89,13 @@ return nil; } UIView *molecule = [self createMoleculeForName:moleculeName]; - [molecule setWithJSON:json delegateObject:delegateObject additionalData:nil]; // Check if we need to constrain this view. UIView *castMolecule = [molecule conformsToProtocol:@protocol(MVMCoreUIViewConstrainingProtocol)] ? (UIView *)molecule : nil; if (constrainIfNeeded && [castMolecule respondsToSelector:@selector(needsToBeConstrained)] && [castMolecule needsToBeConstrained]) { molecule = [[ViewConstrainingView alloc] initWithMolecule:molecule alignment:[castMolecule respondsToSelector:@selector(alignment)] ? [castMolecule alignment] : UIStackViewAlignmentFill]; } + [molecule setWithJSON:json delegateObject:delegateObject additionalData:nil]; return molecule; } From bd365d60d25d7d572a1be38c4c59e83a446a489b Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 26 Jun 2019 13:09:31 -0400 Subject: [PATCH 12/20] background color for constrained views optional --- MVMCoreUI/Atoms/Views/SeparatorView.m | 5 ++++- MVMCoreUI/Atoms/Views/ViewConstrainingView.m | 2 +- MVMCoreUI/OtherHandlers/MVMCoreUIViewConstrainingProtocol.h | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/SeparatorView.m b/MVMCoreUI/Atoms/Views/SeparatorView.m index 9abaeaab..a92c252b 100644 --- a/MVMCoreUI/Atoms/Views/SeparatorView.m +++ b/MVMCoreUI/Atoms/Views/SeparatorView.m @@ -115,7 +115,6 @@ [self setAsLight]; } } - } else { self.hidden = YES; } @@ -169,4 +168,8 @@ return YES; } +- (BOOL)copyBackgroundColor { + return NO; +} + @end diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m index 7166efee..8b4406fc 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m @@ -326,7 +326,7 @@ if (self.molecule) { [self.molecule setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; } - if (self.constrainedView) { + if (self.constrainedView && (![self.constrainedView respondsToSelector:@selector(copyBackgroundColor)] || [self.constrainedView performSelector:@selector(copyBackgroundColor)])) { self.backgroundColor = self.constrainedView.backgroundColor; } } diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIViewConstrainingProtocol.h b/MVMCoreUI/OtherHandlers/MVMCoreUIViewConstrainingProtocol.h index 42114416..afea0ef6 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIViewConstrainingProtocol.h +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIViewConstrainingProtocol.h @@ -21,6 +21,9 @@ /// Can be used to override any standard constraints that may be added. - (BOOL)useStandardConstraints; +/// Determines if the constraining view will copy the background color of the delegate. +- (BOOL)copyBackgroundColor; + /// Will align if it can. - (void)alignHorizontal:(UIStackViewAlignment)alignment; - (void)alignVertical:(UIStackViewAlignment)alignment; From 868593aabe0720f5461d2009a1857250804e57a9 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 27 Jun 2019 10:03:24 -0400 Subject: [PATCH 13/20] move module from page to mfviewcontroller --- MVMCoreUI/BaseControllers/MFViewController.h | 3 ++ MVMCoreUI/BaseControllers/MFViewController.m | 32 +++++++++++++++-- MVMCoreUI/Molecules/ModuleMolecule.swift | 9 +++-- .../Templates/MoleculeListTemplate.swift | 35 ++++++------------- .../Templates/MoleculeStackTemplate.swift | 30 ++++++---------- 5 files changed, 59 insertions(+), 50 deletions(-) diff --git a/MVMCoreUI/BaseControllers/MFViewController.h b/MVMCoreUI/BaseControllers/MFViewController.h index f1b87dc6..df3b67cd 100644 --- a/MVMCoreUI/BaseControllers/MFViewController.h +++ b/MVMCoreUI/BaseControllers/MFViewController.h @@ -131,6 +131,9 @@ // Returns an array of modules to observe for when we receive a response with JSON. Subclass this to have the ui update when the returned page types are cached. - (nullable NSArray *)modulesToListenFor; +/// Aggregated with modulesToListenFor. Returns an array of modules to observe based on the page itself. Subclass this to go into the page logic and see if it dictates any modules are needed. Important: This also updates in the requiredModules in the view controller mapping, so that future page loads account for these modules. +- (nullable NSArray *)requiredModulesFromPageJSON:(nullable NSDictionary *)page; + // The function that gets called by the notification center when the JSON is updated. - (void)responseJSONUpdated:(nonnull NSNotification *)notification; diff --git a/MVMCoreUI/BaseControllers/MFViewController.m b/MVMCoreUI/BaseControllers/MFViewController.m index 708c2d93..6bcb2364 100644 --- a/MVMCoreUI/BaseControllers/MFViewController.m +++ b/MVMCoreUI/BaseControllers/MFViewController.m @@ -93,6 +93,7 @@ #pragma mark - Functions To Subclass - (BOOL)shouldFinishProcessingLoad:(nonnull MVMCoreLoadObject *)loadObject error:(MVMCoreErrorObject *_Nonnull *_Nonnull)error { + [self updateRequiredModulesForPageJSON:loadObject.pageJSON]; self.loadObject = loadObject; self.pageType = loadObject.pageType; return YES; @@ -208,6 +209,20 @@ return nil; } +- (nullable NSArray *)requiredModulesFromPageJSON:(nullable NSDictionary *)page { + return nil; +} + +- (nullable NSArray *)updateRequiredModulesForPageJSON:(nullable NSDictionary *)page { + // get new needed modules and add them to the mapping for future loads. + NSArray *newRequiredModules = [self requiredModulesFromPageJSON:page]; + NSString *pageType = [page string:KeyPageType]; + if (newRequiredModules && pageType) { + [[MVMCoreViewControllerMappingObject sharedViewControllerMappingObject] addRequiredModulesToMapping:newRequiredModules forPageType:pageType]; + } + return newRequiredModules; +} + - (void)responseJSONUpdated:(nonnull NSNotification *)notification { // Checks for a page we are listening for. @@ -223,11 +238,22 @@ }]; // Checks for modules we are listening for. - NSArray *modulesListeningFor = [self modulesToListenFor]; - NSDictionary *modules = [notification.userInfo dict:KeyModuleMap]; + NSMutableArray *modulesListeningFor = [NSMutableArray array]; + NSArray *modules = [self modulesToListenFor]; + if (modules) { + [modulesListeningFor addObjectsFromArray:modules]; + } + + // Check if the page dictates if there are any new modules to load. Would eventually like to consolidate this and modulesToListenFor somehow. + NSArray *requiredForPage = [self updateRequiredModulesForPageJSON:pageUpdated]; + if (requiredForPage) { + [modulesListeningFor addObjectsFromArray:requiredForPage]; + } + + NSDictionary *modulesReceived = [notification.userInfo dict:KeyModuleMap]; __block NSMutableDictionary *modulesUpdated = [NSMutableDictionary dictionary]; [modulesListeningFor enumerateObjectsUsingBlock:^(NSString * _Nonnull moduleToListenFor, NSUInteger idx, BOOL * _Nonnull stop) { - NSDictionary *module = [modules dict:moduleToListenFor]; + NSDictionary *module = [modulesReceived dict:moduleToListenFor]; if (module) { [modulesUpdated setObject:module forKey:moduleToListenFor]; } diff --git a/MVMCoreUI/Molecules/ModuleMolecule.swift b/MVMCoreUI/Molecules/ModuleMolecule.swift index 316f3f2a..f160acda 100644 --- a/MVMCoreUI/Molecules/ModuleMolecule.swift +++ b/MVMCoreUI/Molecules/ModuleMolecule.swift @@ -65,14 +65,17 @@ open class ModuleMolecule: ViewConstrainingView { } public override static func requiredModules(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { - guard let moduleName = json?.optionalStringForKey("moduleName"), let _ = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else { + let moduleName = json?.optionalStringForKey("moduleName") + if moduleName == nil || delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) == nil { if let errorObject = MVMCoreErrorObject(title: nil, message: MVMCoreGetterUtility.hardcodedString(withKey: HardcodedErrorUnableToProcess), code: CoreUIErrorCode.ErrorCodeModuleMolecule.rawValue, domain: ErrorDomainNative, location: String(describing: self)) { error?.pointee = errorObject MVMCoreUILoggingHandler.shared()?.addError(toLog: errorObject) } - return nil } - return [moduleName] + if let moduleName = moduleName { + return [moduleName] + } + return nil } // MARK: - MVMCoreUIViewConstrainingProtocol diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 93e9dab4..511e5ac1 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -11,20 +11,6 @@ import UIKit open class MoleculeListTemplate: ThreeLayerTableViewController { var moleculesInfo: [(identifier: String, class: AnyClass, molecule: [AnyHashable: Any])]? var modulesRequired: NSMutableArray? - - open override func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer) -> Bool { - var shouldFinish = super.shouldFinishProcessingLoad(loadObject, error: error) - guard shouldFinish else { - return shouldFinish - } - - if let firstError = setup()?.firstObject as? MVMCoreErrorObject { - // Don't continue if there was an error loading needed modules. - error.pointee = firstError - shouldFinish = false - } - return shouldFinish - } open override func viewForTop() -> UIView { guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), @@ -44,7 +30,6 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { open override func newDataBuildScreen() { super.newDataBuildScreen() - _ = setup() registerWithTable() } @@ -105,8 +90,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { } open override func modulesToListenFor() -> [Any]? { - // Get all of the molecules that need modules. - return modulesRequired as? [Any] + return loadObject?.requestParameters?.modules } // MARK: - Convenience @@ -134,24 +118,27 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { } /// Sets up the header, footer, molecule list and ensures no errors loading all content. - func setup() -> NSMutableArray? { + func setup(fromPageJSON page: [AnyHashable : Any]?) { let modules: NSMutableArray = [] - let errors: NSMutableArray = [] let delegate = delegateObject() as? MVMCoreUIDelegateObject - MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate, moduleList: modules, errorList: errors) - MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate, moduleList: modules, errorList: errors) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: page?.optionalDictionaryForKey("header"), delegateObject: delegate, moduleList: modules, errorList: nil) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: page?.optionalDictionaryForKey("footer"), delegateObject: delegate, moduleList: modules, errorList: nil) var moleculeList: [(identifier: String, class: AnyClass, molecule: [AnyHashable: Any])] = [] - if let molecules = loadObject?.pageJSON?.optionalArrayForKey(KeyMolecules) as? [[AnyHashable: Any]] { + if let molecules = page?.optionalArrayForKey(KeyMolecules) as? [[AnyHashable: Any]] { for molecule in molecules { if let info = getMoleculeInfo(with: molecule) { moleculeList.append(info) - MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: molecule, delegateObject: delegate, moduleList: modules, errorList: errors) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: molecule, delegateObject: delegate, moduleList: modules, errorList: nil) } } } moleculesInfo = moleculeList modulesRequired = modules - return errors.count > 0 ? errors : nil + } + + open override func requiredModules(fromPageJSON page: [AnyHashable : Any]?) -> [Any]? { + setup(fromPageJSON: page) + return modulesRequired as? [Any] } } diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index 7bf2a1ed..47138961 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -9,17 +9,6 @@ import UIKit public class MoleculeStackTemplate: ThreeLayerViewController { - var modulesRequired: NSMutableArray? - - public override func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer) -> Bool { - var shouldFinish = super.shouldFinishProcessingLoad(loadObject, error: error) - if shouldFinish, let firstError = modulesNeeded().errors?.firstObject as? MVMCoreErrorObject { - // Don't continue if there was an error loading needed modules. - error.pointee = firstError - shouldFinish = false - } - return shouldFinish - } public override func spaceBetweenTopAndMiddle() -> CGFloat? { return 0 @@ -58,19 +47,20 @@ public class MoleculeStackTemplate: ThreeLayerViewController { } public override func modulesToListenFor() -> [Any]? { - // Get all of the molecules that need modules. - return modulesNeeded().modules as? [Any] + return loadObject?.requestParameters?.modules + } + + open override func requiredModules(fromPageJSON page: [AnyHashable : Any]?) -> [Any]? { + return modulesNeeded() as? [Any] } /// Gets the modules needed. - func modulesNeeded() -> (modules: NSMutableArray?, errors: NSMutableArray?) { + func modulesNeeded() -> NSMutableArray? { let modules: NSMutableArray = [] - let errors: NSMutableArray = [] let delegate = delegateObject() as? MVMCoreUIDelegateObject - MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate, moduleList: modules, errorList: errors) - MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate, moduleList: modules, errorList: errors) - MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("moleculeStack"), delegateObject: delegate, moduleList: modules, errorList: errors) - modulesRequired = modules - return (modules.count > 0 ? modules : nil, errors.count > 0 ? errors : nil) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate, moduleList: modules, errorList: nil) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate, moduleList: modules, errorList: nil) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("moleculeStack"), delegateObject: delegate, moduleList: modules, errorList: nil) + return modules.count > 0 ? modules : nil } } From 5a9e1a9a937209bba210dde720f4bd69ae427838 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 27 Jun 2019 10:24:35 -0400 Subject: [PATCH 14/20] remove debug --- MVMCoreUI/Templates/MoleculeListTemplate.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 511e5ac1..36c53654 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -40,7 +40,6 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { return } for moleculeInfo in moleculesInfo { - print(moleculeInfo.identifier) tableView?.register(moleculeInfo.class, forCellReuseIdentifier: moleculeInfo.identifier) } } @@ -50,7 +49,6 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { let estimatedHeight = moleculeInfo.class.estimatedHeight?(forRow: moleculeInfo.molecule, delegateObject: delegateObject() as? MVMCoreUIDelegateObject) else { return 0 } - print("height :" + moleculeInfo.class.description() + " :" + estimatedHeight.description) return estimatedHeight } From 93dfde6fc6516e23b59d41e9e5ca301b9c75d1a3 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 27 Jun 2019 10:42:22 -0400 Subject: [PATCH 15/20] fix to load timing issue for list --- .../Templates/MoleculeListTemplate.swift | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 36c53654..7ef4cf38 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -10,7 +10,6 @@ import UIKit open class MoleculeListTemplate: ThreeLayerTableViewController { var moleculesInfo: [(identifier: String, class: AnyClass, molecule: [AnyHashable: Any])]? - var modulesRequired: NSMutableArray? open override func viewForTop() -> UIView { guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), @@ -30,6 +29,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { open override func newDataBuildScreen() { super.newDataBuildScreen() + setup() registerWithTable() } @@ -116,27 +116,28 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { } /// Sets up the header, footer, molecule list and ensures no errors loading all content. - func setup(fromPageJSON page: [AnyHashable : Any]?) { - let modules: NSMutableArray = [] - let delegate = delegateObject() as? MVMCoreUIDelegateObject - MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: page?.optionalDictionaryForKey("header"), delegateObject: delegate, moduleList: modules, errorList: nil) - MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: page?.optionalDictionaryForKey("footer"), delegateObject: delegate, moduleList: modules, errorList: nil) - + func setup() { var moleculeList: [(identifier: String, class: AnyClass, molecule: [AnyHashable: Any])] = [] - if let molecules = page?.optionalArrayForKey(KeyMolecules) as? [[AnyHashable: Any]] { + if let molecules = loadObject?.pageJSON?.optionalArrayForKey(KeyMolecules) as? [[AnyHashable: Any]] { for molecule in molecules { if let info = getMoleculeInfo(with: molecule) { moleculeList.append(info) - MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: molecule, delegateObject: delegate, moduleList: modules, errorList: nil) } } } moleculesInfo = moleculeList - modulesRequired = modules } open override func requiredModules(fromPageJSON page: [AnyHashable : Any]?) -> [Any]? { - setup(fromPageJSON: page) - return modulesRequired as? [Any] + let modules: NSMutableArray = [] + let delegate = delegateObject() as? MVMCoreUIDelegateObject + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: page?.optionalDictionaryForKey("header"), delegateObject: delegate, moduleList: modules, errorList: nil) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: page?.optionalDictionaryForKey("footer"), delegateObject: delegate, moduleList: modules, errorList: nil) + if let molecules = page?.optionalArrayForKey(KeyMolecules) as? [[AnyHashable: Any]] { + for molecule in molecules { + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: molecule, delegateObject: delegate, moduleList: modules, errorList: nil) + } + } + return modules as? [Any] } } From d742ef9b6a07a64ab34f1efc8c1b7d7f13ebfcc7 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 27 Jun 2019 13:24:32 -0400 Subject: [PATCH 16/20] Digit text box molecule --- MVMCoreUI/Atoms/TextFields/MFDigitTextField.h | 2 - MVMCoreUI/Atoms/TextFields/MFDigitTextField.m | 58 ++++++++++++------- .../Atoms/TextFields/MFDigitTextField.xib | 13 ++--- MVMCoreUI/Atoms/TextFields/MFTextField.m | 14 +++-- MVMCoreUI/Atoms/Views/ViewConstrainingView.h | 28 ++++----- .../MVMCoreUIMoleculeMappingObject.m | 1 + 6 files changed, 65 insertions(+), 51 deletions(-) diff --git a/MVMCoreUI/Atoms/TextFields/MFDigitTextField.h b/MVMCoreUI/Atoms/TextFields/MFDigitTextField.h index 4be970da..377418db 100644 --- a/MVMCoreUI/Atoms/TextFields/MFDigitTextField.h +++ b/MVMCoreUI/Atoms/TextFields/MFDigitTextField.h @@ -15,8 +15,6 @@ + (nullable instancetype)mfDigitTextFieldWithNumberOfDigits:(NSUInteger)numberOfDigits withBothDelegates:(nullable id)delegate; + (nullable instancetype)mfDigitTextFieldWithNumberOfDigits:(NSUInteger)numberOfDigits withBothDelegates:(nullable id)delegate size:(CGFloat)size; -- (void)setMessage:(nullable NSString *)message; - - (void)setAsSecureTextEntry:(BOOL)secureTextEntry; @property (nullable, nonatomic, strong) NSArray *textFields; diff --git a/MVMCoreUI/Atoms/TextFields/MFDigitTextField.m b/MVMCoreUI/Atoms/TextFields/MFDigitTextField.m index 084ba338..5f76e88b 100644 --- a/MVMCoreUI/Atoms/TextFields/MFDigitTextField.m +++ b/MVMCoreUI/Atoms/TextFields/MFDigitTextField.m @@ -18,33 +18,24 @@ #import "MVMCoreUISplitViewController.h" #import "MVMCoreUIUtility.h" #import "MVMCoreUIConstants.h" +#import @import MVMCore.MVMCoreDispatchUtility; @interface MFDigitTextField () @property (nonatomic) NSUInteger numberOfDigits; -@property (nullable, nonatomic, weak) IBOutlet UILabel *messageLabel; @property (nullable, nonatomic, weak) IBOutlet UIView *textFieldsView; @property (nullable, nonatomic, weak) IBOutlet NSLayoutConstraint *messageToTextFieldPin; @property (nullable, nonatomic, weak) IBOutlet NSLayoutConstraint *labelToTextFieldPin; - @property (nonatomic) BOOL switchedAutomatically; @end @implementation MFDigitTextField -+ (nullable instancetype)mfTextField { - MFDigitTextField *view = [super mfTextField]; - [MFStyler styleLabelB2:view.messageLabel]; - [view setMessage:@""]; - return view; -} - - (MFDigitTextBox *)digitField { - MFDigitTextBox *textField = [[MFDigitTextBox alloc] init]; textField.delegate = self; textField.mfTextBoxDelegate = self; @@ -128,8 +119,9 @@ } - (void)updateView:(CGFloat)size { + [super updateView:size]; [MVMCoreDispatchUtility performBlockOnMainThread:^{ - [MFStyler styleLabelB2:self.messageLabel]; + [self.formLabel updateView:size]; // Remove all current UI. if (self.textFields.count > 0) { @@ -146,6 +138,29 @@ }]; } +- (void)setupView { + [super setupView]; + [self.formLabel styleB2:YES]; + [self setFormText:@""]; + [self alignCenterHorizontal]; +} + +#pragma mark - Molecule + +- (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { + NSNumber *digitsNumber = [json optionalNumberForKey:@"digits"]; + NSUInteger digits = digitsNumber ? digitsNumber.integerValue : 4; + if (digits != self.numberOfDigits) { + self.numberOfDigits = digits; + [self buildTextFieldsViewForSize:[MVMCoreUIUtility getWidth]]; + } + [super setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; +} + ++ (CGFloat)estimatedHeightForRow:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject { + return 44; +} + #pragma mark - Getters - (NSString *)placeholder { @@ -172,15 +187,13 @@ #pragma mark - Setters -- (void)setMessage:(nullable NSString *)message { - [MVMCoreDispatchUtility performBlockOnMainThread:^{ - if (message.length > 0) { - self.messageToTextFieldPin.constant = 10; - } else { - self.messageToTextFieldPin.constant = 0; - } - self.messageLabel.text = message; - }]; +- (void)setFormText:(NSString *)formText { + if (formText.length > 0) { + self.messageToTextFieldPin.constant = 10; + } else { + self.messageToTextFieldPin.constant = 0; + } + [super setFormText:formText]; } - (void)setAsSecureTextEntry:(BOOL)secureTextEntry { @@ -284,6 +297,11 @@ - (void)enable:(BOOL)enable { [super enable:enable]; + if (enable) { + [self.formLabel styleB2:YES]; + } else { + self.formLabel.textColor = [UIColor mfBattleshipGrey]; + } for (UITextField *textField in self.textFields) { textField.userInteractionEnabled = enable; textField.enabled = enable; diff --git a/MVMCoreUI/Atoms/TextFields/MFDigitTextField.xib b/MVMCoreUI/Atoms/TextFields/MFDigitTextField.xib index 1792b9f8..37e6609b 100644 --- a/MVMCoreUI/Atoms/TextFields/MFDigitTextField.xib +++ b/MVMCoreUI/Atoms/TextFields/MFDigitTextField.xib @@ -1,24 +1,19 @@ - + - + - - - NHaasGroteskDSStd-65Md - - + - @@ -28,7 +23,7 @@ -