I am running out of space on the Manipulate interface. So, I am looking to see if I can overload a PopupMenu to serve more than one purpose.
Here is the problem:
I have a PopupMenu where I use to select an entry from it. But depending on another choice I make somewhere else, some of these entries in the menu will no longer make sense to select.
So, I was wondering, if I can make some of the entries in the PopupMenu 'selectable' based on a setting of a Dynamic? (may be disabled, or grayed out, or what would be best, have the whole list itself by dynamic, i.e. the whole popUp menu be dyanmic, so I can select different menus based on value of another dynamic. But I do not think this is possible)
Currently, the WHOLE PopupMenu can be enabled or disabled based on a dynamic setting. But I want to do this at the entry level inside the Popupmenu.
Here is an example to illustrate:
Manipulate[selection,
Grid[{
{"x", SetterBar[Dynamic[x], {1, 2}]},
{"selection", PopupMenu[Dynamic[selection],
{
"NONE", "SOR", "SSOR"
}, Enabled -> Dynamic[x == 1]], SpanFromLeft
}
}]
]
In the above, when X=1, the whole menu is enabled.
But what I want, if X=1, is to be able to select only say "NONE" (or the list just show "NONE"), and when X=2, then be able to select only "SOR" and "SSOR" (or the list just show these 2 choices).
i.e. the system will not let "SOR" be selected if x=2. Trying to select it will cause no change and the menu will remain on its previous setting and not change.
Again, I know I can break things into 2 popuMenus, and control each one based on X setting like this below, but I do not have more space to add more menus:
Manipulate[If[x == 1, selectionA, selectionB],
Grid[{
{"x", SetterBar[Dynamic[x], {1, 2}]},
{"selection", PopupMenu[Dynamic[selectionA],
{
"NONE"
}, Enabled -> Dynamic[x == 1]], SpanFromLeft
},
{"selection", PopupMenu[Dynamic[selectionB],
{
"SOR", "SSOR"
}, Enabled -> Dynamic[x == 2]], SpanFromLeft
}
}]
]
My question is: Is there a way to do the above in Mathematica? I am using 8.04.
Best solution would be to have the list of items for the menu itself by Dynamic (or the whole menu be dynamic), so I can tell it to use listA when X=1 or use listB when X=2, etc.. But I do not know how to do this and do not know if it is even possible.
ps. This is my current attempt at a solution
Manipulate[selection,
Grid[{
{"x", SetterBar[Dynamic[x], {1, 2}]},
{"selection", PopupMenu[Dynamic[selection],
{
Dynamic[If[x == 1, listA, listB]]
}
]
}
}
],
Initialization :>
(
listA = {"A", "B"};
listB = {"C", "D"};
)
]
But it is not working too well yet. Will keep at it....
thanks
Update:
Looking at Simon solution below inspired me a little more, so this is what I have so far:
Manipulate[selection,
Grid[{
{"x", SetterBar[Dynamic[x], {1, 2}]},
{"selection",
Dynamic[If[x == 1,
(
selection = "A";
PopupMenu[Dynamic[selection], {"A", "B"}]
),
(
selection = "C";
PopupMenu[Dynamic[selection], {"C", "D"}]
)
]
]
}
}
]
]
Is this the type of thing you're looking for?
Manipulate[
Switch[x,
1, If[selection =!= None, selection = None],
2, If[selection === None, selection = "SOR"]];
selection,
{x, {1, 2}, ControlType -> SetterBar},
{{selection, None}, Switch[x, 1, {None}, 2, {"SOR", "SSOR"}, _, {"huh"}],
ControlType -> PopupMenu}]
Note the Switch
at the top that controls the defaults for selection
when x
is changed.
Following your request to have the menu logic localised to the control Grid
and stealing Heike's default mechanism, here's a new version:
Manipulate[selection,
Grid[With[{menu = {{None}, {"A", "B"}, {"emu", "num"}}},
{{"Which menu?", SetterBar[Dynamic[x], Range[Length[menu]]]},
{"Menu selection:", Dynamic[
If[MemberQ[menu[[x]], selection], selection = menu[[x, 1]]];
PopupMenu[Dynamic[selection], menu[[x]]]]}}]],
{{selection, None}, None}, {{x, 1}, None}]
Note that the menu
list does not need to be localized with a With
statement - it can be set elsewhere in the code.
This solution is similar to Simon's answer, but it doesn't explicitly use the number of lists so it should work for an arbitrary number of lists
choices = {{"a", "b", "c"}, {None}, {"e", "f"}};
Manipulate[
If[Not[MemberQ[x, selection]], selection = x[[1]]];
selection,
{{x, choices[[1]]}, MapIndexed[# -> #2[[1]] &, choices], SetterBar},
{selection, x, ControlType -> PopupMenu}]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With