J'écris un éditeur de texte pour Mac OS X. J'ai besoin d'afficher les caractères cachés dans un NSTextView (comme les espaces, les tabulations et les caractères spéciaux). J'ai passé beaucoup de temps à chercher comment faire cela, mais je n'ai pas encore trouvé de réponse. Si quelqu'un pouvait m'indiquer la bonne direction, je lui en serais reconnaissant.
Réponses
Trop de publicités?Voici une mise en œuvre entièrement fonctionnelle et propre
@interface GILayoutManager : NSLayoutManager
@end
@implementation GILayoutManager
- (void)drawGlyphsForGlyphRange:(NSRange)range atPoint:(NSPoint)point {
NSTextStorage* storage = self.textStorage;
NSString* string = storage.string;
for (NSUInteger glyphIndex = range.location; glyphIndex < range.location + range.length; glyphIndex++) {
NSUInteger characterIndex = [self characterIndexForGlyphAtIndex: glyphIndex];
switch ([string characterAtIndex:characterIndex]) {
case ' ': {
NSFont* font = [storage attribute:NSFontAttributeName atIndex:characterIndex effectiveRange:NULL];
[self replaceGlyphAtIndex:glyphIndex withGlyph:[font glyphWithName:@"periodcentered"]];
break;
}
case '\n': {
NSFont* font = [storage attribute:NSFontAttributeName atIndex:characterIndex effectiveRange:NULL];
[self replaceGlyphAtIndex:glyphIndex withGlyph:[font glyphWithName:@"carriagereturn"]];
break;
}
}
}
[super drawGlyphsForGlyphRange:range atPoint:point];
}
@end
Pour l'installation, utilisez :
[myTextView.textContainer replaceLayoutManager:[[GILayoutManager alloc] init]];
Pour trouver les noms des glyphes des polices, il faut aller dans CoreGraphics :
CGFontRef font = CGFontCreateWithFontName(CFSTR("Menlo-Regular"));
for (size_t i = 0; i < CGFontGetNumberOfGlyphs(font); ++i) {
printf("%s\n", [CFBridgingRelease(CGFontCopyGlyphNameForGlyph(font, i)) UTF8String]);
}
Jetez un coup d'œil à la classe NSLayoutManager. Votre NSTextView sera associé à un gestionnaire de mise en page, qui est chargé d'associer un caractère (espace, tabulation, etc.) à un glyphe (l'image de ce caractère dessinée à l'écran).
Dans votre cas, vous seriez sans doute plus intéressé par la rubrique [replaceGlyphAtIndex:withGlyph:](http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSLayoutManager_Class/Reference/Reference.html#//apple_ref/occ/instm/NSLayoutManager/replaceGlyphAtIndex:withGlyph:)
qui vous permettrait de remplacer des glyphes individuels.
J'ai écrit un éditeur de texte il y a quelques années - voici un code insignifiant qui devrait vous permettre de chercher (avec un peu de chance) dans la bonne direction (il s'agit d'une sous-classe de NSLayoutManager - et oui, je sais qu'elle fuit comme l'évier de cuisine proverbial) :
- (void)drawGlyphsForGlyphRange:(NSRange)glyphRange atPoint:(NSPoint)containerOrigin
{
if ([[[[MJDocumentController sharedDocumentController] currentDocument] editor] showInvisibles])
{
//init glyphs
unichar crlf = 0x00B6;
NSString *CRLF = [[NSString alloc] initWithCharacters:&crlf length:1];
unichar space = 0x00B7;
NSString *SPACE = [[NSString alloc] initWithCharacters:&space length:1];
unichar tab = 0x2192;
NSString *TAB = [[NSString alloc] initWithCharacters:&tab length:1];
NSString *docContents = [[self textStorage] string];
NSString *glyph;
NSPoint glyphPoint;
NSRect glyphRect;
NSDictionary *attr = [[NSDictionary alloc] initWithObjectsAndKeys:[NSUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:@"invisiblesColor"]], NSForegroundColorAttributeName, nil];
//loop thru current range, drawing glyphs
int i;
for (i = glyphRange.location; i < NSMaxRange(glyphRange); i++)
{
glyph = @"";
//look for special chars
switch ([docContents characterAtIndex:i])
{
//space
case ' ':
glyph = SPACE;
break;
//tab
case '\t':
glyph = TAB;
break;
//eol
case 0x2028:
case 0x2029:
case '\n':
case '\r':
glyph = CRLF;
break;
//do nothing
default:
glyph = @"";
break;
}
//should we draw?
if ([glyph length])
{
glyphPoint = [self locationForGlyphAtIndex:i];
glyphRect = [self lineFragmentRectForGlyphAtIndex:i effectiveRange:NULL];
glyphPoint.x += glyphRect.origin.x;
glyphPoint.y = glyphRect.origin.y;
[glyph drawAtPoint:glyphPoint withAttributes:attr];
}
}
}
[super drawGlyphsForGlyphRange:glyphRange atPoint:containerOrigin];
}
J'ai résolu le problème de la conversion entre les NSGlyphes et l'unichar correspondant dans le NSTextView. Le code ci-dessous fonctionne à merveille et remplace les espaces par des puces pour le texte visible :
- (void)drawGlyphsForGlyphRange:(NSRange)range atPoint:(NSPoint)origin
{
NSFont *font = [[CURRENT_TEXT_VIEW typingAttributes]
objectForKey:NSFontAttributeName];
NSGlyph bullet = [font glyphWithName:@"bullet"];
for (int i = range.location; i != range.location + range.length; i++)
{
unsigned charIndex = [self characterIndexForGlyphAtIndex:i];
unichar c =[[[self textStorage] string] characterAtIndex:charIndex];
if (c == ' ')
[self replaceGlyphAtIndex:charIndex withGlyph:bullet];
}
[super drawGlyphsForGlyphRange:range atPoint:origin];
}
- Réponses précédentes
- Plus de réponses