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,
45 characterIndexes: nil,
47 var point = NSPoint(x: StrokeTextFieldCell.boarderWidth, y: 0)
48 point.y -= font.descender
49 if controlView.isFlipped {
50 point.y -= controlView.frame.height
52 let nsGlyph = UnsafeMutablePointer<NSGlyph>.allocate(capacity: range.length)
53 for i in 0...range.length {
54 nsGlyph[i] = NSGlyph(glyph[i])
57 let path = NSBezierPath()
59 path.appendGlyphs(nsGlyph, count: glyphLength, in: font)
60 path.lineWidth = StrokeTextFieldCell.boarderWidth
61 path.lineJoinStyle = .roundLineJoinStyle
62 if controlView.isFlipped {
63 var affineTransform = AffineTransform()
64 affineTransform.scale(x: 1, y: -1)
65 path.transform(using: affineTransform)
73 textStorage.removeLayoutManager(layoutManager)