From c2d200e7f2e43dacd60e471c9b09c1957bc81407 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 8 May 2023 16:08:04 -0500 Subject: [PATCH] fixed textlinkcaret issue Signed-off-by: Matt Bruce --- .../Buttons/TextLinkCaret/TextLinkCaret.swift | 231 +++--------------- 1 file changed, 32 insertions(+), 199 deletions(-) diff --git a/VDS/Components/Buttons/TextLinkCaret/TextLinkCaret.swift b/VDS/Components/Buttons/TextLinkCaret/TextLinkCaret.swift index 52864cf6..6f2ea51d 100644 --- a/VDS/Components/Buttons/TextLinkCaret/TextLinkCaret.swift +++ b/VDS/Components/Buttons/TextLinkCaret/TextLinkCaret.swift @@ -28,11 +28,7 @@ open class TextLinkCaret: ButtonBase { TextStyle.boldBodyLarge } - private var caretView = CaretView().with { - $0.size = CaretView.Size.small(.vertical) - $0.lineWidth = 2 - } - private var imageAttribute: ImageLabelAttribute? + private var imageAttribute: ImageSpaceLabelAttribute? open override var attributes: [any LabelAttributeModel]? { guard let imageAttribute else { return nil } @@ -49,19 +45,7 @@ open class TextLinkCaret: ButtonBase { private var height: CGFloat { 44 } - - private var _text: String? - - open override var text: String? { - get{ _text } - set { - var updatedText = newValue ?? "" - updatedText = iconPosition == .right ? "\(updatedText) " : " \(updatedText)" - _text = updatedText - setNeedsUpdate() - } - } - + open override var textColor: UIColor { textColorConfiguration.getColor(self) } @@ -92,9 +76,6 @@ open class TextLinkCaret: ButtonBase { //-------------------------------------------------- open override func setup() { super.setup() - - let size = caretView.size!.dimensions() - caretView.frame = .init(x: 0, y: 0, width: size.width, height: size.height) } open override func reset() { @@ -112,204 +93,56 @@ open class TextLinkCaret: ButtonBase { var itemWidth = size.width - if let caretWidth = caretView.size?.dimensions().width { + if let caretWidth = imageAttribute?.width { itemWidth += caretWidth } return CGSize(width: itemWidth, height: size.height) } open override func updateView() { - let updatedText = text ?? "" - caretView.surface = surface - caretView.disabled = disabled - caretView.direction = iconPosition == .right ? CaretView.Direction.right : CaretView.Direction.left - - let image = caretView.getImage() - let location = iconPosition == .right ? updatedText.count : 0 - - imageAttribute = ImageLabelAttribute(location: location, - image: image, - tintColor: textColor) + + imageAttribute = ImageSpaceLabelAttribute(tintColor: textColor, position: iconPosition) super.updateView() } } -extension UIView { - public func getImage() -> UIImage { - let renderer = UIGraphicsImageRenderer(size: self.bounds.size) - let image = renderer.image { ctx in - self.drawHierarchy(in: self.bounds, afterScreenUpdates: true) - } - return image - } -} +extension TextLinkCaret { + struct ImageSpaceLabelAttribute: LabelAttributeModel { + var id: UUID = .init() + var location: Int = 0 + var length: Int = 1 + var tintColor: UIColor + var position: IconPosition + var spacerWidth: CGFloat = 2.0 + var width: CGFloat { caretSize.width + spacerWidth } + var caretSize: CGSize { Icon.Size.xsmall.dimensions } -internal class CaretView: View { - //------------------------------------------------------ - // MARK: - Properties - //------------------------------------------------------ - private var caretPath: UIBezierPath = UIBezierPath() - - public var lineWidth: CGFloat = 1 { didSet{ setNeedsUpdate() } } - - public var direction: Direction = .right { didSet{ setNeedsUpdate() } } - - public var size: Size? { didSet{ setNeedsUpdate() } } - - public var colorConfiguration: AnyColorable = ViewColorConfiguration().with { - $0.setSurfaceColors(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark, forDisabled: true) - $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false) - }.eraseToAnyColorable() - - - //------------------------------------------------------ - // MARK: - Constraints - //------------------------------------------------------ - - /// Sizes of CaretView are derived from InVision design specs. They are provided for convenience. - public enum Size { - case small(Orientation) - case medium(Orientation) - case large(Orientation) - - /// Orientation based on the longest line of the view. - public enum Orientation { - case vertical - case horizontal + init(tintColor: UIColor, position: IconPosition) { + self.tintColor = tintColor + self.position = position } - /// Dimensions of container; provided by InVision design. - func dimensions() -> CGSize { + 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 spaceAttr = ImageLabelAttribute(location: 0, imageName: "info", frame: .init(x: 0, y: 0, width: spacerWidth, height: 5.0), tintColor: .clear) - switch self { - case .small(let o): - return o == .vertical ? CGSize(width: 6.9, height: 10.96) : CGSize(width: 10.96, height: 6.9) - - case .medium(let o): - return o == .vertical ? CGSize(width: 9.9, height: 16.96) : CGSize(width: 16.96, height: 9.9) - - case .large(let o): - return o == .vertical ? CGSize(width: 14.9, height: 24.96) : CGSize(width: 24.96, height: 14.9) + guard let image = try? imageAttr.getAttachment(), + let spacer = try? spaceAttr.getAttachment() else { return } + + if position == .right { + attributedString.append(NSAttributedString(attachment: spacer)) + attributedString.append(NSAttributedString(attachment: image)) + } else { + attributedString.insert(NSAttributedString(attachment: image), at: 0) + attributedString.insert(NSAttributedString(attachment: spacer), at: 1) } } - } - - //------------------------------------------------------ - // MARK: - Initialization - //------------------------------------------------------ - - public override init(frame: CGRect) { - super.init(frame: frame) - } - - public convenience init(lineWidth: CGFloat) { - self.init(frame: .zero) - self.lineWidth = lineWidth - } - - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - fatalError("CaretView xib not supported.") - } - - required public convenience init() { - self.init(frame: .zero) - } - - public convenience init(size: Size){ - let dimensions = size.dimensions() - self.init(frame: .init(x: 0, y: 0, width: dimensions.width, height: dimensions.height)) - self.size = size - } - - //------------------------------------------------------ - // MARK: - Setup - //------------------------------------------------------ - - override open func setup() { - super.setup() - defaultState() - isAccessibilityElement = true - accessibilityTraits = .link - } - - //------------------------------------------------------ - // MARK: - Drawing - //------------------------------------------------------ - - /// The direction the caret will be pointing to. - public enum Direction: Int { - case left - case right - case down - case up - } - - override func draw(_ rect: CGRect) { - super.draw(rect) - - caretPath.removeAllPoints() - caretPath.lineJoinStyle = .miter - caretPath.lineWidth = lineWidth - - let inset = lineWidth / 2 - let halfWidth = frame.size.width / 2 - let halfHeight = frame.size.height / 2 - - switch direction { - case .up: - caretPath.move(to: CGPoint(x: inset, y: frame.size.height - inset)) - caretPath.addLine(to: CGPoint(x: halfWidth, y: inset)) - caretPath.addLine(to: CGPoint(x: frame.size.width, y: frame.size.height)) - - case .right: - caretPath.move(to: CGPoint(x: inset, y: inset)) - caretPath.addLine(to: CGPoint(x: frame.size.width - inset, y: halfHeight)) - caretPath.addLine(to: CGPoint(x: inset, y: frame.size.height - inset)) - - case .down: - caretPath.move(to: CGPoint(x: inset, y: inset)) - caretPath.addLine(to: CGPoint(x: halfWidth, y: frame.size.height - inset)) - caretPath.addLine(to: CGPoint(x: frame.size.width - inset, y: inset)) - - case .left: - caretPath.move(to: CGPoint(x: frame.size.width - inset, y: inset)) - caretPath.addLine(to: CGPoint(x: inset, y: halfHeight)) - caretPath.addLine(to: CGPoint(x: frame.size.width - inset, y: frame.size.height - inset)) + func isEqual(_ equatable: ImageSpaceLabelAttribute) -> Bool { + return id == equatable.id && range == equatable.range } - - let color = colorConfiguration.getColor(self) - color.setStroke() - caretPath.stroke() - } - - override func updateView() { - setNeedsDisplay() - } - - //------------------------------------------------------ - // MARK: - Methods - //------------------------------------------------------ - public func setLineColor(_ color: UIColor) { - setNeedsDisplay() - } - - public func defaultState() { - isOpaque = false - isHidden = false - backgroundColor = .clear - } - - /// Ensure you have defined a CaretSize with Orientation before calling. - public func setConstraints() { - - guard let dimensions = size?.dimensions() else { return } - - heightAnchor.constraint(equalToConstant: dimensions.height).isActive = true - widthAnchor.constraint(equalToConstant: dimensions.width).isActive = true } }