2 // StrokeTextFieldCell.swift
5 // Created by Hori,Masaki on 2017/01/01.
6 // Copyright © 2017年 Hori,Masaki. All rights reserved.
11 class StrokeTextFieldCell: NSTextFieldCell {
12 private static let boarderWidth: CGFloat = 2.0
14 private let layoutManager: NSLayoutManager
15 private let textContainer: NSTextContainer
17 required init(coder: NSCoder) {
18 layoutManager = NSLayoutManager()
19 textContainer = NSTextContainer()
20 super.init(coder: coder)
21 layoutManager.addTextContainer(textContainer)
24 override func drawInterior(withFrame cellFrame: NSRect, in controlView: NSView) {
25 let attributedString = attributedStringValue
26 if attributedString.string.hasSuffix("/") {
27 super.drawInterior(withFrame: cellFrame, in: controlView)
30 let attribute = attributedString.attributes(at: 0, effectiveRange: nil)
31 guard let forgroundColor = attribute[NSForegroundColorAttributeName] as? NSColor else { return }
32 if forgroundColor == NSColor.controlTextColor {
33 super.drawInterior(withFrame: cellFrame, in: controlView)
36 guard let font = attribute[NSFontAttributeName] as? NSFont else { return }
38 let textStorage = NSTextStorage(string: attributedString.string, attributes: attribute)
39 textStorage.addLayoutManager(layoutManager)
40 let range = layoutManager.glyphRange(for: textContainer)
41 let glyph = UnsafeMutablePointer<CGGlyph>.allocate(capacity: range.length)
42 let glyphLength = layoutManager.getGlyphs(in: range, glyphs: glyph, properties: nil, characterIndexes: nil, bidiLevels: nil)
43 var point = NSPoint(x: StrokeTextFieldCell.boarderWidth, y: 0)
44 point.y -= font.descender
45 if controlView.isFlipped {
46 point.y -= NSHeight(controlView.frame)
48 let nsGlyph = UnsafeMutablePointer<NSGlyph>.allocate(capacity: range.length)
49 for i in 0...range.length {
50 nsGlyph[i] = NSGlyph(glyph[i])
53 let path = NSBezierPath()
55 path.appendGlyphs(nsGlyph, count: glyphLength, in: font)
56 path.lineWidth = StrokeTextFieldCell.boarderWidth
57 path.lineJoinStyle = .roundLineJoinStyle
58 if controlView.isFlipped {
59 var affineTransform = AffineTransform()
60 affineTransform.scale(x: 1, y: -1)
61 path.transform(using: affineTransform)
69 textStorage.removeLayoutManager(layoutManager)