Comment Restructurer le contenu de NSTextView afin que mes caractères de tabulation sont dessinés avec une largeur de 4 caractères

StackOverflow https://stackoverflow.com/questions/2284150

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?

Était-ce utile?

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top