Re: Optimizing text layout in a log view: should I subclass NSLayoutManager?
Re: Optimizing text layout in a log view: should I subclass NSLayoutManager?
- Subject: Re: Optimizing text layout in a log view: should I subclass NSLayoutManager?
- From: Camillo Lugaresi <email@hidden>
- Date: Thu, 26 Jan 2006 19:22:22 +0100
On 26/gen/06, at 03:10, Rachel Blackman wrote:
I have a non-editable text view that is used for a log. Lines can
be added at the bottom and removed at the top (to keep it to a
certain length). I wrapped an NSTextView in another view that uses
a bottom-based (unflipped) coordinate system, so that the view
sticks to the bottom by default when resizing. This part works
perfectly.
I've solved all my (current) text-view problems except this one, so
I'd love to see or hear what you did.
I tried something along these lines but then couldn't copy-and-
paste from the view, and my most recent attempt involved
subclassing NSClipView (to make it resize the text view and 'stick'
it to the bottom), and subclassing NSScrollView (to replace the
clipview with my class).
The method I used is to set a custom view (with unflipped
coordinates) as the doc view of the scroll view, and make the text
view a subview of the custom view. Hierarchy is scroll > clip >
custom > text. Disable all autosizing in the custom view; install
frame change observers on the clip view and text view; in the
notification method, resize the views as appropriate, fix scroll
position if needed.
I'd go into more detail, but I have a tendinitis and typing one-
handed is hard. Sorry.
The problem is that deleting lines at the top invalidates the
layout for the entire text view, which makes things slow for long
logs, and in general causes undesirable CPU usage. I will
implement the obvious fix of deleting lines less often (eg let the
buffer grow to 1.1 times the desired maximum, and then clip off
the extra 10% in one fell swoop). However, I'd like to solve this
problem more radically.
In my case, I cached the size of each line; when I wanted to delete
(for instance) three lines at the top, I just got the character-
length of the top three lines, added it together, then did
replaceCharactersInRange:withString: with a range of
(0,lineLengths) and an empty NSString.
I don't see why that would be more efficient than using
deleteCharactersInRange:. Both will invalidate the layout of
subsequent text.
Further, I do a bunch of things using performSelector and
cancelPreviousPerformRequestsWithTarget; this means if another line
pops in before I've finished my recalculation, I can cancel the
request, drop everything on the floor and start over. That saves
me a ton of CPU by avoiding requests piling up on multiple lines
coming in.
My calculations currently have negligible impact, though; it's
Cocoa's layout recalc that I want to avoid.
Not as efficient as it could be overall, but a dramatic factor
moreso than the first cut was. I also do some NSClipView voodoo to
hold the view in place and avoid it shifting away from the line
you're on even when clipping off the top of the view; it seems to
help with the CPU a little, but is mostly a usability thing.
This sounds interesting. I faced the same problem, but couldn't
eliminate flicker completely when background layout is used, before I
was forced to suspend development. Is your text view doing layout in
the background?
Camillo
PS: posting my reply on-list to encourage others to join the
discussion, I hope you don't mind.
_______________________________________________
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