Change the way to draw control invisible in find panel

This commit is contained in:
1024jp 2020-04-02 10:27:41 +09:00
parent 7a443050fc
commit 4994eff0b3
2 changed files with 34 additions and 16 deletions

View File

@ -28,6 +28,7 @@ Change Log
- Fix an issue in scripting with AppleScript/JXA where the application crashed by performing `string in ...` method.
- Fix an issue in scripting with AppleScript/JXA where the contents of a document can rerely be overwritten with the contents of another document window under very specific conditions.
- Fix an issue where the print font name in the Print pane was drawn in black even in the dark mode.
- Fix an issue in the find panel's input fields where invisible control characters were drawn in the normal text color under specific conditions.

View File

@ -33,6 +33,8 @@ final class FindPanelLayoutManager: NSLayoutManager {
private var lineHeight: CGFloat = 0
private var baselineOffset: CGFloat = 0
private var controlVisibilityObserver: UserDefaultsObservation?
// MARK: -
@ -46,6 +48,12 @@ final class FindPanelLayoutManager: NSLayoutManager {
self.baselineOffset = self.defaultBaselineOffset(for: self.font)
self.delegate = self
self.controlVisibilityObserver = UserDefaults.standard.observe(key: .showOtherInvisibleChars) { [unowned self] (_) in
let wholeRange = self.attributedString().range
self.invalidateGlyphs(forCharacterRange: wholeRange, changeInLength: 0, actualCharacterRange: nil)
self.invalidateLayout(forCharacterRange: wholeRange, actualCharacterRange: nil)
}
}
@ -55,6 +63,11 @@ final class FindPanelLayoutManager: NSLayoutManager {
}
deinit {
self.controlVisibilityObserver?.invalidate()
}
// MARK: Layout Manager Methods
@ -63,7 +76,6 @@ final class FindPanelLayoutManager: NSLayoutManager {
if UserDefaults.standard[.showInvisibles] {
let string = self.attributedString().string as NSString
let color = NSColor.tertiaryLabelColor
let defaults = UserDefaults.standard
let showsNewLine = defaults[.showInvisibleNewLine]
@ -94,20 +106,7 @@ final class FindPanelLayoutManager: NSLayoutManager {
case .otherControl:
guard showsOtherInvisibles else { continue }
guard self.textStorage?.attribute(.glyphInfo, at: charIndex, effectiveRange: nil) == nil else { continue }
let glyph = (self.font as CTFont).glyph(for: invisible.symbol)
let controlRange = NSRange(location: charIndex, length: 1)
let baseString = string.substring(with: controlRange)
guard let glyphInfo = NSGlyphInfo(cgGlyph: glyph, for: self.font, baseString: baseString) else { assertionFailure(); continue }
// !!!: The following line can cause crash by binary document.
// It's actually dangerous and to be detoured to modify textStorage while drawing.
// (2015-09 by 1024jp)
self.textStorage?.addAttributes([.glyphInfo: glyphInfo,
.foregroundColor: color], range: controlRange)
continue
self.addTemporaryAttribute(.foregroundColor, value: NSColor.clear, forCharacterRange: NSRange(location: charIndex, length: 1))
}
// calculate position to draw glyph
@ -119,7 +118,7 @@ final class FindPanelLayoutManager: NSLayoutManager {
// draw character
let glyphString = NSAttributedString(string: String(invisible.symbol),
attributes: [.font: self.font,
.foregroundColor: color])
.foregroundColor: NSColor.tertiaryLabelColor])
glyphString.draw(at: point)
}
}
@ -127,6 +126,24 @@ final class FindPanelLayoutManager: NSLayoutManager {
super.drawGlyphs(forGlyphRange: glyphsToShow, at: origin)
}
/// replace control glyph
override func setGlyphs(_ glyphs: UnsafePointer<CGGlyph>, properties props: UnsafePointer<NSLayoutManager.GlyphProperty>, characterIndexes charIndexes: UnsafePointer<Int>, font aFont: NSFont, forGlyphRange glyphRange: NSRange) {
guard UserDefaults.standard[.showOtherInvisibleChars] else {
return super.setGlyphs(glyphs, properties: props, characterIndexes: charIndexes, font: aFont, forGlyphRange: glyphRange)
}
let newGlyphs = UnsafeMutablePointer(mutating: glyphs)
let newProps = UnsafeMutablePointer(mutating: props)
for index in 0..<glyphRange.length where props[index] == .controlCharacter {
newGlyphs[index] = (aFont as CTFont).glyph(for: Invisible.otherControl.symbol)
newProps[index] = []
}
super.setGlyphs(newGlyphs, properties: newProps, characterIndexes: charIndexes, font: aFont, forGlyphRange: glyphRange)
}
}