The top function setstyles
is the only one we need to focus on.
However, the four functions below it are needed for this to work. These validate up to 4 properties of user-input, always returning a list of two styles for the on and off states of a 4-state toggle button.
When working correctly, the function setstyles
determines which style properties to return in a list of 4 styles. The argument sta
is the state (1,2,3, or 4) which is key in determining which properties to pick. Once properties are determined, they are set to the dynamic variables as shown {bg, col, app, lab} = {style1, ..., style4}
.
The odd thing is that most of the time it works fine -- absolutely no complaints. But if I change something somewhere else (symbols elsewhere in program) it will start listing an error for each occurrence of First, Last, and Take even though the input is structurally and syntactically the same before edits were made and all values are valid styles.
If you think you can diagnose the errors, your help is most appreciated. If you do help, please pay attention to the comments in the code. Thank you.
(* This is where errors are generated *)
ClearAll[setstyles, colQ]
colQ = (ColorQ@# || # == Automatic || # == None &);
Options[setstyles] = {
"state" -> sta,
"Backgrounds" -> Automatic, "Colors" -> Automatic,
"Appearances" -> Automatic, "Labels" -> Automatic};
setstyles[opts : OptionsPattern[]] := Module[{
s = OptionValue["state"],
vbgs = valbgs[OptionValue["Backgrounds"]],
vcols = valcols[OptionValue["Colors"]],
vapps = valapps[OptionValue["Appearances"]],
vlabs = vallabs[OptionValue["Labels"]],
off = First[#] & /@ {vbgs, vcols, vapps, vlabs},
on = Last[#] & /@ {vbgs, vcols, vapps, vlabs}
},
With[{
styles = Which[s == 1, off, s == 2, on, s == 3, off, s == 3, on]
},
Set[{bg, col, app, lab}, styles]
]];
(* the 4 validators below work properly *)
ClearAll[vallabs];
stage::invlabs = "Option Labels \[Rule] `1`, expected a single Button \
expression (label) or a List of 1 or 2 labels."; vallabs[l_] :=
If[MatchQ[l, Automatic], {"AutoSave", "Saving"}, {l, l}];
vallabs[{l_}] :=
If[MatchQ[l, Automatic], {"AutoSave", "Saving"}, {l, "Saving"}];
vallabs[{m_, n_}] := With[{
a = If[MatchQ[m, Automatic], "AutoSave", m],
b = If[MatchQ[n, Automatic], "Saving", n]
}, {a, b}];
vallabs[e_List] := Message[stage::invlabs, e];
ClearAll[valbgs];
stage::invbgs = "Option Backgounds \[Rule] `1`, expected a valid \
Background (value) or a List of 1 or 2 values.";
valbgs[c_?colQ] := {c, c};
valbgs[{c_?colQ}] := {c, Black};
valbgs[{a_?colQ, b_?colQ}] := {a, b};
valbgs[e_] := Message[stage::invbgs, e];
ClearAll[valcols];
stage::invcols = "Option Colors \[Rule] `1`, expected a Color \
Directive, None, or Automatic (value) or a List of 1 or 2 values.";
valcols[c_?colQ] :=
If[MatchQ[c, None | Automatic], {Black, Black}, {c, c}];
valcols[{c_?colQ}] :=
If[MatchQ[c, None | Automatic], {Black, Black}, {c, Black}];
valcols[{c_?colQ, d_?colQ}] := With[{
a = If[MatchQ[c, None | Automatic], Black, c],
b = If[MatchQ[d, None | Automatic], Black, d]
}, {a, b}];
valcols[e_] := Message[stage::invcols, e];
ClearAll[valapps];
appear = {Automatic, None, "DialogBox", "Frameless", "Palette",
"FramedPalette", "AbuttingLeftRight", "AbuttingRight" , "Pressed"};
stage::invapps =
"Option Appearances \[Rule] `1`, must be a Button Appearance \
(value) or a list of up to 2 values.";
valapps[a_] :=
If[MemberQ[appear, a], {a, {a, "Pressed"}},
Message[stage::invapps, a]];
valapps[{a_}] :=
If[MemberQ[appear, a], {a, {a, "Pressed"}},
Message[stage::invapps, a]];
valapps[{a_, b_}] :=
If[MemberQ[appear, a] && MemberQ[appear, b], {a, {b, "Pressed"}},
Message[stage::invapps, {a, b}]];
(* this code emulates state *)
sta = 1;
Echo[{bg, col, app,
lab}, Row[{Style["Dynamic Vars: {bg, col, app, lab}", White], " \[Rule]"}]];
(* two cases: simple and not so sinple *)
(* all user inpurs are correct even if they appear inconsistent *)
(* validators allow for this and still return 2 values for each style *)
setstyles[]
setstyles[Backgrounds -> {Darker@Blue, Darker@Green}, Colors -> White,
Labels -> {"off", "on"}, Appearances -> "FramedPalette"];
Module
variables in the values for other variables of the sameModule
. You'll need to just declareon
andoff
with no values, and then set them in the body of theModule
$\endgroup$