From: gtslist on
Hi group!

I would like to implement a popup menu that appears when you right-
click on an object or on the white area of a graph, similar to the
menu you get by a right-clicking to explore the properties of a
desktop icon or the desktop itself. The ActionMenu would be ideal, but
I found no way to get just the items list window, without the menu
placeholder. It seem that a sort of "ItemslistView" isn't available as
a separate function from the ActionMenu. Is there a way to easily
implement this without to have to write all the code (and without use
the GUIKit Package)? This function of course already exists as the
current menu functions use it, probably it is accessible but
undocumented.

To better explain what I need I've wrote a small example. The pretty
un-useful code below draws two disk that you can move around. If you
right-click into a disk area, an ActionMenu will display, allowing to
choose some actions. Same if you right-click on the white area outside
the circles. If you choose an action, the popup menu will hides. So
far, so good. But if you click outside the items list area without
choosing any item, the float list hides but the place holder of the
ActionMenu remains there, and you have do to an additional click
somewhere to hide the menu, and prevent to show the float list again
hovering the mouse on the menu placeholder. This of course happen
because the first click away from the items list area is intercepted
by the ActionMenu function for its normal operation (i.e. hiding the
float list) and it seems that there isn't a way to circumvent this.

Also it seems that there is no way to have an hierarchic popup menu,
ones where one or more of its items display a triangle on the right
allowing to open a sub menu displaying more options. Googling around
I've found some threads that complain about the lacking of a sub menu
feature and the difficulty to have a float popup items view, but Mathematica
itself seems to have both for its internal use: for example when you
right-click a notebook area you'll get a float popup hierarchic items
list, that is the same I need to implement (but, hoping, without
reinvent the wheel).

Any hints my friends?

TIA!

Guido


Module[
{bottomMargin = 0,
topMargin = 100,
leftMargin = 0,
rightMargin = 100,
r = 5,
pt1,
pt2,
disk = 0,
pt = {0, 0},
showMenuFlag = False,
menuItem = {},
menuAction = {}
},

pointInCircleQ[point_, circlePos_, radius_] :=
If[Sqrt[Plus @@ ((circlePos - point)^2)] <= radius, True, False];

pt1 = {
RandomInteger[{leftMargin + r, rightMargin - r}],
RandomInteger[{bottomMargin + r, topMargin - r}]};
pt2 = {
RandomInteger[{leftMargin + r, rightMargin - r}],
RandomInteger[{bottomMargin + r, topMargin - r}]};

Dynamic(a)Deploy@EventHandler[

(* --- Draw stuff --- *)
Graphics[{

(* plot Disk 1 *)
Mouseover[
{LightBlue, Disk[pt1, r], Blue, Circle[pt1, r]},
{Thick, LightBlue, Disk[pt1, r], Blue, Circle[pt1, r]}],

(* plot Disk 2 *)
Mouseover[
{LightRed, Disk[pt2, r], Red, Circle[pt2, r]},
{Thick, LightRed, Disk[pt2, r], Red, Circle[pt2, r]}],

(* - Manage the ActionMenu - *)
If[showMenuFlag,

(* setup the items and actions for the ActionMenu.
Eevery action ends hiding the menu (showMenuFlag=False) *)

Which[
(* setup for right-clicking in the blank area *)
disk == 0,
menuItem = {
"Align both disks to Top",
"Align both disks to Bottom"};
menuAction = {
Hold[pt1[[2]] = pt2[[2]] = topMargin - r; showMenuFlag =
False],
Hold[pt1[[2]] = pt2[[2]] = bottomMargin + r; showMenuFlag =
False]}
,
(* setup for right-clicking into blue Disk 1 *)
disk == 1,
menuItem = {
"Align Blue Disk to Top",
"Align Blue Disk to Bottom",
Delimiter,
"Properties"};
menuAction = {
Hold[pt1[[2]] = topMargin - r; showMenuFlag = False],
Hold[pt1[[2]] = bottomMargin + r; showMenuFlag = False],
Null,

Hold[
MessageDialog[
"Properties for Blue disk. Coordinates = " <>
ToString[pt1]];
showMenuFlag = False]}
,
(* setup for right-clicking into red Disk 2 *)
disk == 2,
menuItem = {
"Align Red Disk to Top",
"Align Red Disk to Bottom",
Delimiter,
"Properties"};
menuAction = {
Hold[pt2[[2]] = topMargin - r; showMenuFlag = False],
Hold[pt2[[2]] = bottomMargin + r; showMenuFlag = False],
Null,

Hold[
MessageDialog[
"Properties for Red disk. Coordinates = " <>
ToString[pt2]];
showMenuFlag = False]}
];(* /Which *)

(* - Display the ActionMenu - *)
Inset[
ActionMenu[
(*
I could leave the title string empty making invisible the
menu \
placeholder, but this way is more explicit what and where the problem
is.
And the problem is:
when click outside the popup area without click an item,
the menu placeholder remains active,
because that click is (of course) owned by the ActionMenu
function,
and an additional click is needed to put the menu away. *)

" ActionMenu ",
MapThread[
If[#1 === Delimiter,
Delimiter, (#1 :> ReleaseHold@#2)] &, {menuItem,
menuAction}],
AutoAction -> True,
Appearance -> "None"
](* /ActionMenu *)
, pt](* /Inset *)
, {}](* /
If *)

},
PlotRange -> {{leftMargin, rightMargin}, {bottomMargin,
topMargin}},
AspectRatio -> 1,
Frame -> True,
FrameTicks -> None,
ImageSize -> 300
](* /Graphics *),


(* --- Manage Mouse Actions --- *)

"MouseDown" :> (
pt = MousePosition["Graphics"];

(* If right-click, enable the visualization of ActionMenu,
else hide it *)
If[First[CurrentValue["MouseButtons"]] == 2,
showMenuFlag = True,
showMenuFlag = False]

Which[
pointInCircleQ[pt, pt1, r], disk = 1,
pointInCircleQ[pt, pt2, r], disk = 2,
True, disk = 0;
];
),

"MouseDragged" :> (
pt = MousePosition["Graphics"];
Which[
disk == 1, pt1 = pt,
disk == 2, pt2 = pt];
)
](* /EventHandler *)
](* /Module*)