Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

GeeYouEye

macrumors 68000
Original poster
Dec 9, 2001
1,669
10
State of Denial
I have an app where I've got all the views factored out into different NIBs nicely, and the two windows, a document window and the preferences window, are managed by NSWindowController subclasses. Specifically, my document window is in one nib, the toolbar and an empty NSView for the preferences window are in another nib, and each preference pane (5) is in its own nib. The app controller/delegate maintains an array of document window controllers, and one preferences window controller, as well as the managed object context and persistent store for the application (using Core Data for the prefs since it's a database of objects - which the "document" does math on, but doesn't alter or add to the database).

The preferences menu item targets the app controller's showSetupWindow: action:

Code:
- (IBAction)showSetupWindow:(id)sender
{
	if (setupWindowController == nil)
	{
		setupWindowController = [[CCCESetupWindowController alloc] initWithWindowNibName:@"SetupWindow"];
	}
	[setupWindowController showWindow:sender];
	[setupWindowController changeView:self];
}
initWithWindowNibName: is not overridden, although I do have an awakeFromNib:
Code:
- (void)awakeFromNib
{
	for (NSToolbarItem *i in [toolbar items])
	{
		[i setTarget:self];
		[i setAction:@selector(changeView:)];
	}
	
}
This windowController has an outlet, a custom view to fill with my preference panes, and an NSViewController.
changeView:, which is giving all the headaches, is as follows:
Code:
- (IBAction)changeView:(id)sender
{
	[self willChangeValueForKey:@"viewController"];
	if ([myCurrentViewController view] != nil)
	{
		[[myCurrentViewController view] removeFromSuperview];
	}
	if (myCurrentViewController != nil)
	{
		[myCurrentViewController release];
	}
	if ([sender respondsToSelector:@selector(tag)])
	{
		lastTag = [sender tag];
	}
	else lastTag = kGeneralView;
	switch (lastTag) {
		case kGeneralView:
			myCurrentViewController =[[NSViewController alloc] initWithNibName:@"GeneralSetup" bundle:nil];
			break;
		case kColorsView:
			myCurrentViewController = [[NSViewController alloc] initWithNibName:@"ColorsSetup" bundle:nil];
			break;
		case kFinishesView:
			myCurrentViewController = [[NSViewController alloc] initWithNibName:@"FinishesSetup" bundle:nil];
			break;
		case kAccessoriesView:
			myCurrentViewController = [[NSViewController alloc] initWithNibName:@"AccessoriesSetup" bundle:nil];
			break;
		case kEmbdedmentsView:
			myCurrentViewController = [[NSViewController alloc] initWithNibName:@"EmbedmentsSetup" bundle:nil];
			break;
		case kInstallationView:
			myCurrentViewController = [[NSViewController alloc] initWithNibName:@"InstallationSetup" bundle:nil];
			break;
		default: break;
	}
	[myTargetView addSubview:[myCurrentViewController view]];
	//[[myTargetView window] setContentView:[myCurrentViewController view]];
	[[myTargetView window] setFrame:[[myCurrentViewController view] frame] display:YES animate:YES];
	[self didChangeValueForKey:@"viewController"];
}
If anyone can see what's going horribly wrong now, be my guest.:eek:



What's happening is that every time changeView: is called, a new document window is created, around addSubview: call. I have no idea why. The other problem is that while the window is resizing properly, most of the prefpane views are out of frame (I can only see the bottom of it), and I can't seem to get them back in. Help!
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
I'm not sure about the new window thing... that looks like that problem is elsewhere (not in the code you show).

Code:
[myTargetView addSubview:[myCurrentViewController view]];
[[myTargetView window] setFrame:[[myCurrentViewController view] frame] display:YES animate:YES];

You never set the frame of myCurrentViewController's view. It needs to be relative to the bounds of myTargetView. Also you need to set its autoresizing mask, so that when myTargetView resizes the view resizes along with it. Lastly, a window's frame includes the content view and the extra bits, like title and toolbar. So when setting a window's frame based on its content view, you need to use the frameRectForContentRect: method to calculate the frame.
 

GeeYouEye

macrumors 68000
Original poster
Dec 9, 2001
1,669
10
State of Denial
I'm not sure about the new window thing... that looks like that problem is elsewhere (not in the code you show).

Code:
[myTargetView addSubview:[myCurrentViewController view]];
[[myTargetView window] setFrame:[[myCurrentViewController view] frame] display:YES animate:YES];

You never set the frame of myCurrentViewController's view. It needs to be relative to the bounds of myTargetView. Also you need to set its autoresizing mask, so that when myTargetView resizes the view resizes along with it. Lastly, a window's frame includes the content view and the extra bits, like title and toolbar. So when setting a window's frame based on its content view, you need to use the frameRectForContentRect: method to calculate the frame.

It is at moments like these I wish Macrumors had a reputation system. Thank you! I don't keep a local copy of the code, and I'm off work tomorrow, but I'll try that first thing Monday.
 

GeeYouEye

macrumors 68000
Original poster
Dec 9, 2001
1,669
10
State of Denial
Found the problem with my document window appearing.:eek: My app delegate's awakeFromNib included showing the document window. I'll move it to applicationDidFinishLaunching, but this brings up an architectural question: my nibs (which have array controllers) all need access to the app delegate's managed object context. Do I need an ivar in the window controller to hold the app delegate, and then bind the array controllers in awakeFromNib, or is there an easier way to do it? Clearly I can't just have an app controller object in each nib, that would result in multiple MOCs being created.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.