Я работаю с подклассом NSTextView и хотел бы знать индекс символа рядом с текущей точкой вставки.Более конкретно, я хочу получить их индекс символов для перемещения курсора с помощью клавиши со стрелкой, но без использования семейства moveLeft(_:)
или moveRight(_:)
NSResponder.
Это легко с помощью обычного горизонтального однонаправленного текстапотому что index-1
- это левый, а index+1
- правый (если вы забудете, что буквы состоят из нескольких символов).Тем не менее, при использовании двунаправленного текста, в котором смешаны слева направо и справа налево, порядок визуальных символов, отображаемый в представлении, не совпадает с фактическим индексом символов.
Реализация NSTextView по умолчанию, кажется, как-то выполняет биди-текст.Поэтому я хотел бы получить такое же поведение перемещения курсора NSTextView, но я не смог найти подходящий публичный API для него.
До сих пор я нашел метод NSLayoutManager getGlyphs(in:glyphs:properties:characterIndexes:bidiLevels:)
, который кажется правильным методом дляполучить биди состояниеПоэтому я написал метод расширения, подобный следующему.Но тогда, даже если бы я мог получить состояние RTL определенного местоположения, я не уверен, что индекс символа следующего, когда индекс находится на границе букв RTL и LTR.
extension NSLayoutManager {
func isRTL(at index: Int) -> Bool {
let glyphIndex = self.glyphIndexForCharacter(at: index)
guard glyphIndex > 0 else { return false }
var bidiLevels: [UInt8] = [0]
self.getGlyphs(in: NSRange((glyphIndex-1)..<glyphIndex), glyphs: nil, properties: nil, characterIndexes: nil, bidiLevels: &bidiLevels)
return (bidiLevels[0] % 2 == 1)
}
}
Другой подходчто я сейчас пытаюсь получить его из координаты вида, как показано ниже.Но затем метод пропускает символы нулевой ширины.
extension NSTextView {
func leftIndex(of index: Int) -> Int {
guard
let layoutManager = self.layoutManager,
let textContainer = self.textContainer
else { assertionFailure(); return index }
let glyphIndex = layoutManager.glyphIndexForCharacter(at: index)
let rect = layoutManager.boundingRect(forGlyphRange: NSRange(glyphIndex..<(glyphIndex+1)), in: textContainer)
.offset(by: self.textContainerOrigin)
let point = NSPoint(x: rect.minX - 1, y: rect.midY)
return self.characterIndexForInsertion(at: point)
}
}
У кого-нибудь есть идея выполнить мое требование?