Making a new menu in code

I tried this before and gave up before 10.3, although I think I was close before something shiny distracted me. I want to be able to build a menu in code. I mean say, on my window I have a popup button instance or the applications dock menu or any menu and get the reference to that, I can access the current item, and the items in it, but say that popup button represents a choice of data records that I want to add to and remove from. Does anyone know how to do this. My current attempts involve setting up a set of properties and doing a “make new menu item with properties props” type of thing (Where one of the properties is menu:theMenu). Alternatively going for the obj-c bridge with ‘call method “addItemWithTitle:” of theMenu of class “NSMenu” with parameter theTitle’. Neither one seems to work or spit out a usefull error message. I have scanned the ASS examples and flipped through some documentation, but I have yet to see a really clear explanation of how to do this. Thanks ahead for anyone with the 5ki11z to do this one.

Greetings.

I attach the ‘on will open’ handler below to the window containing the popup button so it updates the menu every time the window opens. You might have to get more sophisticated with your data, but here I just use a simple list. Make sure to set the “name:” property if you wish to reference them by name, otherwise you’ll have to do it by index number (or title). I included an ‘on clicked’ handler to receive all of your events to manipulate the menu. Just point some buttons at them and it should do the job.

on will open theObject
	set menuItems to {"Item1", "Item2", "Item3"}
	delete every menu item of menu of popup button "popupButton" of window "theWindow"

	-- Write any 'permanent' (hard-coded) menu items this way
	make new menu item at the end of menu items of menu of popup button "popupButton" of window "theWindow" with properties {name:"Permanent Item 1", title:"Permanent Item 1", enabled:true}

	-- Write dynamic list of items
	repeat with tempItem in menuItems
		make new menu item at the end of menu items of menu of popup button "popupButton" of window "theWindow" with properties {name:tempItem, title:tempItem, enabled:true}
	end repeat
end will open

on clicked theObject
	if name of the theObject is "GoTo_ByVariable" then
		set itemToGoTo to "Item2"
		set current menu item of popup button "popupButton" of window "theWindow" to menu item itemToGoTo of popup button "popupButton" of window "theWindow"
	else if name of the theObject is "GoTo_ByIndex" then
		set current menu item of popup button "popupButton" of window "theWindow" to menu item 3 of popup button "popupButton" of window "theWindow"
	else if name of the theObject is "GoTo_ByName" then
		set current menu item of popup button "popupButton" of window "theWindow" to menu item "Permanent Item 1" of popup button "popupButton" of window "theWindow"
	else if name of the theObject is "NewItemAtEnd" then
		make new menu item at the end of menu items of menu of popup button "popupButton" of window "theWindow" with properties {name:"Item4", title:"Item4", enabled:true}
	else if name of the theObject is "Delete_ByName" then
		delete menu item "Item2" of menu of popup button "popupButton" of window "theWindow"
	end if
end clicked

I didn’t spend the time to figure out adding items into the middle of the menu, but I’m pretty sure you’ll have to read all of the menu items into a list, and then use a repeat similar to the one in the will open handler to regurgitate the list back out with the new item(s) inserted. Hopefully it’s easier than that though, and someone will chime in with the code.

I know, the code above is kind of ugly…I didn’t bother cleaning it up with tell statements and such. It does work though, I took it straight from my test project and only changed the variable names to describe what the events were handling. You should be able to use most of this code with a few modifications to work in an application menu. The format of calling the application menu’s is…

menu item "Item1" of menu "Menu2" of menu "Menu1" of main menu

Working with the dock menu is a little more complicated, and I’d recommend starting with Jon Nathan’s (jonn8) ‘Dockmenu’ or ‘MenuApp’ as a foundation, which are at Jon’s homepage.

Good luck…
j

I changed my code to this (with context removed for sensitive viewers):


--...get theMenu...
set theMenuItems to the menu items of theMenu
--...get menu items for theMenu
set theIndex to the length of my_items 
--my_items stores item info; items that will be selected by this menu
set new_item_properties to {title:"", tag:0, name:"", enabled:true}
--property set object... can I use tag?
set the title of the new_item_properties to "Item " & theIndex as string
set the tag of the new_item_properties to theIndex
set the name of the new_item_properties to "Item" & theIndex as string
--properties properly set... the code gets here with log statements
make new menu item at end of theMenuItems with properties new_item_properties
--and then it chokes: NSCannotCreateScriptCommandError (10)

I did some more looking and found that jon completed my thought on call method style with the obj-c bridge. That’s nice, but I’d like to do it in applescript. Most of the ASK solutions to this problem delete all the existing entries, or are invoked on the load from nib handler… is that really necessary? I just want to click my “add item” button at RUNTIME and have a new menu item appear in the menu and have it selected… and I don’t want to use obj-c (I like coding projects in one language, and although I could do it again completely in obj-c… no…) :rolleyes:

Ok… more messing around… I created a new project with like the bare essentials and it worked… the problem seems to be with trying to create variables to shorten that line. It works in my code when I write


set the_popup to (*...*) -- snip
set like_this to {(*...*)} -- snip
make new menu item at the end of the menu items of the menu of the_popup with properties like_this

but when I try to shorten that a bit like say:


set the_popup to (*...*)
set the_menu to the menu of the_popup
set the_menu_items of the_menu
set this_spot to the end of the_menu_items
set that_spot to reference to this_spot 
set like_this to {(*...*)}

-- all the code from here are variants that don't work!!! (~_~)*/ #-PIKI
-- this is by no means comrehensive but at any rate,
--  -- I can't use variable to refer to the views below the_popup... 
--  Nande darou nande darou na na na nande darou..

make new menu item at the contents of that_spot with properties like_this
make new menu item at this_spot with properties like_this
make new menu item at the end of the_menu_items with properties like_this
make new menu item at the end of the menu items of the_menu with properties like_this


so instead of making it look nice and clean and fit into a window that fits on my iBook’s screen I have this monster ugly line that forces a horizontal scroll bar to appear! XP