Using Bindings

I have been working thru Shane’s book and am liking how bindings work since they reduce the amount of code I need to write and have to look thru to maintain. I’m wondering if I could do anymore to this code as I feel I’m writing my own action handler.

I have a combo box with three items. {“Combo Item 1”, “Combo Item 2”, “Combo Item 3”} and I have a popup button I want to enable if “Combo Item 2” is selected in the combo box. I have two properties bound in IB. selectedComboBoxItem to the value & enablePopUpbutton to the enable.

I wrote my own action handler on ComboBoxHasChanged_(sender) and attached it to the combo box in IB. This works fine but I’m wondering if there is any other way to do thru bindings. I found NSComboBoxSelectionDidChangeNotification under NSComboBox Class but this looks like something I would have to do in Obj-C. I’m just wondering if there is another way about this before I dive into my project that needs to enable and disable controls depending on values set in other controls.

script SelectionDidChangeAppDelegate
property parent : class “NSObject”
property enablePopUpbutton : false --bound property
property selectedComboBoxItem : missing value --bound property

on ComboBoxHasChanged_(sender)
	if (selectedComboBoxItem as string) is "Combo Item 2" then
		set my enablePopUpbutton to true
	else
		set my enablePopUpbutton to false
	end if
end ComboBoxHasChanged_

end script

As far as I know there is no way to do it without some code unless you are testing for the presence or absence of another variable (that is using the value transformer of NSISNil or NSIsNotNil). You can use the notification method in ASOC or use the comboBox delegate method, comboBoxSelectionDidChange, which receives the notification that you mentioned. The other way is to use a setter method – if your property, selectedComboBoxItem, is bound to the value of you combo box, the the setSelectedComboBoxItem method will be called (if you have one) when you change the value of your comboBox (notice that the “s” in selected is capitalized when combined with “set” in the method).
So, you could do something like this:

on setSelectedComboBoxItem_(sender)
		set selectedComboBoxItem to sender
		if sender as string is "Combo Item 2" then
			set my enablePopUpbutton to "whatever"
		else
			set my enablePopUpbutton to missing value
		end if
	end setSelectedComboBoxItem_

I don’t know if true and false works as you had in your code – I have the popup enabled binding set with enablePopUpbutton as the Model Key Path and NSIsNotNil as the value transformer (so, in the property declaration, you should set enablePopUpbutton to missing value)

Note that you need to have the first line of the method, set selectedComboBoxItem to sender, present to do what would happen automatically if you didn’t have a setter method.

Ric

Hi,

connect the delegate of the ComboBox to your AppDelegate class and implement this method


	on comboBoxSelectionDidChange_(note)
		-- log note's object's objectValueOfSelectedItem()
		set my enablePopUpbutton to (note's object's objectValueOfSelectedItem() as string) is "Combo Item 2"
	end comboBoxSelectionDidChange_

You can’t use “note” here because that’s some kind of applescript word --aNote would work.

But, how would enablePopUpbutton be bound to the popup that would make this work? The value assigned to that variable in this method is either 1 or 0 (or true or false I guess), and neither is “nil”. Is there a way in the bindings to test for true or false or 1 or 0 ?

Ric

After Edit: You could use this method if you have an outlet to the popupButton and then use the method setEnabled instead of using bindings to the popup button.

on comboBoxSelectionDidChange_(aNote)
		popUp's setEnabled_(aNote's object's objectValueOfSelectedItem() as string is "Combo Item 2")
	end comboBoxSelectionDidChange_

I apologize for butting in with a more novice-level question. Please tell me if I should start a new topic. I’m hoping that this one is close enough for the question to be relevant.

I’m having difficulty figuring out how to connect events which occur to interface object to handlers for them in a piece of ASOC script in Xcode.

I have in Interface Builder a ComboBox, to which I am able to add items with my ASOC script. What I’m trying to do is handle the event which is generated when the selected index of the ComboBox changes.

Looking at the documentation, I see:

NSComboBox class NSComboxSelectionDidChangeNotification

and

NSComboBoxDelegate protocol comboBoxSelectionDidChange

In Craig Williams’ “AppleScriptObjC in Xcode” series, there is an event handler for when a user selects a different TableView column header, to change the sort criteria. In the ASOC script, there is a handler called tableView_sortDescriptorsDidChange_. It works, but I’m not sure how the association is made.

I’ve tried adding a handler

on comboBox_comboBoxSelectionDidChange_(aNotification)
   -- do stuff
end comboBox_comboBoxSelectionDidChange_

but with no success so far.

Thanks for your patience and assistance!

Derek

Your handler is right – you just have to make the script object that contains it the delegate of the combobox (which you do in Interface Builder; control-click on the combobox, and drag from the circle next to delegate across the icon representing the script that contains the handler).

Thanks for your speedy response, Shane!

I’m not sure why, but it doesn’t appear to be working for me. Here’s a little more info.

An excerpt of the script:

script Mail_ProcessorAppDelegate
	-- Inheritance
	property parent : class "NSObject"
	
	-- IBOutlets
	property accountNameField : missing value
	property accountsComboBox : missing value
	property textView : missing value
	
	-- Bindings
	property accountName : ""
	
	on comboBox_comboBoxSelectionDidChange_(aNotification)
		beep
		set accountName to accountComboBox's objectValueOfSelectedItem as text
		accountNameField's setStringValue_("something happened")
	end comboBox_comboBoxSelectionDidChange_

-- other stuff, including on awakeFromNib()

end script

and the settings in Interface Builder:

The beep and the “something happened” instead of the text from accountName are intended to just have something concrete to display in the textField, to demonstrate that I’m definitely entering the handler. So far, no go…

But I do appreciate your help.

Derek

Sorry, I misled you – the handler should simply be “on comboBoxSelectionDidChange_(notif)”.

That did it! Thanks so much, Shane

(For anyone reading afterwards, there is a typo in “on comboBoxSelectionDidChange_”. accountComboBox should be accountsComboBox. But once the event handler was actually being called, finding that typo was easy!

Derek

So this leads me to another question: what happens if I have two or more ComboBoxes? Do I determine in the handler which one triggered it? It doesn’t look there’s a way to have a different handler per ComboBox, Or am I missing it?

You either have separate delegates, or you get the object of the notification, which will be the combobox that triggered it.

I think I see. I’ll experiment more later. Thanks again!

Derek