MathGroup Archive 2009

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Re: Radio buttons panel

  • To: mathgroup at smc.vnet.net
  • Subject: [mg102429] Re: [mg102403] Re: [mg102361] Radio buttons panel
  • From: Bob Hanlon <hanlonr at cox.net>
  • Date: Sun, 9 Aug 2009 06:04:59 -0400 (EDT)
  • Reply-to: hanlonr at cox.net

As an alternative to disabling buttons, you could just eliminate them.

sel = {"X", 34, 36, 56};

f[i_] := Table[
  If[MemberQ[Take[x, i - 1], x[[i]]], 
   x[[i]] = Complement[sel, x][[1]]], {k, i, Length[sel]}]

Manipulate[
 x = Take[sel, n];
 Panel[
  Grid[
   Table[
    With[{i = i}, {
      Dynamic[
       RadioButtonBar[
        Dynamic[x[[i]]],
        Complement[f[i]; sel,
         Take[x, i - 1]]]]}],
    {i, n}]]],
 {{n, Length[sel]},
  Range[Length[sel]]}]

Dynamic[x]


Bob Hanlon

---- Leonid Shifrin <lshifr at gmail.com> wrote: 

=============
Hi,

a good question (IMO anyway)!

The first part is easy:

Panel[Grid[#]] &@
 Map[{RadioButtonBar[Dynamic[#], {"X", "34", "36", "56"}]} &,
  Table[Unique[], {3}]]

will do.

If you want to disable radio-buttons conditionally, my understanding is that
RadioButtonBar
wouldn't do -  I could not find a syntax (in documentation) that allows to
disable individual
buttons in a bar. Here is my attempt:


Clear[radioButtonBar];
radioButtonBar[bt_, state : {(_ | {_, True | False}) ..}] :=
  With[{separ = "  "},
   Row@Replace[
     Replace[state, x_?(Not[MatchQ[#, {_, True | False}]] &) :> {x},
      1],
     {val_, enabled : (True | False) : True} :>
      Sequence[RadioButton[bt, val, Enabled -> enabled], separ, val,
       separ], 1]];

radioButtonBar[bt_, state : {(_ | {_, True | False}) ..},
   changeAt : {(_Integer :> (True | False )) ...},
   flag : "Position"] :=
  Module[{newstate = state},
   newstate[[changeAt[[All, 1]]]] =
    MapThread[
     Replace[##, {0}] &, {newstate[[changeAt[[All,
          1]]]], {{x_, val : (True | False)} :> {x, #},
         x_ :> {x, #}} & /@ changeAt[[All, 2]]}];
   radioButtonBar[bt, newstate]];

radioButtonBar[bt_, state : {(_ | {_, True | False}) ..},
   changeAtValue : {(_ :> (True | False )) ...}, flag : "Value"] :=
  radioButtonBar[bt, state,
   RuleDelayed @@@
    Flatten[Map[Thread[{Flatten[Position[state, #[[1]]]], #[[2]] }] &,
       changeAtValue], 1],
   "Position"];


Examples of use:

In[1]:= radioButtonBar[Dynamic[x],{"X",{"34",False},{"36",False},"56"}]


In[2]:= radioButtonBar[Dynamic[x],{"X","34","36","56"},{1:> False,2:>
False},"Position"]


In[3]:= radioButtonBar[Dynamic[x],{"X","34","36","56"},{"34":> False,"56":>
False},"Value"]

As can be seen, this allows to disable readio buttons according to their
positions or value.

This will make a panel then:


Clear[makePanel];
makePanel[nrows_Integer?Positive, vars : Hold[__Symbol], values_List,
   activeRules : {({_Integer, _} :> (True | False)) ...},
   flag : ("Position" | "Value")] :=
  Dynamic[Panel[Grid[#]] &@
    Apply[List, MapIndexed[
      Function[Null, {
        radioButtonBar[Dynamic[#], values,
         Cases[
          activeRules, ((x : ({row_, col_} :> enable_)) /;
             row === First@#2) :> ( col :> enable)], flag]},
       HoldFirst], vars]]];

makePanel[nrows_Integer?Positive, values_List,
   activeRules : {({_Integer, _} :> (True | False)) ...},
   flag : ("Position" | "Value")] :=
  makePanel[nrows,
   panelVariables[] = Hold @@ Evaluate[Table[Unique[], {nrows}]],
   values, activeRules, flag];

makePanel[nrows_Integer?Positive, values_List,
   activeF : (_Function | _Symbol)] :=
  With[{vars =
     panelVariables[] = Hold @@ Evaluate[Table[Unique[], {nrows}]]},
    makePanel[nrows, vars, values, activeF @@ vars, "Value"]];

It is somewhat awkward, but I don't have time to improve at the moment. It
has a syntax that
allows to disable buttons at specific positions:

makePanel[3, {"X", "34", "36",   "56"}, {{1, 3} :> False, {2, 4} :> False},
"Position"]

or specific values of the variables:

makePanel[3, {"X", "34", "36", "56"}, {{1, "34"} :> False, {2, "56"} :>
False}, "Value"]

additionally, it is possible to implement constraints like the one you
mentioned, but
it is not very pretty at the moment. You have to define a function that will
take variable
values and generate the list of button-disabling rules as in the last
example above. For
example, this will not allow two buttons to be filled at the same column:

Clear[activeFn];
activeFn[vars__] :=
 Thread[Flatten[
    MapIndexed[
     Thread[{Complement[Range[Length[{vars}]], #2], #1}] &, {vars}],
    1] :> False];

for example:

In[] = activeFn[a, b, c]

Out[] =
{{2,a}:>False,{3,a}:>False,{1,b}:>False,{3,b}:>False,{1,c}:>False,{2,c}:>False}

Then you call makePanel:

makePanel[4, {"X", "34", "36", "56", "72"}, activeFn]

I also made the values of variables available through global "function"
panelVariables[], which
returns the held list of variable names. By subscripting it as

panelVariables[][[1]] , panelVariables[][[2]],   etc, you get the values of
individual variables.

The drawback is that you can not use it if you have several panels active at
the same time -
it will only give you the variables of the most recently defined one. This
can be fixed.
There are also other flaws, of course.

Perhaps others will give more elegant and compact solutions, but anyway.

Regards,
Leonid


On Fri, Aug 7, 2009 at 1:27 PM, King, Peter R <peter.king at imperial.ac.uk>wrote:

> I want to create an input panel using radio buttons. I can easily do this
> with
>
> Panel[Grid[{{RadioButtonBar[
>     Dynamic[x], {"X", "34", "36", "56"}]}, {RadioButtonBar[
>     Dynamic[y], {"X", "34", "36", "56"}]}, {RadioButtonBar[
>     Dynamic[z], {"X", "34", "36", "56"}]}}]]
>
> Except I want the different variables x, y, z etc to be members of an
> arrayx[[i]]
>
> x = Table["X", {4}];Panel[Grid[
>  Table[{RadioButtonBar[Dynamic[x], {"X", "34", "36", "56"}]}, {i, 1,
>    4}]]]
>
> Doesn't work as it treats x as a scalar not a list.
>
> Panel[Grid[
>  Table[{RadioButtonBar[Dynamic[x[[i]]], {"X", "34", "36", "56"}]}, {i, 1,
>    4}]]]
>
> Gives nonsense.
>
> Is there a neat way to do this? (I could easily use the top version then
> set x[[1]] to x, x[[2]] to y etc (actually I can't use x in two different
> ways but I'm sure you know what I mean).
>
> Furthermore I want the choice selection in one row to influence what
> options are available in the next row. Think of the rows as time going
> downwards.  I have free choice of which option I can use in row 1. In the
> next row then not all options are available. The easiest is that I cannot
> repeat a selection. So I cannot have X in row 1 followed by X in row 2, so I
> would like that button blanked out (or greyed in or some such). Perhaps what
> I want this to look like is initially the panel has all the buttons greyed
> and unusable except for the first row. Having chosen say 34 from the first
> row, the second row buttos are "ungreyed" except for 34 (there are some
> other rules such as 34 cannot be followed by 36 or 56 followed by 36 but I
> can probably sort that out later).
>
> Finally I want the length of the list (set as 4 above) to be dependent on
> the result of a drop down menu at the top of the panel - not shown.
>
> I know this is 3 questions not 1 but they are linked.
>
> Thanks in advance.
>



  • Prev by Date: Re: Re: FrameTicks or LogPlot bug?
  • Next by Date: Re: Re: A Sum-like notation for iteration
  • Previous by thread: Re: Radio buttons panel
  • Next by thread: On solving equations for variables included in functions R^n to R