Ideal size of an NSScrollView?
-
I have a regular NSTextView inside an NSScrollView (with an auto-
hiding vertical scroll bar). The contents of the text view are set
via code depending on the outcome of some operations. The scroll view
is set up to grow as my window is resized. So far, everything is
working great.
Now, I'd like to be able to determine how large the NSTextView ought
to be to avoid scrolling. That way, I can set the window to its
"optimal" size before showing it--just big enough to show the text,
without having a ton of extra white space.
Is there an easy way to do this?
(I tried gradually growing the window until [scrollView
hasVerticalScroller] returned NO, but that didn't work; apparently it
returns YES even if the scroller is hidden. I also tried looking at
the contentSize and documentVisibleRect but it didn't seem to do what
I wanted.) -
on 05/12/19 19:02, John Stiles at <JStiles...> wrote:
> I have a regular NSTextView inside an NSScrollView (with an auto-
> hiding vertical scroll bar). The contents of the text view are set
> via code depending on the outcome of some operations. The scroll view
> is set up to grow as my window is resized. So far, everything is
> working great.
>
> Now, I'd like to be able to determine how large the NSTextView ought
> to be to avoid scrolling. That way, I can set the window to its
> "optimal" size before showing it--just big enough to show the text,
> without having a ton of extra white space.
>
> Is there an easy way to do this?
Nope. No easy way. Maybe in Mac OS 11. Until then we have this:
http://www.cocoabuilder.com/archive/message/2002/2/19/71224
which you can find explained in the docs on your hard drive:
ADC Home > Reference Library > Documentation > Cocoa > Text & Fonts > Text
Layout Programming Guide > Calculating Text Height
The above explains how to do it for constant width and variable height,
which is the opposite of what you want, but their function is easily
modified to do either way:
float MeasureStringDrawing(NSString *myString, NSFont *desiredFont, float
desiredWidth, float desiredHeight)
// One of desiredHeight or desiredWidth must be set to 0.
// The size of the one set to 0 will be returned.
// Operation of this function is explained in:
// ADC Home > Reference Library > Documentation > Cocoa > Text & Fonts >
Text Layout Programming Guide > Calculating Text Height
{
BOOL wantWidth ;
if (desiredWidth == 0)
{
desiredWidth = 1e7 ;
wantWidth = YES ;
}
else if (desiredHeight == 0)
{
desiredHeight = 1e7 ;
wantWidth = NO ;
}
else
NSLog(@ "Internal error calling HeightForStringDrawing") ;
NSTextStorage *textStorage = [[[NSTextStorage alloc]
initWithString:myString] autorelease];
NSTextContainer *textContainer = [[[NSTextContainer alloc]
initWithContainerSize:NSMakeSize(desiredWidth, desiredHeight)] autorelease];
NSLayoutManager *layoutManager = [[[NSLayoutManager alloc] init]
autorelease];
[textStorage addAttribute:NSFontAttributeName value:desiredFont
range:NSMakeRange(0, [textStorage length])];
[textContainer setLineFragmentPadding:0.0]; // padding usually is not
appropriate for string drawing
[layoutManager addTextContainer:textContainer];
[textStorage addLayoutManager:layoutManager];
(void)[layoutManager glyphRangeForTextContainer:textContainer]; //
force layout
if (wantWidth)
return [layoutManager
usedRectForTextContainer:textContainer].size.width;
else
return [layoutManager
usedRectForTextContainer:textContainer].size.height;
}
P.S. You may find that you need to add a little margin. I don't know why,
but to guarantee no wrapping I have to add 15 pixels to the returned
measurement. The required margin may depend on your font, size, etc. -
Thanks to multiple suggestions, I found what appears to be a working
solution. Thanks everyone :)
NSLayoutManager *layoutManager = [textView layoutManager];
NSRect rect = [layoutManager boundingRectForGlyphRange:NSMakeRange
(0, [layoutManager numberOfGlyphs]) inTextContainer:[textView
textContainer]];
"usedRectForTextContainer" also appears to be a working solution, but
it doesn't force glyph layout, so you can get stale information back.
"boundingRectForGlyphRange," OTOH, does force layout.
On Dec 19, 2005, at 7:02 PM, John Stiles wrote:
> I have a regular NSTextView inside an NSScrollView (with an auto-
> hiding vertical scroll bar). The contents of the text view are set
> via code depending on the outcome of some operations. The scroll
> view is set up to grow as my window is resized. So far, everything
> is working great.
>
> Now, I'd like to be able to determine how large the NSTextView
> ought to be to avoid scrolling. That way, I can set the window to
> its "optimal" size before showing it--just big enough to show the
> text, without having a ton of extra white space.
>
> Is there an easy way to do this?
>
> (I tried gradually growing the window until [scrollView
> hasVerticalScroller] returned NO, but that didn't work; apparently
> it returns YES even if the scroller is hidden. I also tried looking
> at the contentSize and documentVisibleRect but it didn't seem to do
> what I wanted.)
> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Cocoa-dev mailing list (<Cocoa-dev...>)
> Help/Unsubscribe/Update your Subscription:
> http://lists.apple.com/mailman/options/cocoa-dev/jstiles%
> 40blizzard.com
>
> This email sent to <jstiles...>
-
Actually, I think I might have found an easier answer.
After forcing the glyphs to re-layout via your method of choice
(there are many), [textView frame].size.height seems to contain the
height. Neat.
On Dec 20, 2005, at 1:53 PM, John Stiles wrote:
> Thanks to multiple suggestions, I found what appears to be a
> working solution. Thanks everyone :)
>
> NSLayoutManager *layoutManager = [textView layoutManager];
> NSRect rect = [layoutManager boundingRectForGlyphRange:NSMakeRange
> (0, [layoutManager numberOfGlyphs]) inTextContainer:[textView
> textContainer]];
>
> "usedRectForTextContainer" also appears to be a working solution,
> but it doesn't force glyph layout, so you can get stale information
> back. "boundingRectForGlyphRange," OTOH, does force layout.
>
>
> On Dec 19, 2005, at 7:02 PM, John Stiles wrote:
>
>> I have a regular NSTextView inside an NSScrollView (with an auto-
>> hiding vertical scroll bar). The contents of the text view are set
>> via code depending on the outcome of some operations. The scroll
>> view is set up to grow as my window is resized. So far, everything
>> is working great.
>>
>> Now, I'd like to be able to determine how large the NSTextView
>> ought to be to avoid scrolling. That way, I can set the window to
>> its "optimal" size before showing it--just big enough to show the
>> text, without having a ton of extra white space.
>>
>> Is there an easy way to do this?
>>
>> (I tried gradually growing the window until [scrollView
>> hasVerticalScroller] returned NO, but that didn't work; apparently
>> it returns YES even if the scroller is hidden. I also tried
>> looking at the contentSize and documentVisibleRect but it didn't
>> seem to do what I wanted.)
>> _______________________________________________
>> Do not post admin requests to the list. They will be ignored.
>> Cocoa-dev mailing list (<Cocoa-dev...>)
>> Help/Unsubscribe/Update your Subscription:
>> http://lists.apple.com/mailman/options/cocoa-dev/jstiles%
>> 40blizzard.com
>>
>> This email sent to <jstiles...>
>



