Comment Restructurer le contenu de NSTextView afin que mes caractères de tabulation sont dessinés avec une largeur de 4 caractères
-
21-09-2019 - |
Question
Je travaille avec un NSTextView et l'une des exigences que j'ai est un caractère de tabulation, \ « t », a la même largeur que quatre espaces.
Ainsi, le texte contenu ressemblerait à ceci:
AAAA
AAAA - 1 tab
AAAA - 4 spaces
Et voici comment je réalise ceci:
// done when NSTextView first loaded and when
// delegate's textDidBeginEditing gets called: (perhaps overkill, but is a work in progress).
- (void)updateMyTextViewTextAttributes
{
NSMutableParagraphStyle* paragraphStyle = [[myTextView defaultParagraphStyle] mutableCopy];
if (paragraphStyle == nil) {
paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
}
float charWidth = [[myFont screenFontWithRenderingMode:NSFontDefaultRenderingMode] advancementForGlyph:(NSGlyph) ' '].width;
[paragraphStyle setDefaultTabInterval:(charWidth * 4)];
[paragraphStyle setTabStops:[NSArray array]];
[myTextView setDefaultParagraphStyle:paragraphStyle];
NSMutableDictionary* typingAttributes = [[myTextView typingAttributes] mutableCopy];
[typingAttributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
[typingAttributes setObject:scriptFont forKey:NSFontAttributeName];
[myTextView setTypingAttributes:typingAttributes];
}
Cela permet la mise en page appropriée à afficher avec le texte initial ainsi que de garder le typage attribue la même.
Le problème est que l'utilisateur final peut changer la police. Et quand cela arrive, le texte devient échantillon désaligné. Tout comme le ci-dessous:
[smaller font]
AAAA
AAAA - 1 tab
AAAA - 4 spaces
[larger font]
AAAA
AAAA - 1 tab
AAAA - 4 spaces
Je l'ai essayé d'appeler le setNeedsDisplay de myTextView: OUI comme je l'ai lu qu'il finit par appeler le setNeedsDisplayInRect de NSTextView: avoidAdditionalLayout avec NO pour le paramètre avoidAdditionalLayout. Cela n'a pas changé quoi que ce soit.
Je l'ai essayé d'appeler mes updateMyTextViewTextAttributes appeler quand myTextView a le nouveau jeu de myFont. Cela ne change rien.
J'ai aussi essayé de dire la LayoutManager de myTextView à ensureLayoutForTextContainer pour la textContainer de myTextView. Aucun changement.
À ce stade, je ne suis pas sûr de ce que pour essayer prochain. Toutes les suggestions?
La solution
Douglas Davidson d'Apple m'a fourni le indices pour se rendre à la réponse via la liste email cocoa-dev@apple.lists.com.
J'ai résolu le problème en mettant à jour la fonction updateMyTextViewTextAttributes comme ceci:
- (void)updateMyTextViewTextAttributes
{
NSMutableParagraphStyle* paragraphStyle = [[myTextView defaultParagraphStyle] mutableCopy];
if (paragraphStyle == nil) {
paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
}
float charWidth = [[myFont screenFontWithRenderingMode:NSFontDefaultRenderingMode] advancementForGlyph:(NSGlyph) ' '].width;
[paragraphStyle setDefaultTabInterval:(charWidth * 4)];
[paragraphStyle setTabStops:[NSArray array]];
[myTextView setDefaultParagraphStyle:paragraphStyle];
NSMutableDictionary* typingAttributes = [[myTextView typingAttributes] mutableCopy];
[typingAttributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
[typingAttributes setObject:scriptFont forKey:NSFontAttributeName];
[myTextView setTypingAttributes:typingAttributes];
/** ADDED CODE BELOW **/
NSRange rangeOfChange = NSMakeRange(0, [[myTextView string] length]);
[myTextView shouldChangeTextInRange:rangeOfChange replacementString:nil];
[[myTextView textStorage] setAttributes:typingAttributes range:rangeOfChange];
[myTextView didChangeText];
[paragraphStyle release];
[typingAttributes release];
}
Autres conseils
Avez-vous essayé de calculer l'avancement de l'espace avec advancementForGlyph:
directement sur la police au lieu de la police de l'écran?
float charWidth = [myFont advancementForGlyph:(NSGlyph) ' '].width;
Police d'écran ne sont pas destinés à être utilisés directement en dehors du serveur de fenêtre:
Les polices d'écran sont pour une utilisation directe avec le seul serveur de fenêtre. Ne jamais les utiliser avec des objets du kit d'application, tels que en SetFont: méthodes. En interne, le Kit d'application utilise automatiquement la police d'écran correspondant pour une police objet tant que la vue n'est pas rotation ou mise à l'échelle.