[Newbie] GUIing unresponsive menus

Greetings, All!

I’m finally rebuilding my life after a horrific accident two years ago and, in theory, only have one more round of head surgery to go. How exciting! I’m diving back into AppleScript and would like to solve two (to start) challenges that I didn’t get to before the accident:

I want to determine if a menu item is selected, i.e. has a check mark to the left of the name, but the property returned is: selected:missing value . For example:


tell application "NoteTaker" to tell the front notebook to tell application "System Events" to tell process "NoteTaker"
	return selected of menu item "Cover" of menu "Window" of menu bar item "Window" of menu bar 1
	--> returns "" (when called as string) or selected:missing value (when called as property)
end tell

Is there a way to determine if the menu is “checked”?

Also, I am calling a menu click, but the menu doesn’t automatically update itself, so it doesn’t register its availability until after the menu is clicked. I can script a mouse movement to click in the menu bar, but is there a more elegant solution? For example:


tell application "Tables" to tell application "System Events" to tell process "Tables"
	-- when a column has been selected
	if (enabled of menu item "Column" of menu "Insert" of menu bar item "Insert" of menu bar 1) is true ¬
		and (enabled of menu item "Row" of menu "Insert" of menu bar item "Insert" of menu bar 1) is false then
		click menu item "Column" of menu "Insert" of menu bar item "Insert" of menu bar 1
		--> even though a column was selected, it would return false until the menu bar was clicked--anywhere in the menu bar
	end if
end tell

I’ve also been trying to see if iKey could figure either out, but in all its glory (and from an old OneClick devotee, thats a lot!) I don’t think that even iKey can figure it out. . . . But then again, without a brain, my skills at code crunching have gone a bit South.

Thank you and Happy New Year!!

Model: B&W G3
AppleScript: 1.9.3
Browser: Firefox 2.0.0.1
Operating System: Mac OS X (10.3.9)

Welcome back to AppleScript, livelife ” and a happy new year to all! :slight_smile:

I’m afraid that I don’t use either NoteTaker or Tables, so I’ll start with an example from Safari to demonstrate how this might work.

The following script should first make Safari the frontmost process (which is often needed to register any menu click properly). Then, if the menu item “Block Pop-Up Windows” of menu bar item “Safari” is unchecked, it should check it. (I’m assuming from your example scripts that your system is localized for English.) If the menu item is already checked, no further action is taken.

Note that, when scripting the GUI of an application process, it’s not necessary to use an introductory tell statement for the application itself; simply tell System Events to target the application process ” something like this:


tell application "System Events" to tell application process "Safari" to if exists then
	set frontmost to true
	tell menu item "Block Pop-Up Windows" of menu 1 of menu bar item "Safari" of menu bar 1
		if value of attribute "AXMenuItemMarkChar" is (ASCII character 0) then click
	end tell
end if


Since you’re evidently using Firefox as your browser, here’s a variation that should hide its status bar (if displayed):


tell application "System Events" to tell application process "firefox-bin" to if exists then
	set frontmost to true
	tell menu item "Status Bar" of menu 1 of menu bar item "View" of menu bar 1
		if value of attribute "AXMenuItemMarkChar" is not (ASCII character 0) then click
	end tell
end if


Thank you, Kai! (My goodness–a response from the King Himself. I’m honored!)

I have spent all day on this (qualified by such severe brain damage that my doctors do not understand how I survived . . . but I digress) and have gotten the following two results:

result 1:


tell application "System Events" to tell process "NoteTaker Trial"
	set frontmost to true
	tell menu item "Cover" of menu "Window" of menu bar item "Window" of menu bar 1
(* bear with me here as I list redundant calls commented out to simplify all this *)

		--return the value of attribute "AXMenuItemMarkChar"
		--> returns "<a mystery character that won't pass Preview>" when the menu is checked
		--> returns "" when the menu is *not* checked, ¬
		(* when the above, which appears to be ASCII character 18 (a check mark), is compiled it is converted to "" from some box-like character --which is not rendering properly in Firefox (so far)*)
	
		(* moving on . . . *)
		--if value of attribute "AXMenuItemMarkChar" is not "" then
		--> the above doesn't work, it always thinks it's checked, checked or not
		
		--if value of attribute "AXMenuItemMarkChar" is "<a mystery character that won't pass Preview>" then
		-- if value of attribute "AXMenuItemMarkChar" is "" then
		if value of attribute "AXMenuItemMarkChar" is (ASCII character 18) then
			--> the above three don't work, it always thinks it's not checked, checked or not
			say "it is not checked"
		else
			say "yes, it is checked"
		end if
	end tell
end tell

Apparently it returns not being checked when I ask if it is and returns being checked when I ask if it is not

result 2 (where it really gets odd–or perhaps clearer for those with brains):


tell application "System Events" to tell process "NoteTaker Trial"
	set frontmost to true
	set x to 1
	set theList to {ASCII character 0, ASCII character 1, ASCII character 2, ASCII character 3, ASCII character 4, ASCII character 5, ASCII character 6, ASCII character 7, ASCII character 8, ASCII character 9, ASCII character 10, ASCII character 11, ASCII character 12, ASCII character 13, ASCII character 14, ASCII character 15, ASCII character 16, ASCII character 17, ASCII character 18, ASCII character 19, ASCII character 20} (* Sorry!! I can't remember how to make a list out of a range! *)
	
	tell menu item "Cover" of menu "Window" of menu bar item "Window" of menu bar 1
		repeat with i in theList
			delay 0.1 (* so I can hear the distinct results *)
			if value of attribute "AXMenuItemMarkChar" is (i as string) then
				beep -- It will do this for all but items 10-14 in the list, regardless of whether the menu is checked or not!
			else
				say (x as string) -- It will do this for items 10-14 in the list, regardless of whether the menu is checked or not!
			end if
			set x to x + 1
		end repeat
	end tell
end tell

Now that is odd. The menu is returning true for a variety of conditions regardless of what the status is–and then false for just a few (which it should do for all but one). Thoughts?

Thank you!

Hi, livelife.

Part of the problem is that a text value from an attribute is actually Unicode text, and we’re comparing it with an ASCII character ” which is a string.

This results in some bugginess when certain control characters (at the lower end of the ASCII range) are compared. The exceptions (those characters that compare accurately) are the more printable ones; ASCII numbers 9 (horizontal tab), 10 (line feed), 11 (vertical tab), 12 (form feed) and 13 (carriage return), and again from ASCII character 32 (space) upwards. There’s a last glitch with ASCII character 127 (delete).

Compare this result…


set o to (ASCII character 0)
set l to {}
repeat with i from 0 to 255
	if o is (ASCII character i) then set l's end to i
end repeat
l ”> {0}

… with this rather more spurious one:


set o to (ASCII character 0) as Unicode text
set l to {}
repeat with i from 0 to 255
	if o is (ASCII character i) then set l's end to i
end repeat
l ”> {0, 1, 2, 3, 4, 5, 6, 7, 8, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 127}

In the context of the original exercise, the anomalies shouldn’t matter too much, since we’re really only asking one question: is the value equivalent to ASCII character 0 or not? In spite of the fact that the checked value can translate into one of two different ASCII numbers, depending on whether it’s left as Unicode text or coerced to string, the Boolean outcome should still be correct:


set u_check to «data utxt2713» as Unicode text
set u_nocheck to «data utxt0000» as Unicode text
set s_check to u_check as string
set s_nocheck to u_nocheck as string
set o to ASCII character 0

display dialog "Is the menu unchecked?" & return & return & ¬
	"Menu checked:" & return & tab & ¬
	" utxt: " & u_check & " --> " & "ASCII number " & (ASCII number u_check) & " --> " & (u_check is o) & return & tab & ¬
	"strng: " & s_check & " --> " & "ASCII number " & (ASCII number s_check) & " --> " & (s_check is o) & return & return & ¬
	"Menu unchecked:" & return & tab & ¬
	" utxt: " & u_nocheck & " --> " & "ASCII number " & (ASCII number u_nocheck) & " --> " & (u_nocheck is o) & return & tab & ¬
	"strng: " & s_nocheck & " --> " & "ASCII number " & (ASCII number s_nocheck) & " --> " & (s_nocheck is o)

For your repeating loop, though, coercing the returned value to a string before comparing it with an ASCII character (already a string) should improve things considerably:


tell application "System Events" to tell process "NoteTaker Trial"
	set frontmost to true
	tell menu item "Cover" of menu "Window" of menu bar item "Window" of menu bar 1
		set v to value of attribute "AXMenuItemMarkChar" as string
	end tell
end tell

repeat with i from 0 to 20
	if v is (ASCII character i) then
		beep
	else
		say i
	end if
	delay 0.1
end repeat

Translating that back to your earlier script, try:


tell application "System Events" to tell process "NoteTaker Trial"
	set frontmost to true
	tell menu item "Cover" of menu "Window" of menu bar item "Window" of menu bar 1
		if value of attribute "AXMenuItemMarkChar" as string is (ASCII character 0) then
			say "no, it is not checked"
		else
			say "yes, it is checked"
		end if
	end tell
end tell

Of course, such issues shouldn’t really be tripping us up like this ” but then there are a number of Unicode wrinkles still to be ironed out…

:slight_smile:

Hi, both.

I don’t see the need to coerce the value to string to compare it with (ASCII character 0), when it could be compared more accurately with («data utxt0000» as Unicode text) or («data utxt2713» as Unicode text). I don’t have Notetaker either, but this should work with any app that uses system-drawn menus.

tell application "System Events" to tell process "NoteTaker Trial"
	set frontmost to true
	tell menu item "Cover" of menu "Window" of menu bar item "Window" of menu bar 1
		if (value of attribute "AXMenuItemMarkChar" is («data utxt0000» as Unicode text)) then
			say "no, it is not checked"
		else
			say "yes, it is checked"
		end if
	end tell
end tell

Hi, Mr G.

Yes, I’d considered (and scripted) that approach, too ” but it was waaaay past my bedtime when I posted. I agree that comparing the richer text is preferable. :slight_smile:

As always, wonderful to see this gentleman’s competition. Glad to see you back, Kai, and Nigel probably is too. :slight_smile: I expect he enjoys these exchanges as much as I do. Neither of you may learn anything, but I always do! :wink:

Thanks, Adam ” it’s good to be back. I’ve really missed you guys. :smiley:

But don’t stay up so late, or you’ll get ill again! :o

That sure told me. :rolleyes:

Very good point, Nig (as always) ” which I’ll take as my cue to bid you all a very good night…