How to disable and enable toolbar items?

(My first post after having learned a lot already from this forum and Shane’s book…)

I’m using a couple of toolbar image-items that target handlers in AppDelegate. Now I’m trying to find out how to disable/enable individual toolbar items dependent on an array being empty or not. So in IB I bound each of the buttons’ Enabled to Array Controller, with key ‘selection’, path ‘count’ and transformer ‘NSIsNil’. While binding similar non-toolbar buttons this way works fine, the toolbar items always remain enabled.

From documentation and other posts I get the idea that I should somehow use NSToolbarItemValidation’s validateToolbarItem:. Is that right? And if so, how and where should I implement that method in ASOC?

Model: iMac
AppleScript: Xcode 4.5
Browser: Safari 536.25
Operating System: Mac OS X (10.8)

You can find a handler in this thread using validateUserInterfaceItem_, which can validate both menu items and toolbar items.

The key is to check the action of the item, to see what’s calling it.

Thanks, you’re fast down there!

So I tried (in AppDelegate):

on validateUserInterfaceItem_(anItem)
    set theSel to anItem's action() as text
    if theSel = "exportTekst:" then
        if notNowFlag = true then return false -- your test
    end if
    -- pass on to the superclass
    return (continue validateUserInterfaceItem_(anItem))
end validateUserInterfaceItem_

(exportTekst: being the action of one of the toolbar items I want to disable)

Upon build this results in an avalanche of stack overflows… after which the application runs but all my toolbar items get disabled before even touching anything. Is this really the way to go?

Also tried replacing validateUserInterfaceItem with validateToolbarItem. That gives less stack overflows: exactly as many as there are toolbar items, to be precise.


there is no need to call super at the end of validateToolbarItem_()
Make sure that the method returns a boolean value anyway

on validateToolbarItem_(anItem)
	set theSel to anItem's action() as text
	if theSel = "exportTekst:" then
		return not notNowFlag -- returns the reverse boolean value of notNowFlag
	end if
	return true
end validateToolbarItem_

Thank you Stefan, that’s a lot better! No more stack overflows and I succeeded in making it work for three of the toolbar items by placing their target actions in a list (these three should be enabled/disabled together):

        if theSel is in {"exportTekst:", "exportWeb:", "exportBuma:"} then

But now I need to change notNowFlag everytime I filled or emptied the array that it all started with. Is there a way of doing that by binding the variable to the array controller’s selection count? Sounds stupid, but I only know how to do bindings using IB and cannot find how it should be done in code.

try to return

arrayController's selectedObjects()'s |count|() as boolean

arrayController is the instance of the NSArrayController

No, that doesn’t work - toolbar buttons stay the same.

What does the job allright is creating a hidden check box with the outlet notNowCheck, binding it’s value to the array controller’s selection @count with NSNegateBoolean, and checking it’s state to determine the value of notNowFlag:

        set theSel to anItem's action() as text
        if theSel is in {"exportTekst:", "exportWeb:", "exportBuma:"} then
            if notNowCheck's state() = 0 then
                set notNowFlag to false
                set notNowFlag to true
            end if
            return not notNowFlag -- returns the reverse boolean value of notNowFlag
        end if
        return true

(Don’t know why this code doesn’t indent suddenly, it does in preview)

As I said, it works, but of course it’s not an elegant solution - or so it feels to me.

Anyway, thanks for now! And if anyone has another suggestion…

I tested it successfully with Objective-C code.
It should also work in ASOC

You last remark made me take another good look and yes: I forgot ‘return’ in front of your line…

Works like a charm now! Thank you very much for helping me out this first time. There’s some friendly and very knowledgeable people on this forum. I’m sure I’ll be back.