OSDN Git Service

処理を簡素化
[kcd/KCD.git] / KCD / StrokeTextFieldCell.swift
1 //
2 //  StrokeTextFieldCell.swift
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2017/01/01.
6 //  Copyright © 2017年 Hori,Masaki. All rights reserved.
7 //
8
9 import Cocoa
10
11 final class StrokeTextFieldCell: NSTextFieldCell {
12     
13     private static let boarderWidth: CGFloat = 2.0
14     
15     private let layoutManager: NSLayoutManager
16     private let textContainer: NSTextContainer
17     
18     required init(coder: NSCoder) {
19         
20         layoutManager = NSLayoutManager()
21         textContainer = NSTextContainer()
22         
23         super.init(coder: coder)
24         
25         layoutManager.addTextContainer(textContainer)
26     }
27     
28     override func drawInterior(withFrame cellFrame: NSRect, in controlView: NSView) {
29         
30         let attributedString = attributedStringValue
31         
32         if attributedString.string.hasSuffix("/") {
33             
34             super.drawInterior(withFrame: cellFrame, in: controlView)
35             
36             return
37         }
38         
39         let attribute = attributedString.attributes(at: 0, effectiveRange: nil)
40         
41         guard let forgroundColor = attribute[NSForegroundColorAttributeName] as? NSColor
42             else { return }
43         
44         if forgroundColor == NSColor.controlTextColor {
45             
46             super.drawInterior(withFrame: cellFrame, in: controlView)
47             
48             return
49         }
50         
51         guard let font = attribute[NSFontAttributeName] as? NSFont
52             else { return }
53         
54         let textStorage = NSTextStorage(string: attributedString.string, attributes: attribute)
55         textStorage.addLayoutManager(layoutManager)
56         let range = layoutManager.glyphRange(for: textContainer)
57         let glyph = UnsafeMutablePointer<CGGlyph>.allocate(capacity: range.length)
58         let glyphLength = layoutManager.getGlyphs(in: range,
59                                                   glyphs: glyph,
60                                                   properties: nil,
61                                                   characterIndexes: nil,
62                                                   bidiLevels: nil)
63         var point = NSPoint(x: StrokeTextFieldCell.boarderWidth, y: 0)
64         point.y -= font.descender
65         
66         if controlView.isFlipped {
67             
68             point.y -= controlView.frame.height
69         }
70         
71         let nsGlyph = UnsafeMutablePointer<NSGlyph>.allocate(capacity: range.length)
72         
73         (0..<range.length).forEach { nsGlyph[$0] = NSGlyph(glyph[$0]) }
74         
75         let path = NSBezierPath()
76         path.move(to: point)
77         path.appendGlyphs(nsGlyph, count: glyphLength, in: font)
78         path.lineWidth = StrokeTextFieldCell.boarderWidth
79         path.lineJoinStyle = .roundLineJoinStyle
80         
81         if controlView.isFlipped {
82             
83             var affineTransform = AffineTransform()
84             affineTransform.scale(x: 1, y: -1)
85             path.transform(using: affineTransform)
86         }
87         
88         NSColor.black.set()
89         path.stroke()
90         forgroundColor.set()
91         path.fill()
92         
93         textStorage.removeLayoutManager(layoutManager)
94     }
95 }