From 277a67184fe62a9e4e12e4edcb34cb5aefe5b829 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 18 Mar 2024 16:55:28 -0500 Subject: [PATCH] added images Signed-off-by: Matt Bruce --- .../Buttons/TextLinkCaret/TextLinkCaret.swift | 113 +++++++++--------- 1 file changed, 56 insertions(+), 57 deletions(-) diff --git a/VDS/Components/Buttons/TextLinkCaret/TextLinkCaret.swift b/VDS/Components/Buttons/TextLinkCaret/TextLinkCaret.swift index f02d2b10..f476f40b 100644 --- a/VDS/Components/Buttons/TextLinkCaret/TextLinkCaret.swift +++ b/VDS/Components/Buttons/TextLinkCaret/TextLinkCaret.swift @@ -40,8 +40,11 @@ open class TextLinkCaret: ButtonBase { /// Enum used to describe the position of the icon in relation to the title label. public enum IconPosition: String, CaseIterable { case left, right + var image: UIImage { + UIImage.image(for: self == .left ? .leftCaretBold : .rightCaretBold)! + } } - + //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- @@ -51,19 +54,12 @@ open class TextLinkCaret: ButtonBase { $0.setSurfaceColors(VDSColor.interactiveActiveOnlight, VDSColor.interactiveActiveOndark, forState: .highlighted) } - private var imageAttribute: CaretLabelAttribute? - //-------------------------------------------------- // MARK: - Public Properties - //-------------------------------------------------- + //-------------------------------------------------- /// Determines icon position of Caret. open var iconPosition: IconPosition = .right { didSet { setNeedsUpdate() } } - open override var textAttributes: [any LabelAttributeModel]? { - guard let imageAttribute else { return nil } - return [imageAttribute] - } - /// UIColor used on the titleLabel text. open override var textColor: UIColor { textColorConfiguration.getColor(self) @@ -72,7 +68,7 @@ open class TextLinkCaret: ButtonBase { open override var textStyle: TextStyle { TextStyle.boldBodyLarge } - + //-------------------------------------------------- // MARK: - Overrides //-------------------------------------------------- @@ -83,7 +79,7 @@ open class TextLinkCaret: ButtonBase { //left align titleLabel in case this is pinned leading/trailing //default is always set to center contentHorizontalAlignment = .left - + accessibilityTraits = .link titleLabel?.numberOfLines = 0 titleLabel?.lineBreakMode = .byWordWrapping @@ -91,7 +87,7 @@ open class TextLinkCaret: ButtonBase { /// Used to make changes to the View based off a change events or from local properties. open override func updateView() { - imageAttribute = CaretLabelAttribute(tintColor: textColor, position: iconPosition) + setImage(iconPosition.image.withTintColor(textColor), for: .normal) super.updateView() } @@ -103,51 +99,54 @@ open class TextLinkCaret: ButtonBase { } /// The natural size for the receiving view, considering only properties of the view itself. - open override var intrinsicContentSize: CGSize { - guard let titleLabel else { return super.intrinsicContentSize } - // Calculate the titleLabel's intrinsic content size - let labelSize = titleLabel.sizeThatFits(CGSize(width: self.frame.width, height: CGFloat.greatestFiniteMagnitude)) - // Adjust the size if needed (add any additional padding if your design requires) - let adjustedSize = CGSize(width: labelSize.width + contentEdgeInsets.left + contentEdgeInsets.right, - height: labelSize.height + contentEdgeInsets.top + contentEdgeInsets.bottom) - return adjustedSize + // Property to specify the icon size + private var imageSize: CGSize = Icon.Size.xsmall.dimensions + + open override func layoutSubviews() { + super.layoutSubviews() + guard let titleLabel = titleLabel, let imageView = imageView else { return } + + // Adjust imageView size based on the imageSize property + imageView.frame.size = imageSize + + let space: CGFloat = 5 // Space between the icon and the text + + // Adjust icon and text positions based on the iconPosition + switch iconPosition { + case .left: + imageView.frame.origin.x = bounds.minX + contentEdgeInsets.left + imageView.frame.origin.y = titleLabel.frame.minY + (textStyle.lineHeight - imageSize.height) / 2.0 + titleLabel.frame.origin.x = imageView.frame.maxX + space + + case .right: + + guard let attribtedText = titleLabel.attributedText else { return } + + let textContainer = NSTextContainer(size: CGSize(width: titleLabel.bounds.width, height: CGFloat.greatestFiniteMagnitude)) + textContainer.lineFragmentPadding = 0 + + let layoutManager = NSLayoutManager() + layoutManager.addTextContainer(textContainer) + + let textStorage = NSTextStorage(attributedString: attribtedText) + textStorage.addLayoutManager(layoutManager) + + let lastGlyphIndex = layoutManager.glyphIndexForCharacter(at: attribtedText.string.utf16.count - 1) + var lastGlyphRect = layoutManager.boundingRect(forGlyphRange: NSRange(location: lastGlyphIndex, length: 1), in: textContainer) + + lastGlyphRect.origin.x += titleLabel.frame.origin.x + lastGlyphRect.origin.y += titleLabel.frame.origin.y + + imageView.frame.origin.x = lastGlyphRect.maxX + space + imageView.frame.origin.y = lastGlyphRect.midY - imageSize.height / 2 + + } + + imageView.contentMode = .scaleAspectFit + } + + private var space: CGFloat { + return 5 // Space between the icon and text, used in multiple places } } -extension TextLinkCaret { - struct CaretLabelAttribute: LabelAttributeModel { - var id: UUID = .init() - var location: Int = 0 - var length: Int = 1 - var tintColor: UIColor - var position: IconPosition - var spacerWidth: CGFloat = 4.0 - var width: CGFloat { caretSize.width + spacerWidth } - var caretSize: CGSize { Icon.Size.xsmall.dimensions } - - init(tintColor: UIColor, position: IconPosition) { - self.tintColor = tintColor - self.position = position - } - - func setAttribute(on attributedString: NSMutableAttributedString) { - let imageAttr = ImageLabelAttribute(location: location, imageName: "\(position.rawValue)-caret-bold", frame: .init(x: 0, y: 0, width: caretSize.width, height: caretSize.height), tintColor: tintColor) - let spacer = NSAttributedString.spacer(for: spacerWidth) - - guard let image = try? imageAttr.getAttachment() else { return } - - if position == .right { - attributedString.append(spacer) - attributedString.append(NSAttributedString(attachment: image)) - } else { - attributedString.insert(NSAttributedString(attachment: image), at: 0) - attributedString.insert(spacer, at: 1) - } - } - - func isEqual(_ equatable: CaretLabelAttribute) -> Bool { - return id == equatable.id && range == equatable.range - } - - } -}