From 8b0d208047f66d01eba28c4a04244876c52c126c Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 2 Dec 2019 15:59:44 -0500 Subject: [PATCH 1/8] Current solution to widow word. --- MVMCoreUI/Atoms/Views/Label.swift | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atoms/Views/Label.swift b/MVMCoreUI/Atoms/Views/Label.swift index 8474d74a..d677cf4b 100644 --- a/MVMCoreUI/Atoms/Views/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label.swift @@ -685,13 +685,20 @@ extension Label { /// 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) { + if clauses.isEmpty { + // Replace the last whitespace with \u{00A0} No-break space. + if let start = text?.lastIndex(of: " "), let end = text?.index(after: start) { + text?.replaceSubrange(start.. Date: Wed, 4 Dec 2019 15:52:18 -0500 Subject: [PATCH 2/8] This needs to be broken down and understood, but the code is here and at least functional. --- MVMCoreUI/Atoms/Views/Label.swift | 61 ++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atoms/Views/Label.swift b/MVMCoreUI/Atoms/Views/Label.swift index d677cf4b..544f7666 100644 --- a/MVMCoreUI/Atoms/Views/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label.swift @@ -695,7 +695,7 @@ extension Label { if clauses.isEmpty { // Replace the last whitespace with \u{00A0} No-break space. if let start = text?.lastIndex(of: " "), let end = text?.index(after: start) { - text?.replaceSubrange(start.. [Any] { + + if lineBreakMode != .byWordWrapping { + lineBreakMode = .byWordWrapping + } + + var lines = [Any]() /* capacity: 10 */ + let wordSeparators = CharacterSet.whitespacesAndNewlines + var currentLine: String? = self.text + let textLength: Int = (self.text?.count ?? 0) + var rCurrentLine = NSRange(location: 0, length: textLength) + var rWhitespace = NSRange(location: 0, length: 0) + var rRemainingText = NSRange(location: 0, length: textLength) + var done: Bool = false + + while !done { + // determine the next whitespace word separator position + rWhitespace.location = rWhitespace.location + rWhitespace.length + rWhitespace.length = textLength - rWhitespace.location + rWhitespace = (self.text! as NSString).rangeOfCharacter(from: wordSeparators, options: .caseInsensitive, range: rWhitespace) + if rWhitespace.location == NSNotFound { + rWhitespace.location = textLength + done = true + } + let rTest = NSRange(location: rRemainingText.location, length: rWhitespace.location - rRemainingText.location) + let textTest: String = (self.text! as NSString).substring(with: rTest) + let fontAttributes: [String: Any]? = [NSAttributedString.Key.font.rawValue: font] + let maxWidth = (textTest as NSString).size(withAttributes: [NSAttributedString.Key(rawValue: NSAttributedString.Key.font.rawValue): font]).width + if maxWidth > self.bounds.size.width { + lines.append(currentLine?.trimmingCharacters(in: wordSeparators) ?? "") + rRemainingText.location = rCurrentLine.location + rCurrentLine.length + rRemainingText.length = textLength - rRemainingText.location + continue + } + rCurrentLine = rTest + currentLine = textTest + } + + lines.append(currentLine?.trimmingCharacters(in: wordSeparators) ?? "") + + return lines + } + + open var lastLineWidth: CGFloat { + + let lines: [Any] = self.getSeparatedLines() + + if !lines.isEmpty { + let lastLine: String = (lines.last as? String)! + let fontAttributes = [NSAttributedString.Key.font.rawValue: font] + return (lastLine as NSString).size(withAttributes: [NSAttributedString.Key(rawValue: NSAttributedString.Key.font.rawValue): font]).width + } + + return 0 + } +} + // MARK: - extension UITapGestureRecognizer { From b36299b69592cf675670fa0ff4a23bf6708b4896 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 29 Jan 2021 17:07:57 -0500 Subject: [PATCH 3/8] latest and greatest --- MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift | 8 +++++++- .../Atomic/Molecules/Items/MoleculeTableViewCell.swift | 10 ++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift index 8a8ca5fb..14d2e247 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift @@ -41,6 +41,12 @@ public typealias ActionBlock = () -> () return NSRange(location: 0, length: text?.count ?? 0) } + open override var text: String? { + didSet { + // TODO....???? + } + } + //------------------------------------------------------ // MARK: - Multi-Action Text //------------------------------------------------------ @@ -892,7 +898,7 @@ extension Label { if clauses.isEmpty { // Replace the last whitespace with \u{00A0} No-break space. if let start = text?.lastIndex(of: " "), let end = text?.index(after: start) { -// text?.replaceSubrange(start.. CGSize { + guard let molecule = molecule as? HeadlineBody else { return super.frame.size } + let cell = self + cell.frame = CGRect(x: 0, y: 0, width: targetSize.width, height: CGFloat(MAXFLOAT)) + cell.layoutIfNeeded() + + return CGSize(width: molecule.bounds.width + cell.contentView.directionalLayoutMargins.leading + cell.contentView.directionalLayoutMargins.trailing, height: molecule.bounds.height + cell.contentView.directionalLayoutMargins.top + cell.contentView.directionalLayoutMargins.bottom) + } } From 5c23e80429bcfc964d0d1ed8d8bae78b89111d82 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 1 Feb 2021 14:13:39 -0500 Subject: [PATCH 4/8] addressing intrinsic content issue --- .../Atomic/Atoms/Views/Label/Label.swift | 71 ++---------------- .../Items/MoleculeTableViewCell.swift | 10 --- .../HeadlineBody.swift | 73 ++++++++----------- 3 files changed, 35 insertions(+), 119 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift index 14d2e247..42827e67 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift @@ -38,13 +38,7 @@ public typealias ActionBlock = () -> () } public var getRange: NSRange { - return NSRange(location: 0, length: text?.count ?? 0) - } - - open override var text: String? { - didSet { - // TODO....???? - } + NSRange(location: 0, length: text?.count ?? 0) } //------------------------------------------------------ @@ -102,6 +96,10 @@ public typealias ActionBlock = () -> () accessibilityCustomActions = [] accessibilityTraits = .staticText +// if #available(iOS 14.0, *) { +// lineBreakStrategy = .init() +// } + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(textLinkTapped)) tapGesture.numberOfTapsRequired = 1 addGestureRecognizer(tapGesture) @@ -918,64 +916,7 @@ extension Label { } } -extension Label { - - open func getSeparatedLines() -> [Any] { - - if lineBreakMode != .byWordWrapping { - lineBreakMode = .byWordWrapping - } - - var lines = [Any]() /* capacity: 10 */ - let wordSeparators = CharacterSet.whitespacesAndNewlines - var currentLine: String? = self.text - let textLength: Int = (self.text?.count ?? 0) - var rCurrentLine = NSRange(location: 0, length: textLength) - var rWhitespace = NSRange(location: 0, length: 0) - var rRemainingText = NSRange(location: 0, length: textLength) - var done: Bool = false - - while !done { - // determine the next whitespace word separator position - rWhitespace.location = rWhitespace.location + rWhitespace.length - rWhitespace.length = textLength - rWhitespace.location - rWhitespace = (self.text! as NSString).rangeOfCharacter(from: wordSeparators, options: .caseInsensitive, range: rWhitespace) - if rWhitespace.location == NSNotFound { - rWhitespace.location = textLength - done = true - } - let rTest = NSRange(location: rRemainingText.location, length: rWhitespace.location - rRemainingText.location) - let textTest: String = (self.text! as NSString).substring(with: rTest) - let fontAttributes: [String: Any]? = [NSAttributedString.Key.font.rawValue: font] - let maxWidth = (textTest as NSString).size(withAttributes: [NSAttributedString.Key(rawValue: NSAttributedString.Key.font.rawValue): font]).width - if maxWidth > self.bounds.size.width { - lines.append(currentLine?.trimmingCharacters(in: wordSeparators) ?? "") - rRemainingText.location = rCurrentLine.location + rCurrentLine.length - rRemainingText.length = textLength - rRemainingText.location - continue - } - rCurrentLine = rTest - currentLine = textTest - } - - lines.append(currentLine?.trimmingCharacters(in: wordSeparators) ?? "") - - return lines - } - - open var lastLineWidth: CGFloat { - - let lines: [Any] = self.getSeparatedLines() - - if !lines.isEmpty { - let lastLine: String = (lines.last as? String)! - let fontAttributes = [NSAttributedString.Key.font.rawValue: font] - return (lastLine as NSString).size(withAttributes: [NSAttributedString.Key(rawValue: NSAttributedString.Key.font.rawValue): font]).width - } - - return 0 - } -} + // MARK: - extension UITapGestureRecognizer { diff --git a/MVMCoreUI/Atomic/Molecules/Items/MoleculeTableViewCell.swift b/MVMCoreUI/Atomic/Molecules/Items/MoleculeTableViewCell.swift index 621cbeee..92d04bed 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/MoleculeTableViewCell.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/MoleculeTableViewCell.swift @@ -42,14 +42,4 @@ import UIKit else { return 80 } return height } - - // TODO: Figure out height..... - open override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize { - guard let molecule = molecule as? HeadlineBody else { return super.frame.size } - let cell = self - cell.frame = CGRect(x: 0, y: 0, width: targetSize.width, height: CGFloat(MAXFLOAT)) - cell.layoutIfNeeded() - - return CGSize(width: molecule.bounds.width + cell.contentView.directionalLayoutMargins.leading + cell.contentView.directionalLayoutMargins.trailing, height: molecule.bounds.height + cell.contentView.directionalLayoutMargins.top + cell.contentView.directionalLayoutMargins.bottom) - } } diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift index d111d1c5..8144fc03 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift @@ -19,19 +19,15 @@ open class HeadlineBody: View { // MARK: - Constraints //-------------------------------------------------- - var spaceBetweenLabelsConstant = PaddingOne + var spaceBetweenLabelsConstant = Padding.One var spaceBetweenLabels: NSLayoutConstraint? - var leftConstraintTitle: NSLayoutConstraint? - var rightConstraintTitle: NSLayoutConstraint? - var leftConstraintMessage: NSLayoutConstraint? - var rightConstraintMessage: NSLayoutConstraint? //-------------------------------------------------- // MARK: - Methods //-------------------------------------------------- func hasText() -> Bool { - return headlineLabel.hasText || messageLabel.hasText + headlineLabel.hasText || messageLabel.hasText } // MARK: - Styling @@ -57,13 +53,13 @@ open class HeadlineBody: View { func styleLandingPageHeader() { headlineLabel.setFontStyle(.Title2XLarge) messageLabel.setFontStyle(.RegularBodySmall) - spaceBetweenLabelsConstant = PaddingTwo + spaceBetweenLabelsConstant = Padding.Two } func stylePageHeader() { headlineLabel.setFontStyle(.BoldTitleLarge) messageLabel.setFontStyle(.RegularBodySmall) - spaceBetweenLabelsConstant = PaddingOne + spaceBetweenLabelsConstant = Padding.Two } func styleListItem() { @@ -86,48 +82,38 @@ open class HeadlineBody: View { super.setupView() backgroundColor = .clear - clipsToBounds = true + isAccessibilityElement = false + shouldGroupAccessibilityChildren = true + accessibilityElements = [headlineLabel, messageLabel] - let view = MVMCoreUICommonViewsUtility.commonView() - addSubview(view) - NSLayoutConstraint.constraintPinSubview(toSuperview: view) + addSubview(headlineLabel) + addSubview(messageLabel) - view.isAccessibilityElement = false - view.shouldGroupAccessibilityChildren = true - view.accessibilityElements = [headlineLabel, messageLabel] + headlineLabel.setContentCompressionResistancePriority(.required, for: .vertical) + messageLabel.setContentCompressionResistancePriority(.required, for: .vertical) - view.addSubview(headlineLabel) - view.addSubview(messageLabel) - - headlineLabel.setContentHuggingPriority(.required, for: .vertical) - messageLabel.setContentHuggingPriority(.required, for: .vertical) - view.setContentHuggingPriority(.required, for: .vertical) - - headlineLabel.topAnchor.constraint(equalTo: view.topAnchor).isActive = true + headlineLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true spaceBetweenLabels = messageLabel.topAnchor.constraint(equalTo: headlineLabel.bottomAnchor, constant: spaceBetweenLabelsConstant) spaceBetweenLabels?.isActive = true - leftConstraintTitle = headlineLabel.leftAnchor.constraint(equalTo: view.leftAnchor) - leftConstraintTitle?.isActive = true - - rightConstraintTitle = view.rightAnchor.constraint(equalTo: headlineLabel.rightAnchor) - rightConstraintTitle?.isActive = true - - leftConstraintMessage = messageLabel.leftAnchor.constraint(equalTo: view.leftAnchor) - leftConstraintMessage?.isActive = true - - rightConstraintMessage = view.rightAnchor.constraint(equalTo: messageLabel.rightAnchor) - rightConstraintMessage?.isActive = true - - view.bottomAnchor.constraint(equalTo: messageLabel.bottomAnchor).isActive = true + NSLayoutConstraint.activate([ + headlineLabel.leadingAnchor.constraint(equalTo: leadingAnchor), + trailingAnchor.constraint(equalTo: headlineLabel.trailingAnchor), + messageLabel.leadingAnchor.constraint(equalTo: leadingAnchor), + trailingAnchor.constraint(equalTo: messageLabel.trailingAnchor), + bottomAnchor.constraint(equalTo: messageLabel.bottomAnchor) + ]) } open override func updateView(_ size: CGFloat) { super.updateView(size) + setSpacing() headlineLabel.updateView(size) messageLabel.updateView(size) - setSpacing() + let padding = MFStyler.defaultHorizontalPadding(forSize: size) * 2 + let maximumTextWidth = (size - (padding + Padding.Four)) + messageLabel.preferredMaxLayoutWidth = maximumTextWidth } //-------------------------------------------------- @@ -146,19 +132,18 @@ open class HeadlineBody: View { // MARK: - MoleculeViewProtocol //-------------------------------------------------- - public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { - return 58 - } + public override class func estimatedHeight(with model: MoleculeModelProtocol, + _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 58 } public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) - guard let headlineBodyModel = model as? HeadlineBodyModel else { return } + guard let model = model as? HeadlineBodyModel else { return } - style(with: headlineBodyModel.style) + style(with: model.style) - headlineLabel.setOptional(with: headlineBodyModel.headline, delegateObject, additionalData) - messageLabel.setOptional(with: headlineBodyModel.body, delegateObject, additionalData) + headlineLabel.setOptional(with: model.headline, delegateObject, additionalData) + messageLabel.setOptional(with: model.body, delegateObject, additionalData) } open override func reset() { From 3872591d50021e8d5eec91d239f963ef7efbdefa Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 1 Feb 2021 14:28:21 -0500 Subject: [PATCH 5/8] rm --- MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift | 6 ------ 1 file changed, 6 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift index 42827e67..9a452e3f 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift @@ -96,10 +96,6 @@ public typealias ActionBlock = () -> () accessibilityCustomActions = [] accessibilityTraits = .staticText -// if #available(iOS 14.0, *) { -// lineBreakStrategy = .init() -// } - let tapGesture = UITapGestureRecognizer(target: self, action: #selector(textLinkTapped)) tapGesture.numberOfTapsRequired = 1 addGestureRecognizer(tapGesture) @@ -916,8 +912,6 @@ extension Label { } } - - // MARK: - extension UITapGestureRecognizer { From a5febf586c21ca6e2497a10263b01e1f20198566 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 1 Feb 2021 14:41:51 -0500 Subject: [PATCH 6/8] updated --- MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift | 7 ------- .../Molecules/VerticalCombinationViews/HeadlineBody.swift | 3 +-- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift index 9a452e3f..4cab6cd7 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift @@ -889,13 +889,6 @@ extension Label { /// Underlines the tappable region and stores the tap logic for interation. private func setTextLinkState(range: NSRange, actionBlock: @escaping ActionBlock) { - if clauses.isEmpty { - // Replace the last whitespace with \u{00A0} No-break space. - if let start = text?.lastIndex(of: " "), let end = text?.index(after: start) { - text?.replaceSubrange(start.. Date: Mon, 1 Feb 2021 14:43:35 -0500 Subject: [PATCH 7/8] updateds --- .../Molecules/VerticalCombinationViews/HeadlineBody.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift index 93eace61..fb744f3e 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift @@ -59,7 +59,7 @@ open class HeadlineBody: View { func stylePageHeader() { headlineLabel.setFontStyle(.BoldTitleLarge) messageLabel.setFontStyle(.RegularBodySmall) - spaceBetweenLabelsConstant = Padding.Two + spaceBetweenLabelsConstant = Padding.One } func styleListItem() { @@ -90,7 +90,9 @@ open class HeadlineBody: View { addSubview(messageLabel) headlineLabel.setContentCompressionResistancePriority(.required, for: .vertical) + headlineLabel.setContentHuggingPriority(.required, for: .vertical) messageLabel.setContentCompressionResistancePriority(.required, for: .vertical) + messageLabel.setContentHuggingPriority(.required, for: .vertical) headlineLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true From 68d9473adcb407af57203938d26a723fbef25256 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 1 Feb 2021 14:45:20 -0500 Subject: [PATCH 8/8] comment --- .../Molecules/VerticalCombinationViews/HeadlineBody.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift index fb744f3e..703793f3 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift @@ -113,6 +113,8 @@ open class HeadlineBody: View { setSpacing() headlineLabel.updateView(size) messageLabel.updateView(size) + + // Provide the label additional size information to help calculate its intrinsic height. let padding = MFStyler.defaultHorizontalPadding(forSize: size) * 2 messageLabel.preferredMaxLayoutWidth = size - padding }