简体   繁体   中英

How to change only font size for the whole styled text in NSTextView

I need to set a text size (for example to 42) of the selected rich text which uses multiple fonts.

I imagine I can check attributes of each group of characters, modify the font size and set attributes back, but looking at the floating Font panel it seems like there should be a very easy and straightforward way to accomplish that. Do I miss something obvious?

On 10.6 there is a convenient way to iterate over the attributes and increase the font size. This method can be added to an NSTextView category.

    - (IBAction)increaseFontSize:(id)sender
{
    NSTextStorage *textStorage = [self textStorage];
    [textStorage beginEditing];
    [textStorage enumerateAttributesInRange: NSMakeRange(0, [textStorage length])
                                     options: 0
                                  usingBlock: ^(NSDictionary *attributesDictionary,
                                                NSRange range,
                                                BOOL *stop)
     {
#pragma unused(stop)
         NSFont *font = [attributesDictionary objectForKey:NSFontAttributeName];
         if (font) {
             [textStorage removeAttribute:NSFontAttributeName range:range];
             font = [[NSFontManager sharedFontManager] convertFont:font toSize:[font pointSize] + 1];
             [textStorage addAttribute:NSFontAttributeName value:font range:range];
         }
     }];
    [textStorage endEditing];
    [self didChangeText];

}

Generalizing on Jonathan's answer a bit, here is a category interface you can simply paste into appropriate files in your Xcode project:

@interface NSTextView (FrameworkAdditions)

-  (IBAction)decrementFontSize:(id)sender;
-  (IBAction)incrementFontSize:(id)sender;

@end

And the corresponding implementation:

@implementation NSTextView (FrameworkAdditions)

- (void)changeFontSize:(CGFloat)delta;
{
    NSFontManager * fontManager = [NSFontManager sharedFontManager];
    NSTextStorage * textStorage = [self textStorage];
    [textStorage beginEditing];
    [textStorage enumerateAttribute:NSFontAttributeName
                            inRange:NSMakeRange(0, [textStorage length])
                            options:0
                         usingBlock:^(id value,
                                      NSRange range,
                                      BOOL * stop)
     {
         NSFont * font = value;
         font = [fontManager convertFont:font
                                  toSize:[font pointSize] + delta];
         if (font != nil) {
             [textStorage removeAttribute:NSFontAttributeName
                                    range:range];
             [textStorage addAttribute:NSFontAttributeName
                                 value:font
                                 range:range];
         }
     }];
    [textStorage endEditing];
    [self didChangeText];
}

-  (IBAction)decrementFontSize:(id)sender;
{
    [self changeFontSize:-1.0];
}

-  (IBAction)incrementFontSize:(id)sender;
{
    [self changeFontSize:1.0];
}

@end

This will double the font size, but you may change the scale property to any value, or provide your fixed size

    NSFont * font = ...;
    CGFloat fontSize =  [[font fontDescriptor].fontAttributes[NSFontSizeAttribute] floatValue];
    font = [NSFont fontWithDescriptor:[font fontDescriptor] size:fontSize * 2.];

    self.textField.font = font;

Note : I assume that you are using a NSTextView and that you can access its text storage (NSTextStorage).

I think it is not possible to only change the font's size over a text that use multiple fonts. In NSAttributedString, font's size is part of the NSFontAttributeName attribute which controls both the font and the size.

One solution is to iterate over the selection and use the attribute:atIndex:longestEffectiveRange:inRange: to capture the range when each font apply, change the font's size and then use the addAttribute:value:range: to set the new font over the range.

Update :

If you take a look at the GNUstep GUI source code for NSTextView (under LGPL), you will see that their implementation use the range iteration.

Since NSTextView is a subclass of NSView , you can use -scaleUnitSquareToSize: to change the magnification level of the text view. For example, to make all the text double sized you'd call:

[textView scaleUnitSquareToSize:NSMakeSize(2.0, 2.0)];

You may need to make some adjustments to the dimensions of the text view's NSTextContainer after performing this operation to ensure the text is laid out correctly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM