Skip to content

Instantly share code, notes, and snippets.

@leonbreedt
Last active June 6, 2016 08:13
Show Gist options
  • Save leonbreedt/b669c00cc17e70e89a232559dfca7d6f to your computer and use it in GitHub Desktop.
Save leonbreedt/b669c00cc17e70e89a232559dfca7d6f to your computer and use it in GitHub Desktop.
Simple attributed string styles
import Cocoa
/// Enumerates the types of fonts supported for attributed strings.
enum TextFontType {
case System
case Named(String)
}
/// Describes font attributes that can be applied to attributed strings.
struct TextFont {
let type: TextFontType
let size: Float
let bold: Bool
let italic: Bool
}
/// Describes colors that can be applied to text in attributed strings.
struct TextColor {
let foreground: NSColor?
let background: NSColor?
}
/// Aggregates all style attributes that can be applied to text in attributed strings.
struct TextStyle {
let font: TextFont
let color: TextColor
let underline: Bool
let strikethrough: Bool
}
/// Protocol for composing text styles in a fluent manner.
protocol TextStyleConfigurable {
func font(type: TextFontType, size: Float, bold: Bool, italic: Bool) -> Self
func font(font: NSFont) -> Self
func underline() -> Self
func strikethrough() -> Self
func foreground(color: NSColor) -> Self
func background(color: NSColor) -> Self
}
final class AttributedTextStyle: TextStyleConfigurable {
private var attributes: [String: NSObject] = [:]
func font(type: TextFontType = .System,
size: Float = Float(NSFont.systemFontSize()),
bold: Bool = false,
italic: Bool = false) -> Self {
let pointSize = CGFloat(size)
let systemFont = NSFont.systemFontOfSize(pointSize)
var font: NSFont
switch type {
case .System:
font = systemFont
case let .Named(name):
font = NSFont(name: name, size: pointSize) ?? systemFont
}
let fontManager = NSFontManager.sharedFontManager()
if bold {
font = fontManager.convertFont(font, toHaveTrait: .BoldFontMask)
}
if italic {
font = fontManager.convertFont(font, toHaveTrait: .ItalicFontMask)
}
self.font(font)
return self
}
func font(font: NSFont) -> Self {
attributes[NSFontAttributeName] = font
return self
}
func underline() -> Self {
attributes[NSUnderlineStyleAttributeName] = 1
return self
}
func strikethrough() -> Self {
attributes[NSStrikethroughStyleAttributeName] = 1
return self
}
func foreground(color: NSColor) -> Self {
attributes[NSForegroundColorAttributeName] = color
return self
}
func background(color: NSColor) -> Self {
attributes[NSBackgroundColorAttributeName] = color
return self
}
}
typealias AttributedTextStyleBlock = AttributedTextStyle -> Void
extension NSMutableAttributedString {
/// Appends a string to this attributed string, after applying the styles provided by the
/// configuration block, if any.
func append(string: String, _ styleConfigurationBlock: AttributedTextStyleBlock? = nil) {
let style = AttributedTextStyle()
styleConfigurationBlock?(style)
appendAttributedString(NSMutableAttributedString(string: string, attributes: style.attributes))
}
}
let boldWhiteAvenirOnRed: AttributedTextStyleBlock = { style in
style
.font(.Named("Avenir"), size: 18, bold: true)
.background(NSColor.redColor())
.foreground(NSColor.whiteColor())
}
// Let's try!
let string = NSMutableAttributedString()
string.append("CocoaPods", boldWhiteAvenirOnRed)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment