Merge branch 'develop' into feature/form_checkbox

This commit is contained in:
Suresh, Kamlesh 2019-04-17 11:05:36 -04:00
commit 725a0a914f
49 changed files with 955 additions and 827 deletions

View File

@ -157,11 +157,11 @@
D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; };
D2C5001821F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */; };
D2C5001D21F8EE67001DA659 /* LabelWithInternalButton.h in Headers */ = {isa = PBXBuildFile; fileRef = D2C5001B21F8EE66001DA659 /* LabelWithInternalButton.h */; settings = {ATTRIBUTES = (Public, ); }; };
D2C5001E21F8EE67001DA659 /* LabelWithInternalButton.m in Sources */ = {isa = PBXBuildFile; fileRef = D2C5001C21F8EE66001DA659 /* LabelWithInternalButton.m */; };
D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.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 */; };
DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391C2245232D001AB423 /* LabelWithInternalButton.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@ -318,11 +318,11 @@
D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerViewController.swift; sourceTree = "<group>"; };
D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewControllerMappingObject.h; sourceTree = "<group>"; };
D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIViewControllerMappingObject.m; sourceTree = "<group>"; };
D2C5001B21F8EE66001DA659 /* LabelWithInternalButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LabelWithInternalButton.h; sourceTree = "<group>"; };
D2C5001C21F8EE66001DA659 /* LabelWithInternalButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LabelWithInternalButton.m; sourceTree = "<group>"; };
D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIDelegateObject.swift; sourceTree = "<group>"; };
DBC4391622442196001AB423 /* CaretView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretView.swift; sourceTree = "<group>"; };
DBC4391722442197001AB423 /* DashLine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DashLine.swift; sourceTree = "<group>"; };
DBC4391A224421A0001AB423 /* CaretButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretButton.swift; sourceTree = "<group>"; };
DBC4391C2245232D001AB423 /* LabelWithInternalButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelWithInternalButton.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -568,8 +568,6 @@
D29DF28621E7AC2B003B2FB9 /* MFLabel.m */,
D29DF31E21ED0CBA003B2FB9 /* LabelView.h */,
D29DF31F21ED0CBA003B2FB9 /* LabelView.m */,
D2C5001B21F8EE66001DA659 /* LabelWithInternalButton.h */,
D2C5001C21F8EE66001DA659 /* LabelWithInternalButton.m */,
D29DF28721E7AC2B003B2FB9 /* ViewConstrainingView.h */,
D29DF28821E7AC2B003B2FB9 /* ViewConstrainingView.m */,
D282AAB9224131D100C46919 /* MFTransparentGIFView.swift */,
@ -591,6 +589,7 @@
D22D1F19220341F50077CEC0 /* MVMCoreUICheckBox.m */,
D22D1F44220496A30077CEC0 /* MVMCoreUISwitch.h */,
D22D1F45220496A30077CEC0 /* MVMCoreUISwitch.m */,
DBC4391C2245232D001AB423 /* LabelWithInternalButton.swift */,
0198F7A02256A80A0066C936 /* MFRadioButton.h */,
0198F7A22256A80A0066C936 /* MFRadioButton.m */,
);
@ -637,6 +636,7 @@
D29DF27021E79B2C003B2FB9 /* OtherHandlers */ = {
isa = PBXGroup;
children = (
D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */,
D28B4F8821FF967C00712C7A /* MVMCoreUIObject.h */,
D28B4F8921FF967C00712C7A /* MVMCoreUIObject.m */,
D29DF27721E7A533003B2FB9 /* MVMCoreUISession.h */,
@ -753,7 +753,6 @@
D29DF17521E69E1F003B2FB9 /* ButtonDelegateProtocol.h in Headers */,
D29DF18221E69E54003B2FB9 /* SeparatorView.h in Headers */,
D29DF26E21E6AA0B003B2FB9 /* FLAnimatedImage.h in Headers */,
D2C5001D21F8EE67001DA659 /* LabelWithInternalButton.h in Headers */,
D29DF11621E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.h in Headers */,
D29DF17721E69E1F003B2FB9 /* MFTextButton.h in Headers */,
01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */,
@ -869,11 +868,13 @@
D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */,
DBC4391922442197001AB423 /* DashLine.swift in Sources */,
D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */,
D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */,
D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */,
D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */,
D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */,
D29DF25321E6A177003B2FB9 /* MFDigitTextField.m in Sources */,
D29DF12F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m in Sources */,
DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */,
D29DF17C21E69E1F003B2FB9 /* MFTextButton.m in Sources */,
D29DF2C521E7BF57003B2FB9 /* MFTabBarSwipeAnimator.m in Sources */,
D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */,
@ -929,7 +930,6 @@
DBC4391B224421A0001AB423 /* CaretButton.swift in Sources */,
0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */,
D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */,
D2C5001E21F8EE67001DA659 /* LabelWithInternalButton.m in Sources */,
D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */,
0105618E224BBE7700E1557D /* FormValidator+TextFields.swift in Sources */,
D29DF2BE21E7BEA4003B2FB9 /* TopTabbar.m in Sources */,

View File

@ -106,15 +106,15 @@ open class CaretButton: MFCustomButton {
//------------------------------------------------------
// Default values for view.
@objc open override func setAsMolecule() {
@objc open func setAsMolecule() {
backgroundColor = .clear
setTitleColor(enabledColor, for: .normal)
setTitleColor(disabledColor, for: .disabled)
}
@objc override open func setWithJSON(_ json: [AnyHashable: Any]?, delegate: NSObject?, additionalData: [AnyHashable: Any]?) {
setWithActionMap(json, delegate: delegate as? (MVMCoreActionDelegateProtocol & NSObjectProtocol), additionalData: additionalData)
open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
setWithActionMap(json, delegateObject: delegateObject, additionalData: additionalData)
guard let dictionary = json else { return }

View File

@ -11,14 +11,14 @@
#import <MVMCoreUI/ButtonDelegateProtocol.h>
#import <MVMCoreUI/MFButtonProtocol.h>
#import <MVMCoreUI/MVMCoreUIMoleculeViewProtocol.h>
@import MVMCore.MVMCoreViewProtocol;
@class DelegateObject;
typedef void (^ButtonTapBlock)(id _Nonnull sender);
extern CGFloat const CloseButtonHeight;
extern CGFloat const CloseButtonWidth;
@interface MFCustomButton : UIButton <MFButtonProtocol, MVMCoreUIMoleculeViewProtocol>
@interface MFCustomButton : UIButton <MFButtonProtocol>
@property (nullable, nonatomic, strong) NSDictionary *actionMap;
@property (nullable, nonatomic, weak) id <ButtonDelegateProtocol> buttonDelegate;
@ -28,14 +28,19 @@ extern CGFloat const CloseButtonWidth;
- (void)addBlock:(nonnull ButtonTapBlock)buttonTapBlock forControlEvents:(UIControlEvents)event;
// Sets up the button with the passed in action map. Will set the title and set the action to use the action handler.
- (void)setWithActionMap:(nullable NSDictionary *)actionMap delegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)delegate additionalData:(nullable NSDictionary *)additionalData;
// Sets up the button with the passed in action map. Will set the title and set the action to use the action handler. Also pass in the button delegate
- (void)setWithActionMap:(nullable NSDictionary *)actionMap actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate additionalData:(nullable NSDictionary *)additionalData buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate;
- (void)setWithActionMap:(nullable NSDictionary *)actionMap delegateObject:(nullable DelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData;
//accessibility
- (void)addAccessibilityForCameraControl;
- (nonnull UIAccessibilityCustomAction *)accessibilityCustomAction;
#pragma mark - Deprecated
// Sets up the button with the passed in action map. Will set the title and set the action to use the action handler.
- (void)setWithActionMap:(nullable NSDictionary *)actionMap delegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)delegate additionalData:(nullable NSDictionary *)additionalData __deprecated;
// Sets up the button with the passed in action map. Will set the title and set the action to use the action handler. Also pass in the button delegate
- (void)setWithActionMap:(nullable NSDictionary *)actionMap actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate additionalData:(nullable NSDictionary *)additionalData buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate __deprecated;
@end

View File

@ -13,6 +13,7 @@
@import MVMCore.NSDictionary_MFConvenience;
#import "MVMCoreUIUtility.h"
#import "MVMCoreUIConstants.h"
#import <MVMCoreUI/MVMCoreUI-Swift.h>
CGFloat const CloseButtonHeight = 40.0f;
CGFloat const CloseButtonWidth = 40.0f;
@ -37,6 +38,54 @@ CGFloat const CloseButtonWidth = 40.0f;
}
}
- (void)setWithActionMap:(nullable NSDictionary *)actionMap delegateObject:(nullable DelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData {
self.actionMap = actionMap;
self.titleLabel.numberOfLines = 0;
self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
[self setTitle:[actionMap stringForKey:KeyTitle] forState:UIControlStateNormal];
[self setEnabled:![actionMap[KeyDisableButton]boolValue]];
if ([delegateObject isKindOfClass:[MVMCoreUIDelegateObject class]]) {
self.buttonDelegate = ((MVMCoreUIDelegateObject *)delegateObject).buttonDelegate;
}
__weak MFCustomButton *weakSelf = self;
[self addBlock:^(id _Nonnull sender) {
BOOL performAction = YES;
if (weakSelf.buttonDelegate && [weakSelf.buttonDelegate respondsToSelector:@selector(button:shouldPerformActionWithMap:additionalData:)]) {
performAction = [weakSelf.buttonDelegate button:weakSelf shouldPerformActionWithMap:actionMap additionalData:additionalData];
}
if (performAction) {
[[MVMCoreActionHandler sharedActionHandler] handleActionWithDictionary:actionMap additionalData:additionalData delegateObject:delegateObject];
}
} forControlEvents:UIControlEventTouchUpInside];
}
//accessibility
-(void)addAccessibilityForCameraControl{
self.accessibilityLabel = [MVMCoreUIUtility hardcodedStringWithKey:@"AccCameraButton"];
self.accessibilityHint = [MVMCoreUIUtility hardcodedStringWithKey:@"AccCameraHint"];
self.accessibilityTraits = UIAccessibilityTraitNone;
}
- (UIAccessibilityCustomAction *)accessibilityCustomAction {
NSString *name = self.accessibilityLabel ?: self.titleLabel.text;
return [[UIAccessibilityCustomAction alloc] initWithName:name target:self selector:@selector(performAccessibilityAction:)];
}
- (BOOL)performAccessibilityAction:(UIAccessibilityCustomAction *)action {
if (self.buttonTapBlock) {
self.buttonTapBlock(self);
}
return YES;
}
#pragma mark - Deprecated
- (void)setWithActionMap:(nullable NSDictionary *)actionMap delegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)delegate additionalData:(nullable NSDictionary *)additionalData {
self.actionMap = actionMap;
@ -53,11 +102,11 @@ CGFloat const CloseButtonWidth = 40.0f;
}
- (void)setWithActionMap:(nullable NSDictionary *)actionMap actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol>*)actionDelegate additionalData:(nullable NSDictionary *)additionalData buttonDelegate:(nullable id <ButtonDelegateProtocol>)buttonDelegate {
if (!buttonDelegate) {
[self setWithActionMap:actionMap delegate:actionDelegate additionalData:additionalData];
} else {
self.actionMap = actionMap;
self.titleLabel.numberOfLines = 0;
self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
@ -86,24 +135,4 @@ CGFloat const CloseButtonWidth = 40.0f;
}
}
//accessibility
-(void)addAccessibilityForCameraControl{
self.accessibilityLabel = [MVMCoreUIUtility hardcodedStringWithKey:@"AccCameraButton"];
self.accessibilityHint = [MVMCoreUIUtility hardcodedStringWithKey:@"AccCameraHint"];
self.accessibilityTraits = UIAccessibilityTraitNone;
}
- (UIAccessibilityCustomAction *)accessibilityCustomAction {
NSString *name = self.accessibilityLabel ?: self.titleLabel.text;
return [[UIAccessibilityCustomAction alloc] initWithName:name target:self selector:@selector(performAccessibilityAction:)];
}
- (BOOL)performAccessibilityAction:(UIAccessibilityCustomAction *)action {
if (self.buttonTapBlock) {
self.buttonTapBlock(self);
}
return YES;
}
@end

View File

@ -128,12 +128,12 @@
#pragma mark - MVMCoreUIMoleculeViewProtocol
- (void)setWithJSON:(NSDictionary *)json delegate:(NSObject *)delegate additionalData:(NSDictionary *)additionalData {
- (void)setWithJSON:(NSDictionary *)json delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData {
NSString *color = [json string:KeyTextColor];
if (color) {
[self setTitleColor:[UIColor mfGetColorForHex:color] forState:UIControlStateNormal];
}
[self setWithActionMap:json actionDelegate:([delegate conformsToProtocol:@protocol(MVMCoreActionDelegateProtocol)] ? (NSObject <MVMCoreActionDelegateProtocol>*)delegate : nil) additionalData:additionalData buttonDelegate:([delegate conformsToProtocol:@protocol(ButtonDelegateProtocol)] ? (id <ButtonDelegateProtocol>)delegate : nil)];
[self setWithActionMap:json delegateObject:delegateObject additionalData:additionalData];
if ([self titleForState:UIControlStateNormal].length == 0) {
self.heightConstraint.constant = 0;
} else {

View File

@ -62,8 +62,8 @@ static CGFloat const PrimaryButtonSmallHeight = 30.0;
+ (nullable instancetype)primaryGraySmallRedButton;
+ (nullable instancetype)primaryWhiteSmallRedButton;
// Returns the current height of the button.
- (CGFloat)getHeight;
#pragma mark - For Subclassing

View File

@ -86,6 +86,10 @@
#pragma mark - Sizing
- (CGFloat)getHeight {
return self.height.constant;
}
- (MFSizeObject *)innerPadding {
return [MFSizeObject sizeObjectWithStandardSize:24.0 standardiPadPortraitSize:32.0 iPadProLandscapeSize:36.0];
}
@ -644,10 +648,11 @@
[self setAsStandardCustom];
}
- (void)setWithJSON:(NSDictionary *)json delegate:(NSObject *)delegate additionalData:(nullable NSDictionary *)additionalData {
[FormValidator setupValidationWithMolecule:self delegate:(id<FormValidationProtocol>)delegate];
- (void)setWithJSON:(NSDictionary *)json delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData {
if ([delegateObject isKindOfClass:[MVMCoreUIDelegateObject class]]) {
[FormValidator setupValidationWithMolecule:self delegate:((MVMCoreUIDelegateObject *)delegateObject).formValidationProtocol];
}
self.primaryButtonType = PrimaryButtonTypeCustom;
NSString *color = [json string:@"fillColor"];
if (color) {
@ -672,7 +677,7 @@
self.validationRequired = [json boolForKey:@"validationRequired"];
[self setAsSmallButton:[json boolForKey:@"small"]];
[self setWithActionMap:json actionDelegate:([delegate conformsToProtocol:@protocol(MVMCoreActionDelegateProtocol)] ? (NSObject <MVMCoreActionDelegateProtocol>*)delegate : nil) additionalData:additionalData buttonDelegate:([delegate conformsToProtocol:@protocol(ButtonDelegateProtocol)] ? (id <ButtonDelegateProtocol>)delegate : nil)];
[self setWithActionMap:json delegateObject:delegateObject additionalData:additionalData];
}
#pragma mark - Handling Validations

View File

@ -116,7 +116,7 @@
+ (nullable instancetype)mfTextFieldWithMap:(nullable NSDictionary *)map bothDelegates:(nullable id<UITextFieldDelegate, MFTextFieldDelegate>)delegate {
MFTextField *textField = [self mfTextField];
textField.translatesAutoresizingMaskIntoConstraints = NO;
[textField setWithJSON:map delegate:delegate additionalData:nil];
[textField setWithJSON:map delegateObject:[MVMCoreUIDelegateObject createWithDelegateForAll:delegate] additionalData:nil];
return textField;
}
@ -558,10 +558,12 @@
self.isMolecule = YES;
}
- (void)setWithJSON:(NSDictionary *)json delegate:(nullable id<UITextFieldDelegate, MFTextFieldDelegate>)delegate additionalData:(NSDictionary *)additionalData {
[FormValidator setupValidationWithMolecule:self delegate:(id<FormValidationProtocol>)delegate];
FormValidator *formValidator = [FormValidator getFormValidatorForDelegate:(id<FormValidationProtocol>)delegate];
[self setWithMap:json bothDelegates:formValidator];
- (void)setWithJSON:(NSDictionary *)json delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData {
if ([delegateObject isKindOfClass:[MVMCoreUIDelegateObject class]]) {
[FormValidator setupValidationWithMolecule:self delegate:((MVMCoreUIDelegateObject *)delegateObject).formValidationProtocol];
FormValidator *formValidator = [FormValidator getFormValidatorForDelegate:((MVMCoreUIDelegateObject *)delegateObject).formValidationProtocol];
[self setWithMap:json bothDelegates:formValidator];
}
}
#pragma mark - FormValidationProtocol

View File

@ -94,10 +94,9 @@ open class CaretView: MFView {
defaultState()
}
@objc override open func setWithJSON(_ json: [AnyHashable: Any]?, delegate: NSObject?, additionalData: [AnyHashable: Any]?) {
super.setWithJSON(json, delegate: delegate, additionalData: additionalData)
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
// Configure class properties with JSON values
guard let jsonDictionary = json else { return }

View File

@ -68,8 +68,8 @@ open class DashLine: MFView {
isHidden = false
}
@objc override open func setWithJSON(_ json: [AnyHashable: Any]?, delegate: NSObject?, additionalData: [AnyHashable: Any]?) {
super.setWithJSON(json, delegate: delegate, additionalData: additionalData)
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
// Configure class properties with JSON values
guard let jsonDictionary = json else { return }

View File

@ -72,9 +72,9 @@
}
}
- (void)setWithJSON:(NSDictionary *)json delegate:(NSObject *)delegate additionalData:(NSDictionary *)additionalData {
[super setWithJSON:json delegate:delegate additionalData:additionalData];
[self.label setWithJSON:json delegate:delegate additionalData:additionalData];
- (void)setWithJSON:(NSDictionary *)json delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData {
[super setWithJSON:json delegateObject:delegateObject additionalData:additionalData];
[self.label setWithJSON:json delegateObject:delegateObject additionalData:additionalData];
}
- (void)alignLeft {

View File

@ -1,94 +0,0 @@
//
// TextMixedWithButtonView.h
// mobilefirst
//
// Created by Chris Yang on 2/25/16.
// Copyright © 2016 Verizon Wireless. All rights reserved.
//
#import<UIKit/UIKit.h>
#import <MVMCore/MVMCoreActionDelegateProtocol.h>
#import <MVMCoreUI/MFView.h>
#import <MVMCoreUI/MFLabel.h>
#import <MVMCoreUI/ButtonDelegateProtocol.h>
#import <MVMCoreUI/MFButtonProtocol.h>
typedef void (^ActionBlock)(void);
@interface LabelWithInternalButton : UIControl <MVMCoreViewProtocol, MFButtonProtocol>
@property (nullable, copy, nonatomic) ActionBlock actionBlock;
@property (nullable, weak, nonatomic) MFLabel *label;
@property (nullable, strong, nonatomic) NSString *frontText;
@property (nullable, strong, nonatomic) NSString *actionText;
@property (nullable, strong, nonatomic) NSString *backText;
@property (nullable, strong, nonatomic) NSAttributedString *attributedText;
//by default, it will follow most of the font standard in zepplin, and should need to be changed
@property (nullable, strong, nonatomic) UIFont *normalTextFont;
@property (nullable, strong, nonatomic) UIFont *actionTextFont;
@property (nullable, strong, nonatomic) UIColor *normalTextColor;
@property (nullable, strong, nonatomic) UIColor *actionTextColor;
@property (nullable, strong, nonatomic) NSString *alternateAttributeForActionText;
@property (assign, nonatomic) BOOL makeWholeViewClickable;
// with button delegate
- (nullable instancetype)initWithActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate buttonDelegate:(nullable NSObject<ButtonDelegateProtocol> *)buttonDelegate;
- (nullable instancetype)initWithFrontText:(nullable NSString *)frontText backText:(nullable NSString *)backText actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate buttonDelegate:(nullable NSObject<ButtonDelegateProtocol> *)buttonDelegate;
- (nullable instancetype)initWithFrontText:(nullable NSString *)frontText actionText:(nullable NSString *)actionText backText:(nullable NSString *)backText actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate buttonDelegate:(nullable NSObject<ButtonDelegateProtocol> *)buttonDelegate;
// set with button delegate
- (void)setActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate buttonDelegate:(nullable NSObject<ButtonDelegateProtocol> *)buttonDelegate;
- (void)setFrontText:(nullable NSString *)frontText actionMap:(nullable NSDictionary *)actionMap backText:(nullable NSString *)backText additionalData:(nullable NSDictionary *)additionalData delegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate buttonDelegate:(nullable NSObject<ButtonDelegateProtocol> *)buttonDelegate;
- (void)setFrontAttributedText:(nullable NSAttributedString *)frontAttributedText actionMap:(nullable NSDictionary *)actionMap backAttributedText:(nullable NSAttributedString *)backText additionalData:(nullable NSDictionary *)additionalData delegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate buttonDelegate:(nullable NSObject<ButtonDelegateProtocol> *)buttonDelegate;
- (void)setFrontAttributedText:(nullable NSAttributedString *)frontAttributedText actionMap:(nullable NSDictionary *)actionMap backAttributedText:(nullable NSAttributedString *)backAttributedText addNewLine:(BOOL) addNewLine additionalData:(nullable NSDictionary *)additionalData delegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate buttonDelegate:(nullable NSObject<ButtonDelegateProtocol> *)buttonDelegate;
// legacy
- (nullable instancetype)initWithFrontText:(nullable NSString *)frontText actionText:(nullable NSString *)actionText backText:(nullable NSString *)backText actionBlock:(nullable ActionBlock)block;
- (nullable instancetype)initWithFrontText:(nullable NSString *)frontText actionText:(nullable NSString *)actionText backText:(nullable NSString *)backText actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate;
- (nullable instancetype)initWithActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate;
//this assume that the action text is the "title" key in action map
- (nullable instancetype)initWithFrontText:(nullable NSString *)frontText backText:(nullable NSString *)backText actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate;
// Convenience Initializer which assumes that the clickable text will be embedded in curly braces {}.
- (nullable instancetype)initWithClickableTextEmbeddedInCurlyBraces:(nullable NSString *)fullText actionMapForClickableText:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate;
// Convenience Initializer which assumes that the clickable text will be embedded in any tag.
- (nullable instancetype)initWithText:(nullable NSString *)fullText startTag:(nullable NSString *)startTag endTag:(nullable NSString *)endTag actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate;
//set action map
- (void)setActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate;
//set text with curly braces
- (void)setCurlyBracedText:(nonnull NSString *)text;
// set text with any tags
- (void)setWithText:(nullable NSString *)fullText startTag:(nullable NSString *)startTag endTag:(nullable NSString *)endTag actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate;
// Reset the text, action map and delegate
- (void)setTextWithClickableTextEmbeddedInCurlyBraces:(nullable NSString *)text textAttributes:(nullable NSDictionary *)attributes actionMapForClickableText:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate;
// Reset the front text, back text, action map
- (void)setFrontText:(nullable NSString *)frontText actionMap:(nullable NSDictionary *)actionMap backText:(nullable NSString *)backText additionalData:(nullable NSDictionary *)additionalData delegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate;
// Reset the front text, back text, action map
- (void)setFrontAttributedText:(nullable NSAttributedString *)frontAttributedText actionMap:(nullable NSDictionary *)actionMap backAttributedText:(nullable NSAttributedString *)backText additionalData:(nullable NSDictionary *)additionalData delegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate;
- (void)setFrontAttributedText:(nullable NSAttributedString *)frontAttributedText actionMap:(nullable NSDictionary *)actionMap backAttributedText:(nullable NSAttributedString *)backAttributedText addNewLine:(BOOL) addNewLine additionalData:(nullable NSDictionary *)additionalData delegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate;
- (void)resetWithActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary * )additionalData delegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate;
- (void)setAlignment:(NSTextAlignment)textAlignment;
- (void)setEnabled:(BOOL)enabled;
- (void)setAlternateActionTextAttributes:(nullable NSDictionary *)attributes;
- (void)setActionTextString:(nullable NSString *)actionText;
- (nonnull UIAccessibilityCustomAction *)accessibilityCustomAction;
@end

View File

@ -1,557 +0,0 @@
//
// TextMixedWithButtonView.m
// mobilefirst
//
// Created by Chris Yang on 2/25/16.
// Copyright © 2016 Verizon Wireless. All rights reserved.
//
#import "LabelWithInternalButton.h"
#import <MVMCore/UILabel+MFCustom.h>
#import <MVMCore/NSDictionary+MFConvenience.h>
#import <MVMCoreUI/MFFonts.h>
#import <MVMCore/MVMCoreJSONConstants.h>
#import <MVMCoreUI/UIColor+MFConvenience.h>
#import <MVMCoreUI/MFStyler.h>
#import <MVMCoreUI/MVMCoreUIConstants.h>
#import <MVMCore/MVMCoreConstants.h>
#import <MVMCore/MVMCoreActionHandler.h>
@interface LabelWithInternalButton ()
@property (nullable, strong, nonatomic) NSString *text;
@end
@implementation LabelWithInternalButton
- (nullable instancetype)initWithActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol> *)delegate buttonDelegate:(nullable NSObject<ButtonDelegateProtocol> *)buttonDelegate {
return [self initWithFrontText:[actionMap stringForKey:KeyTitlePrefix] actionText:[actionMap stringForKey:KeyTitle] backText:[actionMap stringForKey:KeyTitlePostfix] actionMap:actionMap additionalData:additionalData actionDelegate:delegate buttonDelegate:buttonDelegate];
}
- (nullable instancetype)initWithFrontText:(nullable NSString *)frontText backText:(nullable NSString *)backText actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate buttonDelegate:(nullable NSObject<ButtonDelegateProtocol> *)buttonDelegate {
return [self initWithFrontText:frontText actionText:[actionMap stringForKey:KeyTitle] backText:backText actionMap:actionMap additionalData:additionalData actionDelegate:delegate buttonDelegate:buttonDelegate];
}
- (nullable instancetype)initWithFrontText:(nullable NSString *)frontText actionText:(nullable NSString *)actionText backText:(nullable NSString *)backText actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate buttonDelegate:(nullable NSObject<ButtonDelegateProtocol> *)buttonDelegate {
if (self = [super init]) {
[self setFrontText:frontText actionText:actionText actionMap:actionMap backText:backText additionalData:additionalData delegate:delegate buttonDelegate:buttonDelegate];
}
return self;
}
- (void)setActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate buttonDelegate:(nullable NSObject<ButtonDelegateProtocol> *)buttonDelegate {
__weak typeof(self) weakSelf = self;
__weak typeof(delegate) weakDelegate = delegate;
__weak typeof(buttonDelegate) weakButtonDelegate = buttonDelegate;
self.actionBlock = ^{
BOOL performAction = YES;
if (weakButtonDelegate && [weakButtonDelegate respondsToSelector:@selector(button:shouldPerformActionWithMap:additionalData:)]) {
performAction = [weakButtonDelegate button:weakSelf shouldPerformActionWithMap:actionMap additionalData:additionalData];
}
if (performAction) {
[[MVMCoreActionHandler sharedActionHandler] handleActionWithDictionary:actionMap additionalData:additionalData delegate:weakDelegate];
}
};
}
- (void)setFrontText:(NSString *)frontText actionMap:(NSDictionary *)actionMap backText:(NSString *)backText additionalData:(NSDictionary *)additionalData delegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate buttonDelegate:(nullable NSObject<ButtonDelegateProtocol> *)buttonDelegate {
[self setFrontText:frontText actionText:[actionMap stringForKey:KeyTitle] actionMap:actionMap backText:backText additionalData:additionalData delegate:delegate buttonDelegate:buttonDelegate];
}
- (void)setFrontText:(NSString *)frontText actionText:(NSString *)actionText actionMap:(NSDictionary *)actionMap backText:(NSString *)backText additionalData:(NSDictionary *)additionalData delegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate buttonDelegate:(nullable NSObject<ButtonDelegateProtocol> *)buttonDelegate {
self.frontText = frontText;
[self setActionMap:actionMap additionalData:additionalData actionDelegate:delegate buttonDelegate:buttonDelegate];
self.actionText = actionText;
self.backText = backText;
self.text = [self getTextFromStringComponents];
[self setup];
}
- (void)setFrontAttributedText:(nullable NSAttributedString *)frontAttributedText actionMap:(nullable NSDictionary *)actionMap backAttributedText:(nullable NSAttributedString *)backText additionalData:(nullable NSDictionary *)additionalData delegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate buttonDelegate:(nullable NSObject<ButtonDelegateProtocol> *)buttonDelegate {
[self setFrontAttributedText:frontAttributedText actionMap:actionMap backAttributedText:backText addNewLine:NO additionalData:additionalData delegate:delegate buttonDelegate:buttonDelegate];
}
- (void)setFrontAttributedText:(nullable NSAttributedString *)frontAttributedText actionMap:(nullable NSDictionary *)actionMap backAttributedText:(nullable NSAttributedString *)backAttributedText addNewLine:(BOOL) addNewLine additionalData:(nullable NSDictionary *)additionalData delegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate buttonDelegate:(nullable NSObject<ButtonDelegateProtocol> *)buttonDelegate {
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init];
if (frontAttributedText) {
[attributedString appendAttributedString:frontAttributedText];
// need to do this to fix the range issue
self.frontText = frontAttributedText.string;
}
NSString *newLineAttributed = [[NSString alloc] initWithString:addNewLine?@"\n":@" "];
if (actionMap.allKeys.count > 0) {
NSMutableString *actionString = [[actionMap stringForKey:KeyTitle] mutableCopy];
if (actionString.length > 0) {
[actionString appendString:newLineAttributed];
NSAttributedString *actionAttributedString = [MFStyler styleGetAttributedString:actionString font:[MFStyler fontB2] color:[UIColor blackColor]];
self.actionText = actionString;
[self setActionMap:actionMap additionalData:additionalData actionDelegate:delegate buttonDelegate:buttonDelegate];
[attributedString appendAttributedString:actionAttributedString];
}
} else {
self.actionText = nil;
self.actionBlock = nil;
}
if (backAttributedText) {
[attributedString appendAttributedString:backAttributedText];
}
self.attributedText = attributedString;
//added this line for underlining
[self setAlternateActionTextAttributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle)}];
}
#pragma mark - legacy
- (nullable instancetype)initWithFrontText:(nullable NSString *)frontText actionText:(nullable NSString *)actionText backText:(nullable NSString *)backText actionBlock:(nullable ActionBlock)block {
if (self = [super init]) {
self.frontText = frontText;
self.actionText = actionText;
self.backText = backText;
self.actionBlock = block;
self.text = [self getTextFromStringComponents];
[self setup];
}
return self;
}
- (nullable instancetype)initWithFrontText:(nullable NSString *)frontText actionText:(nullable NSString *)actionText backText:(nullable NSString *)backText actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate {
return [self initWithFrontText:frontText actionText:actionText backText:backText actionMap:actionMap additionalData:additionalData actionDelegate:delegate buttonDelegate:nil];
}
- (nullable instancetype)initWithActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol> *)delegate {
return [self initWithFrontText:[actionMap stringForKey:KeyTitlePrefix] actionText:[actionMap stringForKey:KeyTitle] backText:[actionMap stringForKey:KeyTitlePostfix] actionMap:actionMap additionalData:additionalData actionDelegate:delegate];
}
- (instancetype)init
{
self = [super init];
if (self) {
[self setup];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self setup];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
- (nullable instancetype)initWithFrontText:(nullable NSString *)frontText backText:(nullable NSString *)backText actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate {
return [self initWithFrontText:frontText actionText:[actionMap stringForKey:KeyTitle] backText:backText actionMap:actionMap additionalData:additionalData actionDelegate:delegate];
}
// Convenience Initializer which assumes that the clickable text will be embedded in curly braces {}.
- (nullable instancetype)initWithClickableTextEmbeddedInCurlyBraces:(nullable NSString *)fullText actionMapForClickableText:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate {
return [self initWithText:fullText startTag:@"{" endTag:@"}" actionMap:actionMap additionalData:additionalData actionDelegate:delegate];
}
- (instancetype)initWithText:(nullable NSString *)fullText startTag:(nullable NSString *)startTag endTag:(nullable NSString *)endTag actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate
{
self = [super init];
if (self) {
[self setText:fullText startTag:startTag endTag:endTag];
__weak typeof(delegate) weakDelegate = delegate;
self.actionBlock = ^{
[[MVMCoreActionHandler sharedActionHandler] handleActionWithDictionary:actionMap additionalData:additionalData delegate:weakDelegate];
};
}
return self;
}
- (void)setup {
if (!self.label) {
MFLabel *label = [[MFLabel alloc] initWithFrame:CGRectZero];
self.backgroundColor = [UIColor clearColor];
label.translatesAutoresizingMaskIntoConstraints = NO;
label.userInteractionEnabled = NO;
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWordWrapping;
[label setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
[self addSubview:label];
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[label]-0-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(label)]];
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[label]-0-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(label)]];
self.label = label;
[label sizeToFit];
}
if (!self.normalTextColor) {
self.normalTextColor = [UIColor blackColor];
}
if (!self.actionTextColor) {
self.actionTextColor = [UIColor blackColor];
}
if (!self.normalTextFont) {
self.normalTextFont = [MFStyler fontB2];
}
if (!self.actionTextFont) {
self.actionTextFont = [MFStyler fontB2];
}
//adding the underline
[self setAlternateActionTextAttributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle)}];
self.label.attributedText = self.attributedText;
[self.label setAccessibilityTraits:UIAccessibilityTraitButton];
}
- (void)updateView:(CGFloat)size {
//reset font for app size change
self.normalTextFont = [MFStyler fontB2];
self.actionTextFont = [MFStyler fontB2];
self.label.attributedText = self.attributedText;
}
#pragma mark - UIControl overide
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
if ([self areTouchesInActionString:touches]) {
[self sendActionsForControlEvents:UIControlEventTouchUpInside];
[self performAction];
} else {
[self sendActionsForControlEvents:UIControlEventTouchUpOutside];
}
}
#pragma mark - helper
- (NSString *)getTextFromStringComponents {
if (self.frontText.length == 0) {
self.frontText = @"";
} else {
self.frontText = [self.frontText stringByAppendingString:[self spaceBetweenPartOne:self.frontText andPartTwo:self.actionText]];
}
if (self.actionText.length == 0) {
self.actionText = @"";
} else {
self.actionText = [self.actionText stringByAppendingString:[self spaceBetweenPartOne:self.actionText andPartTwo:self.backText]];
}
if (self.backText.length == 0) {
self.backText = @"";
}
return [[NSString alloc] initWithFormat:@"%@%@%@",self.frontText, self.actionText, self.backText];
}
- (NSString *)spaceBetweenPartOne:(NSString *)partOne andPartTwo:(NSString *)partTwo {
/*if (!partTwo || partTwo.length == 0 || [MFUtility validateString:partTwo withRegularExpression:@"[.,?!;:]"] || [partOne hasSuffix:@" "]) {
return @"";
}*/
return @" ";
}
- (NSRange)getActionRange {
return NSMakeRange(self.frontText.length, self.actionText.length);
}
- (NSRange)getFrontRange {
return NSMakeRange(0, self.frontText.length);
}
- (NSRange)getBackRange {
return NSMakeRange(self.frontText.length + self.actionText.length, self.backText.length);}
- (void)performAction {
if (self.actionBlock) {
self.actionBlock();
}
}
- (NSArray *)getRangeArrayOfWordsInString:(NSString *)string withInitalIndex:(NSInteger)index {
NSArray *words = [string componentsSeparatedByString:@" "];
NSMutableArray *rangeArray = [[NSMutableArray alloc] init];
for (NSString *subString in words) {
NSString *finalSubString = [subString stringByAppendingString:@" "];
NSInteger wordIndex = index;
NSInteger length = finalSubString.length;
NSRange subStringRange = NSMakeRange(wordIndex, length);
NSValue *rangeValue = [NSValue valueWithRange:subStringRange];
[rangeArray addObject:rangeValue];
index += length;
}
return rangeArray;
}
- (NSArray *)getRectArrayFromRangeArray:(NSArray *)rangeArray {
NSMutableArray *rectArray = [[NSMutableArray alloc] init];
for (NSValue *aValueOfRange in rangeArray) {
NSRange wordRange = [aValueOfRange rangeValue];
CGRect rect = [self.label boundingRectForCharacterRange:wordRange];
NSValue *rectValue = [NSValue valueWithCGRect:rect];
[rectArray addObject:rectValue];
}
return rectArray;
}
- (BOOL)areTouchesInActionString:(NSSet<UITouch *> *)touches {
if (UIAccessibilityIsVoiceOverRunning() || self.makeWholeViewClickable) {
return YES;
}
CGPoint location = [[touches anyObject] locationInView:self.label];
NSString *actionString = self.actionText;
NSInteger index = [self getActionRange].location;
NSArray *rangeArray = [self getRangeArrayOfWordsInString:actionString withInitalIndex:index];
NSArray *rectArray = [self getRectArrayFromRangeArray:rangeArray];
BOOL result = NO;
for (NSValue *aValueOfRect in rectArray) {
CGRect wordRect = [aValueOfRect CGRectValue];
if (CGRectContainsPoint(wordRect, location)){
result = YES;
break;
} else if (wordRect.origin.x == 0 && wordRect.origin.y == 0 && wordRect.size.height == 0 && wordRect.size.width == 0) {
//incase word rect is not found for any reason, make the whole label to be clicable to avoid non functioning link in production.
result = YES;
break;
}
}
return result;
}
#pragma mark - setter
- (void)setText:(NSString *)text {
if (text) {
_text = text;
self.attributedText = [[NSAttributedString alloc] initWithString:text];
//call the setters to properly set the attributes
[self setNormalTextFont:self.normalTextFont];
[self setActionTextFont:self.actionTextFont];
[self setNormalTextColor:self.normalTextColor];
[self setActionTextColor:self.actionTextColor];
}
}
- (void)setCurlyBracedText:(nonnull NSString *)text {
[self setText:text startTag:@"{" endTag:@"}"];
}
- (void)setText:(NSString *)text startTag:(NSString *)startTag endTag:(NSString *)endTag {
NSRange actionRange = [self rangeOfText:&text startTag:startTag endTag:endTag];
self.frontText = [text substringWithRange:NSMakeRange(0,actionRange.location)];
self.actionText = [text substringWithRange:actionRange];
self.backText = [text substringWithRange:NSMakeRange(self.frontText.length+self.actionText.length, text.length - self.frontText.length-self.actionText.length)];
self.text = [self getTextFromStringComponents];
[self setup];
}
- (NSRange)rangeOfCurlyBracedText:(NSString **)text {
return [self rangeOfText:text startTag:@"{" endTag:@"}"];
}
- (NSRange)rangeOfText:(NSString **)text startTag:(NSString *)startTag endTag:(NSString *)endTag {
NSString *fullText = *text;
NSRange range = NSMakeRange(0, 0);
NSRange rangeOfLeftBrace = [fullText rangeOfString:startTag];
if (rangeOfLeftBrace.location != NSNotFound) {
fullText = [fullText stringByReplacingCharactersInRange:rangeOfLeftBrace withString:@""];
NSRange rangeOfRightBrace = [fullText rangeOfString:endTag];
if (rangeOfRightBrace.location != NSNotFound) {
NSInteger length = (rangeOfRightBrace.location - rangeOfLeftBrace.location);
if (length > 0) {
range = NSMakeRange(rangeOfLeftBrace.location, length);
fullText = [fullText stringByReplacingCharactersInRange:rangeOfRightBrace withString:@""];
}
}
}
*text = fullText;
return range;
}
- (void)setNormalTextColor:(UIColor *)normalTextColor {
if (normalTextColor) {
_normalTextColor = normalTextColor;
[self setAlternateNormalTextAttributes:@{NSForegroundColorAttributeName:normalTextColor}];
}
}
- (void)setActionTextColor:(UIColor *)actionTextColor {
if (actionTextColor) {
_actionTextColor = actionTextColor;
[self setAlternateActionTextAttributes:@{NSForegroundColorAttributeName:actionTextColor}];
}
}
- (void)setAttributedText:(NSAttributedString *)attributedText {
_attributedText = attributedText;
NSMutableAttributedString *mutableAttributedText = [attributedText mutableCopy];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = LabelWithInternalButtonLineSpace;
[mutableAttributedText addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, attributedText.length)];
if (self.label && mutableAttributedText) {
self.label.attributedText = mutableAttributedText;
}
}
- (void)setNormalTextFont:(UIFont *)normalTextFont {
if (normalTextFont) {
_normalTextFont = normalTextFont;
[self setAlternateNormalTextAttributes:@{NSFontAttributeName:normalTextFont}];
}
}
- (void)setActionTextFont:(UIFont *)actionTextFont {
if (actionTextFont) {
_actionTextFont = actionTextFont;
[self setAlternateActionTextAttributes:@{NSFontAttributeName:actionTextFont}];
}
}
- (void)setActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject <MVMCoreActionDelegateProtocol> *)delegate {
[self setActionMap:actionMap additionalData:additionalData actionDelegate:delegate buttonDelegate:nil];
}
// Reset the text and action map
- (void)setTextWithClickableTextEmbeddedInCurlyBraces:(nullable NSString *)text textAttributes:(nullable NSDictionary *)attributes actionMapForClickableText:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate {
self.attributedText = [[NSAttributedString alloc] initWithString:text attributes:attributes];
[self setActionMap:actionMap additionalData:additionalData actionDelegate:delegate];
}
- (void)setWithText:(nullable NSString *)fullText startTag:(nullable NSString *)startTag endTag:(nullable NSString *)endTag actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate {
[self setText:fullText startTag:startTag endTag:endTag];
[self setActionMap:actionMap additionalData:additionalData actionDelegate:delegate];
}
- (void)setEnabled:(BOOL)enabled {
[super setEnabled:enabled];
if (enabled) {
self.alpha = 1;
} else {
self.alpha = DisableOppacity;
}
}
- (void)setFrontText:(NSString *)frontText actionMap:(NSDictionary *)actionMap backText:(NSString *)backText additionalData:(NSDictionary *)additionalData delegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate {
[self setFrontText:frontText actionMap:actionMap backText:backText additionalData:additionalData delegate:delegate buttonDelegate:nil];
}
// Reset the front text, back text, action map
- (void)setFrontAttributedText:(nullable NSAttributedString *)frontAttributedText actionMap:(nullable NSDictionary *)actionMap backAttributedText:(nullable NSAttributedString *)backAttributedText additionalData:(nullable NSDictionary *)additionalData delegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate {
[self setFrontAttributedText:frontAttributedText actionMap:actionMap backAttributedText:backAttributedText addNewLine:NO additionalData:additionalData delegate:delegate];
}
- (void)setFrontAttributedText:(nullable NSAttributedString *)frontAttributedText actionMap:(nullable NSDictionary *)actionMap backAttributedText:(nullable NSAttributedString *)backAttributedText addNewLine:(BOOL) addNewLine additionalData:(nullable NSDictionary *)additionalData delegate:(nullable NSObject<MVMCoreActionDelegateProtocol> *)delegate {
[self setFrontAttributedText:frontAttributedText actionMap:actionMap backAttributedText:backAttributedText addNewLine:addNewLine additionalData:additionalData delegate:delegate buttonDelegate:nil];
}
- (void)setAlignment:(NSTextAlignment)textAlignment {
self.label.textAlignment = textAlignment;
}
- (void)setAlternateActionTextAttributes:(nullable NSDictionary *)attributes {
if (attributes) {
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
[attributedString addAttributes:attributes range:[self getActionRange]];
self.attributedText = attributedString;
}
}
- (void)setAlternateNormalTextAttributes:(nullable NSDictionary *)attributes {
if (attributes) {
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
[attributedString addAttributes:attributes range:[self getFrontRange]];
[attributedString addAttributes:attributes range:[self getBackRange]];
self.attributedText = attributedString;
}
}
- (void)setActionTextString:(nullable NSString *)actionText {
self.actionText = actionText;
self.text = [self getTextFromStringComponents];
[self setup];
}
/// Used to just reset the texts and actions if already initialized
- (void)resetWithActionMap:(NSDictionary *)actionMap additionalData:(NSDictionary *)additionalData delegate:(NSObject<MVMCoreActionDelegateProtocol> *)delegate {
self.frontText = [actionMap stringForKey:KeyTitlePrefix];
self.actionText = [actionMap stringForKey:KeyTitle];
self.backText = [actionMap stringForKey:KeyTitlePostfix];
__weak typeof(delegate) weakDelegate = delegate;
self.actionBlock = ^{
[[MVMCoreActionHandler sharedActionHandler] handleActionWithDictionary:actionMap additionalData:additionalData delegate:weakDelegate];
};
self.text = [self getTextFromStringComponents];
[self setup];
}
//#pragma mark - Accessibility
//
//-(BOOL)isAccessibilityElement{
// return YES;
//}
//
//-(UIAccessibilityTraits)accessibilityTraits{
// return UIAccessibilityTraitLink;
//}
- (NSString *)replaceSpaceWithFakeSpace:(NSString *)string {
NSArray *words = [string componentsSeparatedByString:@" "];
return [words componentsJoinedByString:@"\u00a0"];
}
- (BOOL)accessibilityActivate {
if (self.actionBlock) {
self.actionBlock();
return YES;
} else {
return NO;
}
}
- (UIAccessibilityCustomAction *)accessibilityCustomAction {
if (self.actionText.length) {
NSString *name = self.actionText;
return [[UIAccessibilityCustomAction alloc] initWithName:name target:self selector:@selector(accessibilityActivate)];
} else {
return [[UIAccessibilityCustomAction alloc] init];
}
}
@end

View File

@ -0,0 +1,604 @@
//
// LabelWithInternalButton.swift
// MVMCoreUI
//
// Created by Chris Yang on 2/25/16.
// Converted by Christiano, Kevin on 3/22/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import MVMCore
public typealias ActionBlock = () -> Void
private typealias ActionableStringTuple = (front: String?, middle: String?, end: String?)
public typealias ActionObjectDelegate = (NSObjectProtocol & MVMCoreActionDelegateProtocol)
public typealias ButtonObjectDelegate = (NSObjectProtocol & ButtonDelegateProtocol)
public typealias CoreObjectActionLoadPresentDelegate = MVMCoreActionDelegateProtocol & MVMCoreLoadDelegateProtocol & MVMCorePresentationDelegateProtocol & NSObjectProtocol
@objcMembers open class LabelWithInternalButton: UIControl, MVMCoreViewProtocol, MFButtonProtocol {
//------------------------------------------------------
// MARK: - Properties
//------------------------------------------------------
public var actionBlock: ActionBlock?
public weak var label: MFLabel?
public var attributedText: NSAttributedString? {
willSet(newAttributedText) {
if let newAttribText = newAttributedText, !newAttribText.string.isEmpty {
let mutableAttributedText = NSMutableAttributedString(attributedString: newAttribText)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = CGFloat(LabelWithInternalButtonLineSpace)
mutableAttributedText.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: newAttribText.length))
label?.attributedText = mutableAttributedText
}
}
}
// By default, it will follow most of the font standard in zepplin, and should need to be changed
public var normalTextFont: UIFont? = MFStyler.fontB2() {
willSet(newNormalFont) {
setAlternateNormalTextAttributes([NSAttributedString.Key.font: newNormalFont as Any])
}
}
public var actionTextFont: UIFont? = MFStyler.fontB2() {
willSet(newActionFont) {
setAlternateActionTextAttributes([NSAttributedString.Key.font: newActionFont as Any])
}
}
public var normalTextColor: UIColor = .black {
willSet(newNormalColor) {
setAlternateNormalTextAttributes([NSAttributedString.Key.foregroundColor: newNormalColor as Any])
}
}
public var actionTextColor: UIColor = .black {
willSet(newActionColor) {
setAlternateActionTextAttributes([NSAttributedString.Key.foregroundColor: newActionColor as Any])
}
}
public var makeWholeViewClickable = false
override open var isEnabled: Bool {
didSet {
alpha = isEnabled ? 1 : DisableOppacity
}
}
public var frontText: String?
public var actionText: String?
public var backText: String?
private var text: String? {
willSet(newText) {
attributedText = NSAttributedString(string: newText ?? "")
setAlternateNormalTextAttributes([NSAttributedString.Key.font: normalTextFont as Any])
setAlternateActionTextAttributes([NSAttributedString.Key.font: actionTextFont as Any])
setAlternateNormalTextAttributes([NSAttributedString.Key.foregroundColor: normalTextColor as Any])
setAlternateActionTextAttributes([NSAttributedString.Key.foregroundColor: actionTextColor as Any])
}
}
//------------------------------------------------------
// MARK: - Initializaers
//------------------------------------------------------
public init() {
super.init(frame: CGRect.zero)
setup()
}
required public init?(coder: NSCoder) {
super.init(coder: coder)
setup()
}
override public init(frame: CGRect) {
super.init(frame: frame)
setup()
}
public init(frontText: String?, actionText: String?, backText: String?, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, actionDelegate delegate: ActionObjectDelegate?, buttonDelegate: ButtonObjectDelegate?) {
super.init(frame: CGRect.zero)
setFrontText(frontText, actionText: actionText, actionMap: actionMap, backText: backText, additionalData: additionalData, delegate: delegate, buttonDelegate: buttonDelegate)
}
// MARK: - legacy
public init(frontText: String?, actionText: String?, backText: String?, actionBlock block: ActionBlock?) {
super.init(frame: CGRect.zero)
self.frontText = frontText
self.actionText = actionText
self.backText = backText
actionBlock = block
text = getTextFromStringComponents()
setup()
}
public convenience init(actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, actionDelegate delegate: ActionObjectDelegate?, buttonDelegate: ButtonObjectDelegate?) {
self.init(frontText: actionMap?.optionalStringForKey(KeyTitlePrefix), actionText: actionMap?.optionalStringForKey(KeyTitle), backText: actionMap?.optionalStringForKey(KeyTitlePostfix), actionMap: actionMap, additionalData: additionalData, actionDelegate: delegate, buttonDelegate: buttonDelegate)
}
public convenience init(frontText: String?, backText: String?, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, actionDelegate delegate: ActionObjectDelegate?, buttonDelegate: ButtonObjectDelegate?) {
self.init(frontText: frontText, actionText: actionMap?.optionalStringForKey(KeyTitle), backText: backText, actionMap: actionMap, additionalData: additionalData, actionDelegate: delegate, buttonDelegate: buttonDelegate)
}
public convenience init(frontText: String?, actionText: String?, backText: String?, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, actionDelegate delegate: ActionObjectDelegate?) {
self.init(frontText: frontText, actionText: actionText, backText: backText, actionMap: actionMap, additionalData: additionalData, actionDelegate: delegate, buttonDelegate: nil)
}
public convenience init(actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, actionDelegate delegate: ActionObjectDelegate?) {
self.init(frontText: actionMap?.optionalStringForKey(KeyTitlePrefix), actionText: actionMap?.optionalStringForKey(KeyTitle), backText: actionMap?.optionalStringForKey(KeyTitlePostfix), actionMap: actionMap, additionalData: additionalData, actionDelegate: delegate)
}
public convenience init(frontText: String?, backText: String?, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, actionDelegate delegate: ActionObjectDelegate?) {
self.init(frontText: frontText, actionText: actionMap?.optionalStringForKey(KeyTitle), backText: backText, actionMap: actionMap, additionalData: additionalData, actionDelegate: delegate)
}
// Convenience Initializer which assumes that the clickable text will be embedded in curly braces {}.
public convenience init(clickableTextEmbeddedInCurlyBraces fullText: String?, actionMapForClickableText actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, actionDelegate delegate: ActionObjectDelegate?) {
self.init(text: fullText, startTag: "{", endTag: "}", actionMap: actionMap, additionalData: additionalData, actionDelegate: delegate)
}
public init(text fullText: String?, startTag: String?, endTag: String?, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, actionDelegate delegate: ActionObjectDelegate?) {
super.init(frame: CGRect.zero)
setText(fullText, startTag: startTag, endTag: endTag)
weak var weakDelegate: ActionObjectDelegate? = delegate
actionBlock = {
MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegate: weakDelegate as? CoreObjectActionLoadPresentDelegate)
}
}
//------------------------------------------------------
// MARK: - Configuration
//------------------------------------------------------
private func setup() {
if self.label == nil {
let label = MFLabel(frame: CGRect.zero)
backgroundColor = .clear
label.isUserInteractionEnabled = false
label.setContentCompressionResistancePriority(.required, for: .vertical)
addSubview(label)
NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[label]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["label": label]))
NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[label]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["label": label]))
self.label = label
label.sizeToFit()
}
// Adding the underline
setAlternateActionTextAttributes([NSAttributedString.Key.underlineStyle: NSNumber(value: NSUnderlineStyle.single.rawValue)])
self.label?.attributedText = attributedText
self.label?.accessibilityTraits = .button
}
private func
setActionMap(_ actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, actionDelegate delegate: ActionObjectDelegate?, buttonDelegate: ButtonObjectDelegate?) {
weak var weakSelf: LabelWithInternalButton? = self
weak var weakDelegate: ActionObjectDelegate? = delegate
weak var weakButtonDelegate: ButtonObjectDelegate? = buttonDelegate
actionBlock = {
var performAction = true
if let wSelf = weakSelf, let wButtonDelegate = weakButtonDelegate, wButtonDelegate.responds(to: #selector(ButtonObjectDelegate.button(_:shouldPerformActionWithMap:additionalData:))) {
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)
}
}
}
//------------------------------------------------------
// MARK: - Methods
//------------------------------------------------------
@objc public func setFrontText(_ frontText: String?, actionMap: [AnyHashable: Any]?, backText: String?, additionalData: [AnyHashable: Any]?, delegate: ActionObjectDelegate?, buttonDelegate: ButtonObjectDelegate?) {
setFrontText(frontText, actionText: actionMap?.optionalStringForKey(KeyTitle), actionMap: actionMap, backText: backText, additionalData: additionalData, delegate: delegate, buttonDelegate: buttonDelegate)
}
@objc public func setFrontText(_ frontText: String?, actionText: String?, actionMap: [AnyHashable: Any]?, backText: String?, additionalData: [AnyHashable: Any]?, delegate: ActionObjectDelegate?, buttonDelegate: ButtonObjectDelegate?) {
self.frontText = frontText
setActionMap(actionMap, additionalData: additionalData, actionDelegate: delegate, buttonDelegate: buttonDelegate)
self.actionText = actionText
self.backText = backText
text = getTextFromStringComponents()
setup()
}
@objc public func setFrontAttributedText(_ frontAttributedText: NSAttributedString?, actionMap: [AnyHashable: Any]?, backAttributedText backText: NSAttributedString?, additionalData: [AnyHashable: Any]?, delegate: ActionObjectDelegate?, buttonDelegate: ButtonObjectDelegate?) {
setFrontAttributedText(frontAttributedText, actionMap: actionMap, backAttributedText: backText, addNewLine: false, additionalData: additionalData, delegate: delegate, buttonDelegate: buttonDelegate)
}
private func setFrontAttributedText(_ frontAttributedText: NSAttributedString?, actionMap: [AnyHashable: Any]?, backAttributedText: NSAttributedString?, addNewLine: Bool, additionalData: [AnyHashable: Any]?, delegate: ActionObjectDelegate?, buttonDelegate: ButtonObjectDelegate?) {
let mutableAttributedString = NSMutableAttributedString()
if let frontAttributedText = frontAttributedText {
mutableAttributedString.append(frontAttributedText)
// Need to do this to fix the range issue
frontText = frontAttributedText.string
}
if let b2Font = MFStyler.fontB2(),
let actions = actionMap,
actions.keys.count > 0,
let actionString = actions.optionalStringForKey(KeyTitle),
!actionString.isEmpty {
let actionStringOnLine = actionString + (addNewLine ? "\n" : " ")
actionText = actionStringOnLine
setActionMap(actionMap, additionalData: additionalData, actionDelegate: delegate, buttonDelegate: buttonDelegate)
mutableAttributedString.append(MFStyler.styleGetAttributedString(actionStringOnLine, font: b2Font, color: .black))
} else {
actionText = nil
actionBlock = nil
}
if let backAttributedText = backAttributedText {
mutableAttributedString.append(backAttributedText)
}
attributedText = mutableAttributedString
// Added this line for underlining
setAlternateActionTextAttributes([NSAttributedString.Key.underlineStyle: NSNumber(value: NSUnderlineStyle.single.rawValue)])
}
@objc public func updateView(_ size: CGFloat) {
// Reset font for app size change
normalTextFont = MFStyler.fontB2()
actionTextFont = MFStyler.fontB2()
label?.attributedText = attributedText
}
//------------------------------------------------------
// MARK: - UIControl Override
//------------------------------------------------------
override open func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if areTouches(inActionString: touches) {
sendActions(for: .touchUpInside)
if let action = actionBlock {
action()
}
} else {
sendActions(for: .touchUpOutside)
}
}
private func areTouches(inActionString touches: Set<UITouch>?) -> Bool {
if UIAccessibility.isVoiceOverRunning || makeWholeViewClickable {
return true
}
let location: CGPoint? = touches?.first?.location(in: label)
let actionString = actionText
let index: Int = getActionRange().location
let rangeArray = getRangeArrayOfWords(in: actionString, withInitalIndex: index)
let rectArray = getRectArray(fromRangeArray: rangeArray)
var result = false
for aValueOfRect in rectArray as? [NSValue] ?? [] {
let wordRect: CGRect = aValueOfRect.cgRectValue
if let position = location, wordRect.contains(position) {
result = true
break
} else if wordRect.origin.x == 0 && wordRect.origin.y == 0 && wordRect.size.height == 0 && wordRect.size.width == 0 {
// Incase word rect is not found for any reason, make the whole label to be clicable to avoid non functioning link in production.
result = true
break
}
}
return result
}
//------------------------------------------------------
// MARK: - Helper
//------------------------------------------------------
private func getTextFromStringComponents() -> String {
if let frontTxt = frontText, !frontTxt.isEmpty {
frontText?.append(" ")
}
if let actionTxt = actionText, !actionTxt.isEmpty, let backTxt = backText, !backTxt.isEmpty {
actionText?.append(" ")
}
return "\(frontText ?? "")\(actionText ?? "")\(backText ?? "")"
}
private func getActionRange() -> NSRange {
return NSRange(location: frontText?.count ?? 0, length: actionText?.count ?? 0)
}
private func getRangeArrayOfWords(in string: String?, withInitalIndex index: Int) -> [Any]? {
var index = index
let words = string?.components(separatedBy: " ")
var rangeArray = [AnyHashable]()
for subString in words ?? [] {
let finalSubString = subString + " "
let wordIndex: Int = index
let length: Int = finalSubString.count
let subStringRange = NSRange(location: wordIndex, length: length)
let rangeValue = NSValue(range: subStringRange)
rangeArray.append(rangeValue)
index += length
}
return rangeArray
}
private func getRectArray(fromRangeArray rangeArray: [Any]?) -> [Any]? {
var rectArray = [AnyHashable]()
for aValueOfRange in rangeArray as? [NSValue] ?? [] {
let wordRange: NSRange = aValueOfRange.rangeValue
if let rect: CGRect = label?.boundingRect(forCharacterRange: wordRange) {
let rectValue = NSValue(cgRect: rect)
rectArray.append(rectValue)
}
}
return rectArray
}
@objc public func setCurlyBracedText(_ text: String) {
setText(text, startTag: "{", endTag: "}")
}
private func setText(_ text: String?, startTag: String?, endTag: String?) {
let actionableTuple: ActionableStringTuple = rangeOfText(text, startTag: startTag, endTag: endTag)
if let front = actionableTuple.front, let middle = actionableTuple.middle, let end = actionableTuple.end {
frontText = front.trimmingCharacters(in: .whitespaces)
actionText = middle.trimmingCharacters(in: .whitespaces)
backText = end.trimmingCharacters(in: .whitespaces)
self.text = getTextFromStringComponents()
} else {
frontText = text
self.text = text
}
setup()
}
private func rangeOfText(_ text: String?, startTag: String?, endTag: String?) -> ActionableStringTuple {
var actionableTuple: ActionableStringTuple = (front: nil, middle: nil, end: nil)
guard let text = text else { return actionableTuple }
if let leftTag = startTag, text.contains(leftTag) {
let firstHalf = text.components(separatedBy: leftTag)
actionableTuple.front = firstHalf.first
if let rightTag = endTag, text.contains(rightTag) {
let secondHalf = firstHalf[1].components(separatedBy: rightTag)
actionableTuple.middle = secondHalf[0]
actionableTuple.end = secondHalf[1]
}
}
return actionableTuple
}
@objc public func setActionMap(_ actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, actionDelegate delegate: ActionObjectDelegate?) {
setActionMap(actionMap, additionalData: additionalData, actionDelegate: delegate, buttonDelegate: nil)
}
// Reset the text and action map
@objc public func setTextWithClickableTextEmbeddedInCurlyBraces(_ text: String?, textAttributes attributes: [AnyHashable: Any]?, actionMapForClickableText actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, actionDelegate delegate: ActionObjectDelegate?) {
attributedText = NSAttributedString(string: text ?? "", attributes: attributes as? [NSAttributedString.Key: Any])
setActionMap(actionMap, additionalData: additionalData, actionDelegate: delegate)
}
@objc public func setWithText(_ fullText: String?, startTag: String?, endTag: String?, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, actionDelegate delegate: ActionObjectDelegate?) {
setText(fullText, startTag: startTag, endTag: endTag)
setActionMap(actionMap, additionalData: additionalData, actionDelegate: delegate)
}
@objc public func setFrontText(_ frontText: String?, actionMap: [AnyHashable: Any]?, backText: String?, additionalData: [AnyHashable: Any]?, delegate: ActionObjectDelegate?) {
setFrontText(frontText, actionMap: actionMap, backText: backText, additionalData: additionalData, delegate: delegate, buttonDelegate: nil)
}
// Reset the front text, back text, action map
@objc public func setFrontAttributedText(_ frontAttributedText: NSAttributedString?, actionMap: [AnyHashable: Any]?, backAttributedText: NSAttributedString?, additionalData: [AnyHashable: Any]?, delegate: ActionObjectDelegate?) {
setFrontAttributedText(frontAttributedText, actionMap: actionMap, backAttributedText: backAttributedText, addNewLine: false, additionalData: additionalData, delegate: delegate)
}
@objc public func setFrontAttributedText(_ frontAttributedText: NSAttributedString?, actionMap: [AnyHashable: Any]?, backAttributedText: NSAttributedString?, addNewLine: Bool, additionalData: [AnyHashable: Any]?, delegate: ActionObjectDelegate?) {
setFrontAttributedText(frontAttributedText, actionMap: actionMap, backAttributedText: backAttributedText, addNewLine: addNewLine, additionalData: additionalData, delegate: delegate, buttonDelegate: nil)
}
@objc public func setAlignment(_ textAlignment: NSTextAlignment) {
label?.textAlignment = textAlignment
}
@objc public func setAlternateActionTextAttributes(_ attributes: [AnyHashable: Any]?) {
guard let theseAttributes = attributes as? [NSAttributedString.Key: Any], let thisAttributedText = attributedText else { return }
let attributedString = NSMutableAttributedString(attributedString: thisAttributedText)
if !attributedString.string.isEmpty {
attributedString.addAttributes(theseAttributes, range: getActionRange())
}
attributedText = attributedString
}
public func setAlternateNormalTextAttributes(_ attributes: [AnyHashable: Any]?) {
guard let _attributedText = attributedText, let _attributes = attributes as? [NSAttributedString.Key: Any] else { return }
let attributedString = NSMutableAttributedString(attributedString: _attributedText)
if !attributedString.string.isEmpty {
attributedString.addAttributes(_attributes, range: getFrontRange())
attributedString.addAttributes(_attributes, range: getBackRange())
}
attributedText = attributedString
}
private func getFrontRange() -> NSRange {
return NSRange(location: 0, length: frontText?.count ?? 0)
}
private func getBackRange() -> NSRange {
let textLocation: Int = (frontText?.count ?? 0) + (actionText?.count ?? 0)
let rangeLength: Int = backText?.count ?? 0
return NSRange(location: textLocation, length: rangeLength)
}
@objc public func setActionTextString(_ actionText: String?) {
self.actionText = actionText
text = getTextFromStringComponents()
setup()
}
/// Used to just reset the texts and actions if already initialized
@objc public func reset(withActionMap actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegate: ActionObjectDelegate?) {
frontText = actionMap?.optionalStringForKey(KeyTitlePrefix)
actionText = actionMap?.optionalStringForKey(KeyTitle)
backText = actionMap?.optionalStringForKey(KeyTitlePostfix)
weak var weakDelegate: ActionObjectDelegate? = delegate
actionBlock = {
MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegate: weakDelegate as? CoreObjectActionLoadPresentDelegate)
}
text = getTextFromStringComponents()
setup()
}
//------------------------------------------------------
// MARK: - Accessibility
//------------------------------------------------------
// Not Used
@objc public func replaceSpace(withFakeSpace string: String?) -> String? {
return string?.components(separatedBy: " ").joined(separator: "\u{00a0}")
}
@objc override open func accessibilityActivate() -> Bool {
if let action = actionBlock {
action()
return true
}
return false
}
@objc public func accessibilityCustomAction() -> UIAccessibilityCustomAction? {
if let actionTxt = actionText, !actionTxt.isEmpty {
return UIAccessibilityCustomAction(name: actionTxt, target: self, selector: #selector(LabelWithInternalButton.accessibilityCustomActions))
}
return UIAccessibilityCustomAction()
}
}
extension LabelWithInternalButton: MVMCoreUIMoleculeViewProtocol {
//------------------------------------------------------
// MARK: - Atomization
//------------------------------------------------------
// Default values for view.
@objc open func setAsMolecule() {
}
@objc open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
// Configure class properties with JSON values
guard let dictionary = json else { return }
if let backgroundColorHex = dictionary[KeyBackgroundColor] as? String {
self.backgroundColor = UIColor.mfGet(forHex: backgroundColorHex)
}
if let normalTextFont = dictionary["normalTextFont"] as? String, let normalSize = dictionary["normalSize"] as? CGFloat {
self.normalTextFont = UIFont(name: normalTextFont, size: normalSize)
}
if let actionTextFont = dictionary["actionTextFont"] as? String, let actionSize = dictionary["actionSize"] as? CGFloat {
self.actionTextFont = UIFont(name: actionTextFont, size: actionSize)
}
if let normalTextColorHex = dictionary["normalTextColor"] as? String {
self.normalTextColor = UIColor.mfGet(forHex: normalTextColorHex)
}
if let actionTextColorHex = dictionary["actionTextColor"] as? String {
self.actionTextColor = UIColor.mfGet(forHex: actionTextColorHex)
}
if let makeWholeViewClickable = dictionary["makeWholeViewClickable"] as? Bool {
self.makeWholeViewClickable = makeWholeViewClickable
}
if let frontText = dictionary["frontText"] as? String {
self.frontText = frontText
}
if let backText = dictionary["backText"] as? String {
self.backText = backText
}
if let actionText = dictionary["actionText"] as? String {
self.actionText = actionText
}
// Want this to be last because it has a willSet feature.
if let text = dictionary["text"] as? String {
self.text = text
}
}
}

View File

@ -9,6 +9,7 @@
#import <UIKit/UIKit.h>
#import <MVMCoreUI/MFView.h>
@class MFSizeObject;
@class DelegateObject;
@interface MFLabel : UILabel <MVMCoreViewProtocol, MVMCoreUIMoleculeViewProtocol>
@ -49,7 +50,7 @@
// Setters
+ (void)setLabel:(nullable UILabel *)label withHTML:(nullable NSString *)html;
+ (void)setUILabel:(nullable UILabel *)label withJSON:(nullable NSDictionary *)json delegate:(nullable NSObject *)delegate additionalData:(nullable NSDictionary *)additionalData;
+ (void)setUILabel:(nullable UILabel *)label withJSON:(nullable NSDictionary *)json delegateObject:(nullable DelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData;
- (void)styleH1:(BOOL)scale;
- (void)styleH2:(BOOL)scale;

View File

@ -170,7 +170,7 @@
}
}
+ (void)setUILabel:(nullable UILabel *)label withJSON:(nullable NSDictionary *)json delegate:(nullable NSObject *)delegate additionalData:(nullable NSDictionary *)additionalData {
+ (void)setUILabel:(nullable UILabel *)label withJSON:(nullable NSDictionary *)json delegateObject:(DelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData {
if (label) {
label.text = [json string:KeyText];
[self setLabel:label withHTML:[json string:@"html"]];
@ -232,8 +232,8 @@
}
}
- (void)setWithJSON:(NSDictionary *)json delegate:(NSObject *)delegate additionalData:(NSDictionary *)additionalData {
[MFLabel setUILabel:self withJSON:json delegate:delegate additionalData:additionalData];
- (void)setWithJSON:(NSDictionary *)json delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData {
[MFLabel setUILabel:self withJSON:json delegateObject:delegateObject additionalData:additionalData];
self.originalAttributedString = self.attributedText;
}

View File

@ -203,8 +203,8 @@ import UIKit
}
// MARK: - MVMCoreUIMoleculeViewProtocol functions
open override func setWithJSON(_ json: [AnyHashable : Any]?, delegate: NSObject?, additionalData: [AnyHashable : Any]?) {
super.setWithJSON(json, delegate: delegate, additionalData: additionalData)
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
if let backgroundColorString = json?.optionalStringForKey(KeyBackgroundColor) {
backgroundColor = UIColor.mfGet(forHex: backgroundColorString)
}

View File

@ -7,6 +7,7 @@
//
#import "MFView.h"
@import MVMCore.Swift;
@implementation MFView
@ -43,7 +44,7 @@
#pragma mark - MVMCoreUIMoleculeViewProtocol
- (void)setWithJSON:(NSDictionary *)json delegate:(NSObject *)delegate additionalData:(nullable NSDictionary *)additionalData {
- (void)setWithJSON:(NSDictionary *)json delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData {
self.json = json;
}

View File

@ -95,8 +95,8 @@
}
}
- (void)setWithJSON:(NSDictionary *)json delegate:(NSObject *)delegate additionalData:(NSDictionary *)additionalData {
[super setWithJSON:json delegate:delegate additionalData:additionalData];
- (void)setWithJSON:(NSDictionary *)json delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData {
[super setWithJSON:json delegateObject:delegateObject additionalData:additionalData];
if (json) {
self.hidden = NO;
NSString *type = [json string:KeyType];

View File

@ -140,7 +140,6 @@
#pragma mark - MVMCoreUIMoleculeViewProtocol
- (void)setAsMolecule {
self.updateViewHorizontalDefaults = YES;
}
@end

View File

@ -31,6 +31,7 @@
@class MainMenuViewController;
@class MVMCoreUITabBarPageControlViewController;
@class MVMAnimationManager;
@class DelegateObject;
@interface MFViewController : UIViewController <MVMCoreLoadDelegateProtocol, MVMCorePresentationDelegateProtocol, MVMCoreActionDelegateProtocol, UITextFieldDelegate, UITextViewDelegate, MFTextFieldDelegate, ButtonDelegateProtocol, MVMCoreViewControllerProtocol, MVMCoreViewManagerViewControllerProtocol, MVMCoreUIDetailViewProtocol>

View File

@ -138,7 +138,7 @@
// Creates an initial load object if needed.
if (!self.loadObject) {
self.loadObject = [[MVMCoreLoadObject alloc] initWithDelegate:self];
self.loadObject = [[MVMCoreLoadObject alloc] initWithDelegateObject:[self delegateObject]];
}
// Avoid the setter so we are only setting the bool and wait for view will appear to update the navigation bar.
@ -180,6 +180,10 @@
return YES;
}
- (nullable DelegateObject *)delegateObject {
return [MVMCoreUIDelegateObject createWithDelegateForAll:self];
}
#pragma mark - Response Handling
- (void)observeForResponseJSONUpdates {
@ -339,7 +343,7 @@
if (rightPanelLinkDict) {
[[MVMCoreActionHandler sharedActionHandler] handleActionWithDictionary:rightPanelLinkDict
additionalData:nil
delegate:self];
delegateObject:[self delegateObject]];
return YES;
} else {
return NO;
@ -603,7 +607,7 @@
[self.formValidator addFormParamsWithRequestParameters:requestParameters];
requestParameters.parentPageType = [self.loadObject.pageJSON stringForKey:@"parentPageType"];
[[MVMCoreLoadHandler sharedGlobal] loadRequest:requestParameters dataForPage:additionalData delegate:self];
[[MVMCoreLoadHandler sharedGlobal] loadRequest:requestParameters dataForPage:additionalData delegateObject:[self delegateObject]];
}
- (void)handleBackAction:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData {
@ -658,7 +662,7 @@
- (void)handleUnknownActionType:(nullable NSString *)actionType actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData {
[MVMCoreActionHandler defaultHandleUnknownActionType:actionType actionInformation:actionInformation additionalData:additionalData delegate:self];
[MVMCoreActionHandler defaultHandleUnknownActionType:actionType actionInformation:actionInformation additionalData:additionalData delegateObject:[self delegateObject]];
}
- (void)handleActionError:(nonnull MVMCoreErrorObject *)error additionalData:(nullable NSDictionary *)additionalData {
@ -685,7 +689,7 @@
}
- (nullable MVMCoreAlertObject *)alertObjectToShow:(nonnull MVMCoreLoadObject *)loadObject error:(nullable MVMCoreErrorObject *)errorObject {
return [MVMCoreAlertObject alertObjectForLoadObject:loadObject error:errorObject actionDelegate:self];
return [MVMCoreAlertObject alertObjectForLoadObject:loadObject error:errorObject delegateObject:[self delegateObject]];
}
- (void)handleFieldErrors:(nullable NSArray *)fieldErrors loadObject:(nonnull MVMCoreLoadObject *)loadObject {

View File

@ -29,13 +29,15 @@
// Returns the standard space around ui objects.
+ (UIEdgeInsets)standardSpaceAroundUIObjectForSize:(CGFloat)size;
// Consolidates generateFormViewWithUIArray and spaceArroundUIObject into one class object so other view controllers can take advantage of these functions.
// Consolidates generateFormViewWithUIArray and spaceArroundUIObject into one class object so other view controllers can take advantage of these functions. By default does not pin to margins.
+ (void)populateView:(nonnull UIView *)view withUIArray:(nonnull NSArray <UIView *>*)formUIArray withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock;
+ (void)populateView:(nonnull UIView *)view withUIArray:(nonnull NSArray <UIView *>*)formUIArray useMargins:(BOOL)useMargins withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock;
+ (void)populateViewHorizontally:(nonnull UIView *)view withUIArray:(nonnull NSArray <UIView *>*)formUIArray withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock;
+ (void)populateView:(nonnull UIView *)view withUIArrayForConstrainingViews:(nonnull NSArray <UIView *>*)formUIArray withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock;
// Does the actual laying out. The formuiarray views should already be added to the view.
// Does the actual laying out. The formuiarray views should already be added to the view. By default does not pin to margins
+ (void)autoLayoutView:(nonnull UIView *)view withUIArray:(nonnull NSArray <UIView *>*)formUIArray withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock;
+ (void)autoLayoutView:(nonnull UIView *)view withUIArray:(nonnull NSArray <UIView *>*)formUIArray useMargins:(BOOL)useMargins withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock;
+ (void)autoLayoutViewHorizontally:(nonnull UIView *)view withUIArray:(nonnull NSArray <UIView *>*)formUIArray withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock;
+ (void)autoLayoutViewWithConstrainingViewsWithUIArray:(nonnull NSArray <UIView *>*)formUIArray withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock;

View File

@ -10,6 +10,7 @@
#import "MFStyler.h"
#import "ViewConstrainingView.h"
#import "MVMCoreUIUtility.h"
#import "NSLayoutConstraint+MFConvenience.h"
@interface MVMCoreUIStackableViewController ()
@end
@ -69,11 +70,15 @@
}
+ (void)populateView:(nonnull UIView *)view withUIArray:(nonnull NSArray <UIView *>*)formUIArray withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock {
[self populateView:view withUIArray:formUIArray useMargins:NO withSpacingBlock:spacingBlock];
}
+ (void)populateView:(nonnull UIView *)view withUIArray:(nonnull NSArray <UIView *>*)formUIArray useMargins:(BOOL)useMargins withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock {
if ([formUIArray count] > 0) {
for (UIView *subview in formUIArray) {
[view addSubview:subview];
}
[MVMCoreUIStackableViewController autoLayoutView:view withUIArray:formUIArray withSpacingBlock:spacingBlock];
[MVMCoreUIStackableViewController autoLayoutView:view withUIArray:formUIArray useMargins:useMargins withSpacingBlock:spacingBlock];
}
}
@ -96,34 +101,46 @@
}
}
+ (void)autoLayoutView:(nonnull UIView *)view withUIArray:(nonnull NSArray <UIView *>*)formUIArray withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock {
+ (void)autoLayoutView:(nonnull UIView *)view withUIArray:(nonnull NSArray <UIView *>*)formUIArray useMargins:(BOOL)useMargins withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock {
if ([formUIArray count] > 0) {
// Adds the first object to the view and pins it to the top of the content view.
id previousUIObject = [formUIArray objectAtIndex:0];
UIEdgeInsets spaceAroundObjectPrevious = spacingBlock(previousUIObject);
UIView *previousUIObject = [formUIArray objectAtIndex:0];
[previousUIObject setTranslatesAutoresizingMaskIntoConstraints:NO];
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-top@999-[previousUIObject]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"top":@(spaceAroundObjectPrevious.top)} views:NSDictionaryOfVariableBindings(previousUIObject)]];
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-left@999-[previousUIObject]-right-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"left":@(spaceAroundObjectPrevious.left),@"right":@(spaceAroundObjectPrevious.right)} views:NSDictionaryOfVariableBindings(previousUIObject)]];
UIEdgeInsets spaceAroundObjectPrevious = spacingBlock(previousUIObject);
NSLayoutConstraint *constraint = [NSLayoutConstraint pinViewTopToSuperview:previousUIObject useMargins:useMargins constant:spaceAroundObjectPrevious.top];
constraint.priority = 999;
constraint.active = YES;
constraint = [NSLayoutConstraint pinViewLeftToSuperview:previousUIObject useMargins:useMargins constant:spaceAroundObjectPrevious.left];
constraint.priority = 999;
constraint.active = YES;
[NSLayoutConstraint pinViewRightToSuperview:previousUIObject useMargins:useMargins constant:spaceAroundObjectPrevious.right].active = YES;
// Sets the horizontal spacing and adds vertical spacing between all ui objects.
for (NSUInteger i = 1; i < [formUIArray count]; i++) {
id uiObject = [formUIArray objectAtIndex:i];
UIView *uiObject = [formUIArray objectAtIndex:i];
UIEdgeInsets spaceAroundObjectCurrent = spacingBlock(uiObject);
[uiObject setTranslatesAutoresizingMaskIntoConstraints:NO];
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[previousUIObject]-space-[uiObject]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"space":@(spaceAroundObjectPrevious.bottom + spaceAroundObjectCurrent.top)} views:NSDictionaryOfVariableBindings(previousUIObject,uiObject)]];
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-left@999-[uiObject]-right-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"left":@(spaceAroundObjectCurrent.left),@"right":@(spaceAroundObjectCurrent.right)} views:NSDictionaryOfVariableBindings(uiObject)]];
constraint = [NSLayoutConstraint pinViewLeftToSuperview:uiObject useMargins:useMargins constant:spaceAroundObjectCurrent.left];
constraint.priority = 999;
constraint.active = YES;
[NSLayoutConstraint pinViewRightToSuperview:uiObject useMargins:useMargins constant:spaceAroundObjectCurrent.right].active = YES;
previousUIObject = uiObject;
spaceAroundObjectPrevious = spaceAroundObjectCurrent;
}
// Pins the last object to the bottom of the content view.
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[previousUIObject]-bottom-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"bottom":@(spaceAroundObjectPrevious.bottom)} views:NSDictionaryOfVariableBindings(previousUIObject)]];
[NSLayoutConstraint pinViewBottomToSuperview:previousUIObject useMargins:useMargins constant:spaceAroundObjectPrevious.bottom].active = YES;
}
}
+ (void)autoLayoutView:(nonnull UIView *)view withUIArray:(nonnull NSArray <UIView *>*)formUIArray withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock {
[self autoLayoutView:view withUIArray:formUIArray useMargins:NO withSpacingBlock:spacingBlock];
}
+ (void)autoLayoutViewHorizontally:(nonnull UIView *)view withUIArray:(nonnull NSArray <UIView *>*)formUIArray withSpacingBlock:(nonnull UIEdgeInsets (^) (id _Nullable object))spacingBlock {
if ([formUIArray count] > 0) {

View File

@ -16,6 +16,7 @@ open class ThreeLayerViewController: ProgrammaticScrollViewController {
var topView: UIView?
var middleView: UIView?
var bottomView: UIView?
var useMargins: Bool = true
// The bottom view can be put outside of the scrolling area.
var bottomViewOutsideOfScroll = false
@ -26,6 +27,7 @@ open class ThreeLayerViewController: ProgrammaticScrollViewController {
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)
}
@ -116,9 +118,9 @@ extension ThreeLayerViewController {
return nil
}
contentView.addSubview(topView)
topView.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true
contentView.rightAnchor.constraint(equalTo: topView.rightAnchor).isActive = true
topView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
NSLayoutConstraint.pinViewTop(toSuperview: topView, useMargins: useMargins, constant: 0).isActive = true
NSLayoutConstraint.pinViewLeft(toSuperview: topView, useMargins: useMargins, constant: 0).isActive = true
NSLayoutConstraint.pinViewRight(toSuperview: topView, useMargins: useMargins, constant: 0).isActive = true
return topView
}
@ -133,8 +135,8 @@ extension ThreeLayerViewController {
return nil
}
contentView.addSubview(middleView)
middleView.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true
contentView.rightAnchor.constraint(equalTo: middleView.rightAnchor).isActive = true
NSLayoutConstraint.pinViewLeft(toSuperview: middleView, useMargins: useMargins, constant: 0).isActive = true
NSLayoutConstraint.pinViewRight(toSuperview: middleView, useMargins: useMargins, constant: 0).isActive = true
middleView.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical)
return middleView
}
@ -220,17 +222,17 @@ extension ThreeLayerViewController {
return
}
contentView.addSubview(view);
contentView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
contentView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
view.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true
NSLayoutConstraint.pinViewLeft(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true
NSLayoutConstraint.pinViewRight(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true
NSLayoutConstraint.pinViewBottom(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true
}
func addViewOutsideOfScrollViewBottom(_ view: UIView) {
self.view?.addSubview(view)
if let scrollView = scrollView, let parentView = self.view {
view.topAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
view.leftAnchor.constraint(equalTo: parentView.leftAnchor).isActive = true
parentView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
NSLayoutConstraint.pinViewLeft(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true
NSLayoutConstraint.pinViewRight(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true
if #available(iOS 11.0, *) {
parentView.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
if let safeAreaView = MVMCoreUICommonViewsUtility.getAndSetupSafeAreaView(on: parentView) {
@ -238,7 +240,7 @@ extension ThreeLayerViewController {
self.safeAreaView = safeAreaView
}
} else {
parentView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
NSLayoutConstraint.pinViewBottom(toSuperview: view, useMargins: useMargins, constant: 0).isActive = true
}
}
}

View File

@ -55,6 +55,13 @@ extern NSString * _Nonnull const ConstraintWidth;
+(nullable NSDictionary *)constraintAlignView :(nonnull UIView *)firstView toSecondView :(nonnull UIView *)secondView alignX :(BOOL)alignX alignY :(BOOL)alignY;
#pragma mark - With Margins
+ (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;
+ (nonnull NSLayoutConstraint *)pinViewBottomToSuperview:(nonnull UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant;
#pragma mark - Scaling constraints
// These functions will pin a view to its super view with space that is a ratio of the anchor (by default the super view's width if nothing is passed in). (So if the space is 24 and the super's width is 320 in the design, then the ratio should be 24/320 and this will be multiplied by the super's current width, so that the constraint always linearly scales).

View File

@ -150,6 +150,24 @@ NSString *const ConstraintWidth = @"width";
return constraintsDictionary;
}
#pragma mark - With Margins
+ (NSLayoutConstraint *)pinViewTopToSuperview:(UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant {
return [view.topAnchor constraintEqualToAnchor:(useMargins ? view.superview.layoutMarginsGuide.topAnchor : view.superview.topAnchor) constant:constant];
}
+ (NSLayoutConstraint *)pinViewLeftToSuperview:(UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant {
return [view.leftAnchor constraintEqualToAnchor:(useMargins ? view.superview.layoutMarginsGuide.leftAnchor : view.superview.leftAnchor) constant:constant];
}
+ (NSLayoutConstraint *)pinViewRightToSuperview:(UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant {
return [(useMargins ? view.superview.layoutMarginsGuide.rightAnchor : view.superview.rightAnchor) constraintEqualToAnchor:view.rightAnchor constant:constant];
}
+ (NSLayoutConstraint *)pinViewBottomToSuperview:(UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant {
return [(useMargins ? view.superview.layoutMarginsGuide.bottomAnchor : view.superview.bottomAnchor) constraintEqualToAnchor:view.bottomAnchor constant:constant];
}
#pragma mark - Scaling constraints
+ (nullable NSDictionary *)scalingConstraintPinSubview:(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 baseConstant:(CGFloat)baseConstant {

View File

@ -394,7 +394,7 @@
if (customAdditionalData) {
[additionalData addEntriesFromDictionary:customAdditionalData];
}
[[MVMCoreActionHandler sharedActionHandler] handleActionWithDictionary:actionMap additionalData:additionalData delegate:self];
[[MVMCoreActionHandler sharedActionHandler] handleActionWithDictionary:actionMap additionalData:additionalData delegateObject:[self delegateObject]];
}
}
return NO;

View File

@ -9,11 +9,11 @@
import Foundation
@objc public extension FormValidator {
@objc public func addFormParams(requestParameters: MVMCoreRequestParameters) {
@objc func addFormParams(requestParameters: MVMCoreRequestParameters) {
requestParameters.add(self.getFormParams())
}
@objc public func getFormParams() -> [String: Any] {
@objc func getFormParams() -> [String: Any] {
var extraParam: [String: Any] = [:]
MVMCoreDispatchUtility.performSyncBlock(onMainThread: {
for molecule in self.molecules {

View File

@ -117,7 +117,7 @@
// Sets up the buttons/button.
NSDictionary *primaryButtonDictionary = [self primaryButtonMap];
NSDictionary *secondaryButtonDictionary = [self secondaryButtonMap];
TwoButtonView *buttonView = [[TwoButtonView alloc] initWithPrimaryButtonMap:primaryButtonDictionary secondaryButtonMap:secondaryButtonDictionary actionDelegate:self additionalData:nil buttonDelegate:self];
TwoButtonView *buttonView = [[TwoButtonView alloc] initWithPrimaryButtonMap:primaryButtonDictionary secondaryButtonMap:secondaryButtonDictionary delegateObject:[self delegateObject] additionalData:nil];
self.secondaryButton = buttonView.secondaryButton;
self.primaryButton = buttonView.primaryButton;

View File

@ -127,7 +127,7 @@
// Sets up the buttons/button.
NSDictionary *primaryButtonDictionary = [self primaryButtonMap];
NSDictionary *secondaryButtonDictionary = [self secondaryButtonMap];
TwoButtonView *buttonView = [[TwoButtonView alloc] initWithPrimaryButtonMap:primaryButtonDictionary secondaryButtonMap:secondaryButtonDictionary actionDelegate:self additionalData:nil buttonDelegate:self];
TwoButtonView *buttonView = [[TwoButtonView alloc] initWithPrimaryButtonMap:primaryButtonDictionary secondaryButtonMap:secondaryButtonDictionary delegateObject:[self delegateObject] additionalData:nil];
self.secondaryButton = buttonView.secondaryButton;
self.primaryButton = buttonView.primaryButton;
bottomView = buttonView;

View File

@ -74,7 +74,6 @@ FOUNDATION_EXPORT const unsigned char MVMCoreUIVersionString[];
#pragma mark Views
#import <MVMCoreUI/MFView.h>
#import <MVMCoreUI/MFLabel.h>
#import <MVMCoreUI/LabelWithInternalButton.h>
#import <MVMCoreUI/ViewConstrainingView.h>
#import <MVMCoreUI/MFLoadingSpinner.h>
#import <MVMCoreUI/MFTextView.h>

View File

@ -33,9 +33,9 @@ import UIKit
primaryButton?.isEnabled = enabled
}
public init(withJSON json: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, actionDelegate: NSObject?, buttonDelegate: Any?) {
public init(withJSON json: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {
super.init(frame: .zero)
setWithJSON(json, delegate: actionDelegate, additionalData: additionalData)
setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
}
// MARK: - MVMCoreViewProtocol
@ -58,9 +58,9 @@ import UIKit
primaryButton?.setAsMolecule()
}
open override func setWithJSON(_ json: [AnyHashable : Any]?, delegate: NSObject?, additionalData: [AnyHashable : Any]?) {
super.setWithJSON(json, delegate: delegate, additionalData: additionalData)
primaryButton?.setWithJSON(json, delegate: delegate, additionalData: additionalData)
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
primaryButton?.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
}
// MARK: - Constraining

View File

@ -7,11 +7,12 @@
//
#import <UIKit/UIKit.h>
@class DelegateObject;
@protocol MVMCoreUIMoleculeViewProtocol <NSObject>
// Sets up the ui based on the json
- (void)setWithJSON:(nullable NSDictionary *)json delegate:(nullable NSObject *)delegate additionalData:(nullable NSDictionary *)additionalData;
- (void)setWithJSON:(nullable NSDictionary *)json delegateObject:(nullable DelegateObject *)delegateObject additionalData:(nullable NSDictionary *)additionalData;
@optional

View File

@ -11,18 +11,19 @@ import UIKit
public class MoleculeStackView: MFView {
var spacingBlock: ((Any) -> UIEdgeInsets)?
var moleculesArray: [UIView]?
var useMargins: Bool = false
public override init(frame: CGRect) {
super.init(frame: frame)
}
public init(withJSON json: [AnyHashable : Any]?, delegate: NSObject?, additionalData: [AnyHashable : Any]?) {
public init(withJSON json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) {
super.init(frame: CGRect.zero)
setWithJSON(json, delegate: delegate, additionalData: additionalData)
setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
}
public convenience init(withJSON json: [AnyHashable : Any]?, delegate: NSObject?, spacingBlock: ((Any) -> UIEdgeInsets)?) {
self.init(withJSON: json, delegate: delegate, additionalData: nil)
public convenience init(withJSON json: [AnyHashable: Any]?, delegateObject: DelegateObject?, spacingBlock: ((Any) -> UIEdgeInsets)?) {
self.init(withJSON: json, delegateObject: delegateObject, additionalData: nil)
self.spacingBlock = spacingBlock
}
@ -47,8 +48,8 @@ public class MoleculeStackView: MFView {
}
}
public override func setWithJSON(_ json: [AnyHashable : Any]?, delegate: NSObject?, additionalData: [AnyHashable : Any]?) {
super.setWithJSON(json, delegate: delegate, additionalData: additionalData)
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 {
return
}
@ -57,7 +58,7 @@ public class MoleculeStackView: MFView {
var moleculesArray = [] as [UIView]
for moleculeJSON in molecules {
if let name = moleculeJSON.optionalStringForKey("moleculeName"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForName(name) {
molecule.setWithJSON(moleculeJSON, delegate: delegate, additionalData: additionalData)
molecule.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData)
moleculesArray.append(molecule)
}
}
@ -67,9 +68,9 @@ public class MoleculeStackView: MFView {
}
if let spacingBlock = spacingBlock {
MVMCoreUIStackableViewController.populateView(self, withUIArray: moleculesArray, withSpacingBlock: spacingBlock)
MVMCoreUIStackableViewController.populateView(self, withUIArray: moleculesArray, useMargins: useMargins, withSpacingBlock: spacingBlock)
} else {
MVMCoreUIStackableViewController.populateView(self, withUIArray: moleculesArray) { (object) -> UIEdgeInsets in
MVMCoreUIStackableViewController.populateView(self, withUIArray: moleculesArray, useMargins: useMargins) { (object) -> UIEdgeInsets in
if object as AnyObject? === moleculesArray.first {
return UIEdgeInsets.zero
} else {

View File

@ -103,12 +103,12 @@ public class StandardFooterView: ViewConstrainingView {
rightConstraintTextButton?.constant = constant
}
public override func setWithJSON(_ json: [AnyHashable : Any]?, delegate: NSObject?, additionalData: [AnyHashable : Any]?) {
super.setWithJSON(json, delegate: delegate, additionalData: additionalData)
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) {
backgroundColor = .mfGet(forHex: colorString)
}
twoButtonView.setWithJSON(json?.optionalDictionaryForKey("twoButtonView"), delegate: delegate, additionalData: additionalData)
textButton.setWithJSON(json?.optionalDictionaryForKey("textButton"), delegate: delegate, additionalData: additionalData)
twoButtonView.setWithJSON(json?.optionalDictionaryForKey("twoButtonView"), delegateObject: delegateObject, additionalData: additionalData)
textButton.setWithJSON(json?.optionalDictionaryForKey("textButton"), delegateObject: delegateObject, additionalData: additionalData)
}
}

View File

@ -110,8 +110,8 @@ public class StandardHeaderView: ViewConstrainingView {
separatorView?.rightPin?.constant = constant
}
public override func setWithJSON(_ json: [AnyHashable : Any]?, delegate: NSObject?, additionalData: [AnyHashable : Any]?) {
super.setWithJSON(json, delegate: delegate, additionalData: additionalData)
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) {
backgroundColor = .mfGet(forHex: colorString)
}
@ -123,11 +123,11 @@ public class StandardHeaderView: ViewConstrainingView {
}
let headlineJSON = json?.optionalDictionaryForKey("headline")
headlineLabel.setWithJSON(headlineJSON, delegate: delegate, additionalData: additionalData)
headlineLabel.setWithJSON(headlineJSON, delegateObject: delegateObject, additionalData: additionalData)
let bodyJSON = json?.optionalDictionaryForKey("body")
messageLabel.setWithJSON(bodyJSON, delegate: delegate, additionalData: additionalData)
messageLabel.setWithJSON(bodyJSON, delegateObject: delegateObject, additionalData: additionalData)
let separatorJSON = json?.optionalDictionaryForKey("separator")
separatorView?.setWithJSON(separatorJSON, delegate: delegate, additionalData: additionalData)
separatorView?.setWithJSON(separatorJSON, delegateObject: delegateObject, additionalData: additionalData)
if separatorView?.isHidden ?? true {
bottomPin?.constant = 0

View File

@ -25,6 +25,11 @@ import UIKit
super.init(frame: frame)
}
public func setDefaultCustom() {
primaryButton?.setAsStandardCustom()
secondaryButton?.setAsSecondaryCustom()
}
// MARK: - MVMCoreViewProtocol
open override func updateView(_ size: CGFloat) {
super.updateView(size)
@ -34,18 +39,14 @@ import UIKit
}
// MARK: - MVMCoreUIMoleculeViewProtocol
open override func setWithJSON(_ json: [AnyHashable : Any]?, delegate: NSObject?, additionalData: [AnyHashable : Any]?) {
super.setWithJSON(json, delegate: delegate, additionalData: additionalData)
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
if let backgroundColorString = json?.optionalStringForKey(KeyBackgroundColor) {
backgroundColor = UIColor.mfGet(forHex: backgroundColorString)
}
let primaryButtonMap = json?.optionalDictionaryForKey("primaryButton")
let secondaryButtonMap = json?.optionalDictionaryForKey("secondaryButton")
setupUI(withPrimaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap, legacy: false)
primaryButton?.setAsStandardCustom()
secondaryButton?.setAsSecondaryCustom()
primaryButton?.setWithJSON(primaryButtonMap, delegate: delegate, additionalData: additionalData)
secondaryButton?.setWithJSON(secondaryButtonMap, delegate: delegate, additionalData: additionalData)
set(primaryButtonJSON: primaryButtonMap, secondaryButtonJSON: secondaryButtonMap, delegateObject: delegateObject, additionalData: additionalData)
}
// MARK: - Constraining
@ -141,25 +142,24 @@ import UIKit
}
}
// MARK: - Legacy
open func setup(withButtonMap buttonMap: [AnyHashable: Any]?, actionDelegate: NSObjectProtocol?, additionalData: [AnyHashable: Any]?, buttonDelegate: Any?) {
let secondaryButtonMap = buttonMap?.optionalDictionaryForKey(KeySecondaryButton)
let primaryButtonMap = buttonMap?.optionalDictionaryForKey(KeyPrimaryButton)
setup(primaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap, actionDelegate: actionDelegate, additionalData: additionalData, buttonDelegate: buttonDelegate)
open func set(primaryButtonJSON: [AnyHashable: Any]?, secondaryButtonJSON: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
setupUI(withPrimaryButtonMap: primaryButtonJSON, secondaryButtonMap: secondaryButtonJSON, legacy: false)
setDefaultCustom()
primaryButton?.setWithJSON(primaryButtonJSON, delegateObject: delegateObject, additionalData: additionalData)
secondaryButton?.setWithJSON(secondaryButtonJSON, delegateObject: delegateObject, additionalData: additionalData)
}
open func setup(primaryButtonMap: [AnyHashable: Any]?, secondaryButtonMap: [AnyHashable: Any]?, actionDelegate: NSObjectProtocol?, additionalData: [AnyHashable: Any]?, buttonDelegate: Any?) {
setupUI(withPrimaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap, legacy: true)
if primaryButtonMap != nil, secondaryButtonMap != nil {
primaryButton?.setWithActionMap(primaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol)
secondaryButton?.setWithActionMap(secondaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol)
} else if primaryButtonMap != nil {
primaryButton?.setWithActionMap(primaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol)
primaryButton?.bordered = false
} else if secondaryButtonMap != nil {
primaryButton?.setWithActionMap(secondaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol)
primaryButton?.bordered = true
}
// MARK: - Legacy
public convenience init(primaryButtonMap: [AnyHashable: Any]?, secondaryButtonMap: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
self.init()
setup(primaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap, delegateObject: delegateObject, additionalData: additionalData)
}
public convenience init(buttonSmall small: Bool, buttonMap: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: AnyHashable]?) {
self.init()
setup(withButtonMap: buttonMap, delegateObject: delegateObject, additionalData: additionalData)
primaryButton?.setAsSmall(small)
secondaryButton?.setAsSmall(small)
}
public convenience init(buttonSmall small: Bool, enabled: Bool) {
@ -170,16 +170,24 @@ import UIKit
primaryButton?.isEnabled = enabled
}
public convenience init(buttonSmall small: Bool, buttonMap: [AnyHashable: Any]?, actionDelegate: NSObjectProtocol?, additionalData: [AnyHashable: AnyHashable]?, buttonDelegate: Any?) {
self.init()
setup(withButtonMap: buttonMap, actionDelegate: actionDelegate, additionalData: additionalData, buttonDelegate: buttonMap)
primaryButton?.setAsSmall(small)
secondaryButton?.setAsSmall(small)
open func setup(primaryButtonMap: [AnyHashable: Any]?, secondaryButtonMap: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
setupUI(withPrimaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap, legacy: true)
if primaryButtonMap != nil, secondaryButtonMap != nil {
primaryButton?.setWithActionMap(primaryButtonMap, delegateObject: delegateObject, additionalData: additionalData)
secondaryButton?.setWithActionMap(secondaryButtonMap, delegateObject: delegateObject, additionalData: additionalData)
} else if primaryButtonMap != nil {
primaryButton?.setWithActionMap(primaryButtonMap, delegateObject: delegateObject, additionalData: additionalData)
primaryButton?.bordered = false
} else if secondaryButtonMap != nil {
primaryButton?.setWithActionMap(secondaryButtonMap, delegateObject: delegateObject, additionalData: additionalData)
primaryButton?.bordered = true
}
}
public convenience init(primaryButtonMap: [AnyHashable: Any]?, secondaryButtonMap: [AnyHashable: Any]?, actionDelegate: NSObjectProtocol?, additionalData: [AnyHashable: Any]?, buttonDelegate: Any?) {
self.init()
setup(primaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap, actionDelegate: actionDelegate, additionalData: additionalData, buttonDelegate: buttonDelegate)
open func setup(withButtonMap buttonMap: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
let secondaryButtonMap = buttonMap?.optionalDictionaryForKey(KeySecondaryButton)
let primaryButtonMap = buttonMap?.optionalDictionaryForKey(KeyPrimaryButton)
setup(primaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap, delegateObject: delegateObject, additionalData: additionalData)
}
public func hidePrimaryLeftButton() {
@ -221,3 +229,42 @@ import UIKit
secondaryButton?.isHidden = true
}
}
// MARK: - Deprecate
extension TwoButtonView {
@available(*, deprecated)
open func setup(primaryButtonMap: [AnyHashable: Any]?, secondaryButtonMap: [AnyHashable: Any]?, actionDelegate: NSObjectProtocol?, additionalData: [AnyHashable: Any]?, buttonDelegate: Any?) {
setupUI(withPrimaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap, legacy: true)
if primaryButtonMap != nil, secondaryButtonMap != nil {
primaryButton?.setWithActionMap(primaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol)
secondaryButton?.setWithActionMap(secondaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol)
} else if primaryButtonMap != nil {
primaryButton?.setWithActionMap(primaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol)
primaryButton?.bordered = false
} else if secondaryButtonMap != nil {
primaryButton?.setWithActionMap(secondaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol)
primaryButton?.bordered = true
}
}
@available(*, deprecated)
open func setup(withButtonMap buttonMap: [AnyHashable: Any]?, actionDelegate: NSObjectProtocol?, additionalData: [AnyHashable: Any]?, buttonDelegate: Any?) {
let secondaryButtonMap = buttonMap?.optionalDictionaryForKey(KeySecondaryButton)
let primaryButtonMap = buttonMap?.optionalDictionaryForKey(KeyPrimaryButton)
setup(primaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap, actionDelegate: actionDelegate, additionalData: additionalData, buttonDelegate: buttonDelegate)
}
@available(*, deprecated)
public convenience init(buttonSmall small: Bool, buttonMap: [AnyHashable: Any]?, actionDelegate: NSObjectProtocol?, additionalData: [AnyHashable: AnyHashable]?, buttonDelegate: Any?) {
self.init()
setup(withButtonMap: buttonMap, actionDelegate: actionDelegate, additionalData: additionalData, buttonDelegate: buttonDelegate)
primaryButton?.setAsSmall(small)
secondaryButton?.setAsSmall(small)
}
@available(*, deprecated)
public convenience init(primaryButtonMap: [AnyHashable: Any]?, secondaryButtonMap: [AnyHashable: Any]?, actionDelegate: NSObjectProtocol?, additionalData: [AnyHashable: Any]?, buttonDelegate: Any?) {
self.init()
setup(primaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap, actionDelegate: actionDelegate, additionalData: additionalData, buttonDelegate: buttonDelegate)
}
}

View File

@ -0,0 +1,20 @@
//
// DelegateObject.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 4/12/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import UIKit
open class MVMCoreUIDelegateObject: DelegateObject {
public weak var formValidationProtocol: FormValidationProtocol?
public weak var buttonDelegate: ButtonDelegateProtocol?
open override func setAll(withDelegate delegate: Any) {
super.setAll(withDelegate: delegate)
formValidationProtocol = delegate as? FormValidationProtocol
buttonDelegate = delegate as? ButtonDelegateProtocol
}
}

View File

@ -7,7 +7,6 @@
//
@import MVMCore.MVMCoreLoggingHandler;
@class MVMCoreTopAlertObject;
@class MFViewController;
NS_ASSUME_NONNULL_BEGIN

View File

@ -8,6 +8,7 @@
#import <UIKit/UIKit.h>
#import <MVMCoreUI/MVMCoreUIMoleculeViewProtocol.h>
@class DelegateObject;
@interface MVMCoreUIMoleculeMappingObject : NSObject
@ -19,6 +20,6 @@
// Returns the molecule for the given name.
- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)getMoleculeForName:(nonnull NSString *)name;
- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)getMoleculeForJSON:(nonnull NSDictionary *)json delegate:(nullable NSObject *)delegate;
- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)getMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable DelegateObject *)delegateObject;
@end

View File

@ -56,13 +56,13 @@
return nil;
}
- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)getMoleculeForJSON:(nonnull NSDictionary *)json delegate:(nullable NSObject *)delegate {
- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)getMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject {
NSString *moleculeName = [json string:@"moleculeName"];
if (!moleculeName) {
return nil;
}
UIView <MVMCoreUIMoleculeViewProtocol>*molecule = [self getMoleculeForName:moleculeName];
[molecule setWithJSON:json delegate:delegate additionalData:nil];
[molecule setWithJSON:json delegateObject:delegateObject additionalData:nil];
return molecule;
}

View File

@ -9,7 +9,7 @@
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@class LabelWithInternalButton;
@class MFSizeObject;
//enum for border
@ -90,6 +90,7 @@ B3 -> Legal
+ (CGFloat)defaultVerticalPaddingForApplicationWidth;
+ (CGFloat)defaultHorizontalPaddingForSize:(CGFloat)size;
+ (CGFloat)defaultVerticalPaddingForSize:(CGFloat)size;
+ (void)setDefaultMarginsForView:(nullable UIView *)view size:(CGFloat)size;
//-------------------------------------------------
// Returns the fonts for these styles. Scales them as needed by default

View File

@ -12,6 +12,7 @@
#import "UIColor+MFConvenience.h"
#import "NSLayoutConstraint+MFConvenience.h"
#import "MVMCoreUISplitViewController.h"
@import MVMCore.MVMCoreDispatchUtility;
CGFloat const PaddingDefault = 24;
CGFloat const PaddingDefaultHorizontalSpacing = 32;
@ -88,6 +89,17 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
return [[MFSizeObject sizeObjectWithScalingStandardSize:PaddingDefaultVerticalSpacing] getValueBasedOnSize:size];
}
+ (void)setDefaultMarginsForView:(nullable UIView *)view size:(CGFloat)size {
[MVMCoreDispatchUtility performBlockOnMainThread:^{
CGFloat padding = [MFStyler defaultHorizontalPaddingForSize:size];
if (@available(iOS 11.0, *)) {
view.directionalLayoutMargins = NSDirectionalEdgeInsetsMake(0, padding, 0, padding);
} else {
view.layoutMargins = UIEdgeInsetsMake(0, padding, 0, padding);
}
}];
}
#pragma mark - 2.0 fonts
+ (nullable UIFont *)fontH1:(BOOL)genericScaling {

View File

@ -12,13 +12,13 @@ public class MoleculeStackCenteredTemplate: ThreeLayerViewController {
public override func viewForMiddle() -> UIView? {
let molecule = loadObject?.pageJSON?.optionalDictionaryForKey("moleculeStack")
let moleculeStack = MoleculeStackView(withJSON: molecule, delegate: self, additionalData: nil)
let moleculeStack = MoleculeStackView(withJSON: molecule, delegateObject: delegateObject(), additionalData: nil)
return moleculeStack
}
public override func viewForTop() -> UIView? {
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"),
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegate: self) else {
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(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, delegate: self) else {
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegateObject: delegateObject()) else {
return nil
}
return molecule

View File

@ -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, delegate: self) else {
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegateObject: delegateObject()) else {
return nil
}
return molecule
@ -26,11 +26,11 @@ public class MoleculeStackTemplate: ThreeLayerViewController {
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("moleculeStack") else {
return nil
}
return MoleculeStackView(withJSON: moleculeJSON, delegate: self, additionalData: nil)
return MoleculeStackView(withJSON: moleculeJSON, delegateObject: delegateObject(), additionalData: nil)
}
override public func viewForBottom() -> UIView? {
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegate: self) else {
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegateObject: delegateObject()) else {
return nil
}
return molecule

View File

@ -10,7 +10,6 @@
#import <MVMCore/MVMCoreTopAlertAnimationDelegateProtocol.h>
#import <MVMCoreUI/MFView.h>
@class MVMCoreTopAlertObject;
@class MFCustomButton;
@interface MVMCoreUITopAlertBaseView : MFView

View File

@ -19,6 +19,8 @@
#import "MVMCoreUICommonViewsUtility.h"
#import "MFStyler.h"
#import "MVMCoreUISession.h"
#import <MVMCoreUI/MVMCoreUI-Swift.h>
@import MVMCore.MVMCoreTopAlertDelegateProtocol;
@implementation MVMCoreUITopAlertBaseView
@ -35,7 +37,7 @@
}
if (performAction) {
[[MVMCoreActionHandler sharedActionHandler] handleActionWithDictionary:actionMap additionalData:additionalData delegate:[MVMCoreUISession sharedGlobal].topAlertView];
[[MVMCoreActionHandler sharedActionHandler] handleActionWithDictionary:actionMap additionalData:additionalData delegateObject:[MVMCoreUIDelegateObject createWithDelegateForAll:[MVMCoreUISession sharedGlobal].topAlertView]];
}
} forControlEvents:UIControlEventTouchUpInside];
}

View File

@ -11,6 +11,7 @@
#import <MVMCore/MVMCoreTopAlertAnimationDelegateProtocol.h>
@class PrimaryButton;
@class MVMCoreTopAlertObject;
@interface MVMCoreUITopAlertMainView : MVMCoreUITopAlertBaseView