83 lines
2.8 KiB
Swift
83 lines
2.8 KiB
Swift
//
|
|
// LabelAttributeModel.swift
|
|
// VDS
|
|
//
|
|
// Created by Matt Bruce on 8/3/22.
|
|
//
|
|
|
|
import Foundation
|
|
import UIKit
|
|
|
|
public protocol LabelAttributeModel: AnyEquatable, Withable, Equatable, Identifiable where ID == UUID {
|
|
/// Position of the starting point for this LabelAttribute.
|
|
var location: Int { get set }
|
|
|
|
/// Length from the location.
|
|
var length: Int { get set }
|
|
|
|
/// Applies the attribute to the attributedString that is given.
|
|
/// - Parameter attributedString: AttributedString that the attributed is applied.
|
|
func setAttribute(on attributedString: NSMutableAttributedString)
|
|
}
|
|
|
|
extension LabelAttributeModel {
|
|
/// Range for this AttributeModel
|
|
public var range: NSRange {
|
|
NSRange(location: location, length: length)
|
|
}
|
|
|
|
public static func == (lhs: any LabelAttributeModel, rhs: any LabelAttributeModel) -> Bool {
|
|
lhs.isEqual(rhs)
|
|
}
|
|
|
|
public func isValidRange(on attributedString: NSMutableAttributedString) -> Bool {
|
|
attributedString.isValid(range: range)
|
|
}
|
|
}
|
|
|
|
public extension String {
|
|
func isValid(range: NSRange) -> Bool {
|
|
range.location >= 0 && range.length > 0 && range.location + range.length <= count
|
|
}
|
|
}
|
|
|
|
public extension NSAttributedString {
|
|
func isValid(range: NSRange) -> Bool {
|
|
range.location >= 0 && range.length > 0 && range.location + range.length <= length
|
|
}
|
|
|
|
func createAttributeModels() -> [(any LabelAttributeModel)] {
|
|
var attributes: [any VDS.LabelAttributeModel] = []
|
|
enumerateAttributes(in: NSMakeRange(0, length)) { attributeMap, range, stop in
|
|
attributeMap.forEach { (key: NSAttributedString.Key, value: Any) in
|
|
if let attribute = NSAttributedString.createAttributeModelFor(key: key, range: range, value: value) {
|
|
attributes.append(attribute)
|
|
}
|
|
}
|
|
}
|
|
return attributes
|
|
}
|
|
|
|
static func createAttributeModelFor(key: NSAttributedString.Key, range: NSRange, value: Any) -> (any LabelAttributeModel)? {
|
|
guard let value = value as? AnyHashable else { return nil }
|
|
|
|
guard let font = value as? UIFont, let style = TextStyle.style(for: font.fontName, size: font.pointSize), key == .font
|
|
else {
|
|
return AnyAttribute(location: range.location, length: range.length, key: key, value: value)
|
|
}
|
|
return TextStyleLabelAttribute(location: range.location, length: range.length, textStyle: style)
|
|
}
|
|
}
|
|
|
|
extension NSMutableAttributedString {
|
|
public func apply(attribute: any LabelAttributeModel) {
|
|
guard isValid(range: attribute.range) else { return }
|
|
attribute.setAttribute(on: self)
|
|
}
|
|
|
|
public func apply(attributes: [any LabelAttributeModel]) {
|
|
attributes.forEach { apply(attribute: $0) }
|
|
}
|
|
}
|
|
|