layoutManager:didCompleteLayoutForTextContainer:atEnd: returns atEnd as NO dodgily for me (but works in TextEdit...)
layoutManager:didCompleteLayoutForTextContainer:atEnd: returns atEnd as NO dodgily for me (but works in TextEdit...)
- Subject: layoutManager:didCompleteLayoutForTextContainer:atEnd: returns atEnd as NO dodgily for me (but works in TextEdit...)
- From: Keith Blount <email@hidden>
- Date: Mon, 11 Feb 2008 10:11:57 -0800 (PST)
Hi,
I'm putting together a page layout view a little like the Wrap to Page mode in TextEdit, and I'm having a few issues with NSLayoutManager's delegate method, -layoutManager:didCompleteLayoutForTextContainer:atEnd:. Specifically, there seem to be circumstances in my app whereby an extra container (page) gets added when it's not actually needed.
I have used exactly the same implementation for this as in the TextEdit code (see below). The logic for this is that a page gets added under the following circumstances:
1) if the layout manager is still laying out text and the container that has just finished layout is the last one (because the last container is therefore now full so we need to create another one)
2) if the passed-in text container is nil (because that means we have text laid out nowhere so need to create another container for it)
It is the first of these circumstances that seems to go wrong for me. It seems that sometimes - often in my app, never that I've seen in TextEdit - when this method is called and the last container has just been laid out, even though that container contains the last of the text that needs to be laid out, the atEnd flag still gets passed in as NO - and thus another page gets added, even though the last container was enough to hold all of the text.
I've no idea why this should be happening in my app and not in TextEdit. I tried my page layout view in a separate app and this doesn't happen, so all I can think of that I'm doing different is that my layout manager swaps in and out different text storages using [textStorage addLayoutManager:lm] and [textStorage removeLayoutManager:lm]. I'm not sure why this would cause any oddness, but I can't think of anything else it could be.
It seems that I can fix this by adding pages only under the second circumstance above - i.e. if layout is finished but the text container that is passed in is nil - and according to the documentation for this layout manager method, it seems as though this is an absolutely fine solution ("If nil, there aren’t enough containers to hold all the text; the delegate can use this information as a cue to add another text container."). However, I'm still curious as to why this might cause one more page to be added than necessary under certain circumstances - why atEnd isn't set to YES even though the last container holds all of the text.
Thanks in advance and all the best,
Keith
- (void)layoutManager:(NSLayoutManager *)layoutManager didCompleteLayoutForTextContainer:(NSTextContainer *)textContainer atEnd:(BOOL)layoutFinishedFlag {
if (hasMultiplePages) {
NSArray *containers = [layoutManager textContainers];
if (!layoutFinishedFlag || (textContainer == nil)) {
// Either layout is not finished or it is but there are glyphs laid nowhere.
NSTextContainer *lastContainer = [containers lastObject];
// If I change the line below to get rid of (textContainer == lastContainer), and thus
// only add a new page if the passed-in text container is nil, all is fine; but otherwise
// one extra page may be added, as the this method says that layoutFinishedFlag is NO
// even when lastContainer has just been laid out with the last of the text...
if ((textContainer == lastContainer) || (textContainer == nil)) {
// Add a new page if the newly full container is the last container or the nowhere container.
// Do this only if there are glyphs laid in the last container (temporary solution for 3729692, until AppKit makes something better available.)
if ([layoutManager glyphRangeForTextContainer:lastContainer].length > 0) [self addPage];
}
} else {
// Layout is done and it all fit. See if we can axe some pages.
NSUInteger lastUsedContainerIndex = [containers indexOfObjectIdenticalTo:textContainer];
NSUInteger numContainers = [containers count];
while (++lastUsedContainerIndex < numContainers) {
[self removePage];
}
}
}
}
____________________________________________________________________________________
Be a better friend, newshound, and
know-it-all with Yahoo! Mobile. Try it now. http://mobile.yahoo.com/;_ylt=Ahu06i62sR8HDtDypao8Wcj9tAcJ
_______________________________________________
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