Merge branch 'develop' into feature/swiftified_textField
This commit is contained in:
commit
15c2050c4e
@ -37,10 +37,15 @@ public typealias ActionBlock = () -> ()
|
||||
return !text.isEmpty || !attributedText.string.isEmpty
|
||||
}
|
||||
|
||||
public var getRange: NSRange {
|
||||
return NSRange(location: 0, length: text?.count ?? 0)
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Multi-Action Text
|
||||
//------------------------------------------------------
|
||||
|
||||
/// Data store of the tappable ranges of the text.
|
||||
public var clauses: [ActionableClause] = [] {
|
||||
didSet {
|
||||
isUserInteractionEnabled = !clauses.isEmpty
|
||||
@ -113,6 +118,15 @@ public typealias ActionBlock = () -> ()
|
||||
standardFontSize = size
|
||||
}
|
||||
|
||||
/// Convenience to init Label with a link comprised of range, actionMap and delegateObject
|
||||
@objc convenience public init(text: String, range: NSRange, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {
|
||||
self.init()
|
||||
self.text = text
|
||||
if let actionBlock = createActionBlockFor(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject) {
|
||||
setTextLinkState(range: range, actionBlock: actionBlock)
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Factory Functions
|
||||
//------------------------------------------------------
|
||||
@ -308,8 +322,9 @@ public typealias ActionBlock = () -> ()
|
||||
guard let actionLabel = label as? Label else { continue }
|
||||
|
||||
actionLabel.addActionAttributes(range: range, string: attributedString)
|
||||
let actionBlock = actionLabel.createActionBlockFrom(actionMap: attribute, additionalData: additionalData, delegateObject: delegate)
|
||||
actionLabel.appendActionableClause(range: range, actionBlock: actionBlock)
|
||||
if let actionBlock = actionLabel.createActionBlockFor(actionMap: attribute, additionalData: additionalData, delegateObject: delegate) {
|
||||
actionLabel.appendActionableClause(range: range, actionBlock: actionBlock)
|
||||
}
|
||||
|
||||
default:
|
||||
continue
|
||||
@ -484,7 +499,7 @@ public typealias ActionBlock = () -> ()
|
||||
}
|
||||
|
||||
/// Call to detect in the attributedText contains an NSTextAttachment.
|
||||
func textContainsTextAttachment() -> Bool {
|
||||
func containsTextAttachment() -> Bool {
|
||||
|
||||
guard let attributedText = attributedText else { return false }
|
||||
|
||||
@ -589,7 +604,7 @@ extension Label {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Multi-Action Functionality
|
||||
// MARK: - Multi-Link Functionality
|
||||
extension Label {
|
||||
|
||||
/// Applied to existing text. Removes underlines of tappable links and assoated actionable clauses.
|
||||
@ -608,15 +623,17 @@ extension Label {
|
||||
clauses = []
|
||||
}
|
||||
|
||||
public func createActionBlockFrom(actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) -> ActionBlock {
|
||||
public func createActionBlockFor(actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) -> ActionBlock? {
|
||||
return { [weak self] in
|
||||
if let wSelf = self, (delegateObject as? MVMCoreUIDelegateObject)?.buttonDelegate?.button?(wSelf, shouldPerformActionWithMap: actionMap, additionalData: additionalData) ?? true {
|
||||
guard let self = self else { return }
|
||||
|
||||
if (delegateObject as? MVMCoreUIDelegateObject)?.buttonDelegate?.button?(self, shouldPerformActionWithMap: actionMap, additionalData: additionalData) ?? true {
|
||||
MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addActionAttributes(range: NSRange, string: NSMutableAttributedString?) {
|
||||
private func addActionAttributes(range: NSRange, string: NSMutableAttributedString?) {
|
||||
|
||||
guard let string = string else { return }
|
||||
string.addAttributes([NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue], range: range)
|
||||
@ -640,8 +657,7 @@ extension Label {
|
||||
*/
|
||||
@objc public func addTappableLinkAttribute(range: NSRange, actionBlock: @escaping ActionBlock) {
|
||||
|
||||
setActionAttributes(range: range)
|
||||
appendActionableClause(range: range, actionBlock: actionBlock)
|
||||
setTextLinkState(range: range, actionBlock: actionBlock)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -655,15 +671,35 @@ extension Label {
|
||||
*/
|
||||
@objc public func addTappableLinkAttribute(range: NSRange, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {
|
||||
|
||||
if let actionBlock = createActionBlockFor(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject) {
|
||||
setTextLinkState(range: range, actionBlock: actionBlock)
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the entire text into a link. All characters will be underlined and the intrinsic bounds will respond to tap.
|
||||
@objc public func makeTextButton(actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {
|
||||
|
||||
if let actionBlock = createActionBlockFor(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject) {
|
||||
setTextLinkState(range: getRange, actionBlock: actionBlock)
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the entire text into a link. All characters will be underlined and the intrinsic bounds will respond to tap.
|
||||
@objc public func makeTextButton(actionBlock: @escaping ActionBlock) {
|
||||
|
||||
setTextLinkState(range: getRange, actionBlock: actionBlock)
|
||||
}
|
||||
|
||||
/// Underlines the tappable region and stores the tap logic for interation.
|
||||
private func setTextLinkState(range: NSRange, actionBlock: @escaping ActionBlock) {
|
||||
|
||||
setActionAttributes(range: range)
|
||||
let actionBlock = createActionBlockFrom(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
appendActionableClause(range: range, actionBlock: actionBlock)
|
||||
}
|
||||
|
||||
@objc private func textLinkTapped(_ gesture: UITapGestureRecognizer) {
|
||||
|
||||
for clause in clauses {
|
||||
|
||||
// This determines if we tapped on the desired range of text.
|
||||
if let range = clause.range, gesture.didTapAttributedTextInLabel(self, inRange: range) {
|
||||
clause.performAction()
|
||||
@ -687,9 +723,33 @@ extension UITapGestureRecognizer {
|
||||
let textContainer = abstractContainer.0
|
||||
let layoutManager = abstractContainer.1
|
||||
|
||||
let indexOfGlyph = layoutManager.glyphIndex(for: location(in: label), in: textContainer)
|
||||
let tapLocation = location(in: label)
|
||||
let indexOfGlyph = layoutManager.glyphIndex(for: tapLocation, in: textContainer)
|
||||
let intrinsicWidth = label.intrinsicContentSize.width
|
||||
|
||||
return NSLocationInRange(indexOfGlyph, targetRange)
|
||||
// Assert that tapped occured within acceptable bounds based on alignment.
|
||||
switch label.textAlignment {
|
||||
case .right:
|
||||
if tapLocation.x < label.bounds.width - intrinsicWidth {
|
||||
return false
|
||||
}
|
||||
case .center:
|
||||
let halfBounds = label.bounds.width / 2
|
||||
let halfIntrinsicWidth = intrinsicWidth / 2
|
||||
|
||||
if tapLocation.x > halfBounds + halfIntrinsicWidth {
|
||||
return false
|
||||
} else if tapLocation.x < halfBounds - halfIntrinsicWidth {
|
||||
return false
|
||||
}
|
||||
default: // Left align
|
||||
if tapLocation.x > intrinsicWidth {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Affirms that the tap occured in the desired rect of provided by the target range.
|
||||
return layoutManager.boundingRect(forGlyphRange: targetRange, in: textContainer).contains(tapLocation) && NSLocationInRange(indexOfGlyph, targetRange)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -207,7 +207,7 @@ public typealias CoreObjectActionLoadPresentDelegate = MVMCoreActionDelegateProt
|
||||
|
||||
@objc public func setActionMap(_ actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {
|
||||
|
||||
actionBlock = label?.createActionBlockFrom(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
actionBlock = label?.createActionBlockFor(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
@ -377,7 +377,7 @@ public typealias CoreObjectActionLoadPresentDelegate = MVMCoreActionDelegateProt
|
||||
actionText = actionMap?.optionalStringForKey(KeyTitle)
|
||||
backText = actionMap?.optionalStringForKey(KeyTitlePostfix)
|
||||
text = getTextFromStringComponents()
|
||||
actionBlock = label?.createActionBlockFrom(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
actionBlock = label?.createActionBlockFor(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
setLabelAttributes()
|
||||
}
|
||||
|
||||
|
||||
@ -314,10 +314,14 @@
|
||||
[self.molecule updateView:size];
|
||||
[MFStyler setMarginsForView:self size:size defaultHorizontal:self.updateViewHorizontalDefaults top:(self.updateViewVerticalDefaults ? self.topMarginPadding : 0) bottom:(self.updateViewVerticalDefaults ? self.bottomMarginPadding : 0)];
|
||||
UIEdgeInsets margins = [MVMCoreUIUtility getMarginsForView:self];
|
||||
[self setLeftPinConstant:margins.left];
|
||||
[self setRightPinConstant:margins.right];
|
||||
[self setTopPinConstant:margins.top];
|
||||
[self setBottomPinConstant:margins.bottom];
|
||||
if (self.updateViewHorizontalDefaults) {
|
||||
[self setLeftPinConstant:margins.left];
|
||||
[self setRightPinConstant:margins.right];
|
||||
}
|
||||
if (self.updateViewVerticalDefaults) {
|
||||
[self setTopPinConstant:margins.top];
|
||||
[self setBottomPinConstant:margins.bottom];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - MVMCoreUIMoleculeViewProtocol
|
||||
|
||||
Loading…
Reference in New Issue
Block a user