loading nibs and opening their windows

Hi All,

I have now added several new nibs for utility windows and a progress window to my ASOC project. I have added the load nib call via a button click

tell current application's class "NSBundle"
	loadNibNamed_owner_("progresso", sender)
end tell

which seems to work if I set the progress window to visible at launch - it will show when I clickthe button.

Now how do I show the window programmatically?

property progressWindow : missing value

my progressWindow's orderOut_(sender)

but of course I need to connect the window outlet to my scripts’ property.

I undid “visible at launch”
I opened the progress nib and tried to connect the outlet for the window to my app delegate script over in main.nib.
Obviously you can not cross connect between nibs in that way, which brings up possibilities I don’t quite understand.

Do I need to create a new script with an instance in progresso.nib and connect that way? Then of course I get into having to communicate to the other script from the main script , which isn’t that hard I suppose but I wanted to be able to simply call up the window from my main script where all the processing is happening.

What’s the best way to do this? Any ideas gratefully accepted.

Rob

Tried makeKeyAndOrderFront_(sender) ?

Yes that would probably work but the problem is the window is in another nib. I am wondering if there is any way to call that window from my main script. You can’t make an outlet for the window in the main script since IB doesn’t allow you to make connections from one nib to another.

I will try to move the window call to another script that has an instance in the window nib. But what this means is that I have 5 or 6 nibs and I will haev to have the same amount of scripts, each having an instance in that nib? It is getting too complicated. In ASS, you just load the nib and call its window from the main script:

show window “progress”

Is there any way to do this?

Thanks, Rob

Are you using nibs because you will have multiple of each window? Or will only ever one of each show at a time?

so when you say you’ve tried makeKeyAndOrderFront what have you tried?

I can use this in different scripts to activate teh same window:

this at the top of the script (or multiple scripts) you want to call your window from

gets connected in IB by right clicking on your script (which should be a blue cube you’ve dragged into your nib from the class library), and grabbing the aWindow receiver and connecting it to the proper window
and then
in your script

That’s why I ask, the only reason I believe to load a nib is to create multiple identical windows, typically document apps like TextEdit.

Yes but the window is in another nib and when I try to connect the aWindow receiver from my main nib’s script instance to the the other nibs window, it isn’t allowed. I can’t make any connections between nibs in iB. Can you?

Please let me know what I am missing - something obvious I am sure.

Thanks, Rob

PS I do need multiple nibs, for various utility functions and my understanding has always beem that it is better to load them when they are needed in separate nibs rather than pile them all into the main.nib and open everything at run time needlessly.

Ok, I spent many hours today trying to get something to work here. I read the Aaron Hillegass book’s chapter on nibs and window controllers. That confused me even more.

So just to simplify…

in ASS you could use:

Load nib "progressNib" 

show window "progress"

And you could access and set any element in that window with the olde syntax “set contents of progress bar “progresso” of window “progress” to 10” etc… no problem.

What is the corollary in ASOC?

In ASOC, I know how to add a window to my main nib and call it from any script via outlets to the windows property in the script via makeKeyAndOrderFront.

But I have created a new nib to contain my progress window. You can not connect that window to the instance of your script in the main nib. IB won’t allow any connections between nibs as far as I can see. so I tried adding a new instance of my script in the progress nib and setting it’s class to the script’s name in info panel. Then I tried calling a handler in that script to see if I could open the window that way.

in main script:

tell current application's class "NSBundle"
			loadNibNamed_owner_("progresso", sender)
		end tell
current application's class "progress"'s openProgress_(sender)

in progress script (with instance in progress nib)

script progress
	property parent : class "NSObject"
	property progressWindow : missing value
	
	on openProgress_(sender)
		my progressWindow's makeKeyAndOrderFront_(me)
		log "handler called"
	end openProgress_
end script

it logs ok so the handler is being called but the window isn’t opening probably because I am calling an instance of the script and have no access to the progressWindow variable. That’s a guess…

So, if anyone has been able to load a nib and open its window or have some example they could share about this I would be grateful. I didn’t even mention that I want that progress window to be attached to my main window as a sheet! Aye.

Thanks again, Rob

I’m not sure that separate nibs is the way to go for all but very complicated projects, but if you want to do it, the best method is to create a subclass of NSWindowController. Briefly:

  1. Make a subclass of NSWindowController (New → File, give it a name). Open it and change the parent property to “NSWindowController”. Add the following to it:
	on init()
		continue initWithWindowNibName_("NewWindow") -- name you'll use for xib
		return result
	end init

Do not make an instance of the class.

  1. Add a new .xib file (New → File), named as above. Click on its File’s Owner, and change its class to that of your NSWindowController subclass in the Identity pane of the Inspector. (The xib file will be owned by an instance of your controller; File’s Owner acts as a proxy for the yest-to-be-created instance.)

  2. Add your window to the xib, and connect the File’s Owner’s “window” outlet to it – this lets the xib know which window to open. Also connect the window’s “delegate” outlet to File’s Owner, so you can add window delegate methods to the controller if you wish.

  3. Populate your new window. Add any outlets and handlers to your controller script, and connect them via File’s Owner.

  4. You may want to add other handlers to your controller: windowWillLoad() will be called when the window is about to be shown the first time, and you can add the window delegate method windowShouldClose_(sender) for when performClose_(sender) is called (either by the close button or another button connected to the window’s performClose: action).

  5. Build the handler in your Main.xib script that will create an instance of the controller if one doesn’t exist, and tell the nib to open its window. A connection to the controller will be stored in a property. You can do any other stuff you want to here – for example, set the value of some of the controller’s properties.

	property myWindowController : missing value
	
	on showTheWindow_(sender)
		if myWindowController is missing value then
			set myWindowController to current application's class "NewWindowController"'s alloc()'s init()
		end if
		-- set any properties of myWindowController
		myWindowController's showWindow_(me)
	end showTheWindow_

Thanks Shane,
I had a feeling NSWindowController was my fate. I have been rethinking all the windows and can probably combine them in to two utility windows which could certainly be added to the main nib. I had always heard that it was best to put windows in their own nibs for “modularity” and save on memory at run time. But I can’t imagine a few windows makes much difference these days on these fast machines. That said I can’t resist checking this out.

Thanks, rob

Shane,
Works like a charm. This is a good snippet to have. I got the rough idea of the windowController from the Aaron Hillegass book but would never have been able to translate that into ASOC. It’s the file’s owner that seems to be the bridge between nibs that I couldn’t find.

Thanks, Rob

Ok, one more insidious question. I’ve come this far.

Is it possible to display this window as a sheet?

What to put for customWindow in the showCustomSheet_ handler?

on showCustomSheet_(sender) -- triggered by button in window
		set my contextInfo to "Custom"
		set theApp to current application's class "NSApplication"'s sharedApplication()
		tell theApp to beginSheet_modalForWindow_modalDelegate_didEndSelector_contextInfo_(customWindow, mainWindow, me, "sheetDidEnd:returnCode:contextInfo:", missing value)
	end showCustomSheet_

Good question.

Hillegass’s example has the sheet window in the same nib, and given that sheets are modal for the windows they appear over – and are usually not overly complex – it would seem to make sense. Certainly, trying it with an NSWindowController wouldn’t make sense.

But the Xcode doc Using Custom Sheets shows code for loading a sheet from a nib, using loadNibNamed:owner: and no NSWindowController. But it means it has to be a self-contained dialog, just returning a simple return code. In fact, I posted an example of this somewhere around here a while back.

Ok, I give up on sheets and nib windows. II will consolidate my several windows into the main nib but do like this set up for one of the non-sheets windows. One last question :expressionless:

how do you close the progress window once open. I can get and set the progress bar and text fields easily but I have tried to connect the Close button on the progress window to the File’s owner

Tried two things, no luck yet. “close” is one of the NSWindowController’s tasks but…

script progress
	property parent : class "NSWindowController"
	
	property theProgressBar : missing value
	property theProgresstext : missing value
	
	on closeProgressWindow_()
		close_(me)
	end closeProgressWindow_
	
	on close_(sender)
		return true
	end close_
	
	on init()
		continue initWithWindowNibName_("progresso") -- name you'll use for xib
		return result
	end init
	
	on windowShouldClose_(sender)
		return true
	end windowShouldClose_
	
end script

I will be happy if I can tie up this one loose end and have the windowController as an option if I need it.

Thanks!

Rob

Connect your Close button to the window’s performClose: action.

Doh!

Thanks Shane, I learned this back at the beginning but got blinded by NSwindowControllers and there it is - the obvious.

Apple should be paying to you supply all these helpful examples for their new ASOC bridge.

Rob

I know this is really old but in case it’s useful to someone, I was dealing with this exact issue myself and eventually worked it out. I guess if you’re used to working with nib’s in Objective-C then it’s a no-brainer but if you’re coming from AppleScript Studio then things are a bit different.

As robdut said, in ASS you might write:

Load nib "progressNib" 
show window "progress"

In ASOC the equivalent is:

property progressWindow : missing value
tell current application's NSBundle to loadNibNamed_owner_("progressNib", me)
tell progressWindow to makeKeyAndOrderFront_(me)

(Note you need to put ‘me’ as the nib owner)
But the trick is to connect the outlet in the nib to your property. This is real easy:

  1. Change the class of the “File’s Owner” in your nib to your app delegate script (probably “mainAppDelegate”).
  2. Now you can connect the window to your property in “File’s Owner”.

Interesting note, you cannot have a nib that is compatible with both ASS and ASOC. If an object in a nib has an AppleScript name defined, it will error when trying to load in ASOC.