OP really needs to provide a clear problem specification, since I still completely fail to understand what is meant by recent comment:
The problem with #3 is how to make state be dependent also from a set of other shared variables.
But here is an extendable version of the code I provided in my recent comment.
Clear[state, expr, toggler];
state[1] = False;
state[2] = False;
expr[1, False] := Print["The first checkbox was off"];
expr[2, False] := Print["The second checkbox was off"];
expr[1, True] := Print["The first checkbox was on"];
expr[2, True] := Print["The second checkbox was on"];
toggler[i : (1 | 2)] :=
Button["Change state N" <> ToString[i], state[i] = ! state[i]];
Grid[
Table[With[{i = i}, {Checkbox[
Dynamic[state[i], (expr[i, state[i]]; state[i] = #) &]],
toggler[i]}], {i, 2}]]
Now each checkbox evaluates an expression that is dependent on the index of the checkbox and its current state: expr[i, state[i]]
(so no need for an If
statement any more). Each chekbox is also supplied with a button that toggles the state, but doesn't evaluate expressions.
Here's another example that replicates the behavior of the example provided by OP:
Clear[state, expr, groupExpr, group];
group = False;
state[1] = False;
state[2] = False;
groupExpr[ownState_] := (state[#] = ownState) & /@ Range[2];
expr[1, stateVec_] := (group = Or @@ stateVec);
expr[2, stateVec_] := (group = Or @@ stateVec);
Column[
Prepend[
Table[With[{i = i},
Checkbox[Dynamic[state[i], (state[i] = #; expr[i, state /@ Range[2]]) &]]],
{i, 2}],
Checkbox[Dynamic[group, (group = #; groupExpr[group]) &]]
]
]
Most generally, I would write the following:
Clear[state, expr, groupExpr, group, n];
n = (* some n *);
group = False;
(state[#] = False) & /@ Range[n];
groupExpr[ownState_,
stateVec_] :=(* some code dependent on own state and other states *);
expr[i_, ownState_,
stateVec_] :=(* some code dependent on own state, index, and other \
states *);
Column[
Prepend[
Table[With[{i = i},
Checkbox[
Dynamic[state[
i], (state[i] = #;
expr[i, state[i], state /@ Range[n]]) &]]], {i, n}],
Checkbox[
Dynamic[group, (group = #; groupExpr[group, state /@ Range[n]]) &]]
]
]
Definitions for expr[i,...]
might need to be supplied explicitly for all possible values of i
, depending on the complexity of the logic.
Finally, here's a generalization to two overlapping groups:
Clear[state, expr, groupExpr, groups, reverseGroups];
n = 6;
groups = {{1, 2, 3, 4}, {3, 4, 5, 6}};
reverseGroups = First /@ Position[groups, #] & /@ Range[n];
(group[#] = False) & /@ Range[Length@groups];
(state[#] = False) & /@ Range[n];
groupExpr[i_, ownState_] := (state[#] = ownState) & /@ groups[[i]];
expr[i_, stateVec_] := (group[#] = Or @@ stateVec[[groups[[#]]]]) & /@ reverseGroups[[i]];
Column[Join[
Table[With[{i = i},
Checkbox[Dynamic[group[i], (group[i] = #; groupExpr[i, group[i]]) &]]],
{i, Length@groups}],
Table[With[{i = i},
Checkbox[Dynamic[state[i], (state[i] = #; expr[i, state /@ Range[n]]) &]]],
{i, n}]
]]