From: greg@afs.com (Gregory H. Anderson)
Subject: Re: NXBrowser problem...
Reply-To: greg@afs.com
Date: Fri, 9 Oct 1992 15:11:32 GMT

> Tim McClarren and Brian Willoughby write:
[much misinformation about NXBrowserCells removed, so as not to be  
propogated any further]

Here's the Straight Dope on NXBrowsers and NXBrowserCells in 2.x and 3.0,  
from one of the straightest dopes around (yours truly):

setCellClass: is an *instance* method of browsers, not a class method. So  
anything you do in +initialize is useless, because this method must be  
applied to a specific browser. According to the documentation, the  
cellPrototype is what's actually used when NXBrowser makes a new matrix.  
The setCellClass: method simply sends alloc/init messages to the stated  
class, and then makes that object the cellPrototype. So in effect,  
setCellClass: is just an alternate way of calling setCellPrototype:.

By this logic it follows that initFrame: *is* the right place to include a  
setCellClass: method, because this is the first message a newly allocated  
NXBrowser will get. Note that you should do this *before* calling [super  
initFrame:], because you have no way of knowing what the superclass will  
do in the way of drawing before you get back control. And that's where the  
problem arises in 3.0

In NS 3.0, it appears that the display method for NXBrowsers has been  
"enhanced" to send the initial loadColumnZero message for you if it has  
not been sent yet. I would guess that's why you're having problems. In  
2.x, your code had enough time in appDidInit: to set the cell class before  
the first loadColumnZero message, even if the NXBrowser's Window was  
visible at runtime. In 3.0, that would not be true. If the browser is in  
the main nib file, and its window is visible at runtime, the browser will  
get its first display message long before you get a chance to do anything  
special in appDidInit:. (Actually, this is a useful enhancement, IMHO. If  
you think about it, it's silly that you had to send a loadColumnZero under  
program control in 2.x. I just wish the change had been documented, and it  
didn't cause this kind of havoc in existing code. I too have been burned.)

You here are the options:

1) Don't make the NXBrowser's Window visible at startup. I think (can't  
say for certain) that will defer the offending display message. Set your  
cell class, then send the Window an orderFront: message.

2) Subclass NXBrowser. Then you can do whatever the hell you want in  
initFrame:.

3) If you don't want to subclass NXBrowser (and there are plenty of good  
reasons not to, if you want to manipulate these things properly in IB),  
make a category NXBrowser(Kludge) with an "awake" method. If you  
setCellClass: at that point, things should work out OK. That way ordinary  
browsers that were archived without the right cellPrototype will work  
correctly. The downside is that ALL browsers will get the same  
cellPrototype, which may not be what you want. In that case, subclassing  
is the only answer.

================== start NXBrowserKludge.h ==========================

#import <appkit/NXBrowser.h>

@interface NXBrowser(Kludge)
- awake;
@end

================== end of NXBrowserKludge.h =========================

================== start NXBrowserKludge.m ==========================

#import "NXBrowserKludge.h"

@implementation NXBrowser(Kludge)

- awake
	{
	/* ALL browsers will get this. Is that what you want?  */
	/* Make sure there are no side-effects from using your */
	/* custom cell class universally.                      */

	[self setCellClass:[MyBrowserCell class]];
	return [super awake];
	}

@end

================== end of NXBrowserKludge.m ==========================

Hope this helps. Keep those cards and letters coming.

--
Gregory H. Anderson          | "We're very tolerant around here,
Benevolent Dictator-for-Life |  being only amateurs ourselves."
Anderson Financial Systems   | - Tortoise (Godel, Escher, Bach)
greg@afs.com  (Nextmail OK)  |