NSTextView and layout manager or cells - how to be most efficient?
NSTextView and layout manager or cells - how to be most efficient?
- Subject: NSTextView and layout manager or cells - how to be most efficient?
- From: Keith Blount <email@hidden>
- Date: Wed, 20 Apr 2005 12:39:03 -0700 (PDT)
- Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys
Hello,
I am currently in the process of rewriting a view that
acts as a margin for a text view. This margin holds
lots of notes that stay in sync with the text in the
text view next to it. (Thanks to those who have
already given me some help with this.)
I originally designed this in such a way that every
note was a text view, which was very inefficient. What
I am trying to do now is have it so that the view only
has one text view, which is used to edit any margin
note, and then have the notes just draw themselves
when they are not being edited. However, I have some
major issues (mainly to do with slowdown), as follows,
and would be really grateful to anybody who could give
me any advice on how to address this:
1) I had thought I could use an NSTextFieldCell to
draw all my notes and use the window's field editor to
edit them. However, this is not workable because the
field editor does cannot be resized vertically to fit
text as you type, which is something I require (I
found some old posts by Drew McCormack reporting the
same problem).
2) I therefore tried sticking to using cells for
drawing, but using my own text view for editing.
However, it seems practically impossible to get the
text view to draw exactly the same as a cell
(obviously the field editor does it, but even after
setting the line fragment padding and text container
inset correctly, the line spacing is still all off).
3) Perhaps my preferred option, I used code from the
Sketch.app example to try to get my notes to draw
themselves in the view. I have posted this code (which
uses Sketch's sharedLayoutManager function too) at the
bottom of the post. The problem is that it is waaaay
too slow - it might be fine for Sketch in which only
couple or three text boxes are ever likely to appear
onscreen, but for my needs it is slow. Here's why:
- When my view loads, I need to go through all the
notes it can display and calculate their sizes when
drawn - I use the method below
(sizeWithWidth:attributes:) for this. I need to do
this, because then I calculate their origins, and if
any will overlap, I offset them so that they don't. In
a test app with 200 notes, this takes much too long,
and the sizeWithWidth:attributes: metho is what is
taking the time. (I have to calculate the positions
like this so that I know which ones to draw at any one
time.)
If anyone can give me any advice or pointers on the
best way to approach this problem, I would be very
grateful.
Many thanks in advance,
Keith
THE CODE:
// Draws the note's string in given rect with the
given attributes so that it looks exactly
// like a text view.
- (void)drawInRect:(NSRect)aRect
withAttributes:(NSDictionary *)attributes
{
if ([string length] > 0)
{
NSTextStorage *contents = [[NSTextStorage alloc]
initWithString:string attributes:attributes];
NSLayoutManager *lm = sharedDrawingLayoutManager();
NSTextContainer *tc = [[lm textContainers]
objectAtIndex:0];
NSRange glyphRange;
[tc setContainerSize:aRect.size];
[contents addLayoutManager:lm];
// Force layout of the text and find out how much of
it fits in the container.
glyphRange = [lm glyphRangeForTextContainer:tc];
if (glyphRange.length > 0)
{
[lm drawBackgroundForGlyphRange:glyphRange
atPoint:aRect.origin];
[lm drawGlyphsForGlyphRange:glyphRange
atPoint:aRect.origin];
}
[contents removeLayoutManager:lm];
[contents release];
}
}
// Returns the size with the specified width required
to draw the note's string with the given attributes.
- (NSSize)sizeWithWidth:(float)width
attributes:(NSDictionary *)attributes
{
if ([string length] > 0)
{
NSTextStorage *contents = [[NSTextStorage alloc]
initWithString:string attributes:attributes];
NSLayoutManager *lm =
sharedDrawingLayoutManager();
NSTextContainer *tc = [[lm textContainers]
objectAtIndex:0];
NSRange glyphRange;
NSSize requiredSize;
[tc
setContainerSize:NSMakeSize(width,FLT_MAX)];
[contents addLayoutManager:lm];
// Force layout of the text and find out how
much of it fits in the container
glyphRange = [lm
glyphRangeForTextContainer:tc];
if (glyphRange.length>0)
{
requiredSize = [lm
usedRectForTextContainer:tc].size;
requiredSize.width = width; // Set width regardless
of used rect
}
else
requiredSize = NSZeroSize;
// Cache the info
[cachedDrawingInfo release];
cachedDrawingInfo = [[NSDictionary alloc]
initWithObjectsAndKeys:
contents, KBAttributedStringKey,
[NSValue valueWithSize:requiredSize], KBSizeKey,
nil];
[contents removeLayoutManager:lm];
[contents release];
return requiredSize;
}
else
return NSZeroSize;
}
__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden