سؤال

وأنا أكتب محرر نص لنظام التشغيل Mac OS X. أحتاج لعرض الأحرف المخفية في NSTextView (مثل المسافات وعلامات التبويب وأحرف خاصة). لقد قضيت الكثير من الوقت في البحث عن كيفية القيام بذلك ولكن حتى الآن لم أجد جوابا. إذا كان أي شخص يمكن أن تشير لي في الاتجاه الصحيح وسأكون ممتنا.

هل كانت مفيدة؟

المحلول

وإلقاء نظرة على الطبقة NSLayoutManager. سوف NSTextView لديك مدير تخطيط المرتبطة به، ومدير التخطيط هو المسؤول عن اقتران حرف (مساحة، التبويب، الخ) مع رسومي (صورة تلك الشخصية المرسومة على الشاشة).

في حالة الخاص بك، فإنك ربما يكون الأكثر اهتماما في طريقة replaceGlyphAtIndex:withGlyph:، التي من شأنها أن تسمح لك لتحل محل رموزا الفردية.

نصائح أخرى

وهنا لتنفيذ العمل ونظيفة تماما

@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

لتثبيت واستخدام:

[myTextView.textContainer replaceLayoutManager:[[GILayoutManager alloc] init]];

لتجد أسماء الشكل المنقوش الخط، عليك أن تذهب إلى CoreGraphics:

CGFontRef font = CGFontCreateWithFontName(CFSTR("Menlo-Regular"));
for (size_t i = 0; i < CGFontGetNumberOfGlyphs(font); ++i) {
  printf("%s\n", [CFBridgingRelease(CGFontCopyGlyphNameForGlyph(font, i)) UTF8String]);
}

وكتبت محرر النص قبل بضع سنوات - وهنا بعض التعليمات البرمجية معنى ينبغي أن تحصل تبحث في (أمل) في الاتجاه الصحيح (هذا هو فرعية NSLayoutManager راجع للشغل - ونعم أنا أعلم أنه تسريب مثل بالوعة المطبخ المثل):

- (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];
}

وأنا حل مشكلة تحويل بين NSGlyphs والمقابلة unichar في NSTextView. رمز يعمل تحت جميل ومحل المساحات بوابل من الرصاص للنص مرئية:

- (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];
}

وربما - [setShowsControlCharacters NSLayoutManager:] و / أو - [setShowsInvisibleCharacters NSLayoutManager:] سوف تفعل ما تريد

وهنا هو الحل بول في سويفت:

class MyLayoutManager: NSLayoutManager {
    override func drawGlyphsForGlyphRange(glyphsToShow: NSRange, atPoint origin: NSPoint) {
        if let storage = self.textStorage {
            let s = storage.string
            let startIndex = s.startIndex
            for var glyphIndex = glyphsToShow.location; glyphIndex < glyphsToShow.location + glyphsToShow.length; glyphIndex++ {
                let characterIndex = self.characterIndexForGlyphAtIndex(glyphIndex)
                let ch = s[startIndex.advancedBy(characterIndex)]
                switch ch {
                case " ":
                    let attrs = storage.attributesAtIndex(characterIndex, effectiveRange: nil)
                    if let font = attrs[NSFontAttributeName] {
                        let g = font.glyphWithName("periodcentered")
                        self.replaceGlyphAtIndex(glyphIndex, withGlyph: g)
                    }
                case "\n":
                    let attrs = storage.attributesAtIndex(characterIndex, effectiveRange: nil)
                    if let font = attrs[NSFontAttributeName] {
//                        let g = font.glyphWithName("carriagereturn")
                        let g = font.glyphWithName("paragraph")
                        self.replaceGlyphAtIndex(glyphIndex, withGlyph: g)
                    }
                case "\t":
                    let attrs = storage.attributesAtIndex(characterIndex, effectiveRange: nil)
                    if let font = attrs[NSFontAttributeName] {
                        let g = font.glyphWithName("arrowdblright")
                        self.replaceGlyphAtIndex(glyphIndex, withGlyph: g)
                    }
                default:
                    break
                }
            }
        }
        super.drawGlyphsForGlyphRange(glyphsToShow, atPoint: origin)
    }
}

ولسرد أسماء الشكل المنقوش:

   func listFonts() {
        let font = CGFontCreateWithFontName("Menlo-Regular")
        for var i:UInt16 = 0; i < UInt16(CGFontGetNumberOfGlyphs(font)); i++ {
            if let name = CGFontCopyGlyphNameForGlyph(font, i) {
                print("name: \(name) at index \(i)")
            }
        }
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top