From 5e677c1a72e7c5a0e64d240ee19795294d8e1436 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 23 Jan 2019 13:53:56 -0500 Subject: [PATCH] Label with internal button, first template --- MVMCoreUI.xcodeproj/project.pbxproj | 32 +- .../Atoms/Views/LabelWithInternalButton.h | 94 +++ .../Atoms/Views/LabelWithInternalButton.m | 557 ++++++++++++++++++ MVMCoreUI/MVMCoreUI.h | 4 + .../MVMCoreUIViewControllerMappingObject.h | 17 + .../MVMCoreUIViewControllerMappingObject.m | 26 + .../LargeHeaderSingleLabelViewController.m | 32 - ...MVMCoreUILargeHeaderSingleLabelTemplate.h} | 6 +- .../MVMCoreUILargeHeaderSingleLabelTemplate.m | 102 ++++ MVMCoreUI/Utility/MVMCoreUIConstants.h | 2 + MVMCoreUI/Utility/MVMCoreUIConstants.m | 2 + 11 files changed, 831 insertions(+), 43 deletions(-) create mode 100644 MVMCoreUI/Atoms/Views/LabelWithInternalButton.h create mode 100644 MVMCoreUI/Atoms/Views/LabelWithInternalButton.m create mode 100644 MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.h create mode 100644 MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m delete mode 100644 MVMCoreUI/Templates/LargeHeaderSingleLabelViewController.m rename MVMCoreUI/Templates/{LargeHeaderSingleLabelViewController.h => MVMCoreUILargeHeaderSingleLabelTemplate.h} (50%) create mode 100644 MVMCoreUI/Templates/MVMCoreUILargeHeaderSingleLabelTemplate.m diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index c3f7ef8c..e46cd285 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -18,8 +18,8 @@ D29770FC21F7C77400B2F0D0 /* TextFieldView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29770FA21F7C77400B2F0D0 /* TextFieldView.m */; }; D29770FD21F7C77400B2F0D0 /* TextFieldView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29770FB21F7C77400B2F0D0 /* TextFieldView.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF0D121E404D4003B2FB9 /* MVMCoreUI.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF0CF21E404D4003B2FB9 /* MVMCoreUI.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF0E221E4F3B6003B2FB9 /* LargeHeaderSingleLabelViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF0E021E4F3B6003B2FB9 /* LargeHeaderSingleLabelViewController.h */; }; - D29DF0E321E4F3B6003B2FB9 /* LargeHeaderSingleLabelViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF0E121E4F3B6003B2FB9 /* LargeHeaderSingleLabelViewController.m */; }; + D29DF0E221E4F3B6003B2FB9 /* MVMCoreUILargeHeaderSingleLabelTemplate.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF0E021E4F3B6003B2FB9 /* MVMCoreUILargeHeaderSingleLabelTemplate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D29DF0E321E4F3B6003B2FB9 /* MVMCoreUILargeHeaderSingleLabelTemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF0E121E4F3B6003B2FB9 /* MVMCoreUILargeHeaderSingleLabelTemplate.m */; }; D29DF0E621E4F3C7003B2FB9 /* MVMCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D29DF0E521E4F3C7003B2FB9 /* MVMCore.framework */; }; D29DF11521E6805F003B2FB9 /* UIColor+MFConvenience.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF11121E6805F003B2FB9 /* UIColor+MFConvenience.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF11621E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF11221E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -135,6 +135,10 @@ D29DF32521ED0DA2003B2FB9 /* TextButtonView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF32321ED0DA2003B2FB9 /* TextButtonView.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF32C21EE8736003B2FB9 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D29DF32821EE8736003B2FB9 /* Localizable.strings */; }; D29DF32E21EE8C3D003B2FB9 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D29DF32D21EE8C3D003B2FB9 /* Media.xcassets */; }; + D2C5001821F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */; }; + 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 */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -151,8 +155,8 @@ D29DF0CC21E404D4003B2FB9 /* MVMCoreUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MVMCoreUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D29DF0CF21E404D4003B2FB9 /* MVMCoreUI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUI.h; sourceTree = ""; }; D29DF0D021E404D4003B2FB9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - D29DF0E021E4F3B6003B2FB9 /* LargeHeaderSingleLabelViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LargeHeaderSingleLabelViewController.h; sourceTree = ""; }; - D29DF0E121E4F3B6003B2FB9 /* LargeHeaderSingleLabelViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LargeHeaderSingleLabelViewController.m; sourceTree = ""; }; + D29DF0E021E4F3B6003B2FB9 /* MVMCoreUILargeHeaderSingleLabelTemplate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUILargeHeaderSingleLabelTemplate.h; sourceTree = ""; }; + D29DF0E121E4F3B6003B2FB9 /* MVMCoreUILargeHeaderSingleLabelTemplate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUILargeHeaderSingleLabelTemplate.m; sourceTree = ""; }; D29DF0E521E4F3C7003B2FB9 /* MVMCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MVMCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D29DF11121E6805F003B2FB9 /* UIColor+MFConvenience.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+MFConvenience.h"; sourceTree = ""; }; D29DF11221E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSLayoutConstraint+MFConvenience.h"; sourceTree = ""; }; @@ -270,6 +274,10 @@ D29DF32A21EE8736003B2FB9 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; D29DF32B21EE8736003B2FB9 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/Localizable.strings"; sourceTree = ""; }; D29DF32D21EE8C3D003B2FB9 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = ""; }; + D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewControllerMappingObject.h; sourceTree = ""; }; + D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIViewControllerMappingObject.m; sourceTree = ""; }; + D2C5001B21F8EE66001DA659 /* LabelWithInternalButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LabelWithInternalButton.h; sourceTree = ""; }; + D2C5001C21F8EE66001DA659 /* LabelWithInternalButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LabelWithInternalButton.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -326,8 +334,8 @@ D29DF0DF21E418B2003B2FB9 /* Templates */ = { isa = PBXGroup; children = ( - D29DF0E021E4F3B6003B2FB9 /* LargeHeaderSingleLabelViewController.h */, - D29DF0E121E4F3B6003B2FB9 /* LargeHeaderSingleLabelViewController.m */, + D29DF0E021E4F3B6003B2FB9 /* MVMCoreUILargeHeaderSingleLabelTemplate.h */, + D29DF0E121E4F3B6003B2FB9 /* MVMCoreUILargeHeaderSingleLabelTemplate.m */, ); path = Templates; sourceTree = ""; @@ -493,6 +501,8 @@ D29DF28621E7AC2B003B2FB9 /* MFLabel.m */, D29DF31E21ED0CBA003B2FB9 /* LabelView.h */, D29DF31F21ED0CBA003B2FB9 /* LabelView.m */, + D2C5001B21F8EE66001DA659 /* LabelWithInternalButton.h */, + D2C5001C21F8EE66001DA659 /* LabelWithInternalButton.m */, D29DF28721E7AC2B003B2FB9 /* ViewConstrainingView.h */, D29DF28821E7AC2B003B2FB9 /* ViewConstrainingView.m */, D29DF26221E6A9D9003B2FB9 /* MFTransparentGIFView.h */, @@ -560,6 +570,8 @@ children = ( D29DF27321E79E81003B2FB9 /* MVMCoreUILoggingHandler.h */, D29DF27421E79E81003B2FB9 /* MVMCoreUILoggingHandler.m */, + D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */, + D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */, ); path = OtherHandlers; sourceTree = ""; @@ -654,7 +666,7 @@ D29DF28B21E7AC2B003B2FB9 /* ViewConstrainingView.h in Headers */, D29DF2B321E7B76D003B2FB9 /* MFLoadingSpinner.h in Headers */, D29DF28921E7AC2B003B2FB9 /* MFLabel.h in Headers */, - D29DF0E221E4F3B6003B2FB9 /* LargeHeaderSingleLabelViewController.h in Headers */, + D29DF0E221E4F3B6003B2FB9 /* MVMCoreUILargeHeaderSingleLabelTemplate.h in Headers */, D29DF32521ED0DA2003B2FB9 /* TextButtonView.h in Headers */, D29DF25021E6A177003B2FB9 /* MFDigitTextBox.h in Headers */, D29DF2C621E7BF57003B2FB9 /* MFTabBarInteractor.h in Headers */, @@ -664,6 +676,7 @@ D29DF26E21E6AA0B003B2FB9 /* FLAnimatedImage.h in Headers */, D29DF17321E69E1F003B2FB9 /* MFCaretButton.h in Headers */, D29DF2A621E7B2A0003B2FB9 /* MFCaretView.h in Headers */, + D2C5001D21F8EE67001DA659 /* LabelWithInternalButton.h in Headers */, D29DF11621E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.h in Headers */, D29DF17721E69E1F003B2FB9 /* MFTextButton.h in Headers */, D29DF16221E69996003B2FB9 /* MFViewController.h in Headers */, @@ -677,6 +690,7 @@ D29DF12D21E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h in Headers */, D29DF24E21E6A177003B2FB9 /* MFDigitTextField.h in Headers */, D29770F321F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.h in Headers */, + D2C5001821F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h in Headers */, D29770FD21F7C77400B2F0D0 /* TextFieldView.h in Headers */, D29DF17421E69E1F003B2FB9 /* MFCustomButton.h in Headers */, D29DF29721E7ADB8003B2FB9 /* MFScrollingViewController.h in Headers */, @@ -782,6 +796,7 @@ D29DF17C21E69E1F003B2FB9 /* MFTextButton.m in Sources */, D29DF2C521E7BF57003B2FB9 /* MFTabBarSwipeAnimator.m in Sources */, D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, + D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */, D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */, D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */, D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */, @@ -820,7 +835,8 @@ D29770FC21F7C77400B2F0D0 /* TextFieldView.m in Sources */, D29DF25121E6A177003B2FB9 /* MFDigitTextBox.m in Sources */, D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */, - D29DF0E321E4F3B6003B2FB9 /* LargeHeaderSingleLabelViewController.m in Sources */, + D29DF0E321E4F3B6003B2FB9 /* MVMCoreUILargeHeaderSingleLabelTemplate.m in Sources */, + D2C5001E21F8EE67001DA659 /* LabelWithInternalButton.m in Sources */, D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */, D29DF2BE21E7BEA4003B2FB9 /* TopTabbar.m in Sources */, D29DF32421ED0DA2003B2FB9 /* TextButtonView.m in Sources */, diff --git a/MVMCoreUI/Atoms/Views/LabelWithInternalButton.h b/MVMCoreUI/Atoms/Views/LabelWithInternalButton.h new file mode 100644 index 00000000..10c0bfdd --- /dev/null +++ b/MVMCoreUI/Atoms/Views/LabelWithInternalButton.h @@ -0,0 +1,94 @@ +// +// TextMixedWithButtonView.h +// mobilefirst +// +// Created by Chris Yang on 2/25/16. +// Copyright © 2016 Verizon Wireless. All rights reserved. +// + +#import +#import +#import +#import +#import +#import + +typedef void (^ActionBlock)(void); + +@interface LabelWithInternalButton : UIControl + +@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 *)delegate buttonDelegate:(nullable NSObject *)buttonDelegate; +- (nullable instancetype)initWithFrontText:(nullable NSString *)frontText backText:(nullable NSString *)backText actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject *)delegate buttonDelegate:(nullable NSObject *)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 *)delegate buttonDelegate:(nullable NSObject *)buttonDelegate; +// set with button delegate +- (void)setActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject *)delegate buttonDelegate:(nullable NSObject *)buttonDelegate; +- (void)setFrontText:(nullable NSString *)frontText actionMap:(nullable NSDictionary *)actionMap backText:(nullable NSString *)backText additionalData:(nullable NSDictionary *)additionalData delegate:(nullable NSObject *)delegate buttonDelegate:(nullable NSObject *)buttonDelegate; +- (void)setFrontAttributedText:(nullable NSAttributedString *)frontAttributedText actionMap:(nullable NSDictionary *)actionMap backAttributedText:(nullable NSAttributedString *)backText additionalData:(nullable NSDictionary *)additionalData delegate:(nullable NSObject *)delegate buttonDelegate:(nullable NSObject *)buttonDelegate; +- (void)setFrontAttributedText:(nullable NSAttributedString *)frontAttributedText actionMap:(nullable NSDictionary *)actionMap backAttributedText:(nullable NSAttributedString *)backAttributedText addNewLine:(BOOL) addNewLine additionalData:(nullable NSDictionary *)additionalData delegate:(nullable NSObject *)delegate buttonDelegate:(nullable NSObject *)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 *)delegate; + +- (nullable instancetype)initWithActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject *)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 *)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 *)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 *)delegate; + + +//set action map +- (void)setActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject *)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 *)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 *)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 *)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 *)delegate; +- (void)setFrontAttributedText:(nullable NSAttributedString *)frontAttributedText actionMap:(nullable NSDictionary *)actionMap backAttributedText:(nullable NSAttributedString *)backAttributedText addNewLine:(BOOL) addNewLine additionalData:(nullable NSDictionary *)additionalData delegate:(nullable NSObject *)delegate; + +- (void)resetWithActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary * )additionalData delegate:(nullable NSObject *)delegate; + +- (void)setAlignment:(NSTextAlignment)textAlignment; + +- (void)setEnabled:(BOOL)enabled; + +- (void)setAlternateActionTextAttributes:(nullable NSDictionary *)attributes; + +- (void)setActionTextString:(nullable NSString *)actionText; + +- (nonnull UIAccessibilityCustomAction *)accessibilityCustomAction; + +@end diff --git a/MVMCoreUI/Atoms/Views/LabelWithInternalButton.m b/MVMCoreUI/Atoms/Views/LabelWithInternalButton.m new file mode 100644 index 00000000..c4c509c5 --- /dev/null +++ b/MVMCoreUI/Atoms/Views/LabelWithInternalButton.m @@ -0,0 +1,557 @@ +// +// TextMixedWithButtonView.m +// mobilefirst +// +// Created by Chris Yang on 2/25/16. +// Copyright © 2016 Verizon Wireless. All rights reserved. +// + +#import "LabelWithInternalButton.h" +#import +#import +#import +#import +#import +#import +#import +#import +#import + +@interface LabelWithInternalButton () + +@property (nullable, strong, nonatomic) NSString *text; + +@end + +@implementation LabelWithInternalButton + + + +- (nullable instancetype)initWithActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject *)delegate buttonDelegate:(nullable NSObject *)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 *)delegate buttonDelegate:(nullable NSObject *)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 *)delegate buttonDelegate:(nullable NSObject *)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 *)delegate buttonDelegate:(nullable NSObject *)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 *)delegate buttonDelegate:(nullable NSObject *)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 *)delegate buttonDelegate:(nullable NSObject *)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 *)delegate buttonDelegate:(nullable NSObject *)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 *)delegate buttonDelegate:(nullable NSObject *)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 *)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 *)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 *)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 *)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 *)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 *)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 *)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 *)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 *)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 *)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 *)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 *)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 *)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 *)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 diff --git a/MVMCoreUI/MVMCoreUI.h b/MVMCoreUI/MVMCoreUI.h index 9ab74ae5..f45c3146 100644 --- a/MVMCoreUI/MVMCoreUI.h +++ b/MVMCoreUI/MVMCoreUI.h @@ -65,6 +65,7 @@ FOUNDATION_EXPORT const unsigned char MVMCoreUIVersionString[]; #pragma mark Views #import #import +#import #import #import #import @@ -99,3 +100,6 @@ FOUNDATION_EXPORT const unsigned char MVMCoreUIVersionString[]; #pragma mark - Molecules #import #import + +#pragma mark - Templates +#import diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.h b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.h new file mode 100644 index 00000000..0f40b2a2 --- /dev/null +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.h @@ -0,0 +1,17 @@ +// +// MVMCoreUIViewControllerMappingObject.h +// MVMCoreUI +// +// Created by Scott Pfeil on 1/23/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MVMCoreUIViewControllerMappingObject : MVMCoreViewControllerMappingObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m new file mode 100644 index 00000000..3f73bf85 --- /dev/null +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m @@ -0,0 +1,26 @@ +// +// MVMCoreUIViewControllerMappingObject.m +// MVMCoreUI +// +// Created by Scott Pfeil on 1/23/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +#import "MVMCoreUIViewControllerMappingObject.h" +#import +#import "MVMCoreUILargeHeaderSingleLabelTemplate.h" + +@implementation MVMCoreUIViewControllerMappingObject + +- (NSMutableDictionary *)viewControllerMapping { + + // Keeps a mapping of the given page type + static dispatch_once_t onceToken; + static NSMutableDictionary *viewControllerMapping; + dispatch_once(&onceToken, ^{ + viewControllerMapping = [@{ @"LargeHeaderSingleLabel": [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MVMCoreUILargeHeaderSingleLabelTemplate class]]} mutableCopy]; + }); + return viewControllerMapping; +} + +@end diff --git a/MVMCoreUI/Templates/LargeHeaderSingleLabelViewController.m b/MVMCoreUI/Templates/LargeHeaderSingleLabelViewController.m deleted file mode 100644 index 882a08cc..00000000 --- a/MVMCoreUI/Templates/LargeHeaderSingleLabelViewController.m +++ /dev/null @@ -1,32 +0,0 @@ -// -// LargeHeaderSingleLabelViewController.m -// MVMCoreUI -// -// Created by Scott Pfeil on 1/8/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -#import "LargeHeaderSingleLabelViewController.h" - -@interface LargeHeaderSingleLabelViewController () - -@end - -@implementation LargeHeaderSingleLabelViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - // Do any additional setup after loading the view. -} - -/* -#pragma mark - Navigation - -// In a storyboard-based application, you will often want to do a little preparation before navigation -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - // Get the new view controller using [segue destinationViewController]. - // Pass the selected object to the new view controller. -} -*/ - -@end diff --git a/MVMCoreUI/Templates/LargeHeaderSingleLabelViewController.h b/MVMCoreUI/Templates/MVMCoreUILargeHeaderSingleLabelTemplate.h similarity index 50% rename from MVMCoreUI/Templates/LargeHeaderSingleLabelViewController.h rename to MVMCoreUI/Templates/MVMCoreUILargeHeaderSingleLabelTemplate.h index b1dc85ba..75a7474e 100644 --- a/MVMCoreUI/Templates/LargeHeaderSingleLabelViewController.h +++ b/MVMCoreUI/Templates/MVMCoreUILargeHeaderSingleLabelTemplate.h @@ -1,5 +1,5 @@ // -// LargeHeaderSingleLabelViewController.h +// MVMCoreUILargeHeaderSingleLabelTemplate.h // MVMCoreUI // // Created by Scott Pfeil on 1/8/19. @@ -7,11 +7,11 @@ // #import -#import +#import NS_ASSUME_NONNULL_BEGIN -@interface LargeHeaderSingleLabelViewController : UIViewController +@interface MVMCoreUILargeHeaderSingleLabelTemplate : TopLabelsAndBottomButtonsViewController @end NS_ASSUME_NONNULL_END diff --git a/MVMCoreUI/Templates/MVMCoreUILargeHeaderSingleLabelTemplate.m b/MVMCoreUI/Templates/MVMCoreUILargeHeaderSingleLabelTemplate.m new file mode 100644 index 00000000..b11a8871 --- /dev/null +++ b/MVMCoreUI/Templates/MVMCoreUILargeHeaderSingleLabelTemplate.m @@ -0,0 +1,102 @@ +// +// MVMCoreUILargeHeaderSingleLabelTemplate.m +// MVMCoreUI +// +// Created by Scott Pfeil on 1/8/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +#import "MVMCoreUILargeHeaderSingleLabelTemplate.h" +#import "LabelView.h" +#import "LabelWithInternalButton.h" +#import "UIColor+MFConvenience.h" + +@interface MVMCoreUILargeHeaderSingleLabelTemplate () + +// A label that can go below the top labels. Can be a normal label or one with internal buttons. +@property (nullable, weak, nonatomic) LabelView *labelViewUnderTopLabels; +@property (nullable, weak, nonatomic) LabelWithInternalButton *labelUnderTopLabelsWithInternalButton; + +@end + +@implementation MVMCoreUILargeHeaderSingleLabelTemplate + +- (void)newDataBuildScreen { + [super newDataBuildScreen]; + [self.topLabelsView.headlineLabel styleH1:YES]; + self.topLabelsView.separatorView.hidden = YES; + [self updateTopLabelsColor]; +} + +- (void)initialLoad { + [super initialLoad]; + self.rebuildUIOnSizeChange = NO; +} + +- (nullable NSArray *)buildViewsBetweenLabelsAndButtons { + NSDictionary *labelActionMap = [self actionMapForLabelUnderTopLabelsWithInternalButton]; + NSString *labelString = [self stringForLabelUnderTopLabels]; + NSMutableArray *views = [[NSMutableArray alloc] init]; + if (labelActionMap.count > 0) { + // Use label with internal button. + LabelWithInternalButton *labelWithInternalButton = [[LabelWithInternalButton alloc] initWithActionMap:labelActionMap additionalData:nil actionDelegate:self buttonDelegate:self]; + labelWithInternalButton.translatesAutoresizingMaskIntoConstraints = NO; + [labelWithInternalButton setAlignment:NSTextAlignmentLeft]; + self.labelUnderTopLabelsWithInternalButton = labelWithInternalButton; + [views addObject:labelWithInternalButton]; + } else if (labelString.length > 0){ + // Use regular label + LabelView *labelView = [[LabelView alloc] init]; + labelView.translatesAutoresizingMaskIntoConstraints = NO; + [labelView alignLeft]; + [labelView.label styleB2:YES]; + labelView.label.text = labelString; + [labelView.label setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; + self.labelViewUnderTopLabels = labelView; + [views addObject:labelView]; + } + + return views; +} + +- (nullable NSString *)stringForLabelUnderTopLabels { + return [self.loadObject.pageJSON stringForKey:@"description"]; +} + +- (nullable NSDictionary *)actionMapForLabelUnderTopLabelsWithInternalButton { + return [self.loadObject.pageJSON dictWithChainOfKeysOrIndexes:@[KeyButtonMap,@"Link"]]; +} + +- (NSNumber *)spaceAboveBetweenView { + return @(0); +} + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +#pragma mark - Top labels style + +- (void)updateTopLabelsColor { + self.topLabelsView.headlineLabel.textColor = [UIColor blackColor]; + self.topLabelsView.messageLabel.textColor = [UIColor blackColor]; + NSString *titleColor = [[self mapForTopLabels] string:@"titleBgColor"]; + if (titleColor) { + self.topLabelsView.headlineLabel.textColor = [UIColor mfGetColorForHex:titleColor]; + self.topLabelsView.messageLabel.textColor = [UIColor mfGetColorForHex:titleColor]; + } +} + +- (UIEdgeInsets)paddingForTopLabels { + UIEdgeInsets edge = [super paddingForTopLabels]; + edge.bottom = PaddingTwo; + return edge; +} + +@end diff --git a/MVMCoreUI/Utility/MVMCoreUIConstants.h b/MVMCoreUI/Utility/MVMCoreUIConstants.h index 009009ff..2b7b625d 100644 --- a/MVMCoreUI/Utility/MVMCoreUIConstants.h +++ b/MVMCoreUI/Utility/MVMCoreUIConstants.h @@ -25,6 +25,8 @@ extern NSString * const KeyProgressPercent; extern NSString * const KeyPrimaryButton; extern NSString * const KeySecondaryButton; +extern NSString * const KeyTitlePrefix; +extern NSString * const KeyTitlePostfix; #pragma mark - Values diff --git a/MVMCoreUI/Utility/MVMCoreUIConstants.m b/MVMCoreUI/Utility/MVMCoreUIConstants.m index 9e089b1f..6a0bb090 100644 --- a/MVMCoreUI/Utility/MVMCoreUIConstants.m +++ b/MVMCoreUI/Utility/MVMCoreUIConstants.m @@ -24,6 +24,8 @@ NSString * const KeyProgressPercent = @"progressPercent"; NSString * const KeyPrimaryButton = @"PrimaryButton"; NSString * const KeySecondaryButton = @"SecondaryButton"; +NSString * const KeyTitlePrefix = @"titlePrefix"; +NSString * const KeyTitlePostfix = @"titlePostfix"; #pragma mark - Values