From 2b4d8b95c961fb5dee5bd5575454c23ab920c246 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 3 Apr 2019 14:46:34 -0400 Subject: [PATCH 01/19] checkbox --- MVMCoreUI.xcodeproj/project.pbxproj | 4 ++ MVMCoreUI/Atoms/Views/CheckBoxWithLabel.swift | 31 ++++++++++++ MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h | 3 ++ MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m | 47 ++++++++++++++++++- MVMCoreUI/Atoms/Views/ViewConstrainingView.h | 3 ++ MVMCoreUI/Atoms/Views/ViewConstrainingView.m | 28 ++++++----- .../MVMCoreUIMoleculeMappingObject.m | 3 +- .../Protocols/FormValidationProtocol.swift | 2 +- 8 files changed, 104 insertions(+), 17 deletions(-) create mode 100644 MVMCoreUI/Atoms/Views/CheckBoxWithLabel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 5df32702..201e8d9a 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ 0105618E224BBE7700E1557D /* FormValidator+TextFields.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */; }; 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */; }; 01056191224BBE8000E1557D /* FormValidationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01056190224BBE7F00E1557D /* FormValidationProtocol.swift */; }; + 013DAB042254FCE00092ABB7 /* CheckBoxWithLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 013DAB032254FCE00092ABB7 /* CheckBoxWithLabel.swift */; }; 01DF55E021F8FAA800CC099B /* MFTextFieldListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */; }; 01DF567021FA5AB300CC099B /* TextFieldListFormViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */; }; 01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -167,6 +168,7 @@ 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+TextFields.swift"; sourceTree = ""; }; 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+FormParams.swift"; sourceTree = ""; }; 01056190224BBE7F00E1557D /* FormValidationProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidationProtocol.swift; sourceTree = ""; }; + 013DAB032254FCE00092ABB7 /* CheckBoxWithLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckBoxWithLabel.swift; sourceTree = ""; }; 01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MFTextFieldListView.swift; sourceTree = ""; }; 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldListFormViewController.swift; sourceTree = ""; }; D206997521FB8A0B00CAE0DE /* MVMCoreUINavigationController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUINavigationController.h; sourceTree = ""; }; @@ -595,6 +597,7 @@ D22D1F19220341F50077CEC0 /* MVMCoreUICheckBox.m */, D22D1F44220496A30077CEC0 /* MVMCoreUISwitch.h */, D22D1F45220496A30077CEC0 /* MVMCoreUISwitch.m */, + 013DAB032254FCE00092ABB7 /* CheckBoxWithLabel.swift */, ); path = Views; sourceTree = ""; @@ -870,6 +873,7 @@ D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */, DBC4391922442197001AB423 /* DashLine.swift in Sources */, D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, + 013DAB042254FCE00092ABB7 /* CheckBoxWithLabel.swift in Sources */, D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */, D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */, D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */, diff --git a/MVMCoreUI/Atoms/Views/CheckBoxWithLabel.swift b/MVMCoreUI/Atoms/Views/CheckBoxWithLabel.swift new file mode 100644 index 00000000..533ee060 --- /dev/null +++ b/MVMCoreUI/Atoms/Views/CheckBoxWithLabel.swift @@ -0,0 +1,31 @@ +// +// ChecckBoxWithLabel.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 4/3/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +@objcMembers public class CheckBoxWithLabel: ViewConstrainingView { + let mvmCheckBox = MVMCoreUICheckBox(frame: .zero) + + public init() { + super.init(frame: .zero) + } + + public required init?(coder decoder: NSCoder) { + super.init(coder: decoder) + } + + public override func setupView() { + super.setupView() + addConstrainedView(mvmCheckBox) + } + + override open func setWithJSON(_ json: [AnyHashable: Any]?, delegate: NSObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegate: delegate, additionalData: additionalData) + mvmCheckBox.setWithJSON(json, delegate: delegate, additionalData: additionalData) + } +} diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h index 853293c7..32fb1e02 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h @@ -59,4 +59,7 @@ - (void)setValueForAccessibilityText:(nullable NSString *)text; - (void)hideDescriptionLabelAndPinCheckboxToRight; +// Molecule Design +- (void)setWithJSON:(nullable NSDictionary *)json delegate:(nullable NSObject *)delegate additionalData:(nullable NSDictionary *)additionalData; + @end diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m index c67c628f..f00d9101 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m @@ -16,10 +16,13 @@ #import "UIColor+MFConvenience.h" #import "MVMCoreUIUtility.h" #import "MFStyler.h" +#import + static const CGFloat FaultTolerance = 20.f; static const CGFloat CheckBoxHeightWidth = 18.0; -@interface MVMCoreUICheckBox () + +@interface MVMCoreUICheckBox () @property (nonatomic, readwrite) BOOL isSelected; @property (weak, nonatomic) UIView *checkedSquare; @@ -38,12 +41,32 @@ static const CGFloat CheckBoxHeightWidth = 18.0; @property (nullable, strong, nonatomic) NSLayoutConstraint *checkboxWidth; @property (nullable, strong, nonatomic) NSLayoutConstraint *checkboxHeight; +@property (nonatomic) BOOL isRequired; +@property (nullable, strong, nonatomic) NSString *fieldKey; +@property (nullable, weak) id delegate; + @end @implementation MVMCoreUICheckBox #pragma mark - convenient class methods +- (void)setWithJSON:(nullable NSDictionary *)json delegate:(nullable NSObject *)delegate additionalData:(nullable NSDictionary *)additionalData { + [FormValidator setupValidationWithMolecule:self delegate:(id)delegate]; + self.delegate = (id)delegate; + self.fieldKey = [json stringForKey:@"fieldKey"]; + self.isRequired = [json boolForKey:@"required"]; + + NSString *checkedColorHex = [json string:@"checkedColor"]; + NSString *unCheckedColorHex = [json string:@"unCheckedColor"]; + + UIColor *checkedColor = checkedColorHex ? [UIColor mfGetColorForHex:checkedColorHex]: [UIColor blackColor]; + UIColor *unCheckedColor = unCheckedColorHex ? [UIColor mfGetColorForHex:unCheckedColorHex]: [UIColor clearColor]; + NSString *label = [json string:@"label"]; + + [self setupWithCheckedColor:checkedColor unCheckColor:unCheckedColor text:label]; +} + + (instancetype)mfCheckBox { MVMCoreUICheckBox *checkBox = [[self alloc] initWithFrame:CGRectZero]; checkBox.translatesAutoresizingMaskIntoConstraints = NO; @@ -68,6 +91,23 @@ static const CGFloat CheckBoxHeightWidth = 18.0; return checkBox; } +#pragma mark - FormValidationProtocol + +- (BOOL)isValidField { + if (self.isRequired) { + return self.isSelected; + } + return true; +} + +- (nullable NSString *)formFieldName { + return self.fieldKey; +} + +- (nullable id)formFieldValue { + return @(self.isSelected); +} + #pragma mark - inits - (instancetype)initWithCheckedColor:(UIColor *)checkedColor unCheckColor:(UIColor *)unCheckedColor text:(NSString *)text { @@ -253,7 +293,7 @@ static const CGFloat CheckBoxHeightWidth = 18.0; [self setSelected:selected animated:animated runBlock:YES]; } -- (void)setSelected:(BOOL)selected animated:(BOOL)animated runBlock:(BOOL)runBlock{ +- (void)setSelected:(BOOL)selected animated:(BOOL)animated runBlock:(BOOL)runBlock { [self addAccessibilityLabel:selected]; self.isSelected = selected; @@ -271,6 +311,9 @@ static const CGFloat CheckBoxHeightWidth = 18.0; } completion:nil]; [self.checkMark updateCheckSelected:NO animated:animated]; } + + FormValidator *formValidator = [FormValidator getFormValidatorForDelegate:self.delegate]; + [formValidator enableByValidation]; } - (void)setColor:(nullable UIColor *)color forState:(UIControlState)state { diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.h b/MVMCoreUI/Atoms/Views/ViewConstrainingView.h index bb4740a7..939c3b6f 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.h +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.h @@ -47,4 +47,7 @@ // For setting up the view. - (void)setupView; +// Add a View Constraining View +- (void)addConstrainedView:(nonnull UIView *)view; + @end diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m index a88b61c3..1ef339fb 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m @@ -28,28 +28,30 @@ ViewConstrainingView *constrainingView = [[ViewConstrainingView alloc] initWithFrame:CGRectZero]; constrainingView.translatesAutoresizingMaskIntoConstraints = NO; constrainingView.backgroundColor = [UIColor clearColor]; - + [constrainingView addConstrainedView:view]; + return constrainingView; +} + +- (void)addConstrainedView:(nonnull UIView *)view { view.translatesAutoresizingMaskIntoConstraints = NO; - [constrainingView addSubview:view]; - constrainingView.constrainedView = view; + [self addSubview:view]; + self.constrainedView = view; - NSLayoutConstraint *leftPin = [view.leftAnchor constraintEqualToAnchor:constrainingView.leftAnchor]; - constrainingView.leftPin = leftPin; + NSLayoutConstraint *leftPin = [view.leftAnchor constraintEqualToAnchor:self.leftAnchor]; + self.leftPin = leftPin; leftPin.active = YES; - NSLayoutConstraint *topPin = [view.topAnchor constraintEqualToAnchor:constrainingView.topAnchor]; - constrainingView.topPin = topPin; + NSLayoutConstraint *topPin = [view.topAnchor constraintEqualToAnchor:self.topAnchor]; + self.topPin = topPin; topPin.active = YES; - NSLayoutConstraint *bottomPin = [constrainingView.bottomAnchor constraintEqualToAnchor:view.bottomAnchor]; - constrainingView.bottomPin = bottomPin; + NSLayoutConstraint *bottomPin = [self.bottomAnchor constraintEqualToAnchor:view.bottomAnchor]; + self.bottomPin = bottomPin; bottomPin.active = YES; - NSLayoutConstraint *rightPin = [constrainingView.rightAnchor constraintEqualToAnchor:view.rightAnchor]; - constrainingView.rightPin = rightPin; + NSLayoutConstraint *rightPin = [self.rightAnchor constraintEqualToAnchor:view.rightAnchor]; + self.rightPin = rightPin; rightPin.active = YES; - - return constrainingView; } - (void)pinToSuperView { diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 0936f9df..4eb66001 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -32,7 +32,8 @@ @"standardFooter": StandardFooterView.class, @"caretView": CaretView.class, @"caretButton": CaretButton.class, - @"textField" : MFTextField.class + @"textField" : MFTextField.class, + @"checkbox" : CheckBoxWithLabel.class } mutableCopy]; }); return mapping; diff --git a/MVMCoreUI/Protocols/FormValidationProtocol.swift b/MVMCoreUI/Protocols/FormValidationProtocol.swift index bfdbb0fd..5336af24 100644 --- a/MVMCoreUI/Protocols/FormValidationProtocol.swift +++ b/MVMCoreUI/Protocols/FormValidationProtocol.swift @@ -15,5 +15,5 @@ import Foundation @objc optional func enableField(_ enable: Bool) @objc optional func formFieldName() -> String? - @objc optional func formFieldValue() -> String? + @objc optional func formFieldValue() -> Any? } From 4b02477592314de0fdd0b8876f7f10a93586d8bf Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 9 Apr 2019 14:33:41 -0400 Subject: [PATCH 02/19] merge From fa4b03ac1d0b2f67c68df8f74d827704f63f42cd Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Thu, 11 Apr 2019 11:20:46 -0400 Subject: [PATCH 03/19] code review --- MVMCoreUI.xcodeproj/project.pbxproj | 1 - MVMCoreUI/Atoms/TextFields/MFTextField.m | 2 +- MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h | 1 - MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m | 8 ++++---- MVMCoreUI/Utility/MVMCoreUIConstants.h | 3 +++ MVMCoreUI/Utility/MVMCoreUIConstants.m | 3 +++ 6 files changed, 11 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index c32e376c..eca11941 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -869,7 +869,6 @@ D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */, DBC4391922442197001AB423 /* DashLine.swift in Sources */, D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, - 013DAB042254FCE00092ABB7 /* CheckBoxWithLabel.swift in Sources */, D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */, D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */, D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */, diff --git a/MVMCoreUI/Atoms/TextFields/MFTextField.m b/MVMCoreUI/Atoms/TextFields/MFTextField.m index 565e086c..ff1d3fd8 100644 --- a/MVMCoreUI/Atoms/TextFields/MFTextField.m +++ b/MVMCoreUI/Atoms/TextFields/MFTextField.m @@ -326,7 +326,7 @@ } // key used to send text value to server - string = [map string:@"fieldKey"]; + string = [map string:KeyFieldKey]; if (string.length > 0) { self.fieldKey = string; } diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h index 32fb1e02..831c1994 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h @@ -59,7 +59,6 @@ - (void)setValueForAccessibilityText:(nullable NSString *)text; - (void)hideDescriptionLabelAndPinCheckboxToRight; -// Molecule Design - (void)setWithJSON:(nullable NSDictionary *)json delegate:(nullable NSObject *)delegate additionalData:(nullable NSDictionary *)additionalData; @end diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m index f00d9101..fb81e0b5 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m @@ -54,15 +54,15 @@ static const CGFloat CheckBoxHeightWidth = 18.0; - (void)setWithJSON:(nullable NSDictionary *)json delegate:(nullable NSObject *)delegate additionalData:(nullable NSDictionary *)additionalData { [FormValidator setupValidationWithMolecule:self delegate:(id)delegate]; self.delegate = (id)delegate; - self.fieldKey = [json stringForKey:@"fieldKey"]; - self.isRequired = [json boolForKey:@"required"]; - + self.fieldKey = [json stringForKey:KeyFieldKey]; + self.isRequired = [json boolForKey:KeyRequired]; + NSString *checkedColorHex = [json string:@"checkedColor"]; NSString *unCheckedColorHex = [json string:@"unCheckedColor"]; UIColor *checkedColor = checkedColorHex ? [UIColor mfGetColorForHex:checkedColorHex]: [UIColor blackColor]; UIColor *unCheckedColor = unCheckedColorHex ? [UIColor mfGetColorForHex:unCheckedColorHex]: [UIColor clearColor]; - NSString *label = [json string:@"label"]; + NSString *label = [json string:KeyLabel]; [self setupWithCheckedColor:checkedColor unCheckColor:unCheckedColor text:label]; } diff --git a/MVMCoreUI/Utility/MVMCoreUIConstants.h b/MVMCoreUI/Utility/MVMCoreUIConstants.h index 93f77713..ba0eff4d 100644 --- a/MVMCoreUI/Utility/MVMCoreUIConstants.h +++ b/MVMCoreUI/Utility/MVMCoreUIConstants.h @@ -35,6 +35,9 @@ extern NSString * const KeyTextColor; extern NSString * const KeyIsHidden; extern NSString * const KeyIsOpaque; +extern NSString * const KeyFieldKey; +extern NSString * const KeyRequired; + #pragma mark - Values extern NSString * const StringY; diff --git a/MVMCoreUI/Utility/MVMCoreUIConstants.m b/MVMCoreUI/Utility/MVMCoreUIConstants.m index 684f013b..43763ae2 100644 --- a/MVMCoreUI/Utility/MVMCoreUIConstants.m +++ b/MVMCoreUI/Utility/MVMCoreUIConstants.m @@ -18,6 +18,8 @@ NSString * const KeyValue = @"value"; NSString * const KeyLabel = @"label"; NSString * const KeyDisable = @"disable"; NSString * const KeyFieldName = @"fieldName"; +NSString * const KeyFieldKey = @"fieldKey"; +NSString * const KeyRequired = @"required"; NSString * const KeyHideMainMenu = @"hideMainMenu"; NSString * const KeyProgressPercent = @"progressPercent"; @@ -34,6 +36,7 @@ NSString * const KeyTextColor = @"textColor"; NSString * const KeyIsHidden = @"isHidden"; NSString * const KeyIsOpaque = @"isOpaque"; + #pragma mark - Values NSString * const StringY = @"Y"; From 0abefbcdc00ad1ee90a678361d4590ca18dac3d1 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 17 Apr 2019 11:40:44 -0400 Subject: [PATCH 04/19] using MVMCoreUIDelegateObject --- MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h | 2 -- MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m | 11 ++++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h index 831c1994..853293c7 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.h @@ -59,6 +59,4 @@ - (void)setValueForAccessibilityText:(nullable NSString *)text; - (void)hideDescriptionLabelAndPinCheckboxToRight; -- (void)setWithJSON:(nullable NSDictionary *)json delegate:(nullable NSObject *)delegate additionalData:(nullable NSDictionary *)additionalData; - @end diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m index fb81e0b5..00415b71 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m @@ -43,7 +43,7 @@ static const CGFloat CheckBoxHeightWidth = 18.0; @property (nonatomic) BOOL isRequired; @property (nullable, strong, nonatomic) NSString *fieldKey; -@property (nullable, weak) id delegate; +@property (nullable, weak) DelegateObject *delegate; @end @@ -51,9 +51,10 @@ static const CGFloat CheckBoxHeightWidth = 18.0; #pragma mark - convenient class methods -- (void)setWithJSON:(nullable NSDictionary *)json delegate:(nullable NSObject *)delegate additionalData:(nullable NSDictionary *)additionalData { - [FormValidator setupValidationWithMolecule:self delegate:(id)delegate]; - self.delegate = (id)delegate; +- (void)setWithJSON:(NSDictionary *)json delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { + + [FormValidator setupValidationWithMolecule:self delegate:((MVMCoreUIDelegateObject *)delegateObject).formValidationProtocol]; + self.delegate = delegateObject; self.fieldKey = [json stringForKey:KeyFieldKey]; self.isRequired = [json boolForKey:KeyRequired]; @@ -312,7 +313,7 @@ static const CGFloat CheckBoxHeightWidth = 18.0; [self.checkMark updateCheckSelected:NO animated:animated]; } - FormValidator *formValidator = [FormValidator getFormValidatorForDelegate:self.delegate]; + FormValidator *formValidator = [FormValidator getFormValidatorForDelegate:((MVMCoreUIDelegateObject *)self.delegate).formValidationProtocol]; [formValidator enableByValidation]; } From b00b43eab0b76ca50b072f9ab1e5a860756dd896 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 22 Apr 2019 13:14:22 -0400 Subject: [PATCH 05/19] Helper functions Molecule List. Back to view instead of margins for stack due to background color issues. Standard Header View to margin for internal use. --- MVMCoreUI.xcodeproj/project.pbxproj | 16 ++ .../Views/ConstrainingMoleculeView.swift | 55 ++++ MVMCoreUI/Atoms/Views/MFLabel.m | 4 + MVMCoreUI/Atoms/Views/ViewConstrainingView.m | 2 + MVMCoreUI/BaseControllers/MFViewController.m | 4 + .../ThreeLayerTableViewController.swift | 255 ++++++++++++++++++ .../ThreeLayerViewController.swift | 2 +- .../Molecules/MVMCoreUIMoleculeViewProtocol.h | 3 + MVMCoreUI/Molecules/MoleculeStackView.swift | 7 +- .../Molecules/MoleculeTableViewCell.swift | 34 +++ MVMCoreUI/Molecules/StandardFooterView.swift | 18 +- .../MVMCoreUIMoleculeMappingObject.m | 5 +- .../MVMCoreUIViewControllerMappingObject.m | 3 +- .../Templates/MoleculeListTemplate.swift | 57 ++++ .../Templates/MoleculeStackTemplate.swift | 2 +- 15 files changed, 444 insertions(+), 23 deletions(-) create mode 100644 MVMCoreUI/Atoms/Views/ConstrainingMoleculeView.swift create mode 100644 MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift create mode 100644 MVMCoreUI/Molecules/MoleculeTableViewCell.swift create mode 100644 MVMCoreUI/Templates/MoleculeListTemplate.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 1f3e1d53..6cb9dc9e 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -147,6 +147,7 @@ D29DF32521ED0DA2003B2FB9 /* TextButtonView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF32321ED0DA2003B2FB9 /* TextButtonView.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF32C21EE8736003B2FB9 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D29DF32821EE8736003B2FB9 /* Localizable.strings */; }; D29DF32E21EE8C3D003B2FB9 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D29DF32D21EE8C3D003B2FB9 /* Media.xcassets */; }; + D2A421BF226A14F100A05A88 /* ConstrainingMoleculeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A421BE226A14F100A05A88 /* ConstrainingMoleculeView.swift */; }; D2A514582211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2A514562211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; D2A514592211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2A514572211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m */; }; D2A5145D2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -158,6 +159,9 @@ D2C5001821F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */; }; D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */; }; + D2E1FADD2268B25E00AEFD8C /* MoleculeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADC2268B25E00AEFD8C /* MoleculeTableViewCell.swift */; }; + D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */; }; + D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */; }; DBC4391822442197001AB423 /* CaretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391622442196001AB423 /* CaretView.swift */; }; DBC4391922442197001AB423 /* DashLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391722442197001AB423 /* DashLine.swift */; }; DBC4391B224421A0001AB423 /* CaretButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391A224421A0001AB423 /* CaretButton.swift */; }; @@ -308,6 +312,7 @@ D29DF32A21EE8736003B2FB9 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; D29DF32B21EE8736003B2FB9 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/Localizable.strings"; sourceTree = ""; }; D29DF32D21EE8C3D003B2FB9 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = ""; }; + D2A421BE226A14F100A05A88 /* ConstrainingMoleculeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConstrainingMoleculeView.swift; sourceTree = ""; }; D2A514562211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIMoleculeMappingObject.h; sourceTree = ""; }; D2A514572211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIMoleculeMappingObject.m; sourceTree = ""; }; D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIMoleculeViewProtocol.h; sourceTree = ""; }; @@ -319,6 +324,9 @@ D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewControllerMappingObject.h; sourceTree = ""; }; D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIViewControllerMappingObject.m; sourceTree = ""; }; D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIDelegateObject.swift; sourceTree = ""; }; + D2E1FADC2268B25E00AEFD8C /* MoleculeTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeTableViewCell.swift; sourceTree = ""; }; + D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTableViewController.swift; sourceTree = ""; }; + D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeListTemplate.swift; sourceTree = ""; }; DBC4391622442196001AB423 /* CaretView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretView.swift; sourceTree = ""; }; DBC4391722442197001AB423 /* DashLine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DashLine.swift; sourceTree = ""; }; DBC4391A224421A0001AB423 /* CaretButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretButton.swift; sourceTree = ""; }; @@ -407,6 +415,7 @@ 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */, D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */, D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.swift */, + D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */, ); path = Templates; sourceTree = ""; @@ -442,6 +451,7 @@ D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */, D2A5145E2211DDC100345BFB /* MoleculeStackView.swift */, D274CA322236A78900B01B62 /* StandardFooterView.swift */, + D2E1FADC2268B25E00AEFD8C /* MoleculeTableViewCell.swift */, ); path = Molecules; sourceTree = ""; @@ -462,6 +472,7 @@ D29DF2CC21E7C104003B2FB9 /* MFLoadingViewController.h */, D29DF2CD21E7C104003B2FB9 /* MFLoadingViewController.m */, D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */, + D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */, ); path = BaseControllers; sourceTree = ""; @@ -568,6 +579,7 @@ D29DF28621E7AC2B003B2FB9 /* MFLabel.m */, D29DF31E21ED0CBA003B2FB9 /* LabelView.h */, D29DF31F21ED0CBA003B2FB9 /* LabelView.m */, + D2A421BE226A14F100A05A88 /* ConstrainingMoleculeView.swift */, D29DF28721E7AC2B003B2FB9 /* ViewConstrainingView.h */, D29DF28821E7AC2B003B2FB9 /* ViewConstrainingView.m */, D282AAB9224131D100C46919 /* MFTransparentGIFView.swift */, @@ -868,6 +880,7 @@ D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */, DBC4391922442197001AB423 /* DashLine.swift in Sources */, D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, + D2A421BF226A14F100A05A88 /* ConstrainingMoleculeView.swift in Sources */, D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */, D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */, D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */, @@ -897,6 +910,7 @@ D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */, D282AACB2243C61700C46919 /* ButtonView.swift in Sources */, 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */, + D2E1FADD2268B25E00AEFD8C /* MoleculeTableViewCell.swift in Sources */, D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */, D29DF18121E69E50003B2FB9 /* MFView.m in Sources */, D29DF18321E69E54003B2FB9 /* SeparatorView.m in Sources */, @@ -913,6 +927,7 @@ D29DF2C721E7BF57003B2FB9 /* MFTabBarInteractor.m in Sources */, D29DF29521E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m in Sources */, D29DF16121E69996003B2FB9 /* MFViewController.m in Sources */, + D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */, D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */, D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */, D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */, @@ -920,6 +935,7 @@ 0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */, D29DF29821E7ADB8003B2FB9 /* MFScrollingViewController.m in Sources */, D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */, + D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */, D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */, D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */, D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Views/ConstrainingMoleculeView.swift b/MVMCoreUI/Atoms/Views/ConstrainingMoleculeView.swift new file mode 100644 index 00000000..22e8e09d --- /dev/null +++ b/MVMCoreUI/Atoms/Views/ConstrainingMoleculeView.swift @@ -0,0 +1,55 @@ +// +// ConstrainingMoleculeView.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 4/19/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +@objcMembers open class ConstrainingMoleculeView: MFView { + var molecule: (UIView & MVMCoreUIMoleculeViewProtocol)? + + public init(withMolecule molecule: UIView & MVMCoreUIMoleculeViewProtocol) { + self.molecule = molecule + super.init(frame: .zero) + } + + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + open override func setupView() { + super.setupView() + if let molecule = molecule, molecule.superview == nil { + addSubview(molecule) + molecule.topAnchor.constraint(equalTo: topAnchor).isActive = true + molecule.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor).isActive = true + layoutMarginsGuide.rightAnchor.constraint(equalTo: molecule.rightAnchor).isActive = true + bottomAnchor.constraint(equalTo: molecule.bottomAnchor).isActive = true + } + } + + open override func updateView(_ size: CGFloat) { + if let molecule = molecule as? MVMCoreViewProtocol { + molecule.updateView(size) + } + MFStyler.setDefaultMarginsFor(self, size: size) + } + + open override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + guard let json = json, let molecule = molecule else { + return + } + molecule.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + if let backgroundColor = molecule.backgroundColor { + self.backgroundColor = backgroundColor + } + } + + open override func setAsMolecule() { + molecule?.setAsMolecule?() + } +} diff --git a/MVMCoreUI/Atoms/Views/MFLabel.m b/MVMCoreUI/Atoms/Views/MFLabel.m index 5fb19037..4fba3083 100644 --- a/MVMCoreUI/Atoms/Views/MFLabel.m +++ b/MVMCoreUI/Atoms/Views/MFLabel.m @@ -237,6 +237,10 @@ self.originalAttributedString = self.attributedText; } +- (BOOL)needsToBeConstrained { + return YES; +} + - (void)styleH1:(BOOL)scale { [MFStyler styleLabelH1:self genericScaling:NO]; [self setScale:scale]; diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m index 780b65aa..43ea5f8c 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m @@ -131,6 +131,7 @@ CGFloat padding = [MFStyler defaultHorizontalPaddingForSize:size]; [self setLeftPinConstant:padding]; [self setRightPinConstant:padding]; + [MFStyler setDefaultMarginsForView:self size:size]; }]; } } @@ -138,6 +139,7 @@ #pragma mark - MVMCoreUIMoleculeViewProtocol - (void)setAsMolecule { + self.updateViewHorizontalDefaults = YES; } @end diff --git a/MVMCoreUI/BaseControllers/MFViewController.m b/MVMCoreUI/BaseControllers/MFViewController.m index 0c3b3f3d..1bd5e866 100644 --- a/MVMCoreUI/BaseControllers/MFViewController.m +++ b/MVMCoreUI/BaseControllers/MFViewController.m @@ -521,6 +521,10 @@ } completion:completion]; } +- (BOOL)viewRespectsSystemMinimumLayoutMargins { + return NO; +} + #pragma mark - UITextField Functions // To Remove TextFields Bug: Keyboard is not dismissing after reaching textfield max length limit diff --git a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift new file mode 100644 index 00000000..a44fc4ee --- /dev/null +++ b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift @@ -0,0 +1,255 @@ +// +// ThreeLayerTableViewController.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 4/18/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit +import MVMAnimationFramework + +open class ThreeLayerTableViewController: MFProgrammaticTableViewController { + // The three main views + private var topView: UIView? + private var bottomView: UIView? + private var headerView: UIView? + private var footerView: UIView? + private var safeAreaView: UIView? + var useMargins: Bool = true + var bottomViewOutsideOfScrollArea: Bool = false + private var topViewBottomConstraint: NSLayoutConstraint? + private var bottomViewTopConstraint: NSLayoutConstraint? + + //MARK:-MVMCoreViewProtocol + open override func updateViews() { + super.updateViews() + let width = view.bounds.width + MFStyler.setDefaultMarginsFor(contentView, size: width) + if let topView = topView as? MVMCoreViewProtocol { + topView.updateView(width) + showHeader() + } + if let bottomView = bottomView as? MVMCoreViewProtocol { + bottomView.updateView(width) + showFooter() + } + self.tableView?.reloadData() + } + + //MARK:-MFViewController + open override func newDataBuildScreen() { + super.newDataBuildScreen() + createViewForTableHeader() + createViewForTableFooter() + tableView?.reloadData() + } + + override open func viewDidLoad() { + super.viewDidLoad() + setToHaveNoSectionHeadersFooters() + // Do any additional setup after loading the view. + } + + //MARK:-Spacing + // If both are subclassed to return a value, then the buttons will not be pinned towards the bottom because neither spacing would try to fill the screen. + /// Space between the top view and the table sections, nil to fill. 0 default + open func spaceBelowTopView() -> CGFloat? { + return 0 + } + + /// Space between the bottom view and the table sections, nil to fill. nil default + open func spaceAboveBottomView() -> CGFloat? { + return nil + } + + /// can override to return a minimum fill space. + open func minimumFillSpace() -> CGFloat { + return 0 + } + + open override func updateViewConstraints() { + super.updateViewConstraints() + guard let tableView = tableView else { + return + } + + let minimumSpace: CGFloat = minimumFillSpace() + var currentSpace: CGFloat = 0 + var totalMinimumSpace: CGFloat = 0 + + var fillTop = false + if spaceBelowTopView() == nil, self.tableView?.tableHeaderView != nil { + fillTop = true + currentSpace += topViewBottomConstraint?.constant ?? 0 + totalMinimumSpace += minimumSpace + } + + var fillBottom = false + if spaceAboveBottomView() == nil, !bottomViewOutsideOfScrollArea, self.tableView?.tableFooterView != nil { + fillBottom = true + currentSpace += bottomViewTopConstraint?.constant ?? 0 + totalMinimumSpace += minimumSpace + } + + guard fillTop || fillBottom else { + return + } + let newSpace = MVMCoreUIUtility.getVariableConstraintHeight(currentSpace, in: tableView, minimumHeight: totalMinimumSpace) + + // If the bottom view is outside of the scroll, then only the top view constraint is being used, so we have to double it to account for the bottom constraint not being there when we compare to the new value. + var currentSpaceForCompare: CGFloat = currentSpace + if fillTop && bottomViewOutsideOfScrollArea { + currentSpaceForCompare = currentSpace * 2; + } + + if !MVMCoreGetterUtility.cgfequalwiththreshold(newSpace, currentSpaceForCompare, 0.1) { + if fillTop && fillBottom { + // space both + let half = newSpace / 2 + topViewBottomConstraint?.constant = half + bottomViewTopConstraint?.constant = half + showHeader() + showFooter() + } else if fillTop { + // Only top is spaced (half the size if the bottom view is out of the scroll because it needs to be sized as if there are two spacers but there is only one. + if bottomViewOutsideOfScrollArea { + topViewBottomConstraint?.constant = newSpace / 2 + } else { + topViewBottomConstraint?.constant = newSpace + } + showHeader() + } else if fillBottom { + // Only bottom is spaced. + bottomViewTopConstraint?.constant = newSpace + showFooter() + } + } + } + + //MARK:-Header Footer + /// Gets the top view and adds it to a spacing view, headerView, and then calls showHeader. + open func createViewForTableHeader() { + let topView = viewForTop() + self.topView = topView + + let headerView = MVMCoreUICommonViewsUtility.commonView() + headerView.addSubview(topView) + topView.topAnchor.constraint(equalTo: headerView.topAnchor).isActive = true + topView.leftAnchor.constraint(equalTo: headerView.leftAnchor).isActive = true + headerView.rightAnchor.constraint(equalTo: topView.rightAnchor).isActive = true + topViewBottomConstraint = headerView.bottomAnchor.constraint(equalTo: topView.bottomAnchor, constant: spaceBelowTopView() ?? 0) + topViewBottomConstraint?.isActive = true + self.headerView = headerView + showHeader() + } + + /// Gets the bottom view and adds it to a spacing view, footerView, and then calls showFooter. + open func createViewForTableFooter() { + let bottomView = viewForBottom() + self.bottomView = bottomView + + let footerView = MVMCoreUICommonViewsUtility.commonView() + footerView.addSubview(bottomView) + bottomViewTopConstraint = bottomView.topAnchor.constraint(equalTo: footerView.topAnchor, constant: spaceAboveBottomView() ?? 0) + bottomViewTopConstraint?.isActive = true + bottomView.leftAnchor.constraint(equalTo: footerView.leftAnchor).isActive = true + footerView.rightAnchor.constraint(equalTo: bottomView.rightAnchor).isActive = true + footerView.bottomAnchor.constraint(equalTo: bottomView.bottomAnchor).isActive = true + self.footerView = footerView + showFooter() + } + + /// Takes the current headerView and adds it to the tableHeaderView + func showHeader() { + headerView?.removeFromSuperview() + tableView?.tableHeaderView = nil + guard let headerView = headerView else { + return + } + + // This extra view is needed because of the wonkiness of apple's table header. Things breaks if using autolayout. + MVMCoreUIUtility.sizeView(toFit: headerView) + let tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: MVMCoreUIUtility.getWidth(), height: headerView.frame.height)) + tableHeaderView.addSubview(headerView) + NSLayoutConstraint.constraintPinSubview(toSuperview: headerView) + tableView?.tableHeaderView = tableHeaderView + } + + /// Takes the current footerView and adds it to the tableFooterView + func showFooter() { + footerView?.removeFromSuperview() + safeAreaView?.removeFromSuperview() + guard let footerView = footerView, let tableView = tableView else { + return + } + + if bottomViewOutsideOfScrollArea { + // put bottom view outside of scrolling area. + bottomConstraint?.isActive = false + view.addSubview(footerView) + footerView.topAnchor.constraint(equalTo: tableView.bottomAnchor).isActive = true + footerView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true + view.rightAnchor.constraint(equalTo: footerView.rightAnchor).isActive = true + if #available(iOS 11.0, *) { + view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: footerView.bottomAnchor).isActive = true + safeAreaView = MVMCoreUICommonViewsUtility.getAndSetupSafeAreaView(on: view) + safeAreaView?.backgroundColor = bottomView?.backgroundColor + } else { + view.bottomAnchor.constraint(equalTo: footerView.bottomAnchor).isActive = true + } + } else { + bottomConstraint?.isActive = true + var y: CGFloat? + if let tableFooterView = tableView.tableFooterView { + // if footer already exists, use the same y location to avoid strange moving animation + y = tableFooterView.frame.minY + } + + // This extra view is needed because of the wonkiness of apple's table footer. Things breaks if using autolayout. + MVMCoreUIUtility.sizeView(toFit: footerView) + let tableFooterView = UIView(frame: CGRect(x: 0, y: y ?? 0, width: MVMCoreUIUtility.getWidth(), height: footerView.frame.height)) + tableFooterView.addSubview(footerView) + NSLayoutConstraint.constraintPinSubview(toSuperview: footerView) + tableView.tableFooterView = tableFooterView + } + } + + //MARK:-Functions to subclass + /// Subclass for a top view. + open func viewForTop() -> UIView { + let view = MVMCoreUICommonViewsUtility.commonView() + view.heightAnchor.constraint(equalToConstant: 0).isActive = true + return view + } + + /// Subclass for a bottom view. + open func viewForBottom() -> UIView { + let view = MVMCoreUICommonViewsUtility.commonView() + view.heightAnchor.constraint(equalToConstant: 0).isActive = true + return view + } + + //MARK:-Scrollview + open override func scrollViewDidScroll(_ scrollView: UIScrollView) { + // To stop handscroll animation if animating after scroll + stopHandScrollAnimation(true) + } + + deinit { + tableView?.delegate = nil + } + + //MARK:-Animation + open override func setupIntroAnimations() { + if let topView = topView, topView.subviews.count > 0 { + introAnimationManager?.addAnimation(animation: MVMAnimations.fadeUpAnimation(view: topView)) + } + if let tableView = tableView { + introAnimationManager?.addAnimation(animation: MVMAnimations.animateTableViewFadeInCells(tableView: tableView)) + } + if let bottomView = bottomView, bottomView.subviews.count > 0 { + introAnimationManager?.addAnimation(animation: MVMAnimations.fadeUpAnimation(view: bottomView)) + } + } +} diff --git a/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift index 2573388c..299cdf9b 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift @@ -16,7 +16,7 @@ open class ThreeLayerViewController: ProgrammaticScrollViewController { var topView: UIView? var middleView: UIView? var bottomView: UIView? - var useMargins: Bool = true + var useMargins: Bool = false // The bottom view can be put outside of the scrolling area. var bottomViewOutsideOfScroll = false diff --git a/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h b/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h index ac92e0a1..cce08641 100644 --- a/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h +++ b/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h @@ -19,6 +19,9 @@ // Called after init to provide an early setter for any molecule specific logic - (void)setAsMolecule; +// Notifies the creator that the view needs to be constrained in a view. +- (BOOL)needsToBeConstrained; + @end diff --git a/MVMCoreUI/Molecules/MoleculeStackView.swift b/MVMCoreUI/Molecules/MoleculeStackView.swift index 57b0108c..a43a6a94 100644 --- a/MVMCoreUI/Molecules/MoleculeStackView.swift +++ b/MVMCoreUI/Molecules/MoleculeStackView.swift @@ -70,12 +70,9 @@ public class MoleculeStackView: MFView { if let spacingBlock = spacingBlock { MVMCoreUIStackableViewController.populateView(self, withUIArray: moleculesArray, useMargins: useMargins, withSpacingBlock: spacingBlock) } else { + let separation = json?.optionalCGFloatForKey("separation") ?? PaddingDefault MVMCoreUIStackableViewController.populateView(self, withUIArray: moleculesArray, useMargins: useMargins) { (object) -> UIEdgeInsets in - if object as AnyObject? === moleculesArray.first { - return UIEdgeInsets.zero - } else { - return UIEdgeInsets.init(top: PaddingTwo, left: 0, bottom: 0, right: 0) - } + return UIEdgeInsets.init(top: separation, left: 0, bottom: 0, right: 0) } } } diff --git a/MVMCoreUI/Molecules/MoleculeTableViewCell.swift b/MVMCoreUI/Molecules/MoleculeTableViewCell.swift new file mode 100644 index 00000000..21b05a22 --- /dev/null +++ b/MVMCoreUI/Molecules/MoleculeTableViewCell.swift @@ -0,0 +1,34 @@ +// +// MoleculeTableViewCell.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 4/18/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +@objcMembers open class MoleculeTableViewCell: UITableViewCell, MVMCoreViewProtocol, MVMCoreUIMoleculeViewProtocol { + var molecule: (UIView & MVMCoreUIMoleculeViewProtocol)? + + public func updateView(_ size: CGFloat) { + if let molecule = molecule as? MVMCoreViewProtocol { + molecule.updateView(size) + } + } + + public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) { + guard let json = json else { + return + } + if molecule == nil { + if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(json, delegateObject: delegateObject) { + addSubview(moleculeView) + NSLayoutConstraint.constraintPinSubview(toSuperview: moleculeView) + molecule = moleculeView + } + } else { + molecule?.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + } + } +} diff --git a/MVMCoreUI/Molecules/StandardFooterView.swift b/MVMCoreUI/Molecules/StandardFooterView.swift index a170d023..06d39c47 100644 --- a/MVMCoreUI/Molecules/StandardFooterView.swift +++ b/MVMCoreUI/Molecules/StandardFooterView.swift @@ -46,16 +46,16 @@ public class StandardFooterView: ViewConstrainingView { spaceBetweenButtons = textButton.topAnchor.constraint(equalTo: twoButtonView.bottomAnchor, constant: PaddingTwo) spaceBetweenButtons?.isActive = true - leftConstraintTwoButton = twoButtonView.leftAnchor.constraint(equalTo: leftAnchor) + leftConstraintTwoButton = twoButtonView.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor) leftConstraintTwoButton?.isActive = true - rightConstraintTwoButton = rightAnchor.constraint(equalTo: twoButtonView.rightAnchor) + rightConstraintTwoButton = layoutMarginsGuide.rightAnchor.constraint(equalTo: twoButtonView.rightAnchor) rightConstraintTwoButton?.isActive = true - leftConstraintTextButton = textButton.leftAnchor.constraint(greaterThanOrEqualTo: leftAnchor) + leftConstraintTextButton = textButton.leftAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.leftAnchor) leftConstraintTextButton?.isActive = true - rightConstraintTextButton = rightAnchor.constraint(greaterThanOrEqualTo: textButton.rightAnchor) + rightConstraintTextButton = layoutMarginsGuide.rightAnchor.constraint(greaterThanOrEqualTo: textButton.rightAnchor) rightConstraintTextButton?.isActive = true centerAlignTextButton = textButton.centerXAnchor.constraint(equalTo: centerXAnchor) @@ -93,16 +93,6 @@ public class StandardFooterView: ViewConstrainingView { layoutIfNeeded() } - public override func setLeftPinConstant(_ constant: CGFloat) { - leftConstraintTwoButton?.constant = constant - leftConstraintTextButton?.constant = constant - } - - public override func setRightPinConstant(_ constant: CGFloat) { - rightConstraintTwoButton?.constant = constant - rightConstraintTextButton?.constant = constant - } - open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) if let colorString = json?.optionalStringForKey(KeyBackgroundColor) { diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index c1d7a36d..9407e5c7 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -22,7 +22,7 @@ static NSMutableDictionary *mapping; dispatch_once(&onceToken, ^{ mapping = [@{ - @"label": LabelView.class, + @"label": MFLabel.class, @"separator": SeparatorView.class, @"button": ButtonView.class, @"textButton": MFTextButton.class, @@ -47,6 +47,9 @@ Class class = [self.moleculeMapping objectForKey:name]; if (class) { UIView *view = [[class alloc] init]; + if ([view respondsToSelector:@selector(needsToBeConstrained)] && [view needsToBeConstrained]) { + view = [[ConstrainingMoleculeView alloc] initWithMolecule:view]; + } if ([view respondsToSelector:@selector(setAsMolecule)]) { [view setAsMolecule]; } diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m index 841a7e60..4e33da75 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m @@ -21,7 +21,8 @@ viewControllerMapping = [@{ @"textFieldListForm" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[TextFieldListFormViewController class]], @"moleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackTemplate class]], - @"centerMoleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackCenteredTemplate class]] + @"centerMoleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackCenteredTemplate class]], + @"moleculeList" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeListTemplate class]] } mutableCopy]; }); return viewControllerMapping; diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift new file mode 100644 index 00000000..824b7ea2 --- /dev/null +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -0,0 +1,57 @@ +// +// MoleculeListTemplate.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 4/18/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +public class MoleculeListTemplate: ThreeLayerTableViewController { + + public override func registerWithTable() { + super.registerWithTable() + guard let molecules = loadObject?.pageJSON?.arrayForKey("molecules") else { + return + } + for case let molecule as Dictionary in molecules { + if let moleculeName = molecule.optionalStringForKey("moleculeName") { + tableView?.register(MoleculeTableViewCell.self, forCellReuseIdentifier: moleculeName) + } + } + } + + public override func viewForTop() -> UIView { + guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegateObject: delegateObject()) else { + return super.viewForTop() + } + return molecule + } + + override public func viewForBottom() -> UIView { + guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegateObject: delegateObject()) else { + return viewForBottom() + } + return molecule + } + + public override func newDataBuildScreen() { + super.newDataBuildScreen() + registerWithTable() + } + + public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return loadObject?.pageJSON?.arrayForKey("molecules").count ?? 0 + } + + public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard let molecule = loadObject?.pageJSON?.optionalDictionaryWithChainOfKeysOrIndexes(["molecules",indexPath.row]), + let moleculeName = molecule.optionalStringForKey("moleculeName"), + let cell = tableView.dequeueReusableCell(withIdentifier: moleculeName) as? MoleculeTableViewCell else { + return UITableViewCell() + } + cell.setWithJSON(molecule, delegateObject: delegateObject(), additionalData: nil) + return cell + } +} diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index dfcef277..8b3d652d 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -12,7 +12,7 @@ public class MoleculeStackTemplate: ThreeLayerViewController { public override func spaceBetweenTopAndMiddle() -> CGFloat? { - return PaddingTwo + return 0 } public override func viewForTop() -> UIView? { From 90d22908430318af21abfcd624fe6058368ca94c Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 24 Apr 2019 14:30:16 -0400 Subject: [PATCH 06/19] remove extra view I created --- MVMCoreUI.xcodeproj/project.pbxproj | 4 -- .../Views/ConstrainingMoleculeView.swift | 55 ---------------- MVMCoreUI/Atoms/Views/ViewConstrainingView.h | 6 ++ MVMCoreUI/Atoms/Views/ViewConstrainingView.m | 64 +++++++++++++------ .../MVMCoreUIMoleculeMappingObject.m | 2 +- 5 files changed, 50 insertions(+), 81 deletions(-) delete mode 100644 MVMCoreUI/Atoms/Views/ConstrainingMoleculeView.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 6cb9dc9e..b75c10db 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -147,7 +147,6 @@ D29DF32521ED0DA2003B2FB9 /* TextButtonView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF32321ED0DA2003B2FB9 /* TextButtonView.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF32C21EE8736003B2FB9 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D29DF32821EE8736003B2FB9 /* Localizable.strings */; }; D29DF32E21EE8C3D003B2FB9 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D29DF32D21EE8C3D003B2FB9 /* Media.xcassets */; }; - D2A421BF226A14F100A05A88 /* ConstrainingMoleculeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A421BE226A14F100A05A88 /* ConstrainingMoleculeView.swift */; }; D2A514582211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2A514562211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; D2A514592211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2A514572211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m */; }; D2A5145D2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -312,7 +311,6 @@ D29DF32A21EE8736003B2FB9 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; D29DF32B21EE8736003B2FB9 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/Localizable.strings"; sourceTree = ""; }; D29DF32D21EE8C3D003B2FB9 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = ""; }; - D2A421BE226A14F100A05A88 /* ConstrainingMoleculeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConstrainingMoleculeView.swift; sourceTree = ""; }; D2A514562211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIMoleculeMappingObject.h; sourceTree = ""; }; D2A514572211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIMoleculeMappingObject.m; sourceTree = ""; }; D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIMoleculeViewProtocol.h; sourceTree = ""; }; @@ -579,7 +577,6 @@ D29DF28621E7AC2B003B2FB9 /* MFLabel.m */, D29DF31E21ED0CBA003B2FB9 /* LabelView.h */, D29DF31F21ED0CBA003B2FB9 /* LabelView.m */, - D2A421BE226A14F100A05A88 /* ConstrainingMoleculeView.swift */, D29DF28721E7AC2B003B2FB9 /* ViewConstrainingView.h */, D29DF28821E7AC2B003B2FB9 /* ViewConstrainingView.m */, D282AAB9224131D100C46919 /* MFTransparentGIFView.swift */, @@ -880,7 +877,6 @@ D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */, DBC4391922442197001AB423 /* DashLine.swift in Sources */, D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, - D2A421BF226A14F100A05A88 /* ConstrainingMoleculeView.swift in Sources */, D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */, D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */, D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Views/ConstrainingMoleculeView.swift b/MVMCoreUI/Atoms/Views/ConstrainingMoleculeView.swift deleted file mode 100644 index 22e8e09d..00000000 --- a/MVMCoreUI/Atoms/Views/ConstrainingMoleculeView.swift +++ /dev/null @@ -1,55 +0,0 @@ -// -// ConstrainingMoleculeView.swift -// MVMCoreUI -// -// Created by Scott Pfeil on 4/19/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import UIKit - -@objcMembers open class ConstrainingMoleculeView: MFView { - var molecule: (UIView & MVMCoreUIMoleculeViewProtocol)? - - public init(withMolecule molecule: UIView & MVMCoreUIMoleculeViewProtocol) { - self.molecule = molecule - super.init(frame: .zero) - } - - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - } - - open override func setupView() { - super.setupView() - if let molecule = molecule, molecule.superview == nil { - addSubview(molecule) - molecule.topAnchor.constraint(equalTo: topAnchor).isActive = true - molecule.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor).isActive = true - layoutMarginsGuide.rightAnchor.constraint(equalTo: molecule.rightAnchor).isActive = true - bottomAnchor.constraint(equalTo: molecule.bottomAnchor).isActive = true - } - } - - open override func updateView(_ size: CGFloat) { - if let molecule = molecule as? MVMCoreViewProtocol { - molecule.updateView(size) - } - MFStyler.setDefaultMarginsFor(self, size: size) - } - - open override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) { - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - guard let json = json, let molecule = molecule else { - return - } - molecule.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - if let backgroundColor = molecule.backgroundColor { - self.backgroundColor = backgroundColor - } - } - - open override func setAsMolecule() { - molecule?.setAsMolecule?() - } -} diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.h b/MVMCoreUI/Atoms/Views/ViewConstrainingView.h index bb4740a7..377c7821 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.h +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.h @@ -26,6 +26,9 @@ // Returns a view with the provided view as a subview, pinned. + (nonnull ViewConstrainingView *)viewConstrainingView:(nonnull UIView *)view; +// Can be initialized with a molecule to constrain +- (nullable instancetype)initWithMolecule:(nonnull UIView *)molecule; + // Use these to sets the constants, because subclasses may align differently. - (void)setPinConstantsWithInsets:(UIEdgeInsets)insets; - (void)setTopPinConstant:(CGFloat)top left:(CGFloat)left bottom:(CGFloat)bottom right:(CGFloat)right; @@ -41,6 +44,9 @@ // Pins all edges to its super. 0 constant - (void)pinToSuperView; +// Add a view to be constrained in this view. +- (void)addConstrainedView:(nonnull UIView *)view; + // Resets all the constraints to default. - (void)resetConstraints; diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m index 43ea5f8c..1c96040b 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m @@ -13,10 +13,18 @@ @interface ViewConstrainingView () @property (weak, nullable, nonatomic) UIView *constrainedView; +@property (strong, nullable, nonatomic) UIView *molecule; @end @implementation ViewConstrainingView +- (nullable instancetype)initWithMolecule:(nonnull UIView *)molecule { + if (self = [super init]) { + self.molecule = molecule; + } + return self; +} + + (nonnull ViewConstrainingView *)emptyView { ViewConstrainingView *view = [[ViewConstrainingView alloc] initWithFrame:CGRectZero]; view.translatesAutoresizingMaskIntoConstraints = NO; @@ -28,27 +36,7 @@ ViewConstrainingView *constrainingView = [[ViewConstrainingView alloc] initWithFrame:CGRectZero]; constrainingView.translatesAutoresizingMaskIntoConstraints = NO; constrainingView.backgroundColor = [UIColor clearColor]; - - view.translatesAutoresizingMaskIntoConstraints = NO; - [constrainingView addSubview:view]; - constrainingView.constrainedView = view; - - NSLayoutConstraint *leftPin = [view.leftAnchor constraintEqualToAnchor:constrainingView.leftAnchor]; - constrainingView.leftPin = leftPin; - leftPin.active = YES; - - NSLayoutConstraint *topPin = [view.topAnchor constraintEqualToAnchor:constrainingView.topAnchor]; - constrainingView.topPin = topPin; - topPin.active = YES; - - NSLayoutConstraint *bottomPin = [constrainingView.bottomAnchor constraintEqualToAnchor:view.bottomAnchor]; - constrainingView.bottomPin = bottomPin; - bottomPin.active = YES; - - NSLayoutConstraint *rightPin = [constrainingView.rightAnchor constraintEqualToAnchor:view.rightAnchor]; - constrainingView.rightPin = rightPin; - rightPin.active = YES; - + [constrainingView addConstrainedView:view]; return constrainingView; } @@ -115,10 +103,35 @@ self.backgroundColor = [UIColor clearColor]; } +- (void)addConstrainedView:(nonnull UIView *)view { + view.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:view]; + self.constrainedView = view; + + NSLayoutConstraint *leftPin = [view.leftAnchor constraintEqualToAnchor:self.leftAnchor]; + self.leftPin = leftPin; + leftPin.active = YES; + + NSLayoutConstraint *topPin = [view.topAnchor constraintEqualToAnchor:self.topAnchor]; + self.topPin = topPin; + topPin.active = YES; + + NSLayoutConstraint *bottomPin = [self.bottomAnchor constraintEqualToAnchor:view.bottomAnchor]; + self.bottomPin = bottomPin; + bottomPin.active = YES; + + NSLayoutConstraint *rightPin = [self.rightAnchor constraintEqualToAnchor:view.rightAnchor]; + self.rightPin = rightPin; + rightPin.active = YES; +} + - (void)setupView { [super setupView]; self.translatesAutoresizingMaskIntoConstraints = NO; self.backgroundColor = [UIColor clearColor]; + if (!self.molecule.superview) { + [self addConstrainedView:self.molecule]; + } } - (void)updateView:(CGFloat)size { @@ -140,6 +153,15 @@ - (void)setAsMolecule { self.updateViewHorizontalDefaults = YES; + [self.molecule setAsMolecule]; +} + +- (void)setWithJSON:(NSDictionary *)json delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { + [super setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; + if (self.molecule) { + [self.molecule setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; + self.backgroundColor = self.molecule.backgroundColor; + } } @end diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 9407e5c7..b757c78b 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -48,7 +48,7 @@ if (class) { UIView *view = [[class alloc] init]; if ([view respondsToSelector:@selector(needsToBeConstrained)] && [view needsToBeConstrained]) { - view = [[ConstrainingMoleculeView alloc] initWithMolecule:view]; + view = [[ViewConstrainingView alloc] initWithMolecule:view]; } if ([view respondsToSelector:@selector(setAsMolecule)]) { [view setAsMolecule]; From 1573e57f2caba2751f4eb192ba9bbbd1371dede8 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 24 Apr 2019 15:38:59 -0400 Subject: [PATCH 07/19] constraining --- MVMCoreUI/Atoms/Views/Label.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MVMCoreUI/Atoms/Views/Label.swift b/MVMCoreUI/Atoms/Views/Label.swift index 8ca484e3..2d53adb8 100644 --- a/MVMCoreUI/Atoms/Views/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label.swift @@ -301,6 +301,10 @@ import MVMCore originalAttributedString = attributedText } + + public func needsToBeConstrained() -> Bool { + return true; + } } extension Label { From 8a349ae16f6940a17ecdb9ca5291d038360fd6c2 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 24 Apr 2019 16:14:22 -0400 Subject: [PATCH 08/19] constraining for stack --- MVMCoreUI/Atoms/Buttons/CaretButton.swift | 4 ++++ MVMCoreUI/Atoms/Buttons/MFTextButton.m | 4 ++++ MVMCoreUI/Atoms/Views/CaretView.swift | 5 ++++- MVMCoreUI/Atoms/Views/Label.swift | 2 -- MVMCoreUI/Atoms/Views/ViewConstrainingView.m | 12 +++++++----- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/CaretButton.swift b/MVMCoreUI/Atoms/Buttons/CaretButton.swift index 6aa4a754..47697980 100644 --- a/MVMCoreUI/Atoms/Buttons/CaretButton.swift +++ b/MVMCoreUI/Atoms/Buttons/CaretButton.swift @@ -131,4 +131,8 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol { disabledColor = UIColor.mfGet(forHex: disabledColorHex) } } + + public func needsToBeConstrained() -> Bool { + return true + } } diff --git a/MVMCoreUI/Atoms/Buttons/MFTextButton.m b/MVMCoreUI/Atoms/Buttons/MFTextButton.m index 0a72eee7..96a99a18 100644 --- a/MVMCoreUI/Atoms/Buttons/MFTextButton.m +++ b/MVMCoreUI/Atoms/Buttons/MFTextButton.m @@ -141,4 +141,8 @@ } } +- (BOOL)needsToBeConstrained { + return YES; +} + @end diff --git a/MVMCoreUI/Atoms/Views/CaretView.swift b/MVMCoreUI/Atoms/Views/CaretView.swift index eb3a4c4b..fff6181e 100644 --- a/MVMCoreUI/Atoms/Views/CaretView.swift +++ b/MVMCoreUI/Atoms/Views/CaretView.swift @@ -91,7 +91,6 @@ open class CaretView: MFView { // Default values for view. @objc open override func setAsMolecule() { - defaultState() } @@ -120,4 +119,8 @@ open class CaretView: MFView { lineWidth = lineWidthValue } } + + open override func needsToBeConstrained() -> Bool { + return true + } } diff --git a/MVMCoreUI/Atoms/Views/Label.swift b/MVMCoreUI/Atoms/Views/Label.swift index 2d53adb8..0cd77ee0 100644 --- a/MVMCoreUI/Atoms/Views/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label.swift @@ -268,7 +268,6 @@ import MVMCore } }) attributedText = attributedString - } else if !MVMCoreGetterUtility.fequal(a: Float(standardFontSize), b: 0.0), let sizeObject: MFSizeObject = self.sizeObject ?? MFStyler.sizeObjectGeneric(forCurrentDevice: standardFontSize) { self.font = self.font.withSize(sizeObject.getValueBased(onSize: size)) } @@ -298,7 +297,6 @@ import MVMCore @objc public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) { Label.setUILabel(self, withJSON: json, delegate: delegateObject, additionalData: additionalData) - originalAttributedString = attributedText } diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m index 1c96040b..d14163a6 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m @@ -13,13 +13,16 @@ @interface ViewConstrainingView () @property (weak, nullable, nonatomic) UIView *constrainedView; -@property (strong, nullable, nonatomic) UIView *molecule; +@property (weak, nullable, nonatomic) UIView *molecule; @end @implementation ViewConstrainingView - (nullable instancetype)initWithMolecule:(nonnull UIView *)molecule { if (self = [super init]) { + if (!molecule.superview) { + [self addConstrainedView:molecule]; + } self.molecule = molecule; } return self; @@ -129,9 +132,6 @@ [super setupView]; self.translatesAutoresizingMaskIntoConstraints = NO; self.backgroundColor = [UIColor clearColor]; - if (!self.molecule.superview) { - [self addConstrainedView:self.molecule]; - } } - (void)updateView:(CGFloat)size { @@ -153,7 +153,9 @@ - (void)setAsMolecule { self.updateViewHorizontalDefaults = YES; - [self.molecule setAsMolecule]; + if ([self.molecule respondsToSelector:@selector(setAsMolecule)]) { + [self.molecule setAsMolecule]; + } } - (void)setWithJSON:(NSDictionary *)json delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { From d3361fedebba3db1008dd76e60a1611cbb7fc720 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 24 Apr 2019 16:21:16 -0400 Subject: [PATCH 09/19] molecule list fix --- MVMCoreUI/Templates/MoleculeListTemplate.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 824b7ea2..f1226056 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -52,6 +52,7 @@ public class MoleculeListTemplate: ThreeLayerTableViewController { return UITableViewCell() } cell.setWithJSON(molecule, delegateObject: delegateObject(), additionalData: nil) + cell.updateView(tableView.bounds.width) return cell } } From 302a2f887fadcf336e29ef0368209a0fed625583 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 29 Apr 2019 13:36:36 -0400 Subject: [PATCH 10/19] thickness. molecule alignment --- MVMCoreUI/Atoms/Buttons/CaretButton.swift | 4 ++ MVMCoreUI/Atoms/Buttons/MFTextButton.m | 4 ++ MVMCoreUI/Atoms/Views/CaretView.swift | 25 +++++-- MVMCoreUI/Atoms/Views/MFView.m | 2 +- MVMCoreUI/Atoms/Views/ViewConstrainingView.h | 2 +- MVMCoreUI/Atoms/Views/ViewConstrainingView.m | 69 +++++++++---------- .../NSLayoutConstraint+MFConvenience.h | 5 ++ .../NSLayoutConstraint+MFConvenience.m | 24 +++++-- MVMCoreUI/Molecules/MoleculeStackView.swift | 3 +- .../Molecules/MoleculeTableViewCell.swift | 52 +++++++++++++- .../MVMCoreUIMoleculeViewProtocol.h | 6 ++ .../MVMCoreUIMoleculeMappingObject.h | 3 + .../MVMCoreUIMoleculeMappingObject.m | 32 ++++++--- .../Templates/MoleculeListTemplate.swift | 12 +++- .../MoleculeStackCenteredTemplate.swift | 4 +- .../Templates/MoleculeStackTemplate.swift | 4 +- 16 files changed, 179 insertions(+), 72 deletions(-) rename MVMCoreUI/Molecules/{ => Protocols}/MVMCoreUIMoleculeViewProtocol.h (79%) diff --git a/MVMCoreUI/Atoms/Buttons/CaretButton.swift b/MVMCoreUI/Atoms/Buttons/CaretButton.swift index 47697980..c8bf3fdf 100644 --- a/MVMCoreUI/Atoms/Buttons/CaretButton.swift +++ b/MVMCoreUI/Atoms/Buttons/CaretButton.swift @@ -135,4 +135,8 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol { public func needsToBeConstrained() -> Bool { return true } + + open func moleculeAlignment() -> UIStackView.Alignment { + return UIStackView.Alignment.leading; + } } diff --git a/MVMCoreUI/Atoms/Buttons/MFTextButton.m b/MVMCoreUI/Atoms/Buttons/MFTextButton.m index 96a99a18..d78df33d 100644 --- a/MVMCoreUI/Atoms/Buttons/MFTextButton.m +++ b/MVMCoreUI/Atoms/Buttons/MFTextButton.m @@ -145,4 +145,8 @@ return YES; } +- (UIStackViewAlignment)moleculeAlignment { + return UIStackViewAlignmentLeading; +} + @end diff --git a/MVMCoreUI/Atoms/Views/CaretView.swift b/MVMCoreUI/Atoms/Views/CaretView.swift index fff6181e..2be52f11 100644 --- a/MVMCoreUI/Atoms/Views/CaretView.swift +++ b/MVMCoreUI/Atoms/Views/CaretView.swift @@ -13,9 +13,15 @@ open class CaretView: MFView { // MARK: - Properties //------------------------------------------------------ + // Objc can't use float enum. + @objc public static let thin: CGFloat = 6.0 + @objc public static let standard: CGFloat = 2.6 + @objc public static let thick: CGFloat = 1.5 + private(set) var strokeColor: UIColor? private var lineWidth: CGFloat? - + private var lineThickness: CGFloat? + //------------------------------------------------------ // MARK: - Initialization //------------------------------------------------------ @@ -32,14 +38,19 @@ open class CaretView: MFView { super.init(coder: aDecoder) } + /// Can init with a specific line width. @objc public init(lineWidth: CGFloat) { super.init(frame: CGRect()) - self.lineWidth = lineWidth } + /// Can init with a specific line thickness, scales based on width and height. + @objc public init(lineThickness: CGFloat) { + super.init(frame: CGRect()) + self.lineThickness = lineThickness + } + @objc override open func setupView() { - defaultState() } @@ -48,7 +59,6 @@ open class CaretView: MFView { //------------------------------------------------------ private func defaultState() { - isOpaque = false isHidden = false backgroundColor = .clear @@ -64,7 +74,7 @@ open class CaretView: MFView { let context = UIGraphicsGetCurrentContext() context?.clear(rect) - let lineWidthToDraw: CGFloat = lineWidth ?? frame.size.width / 2.6 + let lineWidthToDraw: CGFloat = lineWidth ?? frame.size.width / (lineThickness ?? 2.6) let path = UIBezierPath() path.move(to: CGPoint(x: lineWidthToDraw / 2.0, y: 0.0)) @@ -80,7 +90,6 @@ open class CaretView: MFView { } @objc public func setLineColor(_ color: UIColor?) { - strokeColor = color setNeedsDisplay() } @@ -123,4 +132,8 @@ open class CaretView: MFView { open override func needsToBeConstrained() -> Bool { return true } + + open override func moleculeAlignment() -> UIStackView.Alignment { + return UIStackView.Alignment.leading; + } } diff --git a/MVMCoreUI/Atoms/Views/MFView.m b/MVMCoreUI/Atoms/Views/MFView.m index 4bd73485..b22a5674 100644 --- a/MVMCoreUI/Atoms/Views/MFView.m +++ b/MVMCoreUI/Atoms/Views/MFView.m @@ -36,7 +36,7 @@ } - (void)setupView { - + self.preservesSuperviewLayoutMargins = YES; } - (void)updateView:(CGFloat)size { diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.h b/MVMCoreUI/Atoms/Views/ViewConstrainingView.h index 377c7821..528a79e6 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.h +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.h @@ -27,7 +27,7 @@ + (nonnull ViewConstrainingView *)viewConstrainingView:(nonnull UIView *)view; // Can be initialized with a molecule to constrain -- (nullable instancetype)initWithMolecule:(nonnull UIView *)molecule; +- (nullable instancetype)initWithMolecule:(nonnull UIView *)molecule alignment:(UIStackViewAlignment)alignment; // Use these to sets the constants, because subclasses may align differently. - (void)setPinConstantsWithInsets:(UIEdgeInsets)insets; diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m index d14163a6..861db8cd 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m @@ -9,6 +9,7 @@ #import "ViewConstrainingView.h" @import MVMCore.MVMCoreConstants; @import MVMCore.MVMCoreDispatchUtility; +#import "NSLayoutConstraint+MFConvenience.h" #import "MFStyler.h" @interface ViewConstrainingView () @@ -18,10 +19,11 @@ @implementation ViewConstrainingView -- (nullable instancetype)initWithMolecule:(nonnull UIView *)molecule { +- (nullable instancetype)initWithMolecule:(nonnull UIView *)molecule alignment:(UIStackViewAlignment)alignment { if (self = [super init]) { if (!molecule.superview) { - [self addConstrainedView:molecule]; + [self addConstrainedView:molecule alignment:alignment]; + [self setAsMolecule]; } self.molecule = molecule; } @@ -44,23 +46,11 @@ } - (void)pinToSuperView { - - // Align left and right constants. - NSLayoutConstraint *leftPin = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0]; - self.leftPin = leftPin; - leftPin.active = YES; - - NSLayoutConstraint *topPin = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeTop multiplier:1.0 constant:0]; - self.topPin = topPin; - topPin.active = YES; - - NSLayoutConstraint *bottomPin = [NSLayoutConstraint constraintWithItem:self.superview attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0]; - self.bottomPin = bottomPin; - bottomPin.active = YES; - - NSLayoutConstraint *rightPin = [NSLayoutConstraint constraintWithItem:self.superview attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1.0 constant:0]; - self.rightPin = rightPin; - rightPin.active = YES; + NSDictionary *dictionary = [NSLayoutConstraint constraintPinSubviewToSuperview:self]; + self.leftPin = dictionary[ConstraintLeading]; + self.topPin = dictionary[ConstraintTop]; + self.bottomPin = dictionary[ConstraintBot]; + self.rightPin = dictionary[ConstraintTrailing]; } - (void)setPinConstantsWithInsets:(UIEdgeInsets)insets { @@ -106,26 +96,32 @@ self.backgroundColor = [UIColor clearColor]; } -- (void)addConstrainedView:(nonnull UIView *)view { +- (void)addConstrainedView:(nonnull UIView *)view alignment:(UIStackViewAlignment)alignment { view.translatesAutoresizingMaskIntoConstraints = NO; [self addSubview:view]; self.constrainedView = view; - NSLayoutConstraint *leftPin = [view.leftAnchor constraintEqualToAnchor:self.leftAnchor]; - self.leftPin = leftPin; - leftPin.active = YES; - - NSLayoutConstraint *topPin = [view.topAnchor constraintEqualToAnchor:self.topAnchor]; - self.topPin = topPin; - topPin.active = YES; - - NSLayoutConstraint *bottomPin = [self.bottomAnchor constraintEqualToAnchor:view.bottomAnchor]; - self.bottomPin = bottomPin; - bottomPin.active = YES; - - NSLayoutConstraint *rightPin = [self.rightAnchor constraintEqualToAnchor:view.rightAnchor]; - self.rightPin = rightPin; - rightPin.active = YES; + NSLayoutRelation leftRelation; + if (alignment == UIStackViewAlignmentFill || alignment == UIStackViewAlignmentLeading || alignment == UIStackViewAlignmentFirstBaseline) { + leftRelation = NSLayoutRelationEqual; + } else { + leftRelation = NSLayoutRelationGreaterThanOrEqual; + } + NSLayoutRelation rightRelation; + if (alignment == UIStackViewAlignmentFill || alignment == UIStackViewAlignmentTrailing || alignment == UIStackViewAlignmentLastBaseline) { + rightRelation = NSLayoutRelationEqual; + } else { + rightRelation = NSLayoutRelationGreaterThanOrEqual; + } + NSDictionary *dictionary = [NSLayoutConstraint constraintPinSubview:view topRelation:NSLayoutRelationEqual bottomRelation:NSLayoutRelationEqual leftRelation:leftRelation rightRelation:rightRelation]; + self.leftPin = dictionary[ConstraintLeading]; + self.topPin = dictionary[ConstraintTop]; + self.bottomPin = dictionary[ConstraintBot]; + self.rightPin = dictionary[ConstraintTrailing]; +} + +- (void)addConstrainedView:(nonnull UIView *)view { + [self addConstrainedView:view alignment:UIStackViewAlignmentFill]; } - (void)setupView { @@ -153,9 +149,6 @@ - (void)setAsMolecule { self.updateViewHorizontalDefaults = YES; - if ([self.molecule respondsToSelector:@selector(setAsMolecule)]) { - [self.molecule setAsMolecule]; - } } - (void)setWithJSON:(NSDictionary *)json delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { diff --git a/MVMCoreUI/Categories/NSLayoutConstraint+MFConvenience.h b/MVMCoreUI/Categories/NSLayoutConstraint+MFConvenience.h index c8e12cae..0d0d281c 100644 --- a/MVMCoreUI/Categories/NSLayoutConstraint+MFConvenience.h +++ b/MVMCoreUI/Categories/NSLayoutConstraint+MFConvenience.h @@ -31,8 +31,12 @@ extern NSString * _Nonnull const ConstraintWidth; + (nullable NSDictionary *)constraintPinSubview:(nullable UIView *)subview pinTop:(BOOL)pinTop pinBottom:(BOOL)pinBottom pinLeft:(BOOL)pinLeft pinRight:(BOOL)pinRight; ++ (nullable NSDictionary *)constraintPinSubview:(nullable UIView *)subview topRelation:(NSLayoutRelation)topRelation bottomRelation:(NSLayoutRelation)bottomRelation leftRelation:(NSLayoutRelation)leftRelation rightRelation:(NSLayoutRelation)rightRelation; + + (nullable NSDictionary *)constraintPinSubview:(nullable UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant; ++ (nullable NSDictionary *)constraintPinSubview:(nullable UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant topRelation:(NSLayoutRelation)topRelation pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant bottomRelation:(NSLayoutRelation)bottomRelation pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant leftRelation:(NSLayoutRelation)leftRelation pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant rightRelation:(NSLayoutRelation)rightRelation; + // Pin subview with 1 side + (nullable NSDictionary *)constraintPinTopSubview:(nonnull UIView *)subview topConstant:(CGFloat)topConstant; + (nullable NSDictionary *)constraintPinBottomSubview:(nonnull UIView *)subview bottomConstant:(CGFloat)bottomConstant; @@ -57,6 +61,7 @@ extern NSString * _Nonnull const ConstraintWidth; #pragma mark - With Margins ++ (nonnull NSDictionary *)pinViewToSuperview:(nonnull UIView *)subview useMargins:(BOOL)useMargins; + (nonnull NSLayoutConstraint *)pinViewTopToSuperview:(nonnull UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant; + (nonnull NSLayoutConstraint *)pinViewLeftToSuperview:(nonnull UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant; + (nonnull NSLayoutConstraint *)pinViewRightToSuperview:(nonnull UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant; diff --git a/MVMCoreUI/Categories/NSLayoutConstraint+MFConvenience.m b/MVMCoreUI/Categories/NSLayoutConstraint+MFConvenience.m index 39a315c1..72aad96f 100644 --- a/MVMCoreUI/Categories/NSLayoutConstraint+MFConvenience.m +++ b/MVMCoreUI/Categories/NSLayoutConstraint+MFConvenience.m @@ -44,29 +44,37 @@ NSString *const ConstraintWidth = @"width"; return [NSLayoutConstraint constraintPinSubview:subview pinTop:pinTop topConstant:0 pinBottom:pinBottom bottomConstant:0 pinLeft:pinLeft leftConstant:0 pinRight:pinRight rightConstant:0]; } ++ (nullable NSDictionary *)constraintPinSubview:(nullable UIView *)subview topRelation:(NSLayoutRelation)topRelation bottomRelation:(NSLayoutRelation)bottomRelation leftRelation:(NSLayoutRelation)leftRelation rightRelation:(NSLayoutRelation)rightRelation { + return [self constraintPinSubview:subview pinTop:YES topConstant:0 topRelation:topRelation pinBottom:YES bottomConstant:0 bottomRelation:bottomRelation pinLeft:YES leftConstant:0 leftRelation:leftRelation pinRight:YES rightConstant:0 rightRelation:rightRelation]; +} + + (NSDictionary *)constraintPinSubview:(UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant { + return [self constraintPinSubview:subview pinTop:pinTop topConstant:topConstant topRelation:NSLayoutRelationEqual pinBottom:pinBottom bottomConstant:bottomConstant bottomRelation:NSLayoutRelationEqual pinLeft:pinLeft leftConstant:leftConstant leftRelation:NSLayoutRelationEqual pinRight:pinRight rightConstant:rightConstant rightRelation:NSLayoutRelationEqual]; +} + ++ (NSDictionary *)constraintPinSubview:(UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant topRelation:(NSLayoutRelation)topRelation pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant bottomRelation:(NSLayoutRelation)bottomRelation pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant leftRelation:(NSLayoutRelation)leftRelation pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant rightRelation:(NSLayoutRelation)rightRelation { UIView *superview = subview.superview; NSMutableDictionary *constraintDic = [[NSMutableDictionary alloc] init]; if (pinTop) { - NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeTop multiplier:1 constant:topConstant]; + NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTop relatedBy:topRelation toItem:superview attribute:NSLayoutAttributeTop multiplier:1 constant:topConstant]; top.priority = 999; top.active = YES; [constraintDic setObject:top forKey:ConstraintTop]; } if (pinBottom) { - NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:superview attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:subview attribute:NSLayoutAttributeBottom multiplier:1 constant:bottomConstant]; + NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:superview attribute:NSLayoutAttributeBottom relatedBy:bottomRelation toItem:subview attribute:NSLayoutAttributeBottom multiplier:1 constant:bottomConstant]; bottom.priority = 999; bottom.active = YES; [constraintDic setObject:bottom forKey:ConstraintBot]; } if (pinLeft) { - NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeLeading multiplier:1 constant:leftConstant]; + NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeLeading relatedBy:leftRelation toItem:superview attribute:NSLayoutAttributeLeading multiplier:1 constant:leftConstant]; leading.priority = 999; leading.active = YES; [constraintDic setObject:leading forKey:ConstraintLeading]; } if (pinRight) { - NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:superview attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:subview attribute:NSLayoutAttributeTrailing multiplier:1 constant:rightConstant]; + NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:superview attribute:NSLayoutAttributeTrailing relatedBy:rightRelation toItem:subview attribute:NSLayoutAttributeTrailing multiplier:1 constant:rightConstant]; trailing.priority = 999; trailing.active = YES; [constraintDic setObject:trailing forKey:ConstraintTrailing]; @@ -152,6 +160,14 @@ NSString *const ConstraintWidth = @"width"; #pragma mark - With Margins ++ (nonnull NSDictionary *)pinViewToSuperview:(nonnull UIView *)subview useMargins:(BOOL)useMargins { + return @{ConstraintTop:[self pinViewTopToSuperview:subview useMargins:useMargins constant:0], + ConstraintLeading:[self pinViewLeftToSuperview:subview useMargins:useMargins constant:0], + ConstraintTrailing:[self pinViewRightToSuperview:subview useMargins:useMargins constant:0], + ConstraintBot:[self pinViewBottomToSuperview:subview useMargins:useMargins constant:0], + }; +} + + (NSLayoutConstraint *)pinViewTopToSuperview:(UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant { return [view.topAnchor constraintEqualToAnchor:(useMargins ? view.superview.layoutMarginsGuide.topAnchor : view.superview.topAnchor) constant:constant]; } diff --git a/MVMCoreUI/Molecules/MoleculeStackView.swift b/MVMCoreUI/Molecules/MoleculeStackView.swift index a43a6a94..10e048d3 100644 --- a/MVMCoreUI/Molecules/MoleculeStackView.swift +++ b/MVMCoreUI/Molecules/MoleculeStackView.swift @@ -57,8 +57,7 @@ public class MoleculeStackView: MFView { // Create the molecules and set the json. var moleculesArray = [] as [UIView] for moleculeJSON in molecules { - if let name = moleculeJSON.optionalStringForKey("moleculeName"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForName(name) { - molecule.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData) + if let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForStack(withJSON: moleculeJSON, delegateObject: delegateObject) { moleculesArray.append(molecule) } } diff --git a/MVMCoreUI/Molecules/MoleculeTableViewCell.swift b/MVMCoreUI/Molecules/MoleculeTableViewCell.swift index 21b05a22..4cd0dfd5 100644 --- a/MVMCoreUI/Molecules/MoleculeTableViewCell.swift +++ b/MVMCoreUI/Molecules/MoleculeTableViewCell.swift @@ -10,11 +10,42 @@ import UIKit @objcMembers open class MoleculeTableViewCell: UITableViewCell, MVMCoreViewProtocol, MVMCoreUIMoleculeViewProtocol { var molecule: (UIView & MVMCoreUIMoleculeViewProtocol)? + + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setupView() + } + + public required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setupView() + } + + // For the accessory view convenience. + var caretView: CaretView? + private var caretViewWidthSizeObject: MFSizeObject? + private var caretViewHeightSizeObject: MFSizeObject? public func updateView(_ size: CGFloat) { + MFStyler.setDefaultMarginsFor(self, size: size) + if #available(iOS 11.0, *) { + contentView.directionalLayoutMargins = directionalLayoutMargins + } else { + contentView.layoutMargins = layoutMargins + } + if let molecule = molecule as? MVMCoreViewProtocol { molecule.updateView(size) } + if let _ = accessoryView, let caretView = caretView, let widthObject = caretViewWidthSizeObject, let heightObject = caretViewHeightSizeObject { + caretView.frame = CGRect(x: 0, y: 0, width: widthObject.getValueBased(onSize: size), height: heightObject.getValueBased(onSize: size)) + } + } + + public func setupView() { + preservesSuperviewLayoutMargins = false + contentView.preservesSuperviewLayoutMargins = false + selectionStyle = .none } public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) { @@ -22,13 +53,28 @@ import UIKit return } if molecule == nil { - if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(json, delegateObject: delegateObject) { - addSubview(moleculeView) - NSLayoutConstraint.constraintPinSubview(toSuperview: moleculeView) + if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForStack(withJSON: json, delegateObject: delegateObject) { + contentView.addSubview(moleculeView) + NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: moleculeView, useMargins: moleculeView.needsToBeConstrained?() ?? false).values)) molecule = moleculeView } } else { molecule?.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) } + backgroundColor = molecule?.backgroundColor + } + + // MARK- Convenience + public func addCaretViewAccessory() { + guard accessoryView == nil else { + return + } + let width: CGFloat = 6 + let height: CGFloat = 10 + caretView = CaretView(lineThickness: CaretView.thin) + caretView?.frame = CGRect(x: 0, y: 0, width: width, height: height) + caretViewWidthSizeObject = MFSizeObject(scalingStandardSize: width) + caretViewHeightSizeObject = MFSizeObject(scalingStandardSize: height) + accessoryView = caretView } } diff --git a/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h b/MVMCoreUI/Molecules/Protocols/MVMCoreUIMoleculeViewProtocol.h similarity index 79% rename from MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h rename to MVMCoreUI/Molecules/Protocols/MVMCoreUIMoleculeViewProtocol.h index cce08641..12557967 100644 --- a/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h +++ b/MVMCoreUI/Molecules/Protocols/MVMCoreUIMoleculeViewProtocol.h @@ -22,6 +22,12 @@ // Notifies the creator that the view needs to be constrained in a view. - (BOOL)needsToBeConstrained; +// The alignment for the molecule if constrained. +- (UIStackViewAlignment)moleculeAlignment; + +// For the molecule list to load more efficiently. ++ (CGFloat)estimatedHeightForRow; + @end diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.h b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.h index a79ca208..43a113c9 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.h +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.h @@ -22,4 +22,7 @@ - (nullable UIView *)getMoleculeForName:(nonnull NSString *)name; - (nullable UIView *)getMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable DelegateObject *)delegateObject; +// Similar to above but also checks if the molecule needs to be constrained for a stack. +- (nullable UIView *)getMoleculeForStackWithJSON:(nonnull NSDictionary *)json delegateObject:(nullable DelegateObject *)delegateObject; + @end diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index f12179bc..9deb6cd5 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -45,20 +45,17 @@ - (nullable UIView *)getMoleculeForName:(nonnull NSString *)name { Class class = [self.moleculeMapping objectForKey:name]; - if (class) { - UIView *view = [[class alloc] init]; - if ([view respondsToSelector:@selector(needsToBeConstrained)] && [view needsToBeConstrained]) { - view = [[ViewConstrainingView alloc] initWithMolecule:view]; - } - if ([view respondsToSelector:@selector(setAsMolecule)]) { - [view setAsMolecule]; - } - return view; + if (!class) { + return nil; } - return nil; + UIView *molecule = [[class alloc] init]; + if ([molecule respondsToSelector:@selector(setAsMolecule)]) { + [molecule setAsMolecule]; + } + return molecule; } -- (nullable UIView *)getMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject { +- (nullable UIView *)getMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable DelegateObject *)delegateObject { NSString *moleculeName = [json string:@"moleculeName"]; if (!moleculeName) { return nil; @@ -69,4 +66,17 @@ } +- (nullable UIView *)getMoleculeForStackWithJSON:(nonnull NSDictionary *)json delegateObject:(nullable DelegateObject *)delegateObject { + NSString *moleculeName = [json string:@"moleculeName"]; + if (!moleculeName) { + return nil; + } + UIView *molecule = [self getMoleculeForName:moleculeName]; + if ([molecule respondsToSelector:@selector(needsToBeConstrained)] && [molecule needsToBeConstrained]) { + molecule = [[ViewConstrainingView alloc] initWithMolecule:molecule alignment:[molecule respondsToSelector:@selector(moleculeAlignment)] ? [molecule moleculeAlignment] : UIStackViewAlignmentFill]; + } + [molecule setWithJSON:json delegateObject:delegateObject additionalData:nil]; + return molecule; +} + @end diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index f1226056..ba6e7f15 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -23,14 +23,14 @@ public class MoleculeListTemplate: ThreeLayerTableViewController { } public override func viewForTop() -> UIView { - guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegateObject: delegateObject()) else { + guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForStack(withJSON: moleculeJSON, delegateObject: delegateObject()) else { return super.viewForTop() } return molecule } override public func viewForBottom() -> UIView { - guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegateObject: delegateObject()) else { + guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForStack(withJSON: moleculeJSON, delegateObject: delegateObject()) else { return viewForBottom() } return molecule @@ -41,6 +41,14 @@ public class MoleculeListTemplate: ThreeLayerTableViewController { registerWithTable() } + public override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { + if let moleculeName = loadObject?.pageJSON?.stringOptionalWithChainOfKeysOrIndexes(["molecules",indexPath.row,"moleculeName"]), let theClass = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping?[moleculeName] as? MVMCoreUIMoleculeViewProtocol.Type, + let estimatedHeightForRow = theClass.estimatedHeightForRow { + return estimatedHeightForRow() + } + return 0 + } + public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return loadObject?.pageJSON?.arrayForKey("molecules").count ?? 0 } diff --git a/MVMCoreUI/Templates/MoleculeStackCenteredTemplate.swift b/MVMCoreUI/Templates/MoleculeStackCenteredTemplate.swift index bdd187fe..b359ecf5 100644 --- a/MVMCoreUI/Templates/MoleculeStackCenteredTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackCenteredTemplate.swift @@ -18,7 +18,7 @@ public class MoleculeStackCenteredTemplate: ThreeLayerViewController { public override func viewForTop() -> UIView? { guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), - let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegateObject: delegateObject()) else { + let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForStack(withJSON: moleculeJSON, delegateObject: delegateObject()) else { return nil } return molecule @@ -26,7 +26,7 @@ public class MoleculeStackCenteredTemplate: ThreeLayerViewController { override public func viewForBottom() -> UIView? { guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), - let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegateObject: delegateObject()) else { + let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForStack(withJSON: moleculeJSON, delegateObject: delegateObject()) else { return nil } return molecule diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index 8b3d652d..51b3ed7f 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -16,7 +16,7 @@ public class MoleculeStackTemplate: ThreeLayerViewController { } public override func viewForTop() -> UIView? { - guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegateObject: delegateObject()) else { + guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForStack(withJSON: moleculeJSON, delegateObject: delegateObject()) else { return nil } return molecule @@ -30,7 +30,7 @@ public class MoleculeStackTemplate: ThreeLayerViewController { } override public func viewForBottom() -> UIView? { - guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegateObject: delegateObject()) else { + guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForStack(withJSON: moleculeJSON, delegateObject: delegateObject()) else { return nil } return molecule From 9709c7195dd9e40a45820e2011097ab4330a90d9 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 29 Apr 2019 15:00:29 -0400 Subject: [PATCH 11/19] use molecule label --- MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m | 35 +++++++++++++++++------ 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m index 9d3b80a9..bd717f88 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m @@ -62,9 +62,17 @@ static const CGFloat CheckBoxHeightWidth = 18.0; UIColor *checkedColor = checkedColorHex ? [UIColor mfGetColorForHex:checkedColorHex]: [UIColor blackColor]; UIColor *unCheckedColor = unCheckedColorHex ? [UIColor mfGetColorForHex:unCheckedColorHex]: [UIColor clearColor]; + NSString *label = [json string:KeyLabel]; - - [self setupWithCheckedColor:checkedColor unCheckColor:unCheckedColor text:label]; + if (label) { + [self setupWithCheckedColor:checkedColor unCheckColor:unCheckedColor text:label]; + } else { + [self setupWithCheckedColor:checkedColor + unCheckColor:unCheckedColor + label:[json dict:KeyLabel] + delegateObject:delegateObject + additionalData: additionalData]; + } } + (instancetype)mfCheckBox { @@ -246,17 +254,26 @@ static const CGFloat CheckBoxHeightWidth = 18.0; } } +- (void)setupWithCheckedColor:(UIColor *)checkedColor unCheckColor:(UIColor *)unCheckedColor { + [self setupView]; + if (checkedColor) { + self.checkedColor = checkedColor; + } + if (unCheckedColor) { + self.unCheckedColor = unCheckedColor; + } +} + - (void)setupWithCheckedColor:(UIColor *)checkedColor unCheckColor:(UIColor *)unCheckedColor text:(NSString *)text { - [self setupView]; - if (checkedColor) { - self.checkedColor = checkedColor; - } - if (unCheckedColor) { - self.unCheckedColor = unCheckedColor; - } + [self setupWithCheckedColor:checkedColor unCheckColor:unCheckedColor]; [self setDescriptionText:text]; } +- (void)setupWithCheckedColor:(UIColor *)checkedColor unCheckColor:(UIColor *)unCheckedColor label:(NSDictionary *)labelJson delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData{ + [self setupWithCheckedColor:checkedColor unCheckColor:unCheckedColor]; + [self.descriptionLabel setWithJSON:labelJson delegateObject:delegateObject additionalData:additionalData]; +} + - (void)updateView:(CGFloat)size { [MVMCoreDispatchUtility performBlockOnMainThread:^{ [self.descriptionLabel updateView:size]; From d2d4c30cf69f4f21bcc93cdbd7042fcb4a0d2c66 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 29 Apr 2019 16:20:27 -0400 Subject: [PATCH 12/19] labelMap --- MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m index bd717f88..1aa182ab 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m @@ -69,7 +69,7 @@ static const CGFloat CheckBoxHeightWidth = 18.0; } else { [self setupWithCheckedColor:checkedColor unCheckColor:unCheckedColor - label:[json dict:KeyLabel] + label:[json dict:@"labelMap"] delegateObject:delegateObject additionalData: additionalData]; } @@ -118,6 +118,14 @@ static const CGFloat CheckBoxHeightWidth = 18.0; #pragma mark - inits +- (instancetype)init { + self = [super init]; + if (self) { + [self setupView]; + } + return self; +} + - (instancetype)initWithCheckedColor:(UIColor *)checkedColor unCheckColor:(UIColor *)unCheckedColor text:(NSString *)text { if (self = [super init]) { [self setupWithCheckedColor:checkedColor unCheckColor:unCheckedColor text:text]; @@ -255,7 +263,6 @@ static const CGFloat CheckBoxHeightWidth = 18.0; } - (void)setupWithCheckedColor:(UIColor *)checkedColor unCheckColor:(UIColor *)unCheckedColor { - [self setupView]; if (checkedColor) { self.checkedColor = checkedColor; } @@ -269,7 +276,7 @@ static const CGFloat CheckBoxHeightWidth = 18.0; [self setDescriptionText:text]; } -- (void)setupWithCheckedColor:(UIColor *)checkedColor unCheckColor:(UIColor *)unCheckedColor label:(NSDictionary *)labelJson delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData{ +- (void)setupWithCheckedColor:(UIColor *)checkedColor unCheckColor:(UIColor *)unCheckedColor label:(NSDictionary *)labelJson delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { [self setupWithCheckedColor:checkedColor unCheckColor:unCheckedColor]; [self.descriptionLabel setWithJSON:labelJson delegateObject:delegateObject additionalData:additionalData]; } From 2fafde090e2e76d5595f398392007698b4989c87 Mon Sep 17 00:00:00 2001 From: "Christiano, Kevin" Date: Mon, 29 Apr 2019 16:55:22 -0400 Subject: [PATCH 13/19] matching change from release. --- MVMCoreUI/Atoms/Views/LabelWithInternalButton.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/LabelWithInternalButton.swift b/MVMCoreUI/Atoms/Views/LabelWithInternalButton.swift index ca314365..502c766a 100644 --- a/MVMCoreUI/Atoms/Views/LabelWithInternalButton.swift +++ b/MVMCoreUI/Atoms/Views/LabelWithInternalButton.swift @@ -604,8 +604,8 @@ public typealias CoreObjectActionLoadPresentDelegate = MVMCoreActionDelegateProt performAction = wButtonDelegate.button?(wSelf, shouldPerformActionWithMap: actionMap, additionalData: additionalData) ?? false } - if let wDelegate = weakDelegate as? CoreObjectActionLoadPresentDelegate, performAction { - MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegate: wDelegate) + if performAction { + MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegate: weakDelegate as? CoreObjectActionLoadPresentDelegate) } } } From 2d73f89fd45007e510e6cc790bc2f69e7596b67e Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 30 Apr 2019 10:34:25 -0400 Subject: [PATCH 14/19] separator keys clean up --- .../ThreeLayerTableViewController.swift | 14 +-- MVMCoreUI/Molecules/MoleculeStackView.swift | 5 +- .../Molecules/MoleculeTableViewCell.swift | 86 +++++++++++++++++-- .../MVMCoreUIMoleculeMappingObject.m | 4 +- .../Templates/MoleculeListTemplate.swift | 32 +++---- MVMCoreUI/Utility/MVMCoreUIConstants.h | 3 + MVMCoreUI/Utility/MVMCoreUIConstants.m | 3 + 7 files changed, 115 insertions(+), 32 deletions(-) diff --git a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift index a44fc4ee..85127a45 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift @@ -21,7 +21,7 @@ open class ThreeLayerTableViewController: MFProgrammaticTableViewController { private var topViewBottomConstraint: NSLayoutConstraint? private var bottomViewTopConstraint: NSLayoutConstraint? - //MARK:-MVMCoreViewProtocol + //MARK: - MVMCoreViewProtocol open override func updateViews() { super.updateViews() let width = view.bounds.width @@ -37,7 +37,7 @@ open class ThreeLayerTableViewController: MFProgrammaticTableViewController { self.tableView?.reloadData() } - //MARK:-MFViewController + //MARK: - MFViewController open override func newDataBuildScreen() { super.newDataBuildScreen() createViewForTableHeader() @@ -51,7 +51,7 @@ open class ThreeLayerTableViewController: MFProgrammaticTableViewController { // Do any additional setup after loading the view. } - //MARK:-Spacing + //MARK: - Spacing // If both are subclassed to return a value, then the buttons will not be pinned towards the bottom because neither spacing would try to fill the screen. /// Space between the top view and the table sections, nil to fill. 0 default open func spaceBelowTopView() -> CGFloat? { @@ -127,7 +127,7 @@ open class ThreeLayerTableViewController: MFProgrammaticTableViewController { } } - //MARK:-Header Footer + //MARK: - Header Footer /// Gets the top view and adds it to a spacing view, headerView, and then calls showHeader. open func createViewForTableHeader() { let topView = viewForTop() @@ -215,7 +215,7 @@ open class ThreeLayerTableViewController: MFProgrammaticTableViewController { } } - //MARK:-Functions to subclass + //MARK: - Functions to subclass /// Subclass for a top view. open func viewForTop() -> UIView { let view = MVMCoreUICommonViewsUtility.commonView() @@ -230,7 +230,7 @@ open class ThreeLayerTableViewController: MFProgrammaticTableViewController { return view } - //MARK:-Scrollview + //MARK: - Scrollview open override func scrollViewDidScroll(_ scrollView: UIScrollView) { // To stop handscroll animation if animating after scroll stopHandScrollAnimation(true) @@ -240,7 +240,7 @@ open class ThreeLayerTableViewController: MFProgrammaticTableViewController { tableView?.delegate = nil } - //MARK:-Animation + //MARK: - Animation open override func setupIntroAnimations() { if let topView = topView, topView.subviews.count > 0 { introAnimationManager?.addAnimation(animation: MVMAnimations.fadeUpAnimation(view: topView)) diff --git a/MVMCoreUI/Molecules/MoleculeStackView.swift b/MVMCoreUI/Molecules/MoleculeStackView.swift index 10e048d3..ef060718 100644 --- a/MVMCoreUI/Molecules/MoleculeStackView.swift +++ b/MVMCoreUI/Molecules/MoleculeStackView.swift @@ -13,6 +13,7 @@ public class MoleculeStackView: MFView { var moleculesArray: [UIView]? var useMargins: Bool = false + // MARK: - Inits public override init(frame: CGRect) { super.init(frame: frame) } @@ -31,6 +32,7 @@ public class MoleculeStackView: MFView { fatalError("init(coder:) has not been implemented") } + // MARK: - MFViewProtocol public override func setupView() { super.setupView() translatesAutoresizingMaskIntoConstraints = false @@ -48,9 +50,10 @@ public class MoleculeStackView: MFView { } } + // MARK: - MVMCoreUIMoleculeViewProtocol open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - guard let molecules = json?.arrayForKey("molecules") as? [[String: Any]] else { + guard let molecules = json?.arrayForKey(KeyMolecules) as? [[String: Any]] else { return } diff --git a/MVMCoreUI/Molecules/MoleculeTableViewCell.swift b/MVMCoreUI/Molecules/MoleculeTableViewCell.swift index 4cd0dfd5..1df0e67d 100644 --- a/MVMCoreUI/Molecules/MoleculeTableViewCell.swift +++ b/MVMCoreUI/Molecules/MoleculeTableViewCell.swift @@ -9,8 +9,24 @@ import UIKit @objcMembers open class MoleculeTableViewCell: UITableViewCell, MVMCoreViewProtocol, MVMCoreUIMoleculeViewProtocol { - var molecule: (UIView & MVMCoreUIMoleculeViewProtocol)? + open var molecule: (UIView & MVMCoreUIMoleculeViewProtocol)? + // For the accessory view convenience. + public var caretView: CaretView? + private var caretViewWidthSizeObject: MFSizeObject? + private var caretViewHeightSizeObject: MFSizeObject? + + // For separation between cells. + public var topSeparatorView: SeparatorView? + public var bottomSeparatorView: SeparatorView? + public enum SeparatorFrequency: String { + case All = "all" + case AllExceptTop = "allExceptTop" + case AllExceptBottom = "allExceptBottom" + case Between = "between" + } + + // MARK: - Inits public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) setupView() @@ -21,17 +37,17 @@ import UIKit setupView() } - // For the accessory view convenience. - var caretView: CaretView? - private var caretViewWidthSizeObject: MFSizeObject? - private var caretViewHeightSizeObject: MFSizeObject? - + // MARK: - MFViewProtocol public func updateView(_ size: CGFloat) { MFStyler.setDefaultMarginsFor(self, size: size) if #available(iOS 11.0, *) { contentView.directionalLayoutMargins = directionalLayoutMargins + topSeparatorView?.setLeftAndRightPinConstant(directionalLayoutMargins.leading) + bottomSeparatorView?.setLeftAndRightPinConstant(directionalLayoutMargins.leading) } else { contentView.layoutMargins = layoutMargins + topSeparatorView?.setLeftAndRightPinConstant(layoutMargins.left) + bottomSeparatorView?.setLeftAndRightPinConstant(layoutMargins.left) } if let molecule = molecule as? MVMCoreViewProtocol { @@ -40,6 +56,8 @@ import UIKit if let _ = accessoryView, let caretView = caretView, let widthObject = caretViewWidthSizeObject, let heightObject = caretViewHeightSizeObject { caretView.frame = CGRect(x: 0, y: 0, width: widthObject.getValueBased(onSize: size), height: heightObject.getValueBased(onSize: size)) } + topSeparatorView?.updateView(size) + bottomSeparatorView?.updateView(size) } public func setupView() { @@ -48,6 +66,7 @@ import UIKit selectionStyle = .none } + // MARK: - MVMCoreUIMoleculeViewProtocol public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) { guard let json = json else { return @@ -64,7 +83,8 @@ import UIKit backgroundColor = molecule?.backgroundColor } - // MARK- Convenience + // MARK: - Convenience + /// Adds the standard mvm style caret to the accessory view public func addCaretViewAccessory() { guard accessoryView == nil else { return @@ -77,4 +97,56 @@ import UIKit caretViewHeightSizeObject = MFSizeObject(scalingStandardSize: height) accessoryView = caretView } + + func addSeparatorsIfNeeded() { + if topSeparatorView == nil { + topSeparatorView = SeparatorView.separatorAdd(to: self, position: SeparatorPositionTop) + topSeparatorView?.hide() + } + if bottomSeparatorView == nil { + bottomSeparatorView = SeparatorView.separatorAdd(to: self, position: SeparatorPositionBot) + bottomSeparatorView?.hide() + } + } + + /// For when the separator between cells shows using json and frequency. + public func setSeparatorWithJSON(_ json: [AnyHashable : Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?, indexPath: IndexPath) { + guard let json = json else { + return + } + addSeparatorsIfNeeded() + topSeparatorView?.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + bottomSeparatorView?.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + if let separatorFrequencyString = json.optionalStringForKey("frequency"), let separatorFrequency = SeparatorFrequency(rawValue: separatorFrequencyString) { + setSeparatorFrequency(separatorFrequency, indexPath: indexPath) + } + } + + /// For when the separator between cells shows. + public func setSeparatorFrequency(_ separatorFrequency: SeparatorFrequency, indexPath: IndexPath) { + switch separatorFrequency { + case .All: + if indexPath.row == 0 { + topSeparatorView?.show() + } else { + topSeparatorView?.hide() + } + bottomSeparatorView?.show() + case .AllExceptBottom: + topSeparatorView?.show() + bottomSeparatorView?.hide() + case .Between: + if indexPath.row == 0 { + topSeparatorView?.hide() + } else { + topSeparatorView?.show() + } + bottomSeparatorView?.hide() + case .AllExceptTop: + fallthrough + default: + topSeparatorView?.hide() + bottomSeparatorView?.show() + } + } } diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 9deb6cd5..66039753 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -56,7 +56,7 @@ } - (nullable UIView *)getMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable DelegateObject *)delegateObject { - NSString *moleculeName = [json string:@"moleculeName"]; + NSString *moleculeName = [json string:KeyMoleculeName]; if (!moleculeName) { return nil; } @@ -67,7 +67,7 @@ - (nullable UIView *)getMoleculeForStackWithJSON:(nonnull NSDictionary *)json delegateObject:(nullable DelegateObject *)delegateObject { - NSString *moleculeName = [json string:@"moleculeName"]; + NSString *moleculeName = [json string:KeyMoleculeName]; if (!moleculeName) { return nil; } diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index ba6e7f15..fe891a93 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -8,58 +8,60 @@ import UIKit -public class MoleculeListTemplate: ThreeLayerTableViewController { +open class MoleculeListTemplate: ThreeLayerTableViewController { - public override func registerWithTable() { + open override func registerWithTable() { super.registerWithTable() - guard let molecules = loadObject?.pageJSON?.arrayForKey("molecules") else { + guard let molecules = loadObject?.pageJSON?.arrayForKey(KeyMolecules) else { return } for case let molecule as Dictionary in molecules { - if let moleculeName = molecule.optionalStringForKey("moleculeName") { + if let moleculeName = molecule.optionalStringForKey(KeyMoleculeName) { tableView?.register(MoleculeTableViewCell.self, forCellReuseIdentifier: moleculeName) } } } - public override func viewForTop() -> UIView { + open override func viewForTop() -> UIView { guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForStack(withJSON: moleculeJSON, delegateObject: delegateObject()) else { return super.viewForTop() } return molecule } - override public func viewForBottom() -> UIView { + override open func viewForBottom() -> UIView { guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForStack(withJSON: moleculeJSON, delegateObject: delegateObject()) else { return viewForBottom() } return molecule } - public override func newDataBuildScreen() { + open override func newDataBuildScreen() { super.newDataBuildScreen() registerWithTable() } - public override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { - if let moleculeName = loadObject?.pageJSON?.stringOptionalWithChainOfKeysOrIndexes(["molecules",indexPath.row,"moleculeName"]), let theClass = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping?[moleculeName] as? MVMCoreUIMoleculeViewProtocol.Type, + open override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { + if let moleculeName = loadObject?.pageJSON?.stringOptionalWithChainOfKeysOrIndexes([KeyMolecules,indexPath.row,KeyMoleculeName]), let theClass = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping?[moleculeName] as? MVMCoreUIMoleculeViewProtocol.Type, let estimatedHeightForRow = theClass.estimatedHeightForRow { return estimatedHeightForRow() } return 0 } - public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return loadObject?.pageJSON?.arrayForKey("molecules").count ?? 0 + open override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return loadObject?.pageJSON?.arrayForKey(KeyMolecules).count ?? 0 } - public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - guard let molecule = loadObject?.pageJSON?.optionalDictionaryWithChainOfKeysOrIndexes(["molecules",indexPath.row]), - let moleculeName = molecule.optionalStringForKey("moleculeName"), + open override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard let molecule = loadObject?.pageJSON?.optionalDictionaryWithChainOfKeysOrIndexes([KeyMolecules,indexPath.row]), + let moleculeName = molecule.optionalStringForKey(KeyMoleculeName), let cell = tableView.dequeueReusableCell(withIdentifier: moleculeName) as? MoleculeTableViewCell else { return UITableViewCell() } - cell.setWithJSON(molecule, delegateObject: delegateObject(), additionalData: nil) + let delegate = delegateObject() + cell.setWithJSON(molecule, delegateObject: delegate, additionalData: nil) + cell.setSeparatorWithJSON(loadObject?.pageJSON?.optionalDictionaryForKey("separator"), delegateObject: delegate, additionalData: nil, indexPath: indexPath) cell.updateView(tableView.bounds.width) return cell } diff --git a/MVMCoreUI/Utility/MVMCoreUIConstants.h b/MVMCoreUI/Utility/MVMCoreUIConstants.h index 93f77713..a1d2759a 100644 --- a/MVMCoreUI/Utility/MVMCoreUIConstants.h +++ b/MVMCoreUI/Utility/MVMCoreUIConstants.h @@ -13,6 +13,9 @@ extern NSString * const KeyScreenHeading; +extern NSString * const KeyMolecules; +extern NSString * const KeyMoleculeName; + extern NSString * const KeyDisableButton; extern NSString * const KeyValue; diff --git a/MVMCoreUI/Utility/MVMCoreUIConstants.m b/MVMCoreUI/Utility/MVMCoreUIConstants.m index 684f013b..76949ccf 100644 --- a/MVMCoreUI/Utility/MVMCoreUIConstants.m +++ b/MVMCoreUI/Utility/MVMCoreUIConstants.m @@ -12,6 +12,9 @@ NSString * const KeyScreenHeading = @"screenHeading"; +NSString * const KeyMolecules = @"molecules"; +NSString * const KeyMoleculeName = @"moleculeName"; + NSString * const KeyDisableButton = @"disableAction"; NSString * const KeyValue = @"value"; From 973ba11822d959888011a17fd37aeaa002ade18e Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 30 Apr 2019 13:29:30 -0400 Subject: [PATCH 15/19] fix --- .../Molecules/{Protocols => }/MVMCoreUIMoleculeViewProtocol.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename MVMCoreUI/Molecules/{Protocols => }/MVMCoreUIMoleculeViewProtocol.h (100%) diff --git a/MVMCoreUI/Molecules/Protocols/MVMCoreUIMoleculeViewProtocol.h b/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h similarity index 100% rename from MVMCoreUI/Molecules/Protocols/MVMCoreUIMoleculeViewProtocol.h rename to MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h From 257cac3794860e62ed463eeb764a3e30384688f4 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 30 Apr 2019 13:47:08 -0400 Subject: [PATCH 16/19] file --- .../Molecules/MVMCoreUIMoleculeViewProtocol.h | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h diff --git a/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h b/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h new file mode 100644 index 00000000..12557967 --- /dev/null +++ b/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h @@ -0,0 +1,33 @@ +// +// MVMCoreUIMoleculeViewProtocol.h +// MVMCoreUI +// +// Created by Scott Pfeil on 2/11/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +#import +@class DelegateObject; + +@protocol MVMCoreUIMoleculeViewProtocol + +// Sets up the ui based on the json +- (void)setWithJSON:(nullable NSDictionary *)json delegateObject:(nullable DelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData; + +@optional + +// Called after init to provide an early setter for any molecule specific logic +- (void)setAsMolecule; + +// Notifies the creator that the view needs to be constrained in a view. +- (BOOL)needsToBeConstrained; + +// The alignment for the molecule if constrained. +- (UIStackViewAlignment)moleculeAlignment; + +// For the molecule list to load more efficiently. ++ (CGFloat)estimatedHeightForRow; + +@end + + From 8282e9a61737f8e35ccc0cb61df5a88cb5118474 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 30 Apr 2019 15:14:38 -0400 Subject: [PATCH 17/19] fixes with constaints --- MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m | 21 ++++++++++++++----- MVMCoreUI/Atoms/Views/ViewConstrainingView.h | 3 --- .../FormValidationProtocol.swift | 4 ++-- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m index 4a57aeb7..f7239def 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m @@ -21,7 +21,7 @@ static const CGFloat FaultTolerance = 20.f; static const CGFloat CheckBoxHeightWidth = 18.0; -@interface MVMCoreUICheckBox () +@interface MVMCoreUICheckBox () @property (nonatomic, readwrite) BOOL isSelected; @property (weak, nonatomic) UIView *checkedSquare; @@ -42,16 +42,24 @@ static const CGFloat CheckBoxHeightWidth = 18.0; @property (nonatomic) BOOL isRequired; @property (nullable, strong, nonatomic) NSString *fieldKey; -@property (nullable, weak) DelegateObject *delegate; +@property (nullable, strong, nonatomic) DelegateObject *delegate; @end @implementation MVMCoreUICheckBox -#pragma mark - convenient class methods +#pragma mark - MVMCoreUIMoleculeViewProtocol + +- (BOOL)needsToBeConstrained { + return YES; +} + +- (UIStackViewAlignment)moleculeAlignment { + return UIStackViewAlignmentLeading; +} - (void)setWithJSON:(NSDictionary *)json delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { - + [FormValidator setupValidationWithMolecule:self delegate:((MVMCoreUIDelegateObject *)delegateObject).formValidationProtocol]; self.delegate = delegateObject; self.fieldKey = [json stringForKey:KeyFieldKey]; @@ -70,6 +78,9 @@ static const CGFloat CheckBoxHeightWidth = 18.0; additionalData: additionalData]; } + +#pragma mark - convenient class methods + + (instancetype)mfCheckBox { MVMCoreUICheckBox *checkBox = [[self alloc] initWithFrame:CGRectZero]; checkBox.translatesAutoresizingMaskIntoConstraints = NO; @@ -331,7 +342,7 @@ static const CGFloat CheckBoxHeightWidth = 18.0; [self.checkMark updateCheckSelected:NO animated:animated]; } - FormValidator *formValidator = [FormValidator getFormValidatorForDelegate:((MVMCoreUIDelegateObject *)self.delegate).formValidationProtocol]; + FormValidator *formValidator = ((MVMCoreUIDelegateObject *)self.delegate).formValidationProtocol.formValidatorModel; [formValidator enableByValidation]; } diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.h b/MVMCoreUI/Atoms/Views/ViewConstrainingView.h index 9e1f0316..e4b9e585 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.h +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.h @@ -44,9 +44,6 @@ // Pins all edges to its super. 0 constant - (void)pinToSuperView; -// Add a view to be constrained in this view. -- (void)addConstrainedView:(nonnull UIView *)view; - // Resets all the constraints to default. - (void)resetConstraints; diff --git a/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift b/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift index afce4d28..63ef182d 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift @@ -22,6 +22,6 @@ import Foundation // The Field name key value pair for sending to server @objc optional func formFieldName() -> String? - // The Feild value key value paid for sending to server - @objc optional func formFieldValue() -> String? + // The Feild value key value pair for sending to server + @objc optional func formFieldValue() -> Any? } From 175fe574c71474ef461b4e931289c0a1285bd85c Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 30 Apr 2019 16:04:51 -0400 Subject: [PATCH 18/19] typo --- MVMCoreUI/Atoms/Views/ViewConstrainingView.h | 2 +- MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.h b/MVMCoreUI/Atoms/Views/ViewConstrainingView.h index e4b9e585..6b97f891 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.h +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.h @@ -50,7 +50,7 @@ // For setting up the view. - (void)setupView; -// Add a View Constraining View +// Add a view to be constrained in this view. - (void)addConstrainedView:(nonnull UIView *)view; @end diff --git a/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift b/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift index 63ef182d..b593a503 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift @@ -22,6 +22,6 @@ import Foundation // The Field name key value pair for sending to server @objc optional func formFieldName() -> String? - // The Feild value key value pair for sending to server + // The Field value key value pair for sending to server @objc optional func formFieldValue() -> Any? } From cff8361f9f63f94551018bd6263cbe42b9484a12 Mon Sep 17 00:00:00 2001 From: "Chowdhury, Shohrab" Date: Wed, 1 May 2019 14:00:57 -0400 Subject: [PATCH 19/19] allow user to overrise pannable Percentage value --- MVMCoreUI/Containers/TabBarController/MFTabBarInteractor.h | 3 +++ MVMCoreUI/Containers/TabBarController/MFTabBarInteractor.m | 7 +++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Containers/TabBarController/MFTabBarInteractor.h b/MVMCoreUI/Containers/TabBarController/MFTabBarInteractor.h index b08129f0..cfcf6320 100644 --- a/MVMCoreUI/Containers/TabBarController/MFTabBarInteractor.h +++ b/MVMCoreUI/Containers/TabBarController/MFTabBarInteractor.h @@ -25,6 +25,9 @@ // true while panning @property (nonatomic) BOOL panning; +//set pannable percentage 0 to 1 +@property (nonatomic) CGFloat pannablePercentage; + // can be used to keep track of if we are .. @property (nonatomic) BOOL interactive; diff --git a/MVMCoreUI/Containers/TabBarController/MFTabBarInteractor.m b/MVMCoreUI/Containers/TabBarController/MFTabBarInteractor.m index de20ef53..b8e2cee4 100644 --- a/MVMCoreUI/Containers/TabBarController/MFTabBarInteractor.m +++ b/MVMCoreUI/Containers/TabBarController/MFTabBarInteractor.m @@ -8,8 +8,6 @@ #import "MFTabBarInteractor.h" -static CGFloat pannablePercentage = 0.15; - typedef NS_ENUM(NSUInteger, MFTabBarPanningDirection) { MFTabBarPanningDirectionLeft, MFTabBarPanningDirectionRight @@ -33,6 +31,7 @@ typedef NS_ENUM(NSUInteger, MFTabBarPanningDirection) { - (nullable instancetype)initWithViewController:(nullable UIViewController *)viewController delegate:(nullable id)delegate { if (self = [super init]) { + self.pannablePercentage = 0.15; self.panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)]; [viewController.view addGestureRecognizer:self.panGesture]; self.delegate = delegate; @@ -48,8 +47,8 @@ typedef NS_ENUM(NSUInteger, MFTabBarPanningDirection) { // Simulates an edge gesture by only accepting pans at the edge of the screen. Needed because edge gesture doesn't work nicely with extended menus such as on ipad. CGRect frame = pan.view.frame; - CGRect pannableFrameLeft = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width*pannablePercentage, frame.size.height); - CGRect pannableFrameRight = CGRectMake(frame.origin.x + frame.size.width*(1-pannablePercentage), frame.origin.y, frame.size.width*pannablePercentage, frame.size.height); + CGRect pannableFrameLeft = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width*self.pannablePercentage, frame.size.height); + CGRect pannableFrameRight = CGRectMake(frame.origin.x + frame.size.width*(1-self.pannablePercentage), frame.origin.y, frame.size.width*self.pannablePercentage, frame.size.height); switch (pan.state) { case UIGestureRecognizerStateBegan: