Re: Cocoa Text System - Temporarily Disabling Layout
Re: Cocoa Text System - Temporarily Disabling Layout
- Subject: Re: Cocoa Text System - Temporarily Disabling Layout
- From: Jonathan Dann <email@hidden>
- Date: Sun, 26 Sep 2010 14:06:00 +0200
On 24 Sep 2010, at 19:59, Martin Wierschin wrote:
>>>>> when I resize the window and need to adjust the frames of both scroll views, calling -[NSTextView setFrame:] results in the layout manager invalidating and ensuring layout for the newly visible character range.
>>>
>>> Why not just turn off text view width/height tracking for the container during the resize? That should let the layout manager use the existing layout information (ie: for the stale container size).
>>
>> Because that's just moving the problem further down the line. When I finally update the text container size for the first text view it will begin to layout before I've reached the next line of my code where I can fix the size of the second view.
>
> My next suggestion would be to subclass NSLayoutManager and override methods that handle invalidation, eg:
>
> - (void) textContainerChangedGeometry:(NSTextContainer*)tc ;
> - (void) invalidateLayoutForCharacterRange:(NSRange)charRng isSoft:(BOOL)isSoft actualCharacterRange:(NSRange*)charRngPtr ;
> - (void) invalidateLayoutForCharacterRange:(NSRange)charRng actualCharacterRange:(NSRange*)charRngPtr ;
>
> When your resize starts, set some flag on your subclass that makes all those methods no-ops. When you've finished resizing both text systems, clear your flag and re-invalidate as necessary.
I'll take another look at this, I seem to remember finding some layout backtrace that bypassed these, but it's been a long time so I'm probably mistaken.
> But really, I might ask you why your own code is so delicate that it needs both layout systems to be in some perfectly matched state at all times. Surely your code could have a flag that tells it layout is not yet synced up, and ancillary tasks should be avoided/delayed until a stable state is established.
Always a good question. In Kaleidoscope (one way) we display the diff between two text views by creating gaps (by offsetting the proposed line fragment rects for specific lines) in the other text view. For example, a deleted line would cause a gap in the text view on the right, and an inserted line causes a a gap in the text view on the left. The equal lines are then positioned at the same y-ordinate in each text view. This requires (when considering wrapped text) the text views to be the same width. When resizing, the I have to account for odd or even window widths (not in itself a problem) but also support the cases where the text views are scrolled to the top such that they layout their strings while resizing, and when the text system delays relayout (when scrolled far down) until the views aren't resizing any more. Therefore to layout out line x in the left text view all lines above x in the right text view also need to be laid out so I can know whether, and how much, to increase the y-origin of line x by.
What will make this easier is to have, as you rightly suggest some flag so I can better control when to/not to layout. The problem, since the text system tries to layout upon resizing the text view in a lot of cases, is finding all the right places to put this flag.
>
>>> The other "state change" you explicitly touch upon is editing the text. If you bracket all your changes to the text storage with begin/end editing calls, you shouldn't trigger layout until all your changes are finished (unless you're also inadvertently triggering layout in other ways).
>>
>> I'll see how that fits in with setting the 2 strings that are dependent on each other. It may be a nice workaround.
>
> Just be careful that you don't trigger layout while the text storage has an edit open, eg:
>
> [textStorage beginEditing];
> [textStorage deleteCharactersInRange:someRange];
> [layoutManager ensureLayoutForCharacterRange:NSMakeRange(0, [textStorage length])];
> [textStorage endEditing];
>
> The layout system isn't tolerant of that. It used to just throw out-of-bounds exceptions, though now it seems to give you exceptions with nice explanations of what you've done wrong.
That's a good one to keep an eye out for.
Thank you very much. I really appreciate having some fresh eyes on the problem.
Jonathan
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden