From 988e30daa9bca0163a5a234a156638aa2ea90d71 Mon Sep 17 00:00:00 2001 From: "Robinson, Blake" Date: Mon, 2 Dec 2019 11:15:50 -0500 Subject: [PATCH] Creates Link atom to replace MFTextButton --- MVMCoreUI.xcodeproj/project.pbxproj | 4 + MVMCoreUI/Atoms/Buttons/Link.swift | 155 +++++++++++++++++++++++++ MVMCoreUI/Utility/MVMCoreUIConstants.h | 1 + MVMCoreUI/Utility/MVMCoreUIConstants.m | 1 + 4 files changed, 161 insertions(+) create mode 100644 MVMCoreUI/Atoms/Buttons/Link.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 391e20f5..70cbe5ff 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -32,6 +32,7 @@ 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */; }; 9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */; }; 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948DB67D2326DCD90011F916 /* MultiProgress.swift */; }; + C07065C42395677300FBF997 /* Link.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07065C32395677300FBF997 /* Link.swift */; }; D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; D224798A2314445E003FCCF9 /* LabelSwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22479892314445E003FCCF9 /* LabelSwitch.swift */; }; @@ -228,6 +229,7 @@ 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphViewAnimationHandler.swift; sourceTree = ""; }; 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MVMAnimationFramework.framework; path = ../SharedFrameworks/MVMAnimationFramework.framework; sourceTree = ""; }; 948DB67D2326DCD90011F916 /* MultiProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgress.swift; sourceTree = ""; }; + C07065C32395677300FBF997 /* Link.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Link.swift; sourceTree = ""; }; D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = ""; }; D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; D22479892314445E003FCCF9 /* LabelSwitch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelSwitch.swift; sourceTree = ""; }; @@ -729,6 +731,7 @@ D282AACA2243C61700C46919 /* ButtonView.swift */, D29DF16D21E69E1F003B2FB9 /* MFTextButton.h */, D29DF17221E69E1F003B2FB9 /* MFTextButton.m */, + C07065C32395677300FBF997 /* Link.swift */, ); path = Buttons; sourceTree = ""; @@ -1060,6 +1063,7 @@ 943784F5236B77BB006A1E82 /* GraphView.swift in Sources */, D29DF32121ED0CBA003B2FB9 /* LabelView.m in Sources */, DBC4391822442197001AB423 /* CaretView.swift in Sources */, + C07065C42395677300FBF997 /* Link.swift in Sources */, D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */, D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */, DBC4391922442197001AB423 /* DashLine.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Buttons/Link.swift b/MVMCoreUI/Atoms/Buttons/Link.swift new file mode 100644 index 00000000..a89f8e71 --- /dev/null +++ b/MVMCoreUI/Atoms/Buttons/Link.swift @@ -0,0 +1,155 @@ +// +// Link.swift +// MVMCoreUI +// +// Created by Robinson, Blake on 11/26/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +@objcMembers open class Link: MFCustomButton { + + lazy var sizeObject:MFSizeObject? = { + return MFSizeObject(standardSize: 30, standardiPadPortraitSize: 36, iPadProLandscapeSize: 42) + }() + + public override init(frame: CGRect) { + super.init(frame: frame) + self.setupView() + } + + public required init?(coder: NSCoder) { + super.init(coder: coder) + self.setupView() + } + + open override func draw(_ rect: CGRect) { + guard let textRect = self.titleLabel?.frame else { return } + + let contextRef = UIGraphicsGetCurrentContext() + + //set to the same color as the text + if let color = self.titleLabel?.textColor?.cgColor { + contextRef?.setStrokeColor(color) + } + + //x should be according to the text, not the button + let x = textRect.origin.x + // line is 1 point below the text + let y = textRect.origin.y + textRect.size.height + 1 + + contextRef?.move(to: CGPoint(x: x, y: y)) + contextRef?.addLine(to: CGPoint(x: x + textRect.size.width, y: y)) + contextRef?.closePath() + contextRef?.drawPath(using: .stroke) + } + + public static func link() -> Link { + return Link.link(nil, constrainHeight: true, width: CGFloat.leastNormalMagnitude) + } + + public static func link(_ button: UIButton?, constrainHeight: Bool, width:CGFloat) -> Link { + + let link = linkHelper(button) + + //Adds the height constraint. + if let constant = link.sizeObject?.standardSize, + constrainHeight { + + let heightConstraint = NSLayoutConstraint(item: link as Any, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: constant) + link.addConstraint(heightConstraint) + heightConstraint.isActive = true + link.heightConstraint = heightConstraint + + } else { + link.setContentHuggingPriority(.required, for: .vertical) + } + link.updateView(width) + + return link + } + + public static func linkHelper(_ button: UIButton?) -> Link { + guard let unwrappedButton = button else { return Link(type:.custom) } + guard let link = unwrappedButton as? Link else { return Link(type:.custom) } + return link + } +} + +extension Link: MVMCoreViewProtocol { + + public func updateView(_ size: CGFloat) { + MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in + guard let self = self else { return } + + var width = size + if MVMCoreGetterUtility.fequal(a: Float(CGFloat.leastNormalMagnitude), b: Float(size)) { + width = MVMCoreUISplitViewController.getApplicationViewWidth() + } + self.titleLabel?.font = MFStyler.fontB2(forWidth: width) + guard let heightConstraint = self.heightConstraint else { return } + if !MVMCoreGetterUtility.fequal(a: 0, b: Float(heightConstraint.constant)) { + guard let sizeObject = self.sizeObject else { return } + self.heightConstraint?.constant = sizeObject.getValueBased(onSize: width) + } + }) + } + + public func setupView() { + self.translatesAutoresizingMaskIntoConstraints = false; + self.backgroundColor = .clear + self.contentMode = .redraw + self.setTitleColor(UIColor.mfTextButton(), for: .normal) + self.setTitleColor(UIColor.mfCharcoal(), for: .highlighted) + // left alignment by default + self.titleLabel?.textAlignment = .left + self.contentHorizontalAlignment = .left + } +} + +extension Link: MVMCoreUIMoleculeViewProtocol { + + public func reset() { + self.setTitleColor(UIColor.mfTextButton(), for: .normal) + } + + public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + if let unwrappedJson = json { + let color = unwrappedJson.stringForkey(KeyTextColor) + setTitleColor(UIColor.mfGet(forHex: color), for: .normal) + + setWithActionMap(json, delegateObject: delegateObject, additionalData: additionalData) + + //enabling must happen after setWithActionMap is called because + //that method enables buttons when the actionMap does not contain + //disableAction = true + if let enabled = unwrappedJson[KeyEnabled] as? Bool { + isEnabled = enabled + } + } + + if let title = self.title(for: .normal), + title.isEmpty { + self.heightConstraint?.constant = 0 + } else { + guard let standardSize = sizeObject?.standardSize else { return } + self.heightConstraint?.constant = standardSize + } + } + + public static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + return 31 + } +} + +extension Link: MVMCoreUIViewConstrainingProtocol { + + public func needsToBeConstrained() -> Bool { + return true + } + + public func alignment() -> UIStackView.Alignment { + return .leading + } +} diff --git a/MVMCoreUI/Utility/MVMCoreUIConstants.h b/MVMCoreUI/Utility/MVMCoreUIConstants.h index 778ede4f..2cb09859 100644 --- a/MVMCoreUI/Utility/MVMCoreUIConstants.h +++ b/MVMCoreUI/Utility/MVMCoreUIConstants.h @@ -22,6 +22,7 @@ extern NSString * const KeyDisableButton; extern NSString * const KeyValue; extern NSString * const KeyLabel; extern NSString * const KeyDisable; +extern NSString * const KeyEnabled; extern NSString * const KeyFieldName; extern NSString * const KeyHideMainMenu; diff --git a/MVMCoreUI/Utility/MVMCoreUIConstants.m b/MVMCoreUI/Utility/MVMCoreUIConstants.m index 26636266..0ac5fcdb 100644 --- a/MVMCoreUI/Utility/MVMCoreUIConstants.m +++ b/MVMCoreUI/Utility/MVMCoreUIConstants.m @@ -21,6 +21,7 @@ NSString * const KeyDisableButton = @"disableAction"; NSString * const KeyValue = @"value"; NSString * const KeyLabel = @"label"; NSString * const KeyDisable = @"disable"; +NSString * const KeyEnabled = @"enabled"; NSString * const KeyFieldName = @"fieldName"; NSString * const KeyFieldKey = @"fieldKey"; NSString * const KeyRequired = @"required";