如何在 cocoa 中以编程方式切换 NSTextView 中的富文本格式

发布于 2024-11-17 22:44:07 字数 296 浏览 2 评论 0原文

我想在 NSTextView 中切换富文本格式。我尝试过以下操作:

[contentView setRichText:NO];
[contentView setImportsGraphics:NO];

但是,这并没有改变 NSTextView 内容,并且仍然允许进行文本格式设置。

请让我知道在 NSTextView 中切换/切换富文本格式的简单方法,就像 TextEdit 一样。

我已经检查了“TextEdit”示例项目,但似乎很难从中找到可用的代码。

谢谢

I want to toggle rich text formatting in NSTextView. I have tried following:

[contentView setRichText:NO];
[contentView setImportsGraphics:NO];

but, that didn't changed the NSTextView content and still allowing to do the text formatting.

Please let me know the simple way to toggle/switch rich text formatting in NSTextView just like TextEdit.

I already check the "TextEdit" sample project, but it seems to be very hard to find the usable code from it.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

君勿笑 2024-11-24 22:44:07

我为视图控制器创建了类别,如下所示:

#define TabWidth @"TabWidth"

@interface MyViewController (Helper)

- (NSDictionary *)defaultTextAttributes:(BOOL)forRichText;
- (void)removeAttachments;
- (void)setRichText:(BOOL)flag;

@end

@implementation MyViewController (Helper)

- (NSDictionary *)defaultTextAttributes:(BOOL)forRichText {
    static NSParagraphStyle *defaultRichParaStyle = nil;
    NSMutableDictionary *textAttributes = [[[NSMutableDictionary alloc] initWithCapacity:2] autorelease];
    if (forRichText) {
        [textAttributes setObject:[NSFont userFontOfSize:0.0] forKey:NSFontAttributeName];
        if (defaultRichParaStyle == nil) {  // We do this once...
            NSInteger cnt;
            NSString *measurementUnits = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleMeasurementUnits"];
            CGFloat tabInterval = ([@"Centimeters" isEqual:measurementUnits]) ? (72.0 / 2.54) : (72.0 / 2.0);  // Every cm or half inch
            NSMutableParagraphStyle *paraStyle = [[[NSMutableParagraphStyle alloc] init] autorelease];
            [paraStyle setTabStops:[NSArray array]];    // This first clears all tab stops
            for (cnt = 0; cnt < 12; cnt++) {    // Add 12 tab stops, at desired intervals...
                NSTextTab *tabStop = [[NSTextTab alloc] initWithType:NSLeftTabStopType location:tabInterval * (cnt + 1)];
                [paraStyle addTabStop:tabStop];
                [tabStop release];
            }
            defaultRichParaStyle = [paraStyle copy];
        }
        [textAttributes setObject:defaultRichParaStyle forKey:NSParagraphStyleAttributeName];
    } else {
        NSFont *plainFont = [NSFont userFixedPitchFontOfSize:0.0];
        NSInteger tabWidth = [[NSUserDefaults standardUserDefaults] integerForKey:TabWidth];
        CGFloat charWidth = [@" " sizeWithAttributes:[NSDictionary dictionaryWithObject:plainFont forKey:NSFontAttributeName]].width;
        if (charWidth == 0) charWidth = [[plainFont screenFontWithRenderingMode:NSFontDefaultRenderingMode] maximumAdvancement].width;
        
        // Now use a default paragraph style, but with the tab width adjusted
        NSMutableParagraphStyle *mStyle = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
        [mStyle setTabStops:[NSArray array]];
        [mStyle setDefaultTabInterval:(charWidth * tabWidth)];
        [textAttributes setObject:[[mStyle copy] autorelease] forKey:NSParagraphStyleAttributeName];
        
        // Also set the font
        [textAttributes setObject:plainFont forKey:NSFontAttributeName];
    }
    return textAttributes;
}

/* Used when converting to plain text
 */
- (void)removeAttachments {
    NSTextStorage *attrString = [contentView textStorage];
    NSUInteger loc = 0;
    NSUInteger end = [attrString length];
    [attrString beginEditing];
    while (loc < end) { /* Run through the string in terms of attachment runs */
        NSRange attachmentRange;    /* Attachment attribute run */
        NSTextAttachment *attachment = [attrString attribute:NSAttachmentAttributeName atIndex:loc longestEffectiveRange:&attachmentRange inRange:NSMakeRange(loc, end-loc)];
        if (attachment) {   /* If there is an attachment and it is on an attachment character, remove the character */
            unichar ch = [[attrString string] characterAtIndex:loc];
            if (ch == NSAttachmentCharacter) {
                if ([contentView shouldChangeTextInRange:NSMakeRange(loc, 1) replacementString:@""]) {
                    [attrString replaceCharactersInRange:NSMakeRange(loc, 1) withString:@""];
                    [contentView didChangeText];
                }
                end = [attrString length];  /* New length */
            }
            else loc++; /* Just skip over the current character... */
        }
        else loc = NSMaxRange(attachmentRange);
    }
    [attrString endEditing];
}

- (void)setRichText:(BOOL)flag {
    NSDictionary *textAttributes;
    
    BOOL isRichText = flag;
    
    if (!isRichText) [self removeAttachments];
    
    [contentView setRichText:isRichText];
    [contentView setUsesRuler:isRichText];    /* If NO, this correctly gets rid
                                               of the ruler if it was up */
    if (isRichText && NO)
        [contentView setRulerVisible:YES];    /* Show ruler if rich, and desired */
    [contentView setImportsGraphics:isRichText];
    
    textAttributes = [self defaultTextAttributes:isRichText];
    
    if ([[contentView textStorage] length]) {
        [[contentView textStorage] setAttributes:textAttributes range: NSMakeRange(0,[[contentView textStorage] length])];
    }
    [contentView setTypingAttributes:textAttributes];
}

@end

其中 contentView 是 NSTextView 的 IBOutlet。希望这会对某人有所帮助,或者让我知道是否有人有更短的方法。

谢谢

I have created category for my view controller as follows:

#define TabWidth @"TabWidth"

@interface MyViewController (Helper)

- (NSDictionary *)defaultTextAttributes:(BOOL)forRichText;
- (void)removeAttachments;
- (void)setRichText:(BOOL)flag;

@end

@implementation MyViewController (Helper)

- (NSDictionary *)defaultTextAttributes:(BOOL)forRichText {
    static NSParagraphStyle *defaultRichParaStyle = nil;
    NSMutableDictionary *textAttributes = [[[NSMutableDictionary alloc] initWithCapacity:2] autorelease];
    if (forRichText) {
        [textAttributes setObject:[NSFont userFontOfSize:0.0] forKey:NSFontAttributeName];
        if (defaultRichParaStyle == nil) {  // We do this once...
            NSInteger cnt;
            NSString *measurementUnits = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleMeasurementUnits"];
            CGFloat tabInterval = ([@"Centimeters" isEqual:measurementUnits]) ? (72.0 / 2.54) : (72.0 / 2.0);  // Every cm or half inch
            NSMutableParagraphStyle *paraStyle = [[[NSMutableParagraphStyle alloc] init] autorelease];
            [paraStyle setTabStops:[NSArray array]];    // This first clears all tab stops
            for (cnt = 0; cnt < 12; cnt++) {    // Add 12 tab stops, at desired intervals...
                NSTextTab *tabStop = [[NSTextTab alloc] initWithType:NSLeftTabStopType location:tabInterval * (cnt + 1)];
                [paraStyle addTabStop:tabStop];
                [tabStop release];
            }
            defaultRichParaStyle = [paraStyle copy];
        }
        [textAttributes setObject:defaultRichParaStyle forKey:NSParagraphStyleAttributeName];
    } else {
        NSFont *plainFont = [NSFont userFixedPitchFontOfSize:0.0];
        NSInteger tabWidth = [[NSUserDefaults standardUserDefaults] integerForKey:TabWidth];
        CGFloat charWidth = [@" " sizeWithAttributes:[NSDictionary dictionaryWithObject:plainFont forKey:NSFontAttributeName]].width;
        if (charWidth == 0) charWidth = [[plainFont screenFontWithRenderingMode:NSFontDefaultRenderingMode] maximumAdvancement].width;
        
        // Now use a default paragraph style, but with the tab width adjusted
        NSMutableParagraphStyle *mStyle = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
        [mStyle setTabStops:[NSArray array]];
        [mStyle setDefaultTabInterval:(charWidth * tabWidth)];
        [textAttributes setObject:[[mStyle copy] autorelease] forKey:NSParagraphStyleAttributeName];
        
        // Also set the font
        [textAttributes setObject:plainFont forKey:NSFontAttributeName];
    }
    return textAttributes;
}

/* Used when converting to plain text
 */
- (void)removeAttachments {
    NSTextStorage *attrString = [contentView textStorage];
    NSUInteger loc = 0;
    NSUInteger end = [attrString length];
    [attrString beginEditing];
    while (loc < end) { /* Run through the string in terms of attachment runs */
        NSRange attachmentRange;    /* Attachment attribute run */
        NSTextAttachment *attachment = [attrString attribute:NSAttachmentAttributeName atIndex:loc longestEffectiveRange:&attachmentRange inRange:NSMakeRange(loc, end-loc)];
        if (attachment) {   /* If there is an attachment and it is on an attachment character, remove the character */
            unichar ch = [[attrString string] characterAtIndex:loc];
            if (ch == NSAttachmentCharacter) {
                if ([contentView shouldChangeTextInRange:NSMakeRange(loc, 1) replacementString:@""]) {
                    [attrString replaceCharactersInRange:NSMakeRange(loc, 1) withString:@""];
                    [contentView didChangeText];
                }
                end = [attrString length];  /* New length */
            }
            else loc++; /* Just skip over the current character... */
        }
        else loc = NSMaxRange(attachmentRange);
    }
    [attrString endEditing];
}

- (void)setRichText:(BOOL)flag {
    NSDictionary *textAttributes;
    
    BOOL isRichText = flag;
    
    if (!isRichText) [self removeAttachments];
    
    [contentView setRichText:isRichText];
    [contentView setUsesRuler:isRichText];    /* If NO, this correctly gets rid
                                               of the ruler if it was up */
    if (isRichText && NO)
        [contentView setRulerVisible:YES];    /* Show ruler if rich, and desired */
    [contentView setImportsGraphics:isRichText];
    
    textAttributes = [self defaultTextAttributes:isRichText];
    
    if ([[contentView textStorage] length]) {
        [[contentView textStorage] setAttributes:textAttributes range: NSMakeRange(0,[[contentView textStorage] length])];
    }
    [contentView setTypingAttributes:textAttributes];
}

@end

Where contentView is IBOutlet of NSTextView. Hope this will help someone or let me know if someone has shorter method.

Thanks

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文