4

How do I make ActionMenu's menu appear with one mouseclick of the button and disappear with a second consecutive click on the same button? I would like to be able to click on an ActionMenu in order to inspect the action labels and then click on the ActionMenu button again to close the menu. I believe this behavior is likely seen in many operating systems. This functionality doesn't appear to be obviously supported within Mathematica's control objects, but I hope I'm wrong.

As my first attempt to get this working, I tried the following hoping that the EventHandler would re-evaluate the ActionMenu and set it to the initial view with the menu not visible but this "hacky" attempt didn't yield anything. Here's the code:

EventHandler[ActionMenu["Print Factorials", {"4!" :> Print[4!], "7!" :> Print[7!], 
"10!" :> Print[10!]}], {"MouseClicked" :> ActionMenu[
"Print Factorials", {"4!" :> Print[4!], "7!" :> Print[7!], 
 "10!" :> Print[10!]}]}, PassEventsDown -> True]

I've also tried using Mouseover to achieve this idiomatic functionality without any luck. Again, here's the code in case this helps:

Mouseover[ActionMenu[
Style["Print Factorials", FontFamily -> "Arial", 
FontSize -> 12], {"4!" :> Print[4!], "7!" :> Print[7!], 
"10!" :> Print[10!]}, Appearance -> None, Enabled -> False], 
ActionMenu[
Style["Print Factorials", FontFamily -> "Arial", 
FontSize -> 12], {"4!" :> Print[4!], "7!" :> Print[7!], 
"10!" :> Print[10!]}, Appearance -> None]]
rfrasier
  • 592
  • 3
  • 12
  • The default behaviour of ActionMenu seems to be exactly as you want it to... if you click on any menu item or outside of the menu, it disappears. – Gerli Dec 04 '15 at 11:36
  • 1
    @Gerli, create an ActionMenu and click the button to display the menu and then click the button again only to see that the menu remains displayed. I never allowed for clicking outside of the button in my question but yes, I realize that this does cause the menu to disappear. Now just try clicking the start menu in windows or a menu button on Linux and click once again on the same button to see the menu disappear. I really don't see how this could be any more clearly asked in the subject. – rfrasier Dec 05 '15 at 10:50
  • I voted to reopen, but you may want to add why you don't use a PopupMenu instead of an ActionMenu. – Karsten7 Dec 05 '15 at 11:45
  • Using PopupView is another alternative. – Karsten7 Dec 05 '15 at 11:58
  • @Karsten7. Only ActionMenu has Method -> "Queued". – Kuba Dec 05 '15 at 12:13
  • @Kuba Unlike ActionMenu PopupMenu and PopupView don't perform evaluations by themselves. – Karsten7 Dec 05 '15 at 12:28
  • @Karsten7. They do, assignment to variable is an action, can be extended with 2nd argument of Dynamic, but that's not the point ;) You asked why not PopupMenu, can't be an alternative. – Kuba Dec 05 '15 at 12:36
  • 1
    @Karsten 7., thanks for reopening. The functionality of PopupMenu and PopupView satisfy my question regarding clicking to reveal and hide the menu, but my use-case constraint is to have an evaluation triggered by the selection of a menu item. For example, I'd like to have a new notebook opened with some operations done. This evaluation functionality didn't seem obvious to me in PopupMenu. – rfrasier Dec 05 '15 at 13:24
  • @rfrasier-mlp, on Linux, I can click on the button and it will disappear as well... but if I do a double click it will not disappear. What OS are you on? – Gerli Dec 07 '15 at 12:55

2 Answers2

4

Since a PopupMenu exhibits a behavior you are after, let's adjust it to act like an ActionMenu:

myActionMenu[lbl_, actions_, opts___] := DynamicModule[{x = Unique[x]},
  PopupMenu[Dynamic[x, (# /. actions) &], First /@ actions, lbl, opts]
]


myActionMenu[
   "Print Factorials", 
   {"4!" :> Print[4!], "7!" :> Print[7!], "10!" :> Print[10!]}
]
Kuba
  • 136,707
  • 13
  • 279
  • 740
3

A modified version of the solution provided by Kuba, that behaves like an ActionMenu with the option setting Method -> "Queued"

popupActionMenu[lbl_, actions_] := 
 DynamicModule[{x, trigger}, 
  Row[{PopupMenu[Dynamic[Refresh[x, TrackedSymbols :> {}], (trigger =.; trigger = #) &], 
     First /@ actions, lbl, BaseStyle -> "ActionMenu", Appearance -> "ActionMenu"], 
    DynamicWrapper["", Refresh[trigger /. actions, TrackedSymbols :> {trigger}], 
     SynchronousUpdating -> False]}]]


popupActionMenu["Print Factorials", 
  {"4!" :> Print[4!], "7!" :> (Pause[6]; Print[7!]), "10!" :> Print[10!]}]

The DynamicWrapper could be replaced with

Dynamic[trigger /. actions; "", TrackedSymbols :> {trigger}, SynchronousUpdating -> False]

A version based on PopupView

popupActionMenu[lbl_, actions_] := DynamicModule[{n = 1},
  PopupView[actions[[All, 1]], Dynamic[n, (actions[[#, 2]]) &], ActionMenu[lbl, {}]]]


popupActionMenu["Print Factorials", 
  {"4!" :> Print[4!], "7!" :> Print[7!], "10!" :> Print[10!]}]
Karsten7
  • 27,448
  • 5
  • 73
  • 134