My primary objective is to build a file chooser that aides a user in selecting files into one of two categories. Files can be individually selected, or based on the clicking of a specific checkbox, all files listed above it will be selected, or de-selected.
Consider Code Snippet 1: (this code almost accomplishes what I need)
celdatafiles = {"GSM15432", "GSM98765", "GSM34521", "GSM65912",
Style["Select All", Bold, Red],
Style["Unselect All", Bold, Red]};(* arbitrary test data *)
expsym = ConstantArray[False, Length[celdatafiles]];
contsym = ConstantArray[False, Length[celdatafiles]];
expcheckbox =
Table[With[{i = i}, Checkbox[Dynamic[expsym[[i]]]]], {i, 1,
Length[expsym]}];
contcheckbox =
Table[With[{i = i}, Checkbox[Dynamic[contsym[[i]]]]], {i, 1,
Length[contsym]}];
celoptions =
MapThread[List, {celdatafiles, expcheckbox, contcheckbox}];
(* BEGIN CODE to add control over Select All and Unselect All \
functionality *)
Dynamic[Which[
expsym[[-2]] == True \[And]
expsym[[-1]] == False, (expsym[[1 ;; (Length[expsym] - 2)]] =
ConstantArray[True, (Length[expsym] - 2)];
expsym[[-2]] = False),
expsym[[-2]] == False \[And]
expsym[[-1]] == True, (expsym[[1 ;; (Length[expsym] - 2)]] =
ConstantArray[False, (Length[expsym] - 2)];
expsym[[-1]] =
False)]](* do NOT use semicolon at end of statement, because it \
affects display updating *)
(* control code for Select All and UnSelect All functionality \
*)Dynamic[
Which[contsym[[-2]] == True \[And]
contsym[[-1]] == False, (contsym[[1 ;; (Length[contsym] - 2)]] =
ConstantArray[True, (Length[contsym] - 2)];
contsym[[-2]] = False),
contsym[[-2]] == False \[And]
contsym[[-1]] == True, (contsym[[1 ;; (Length[contsym] - 2)]] =
ConstantArray[False, (Length[contsym] - 2)];
contsym[[-1]] = False)]]
expchips =
Dynamic[Pick[celdatafiles, expsym,
True]];(* grab experimental chips that were selected *)
contchips =
Dynamic[Pick[celdatafiles, contsym,
True]];(* grab control chips that were selected *)
analysisfiles =
TableForm[celoptions, TableAlignments -> Center,
TableHeadings -> {None,
Map[Style[#, Bold, Blue] &, {"File Name", "Experimental?",
"Control?"}]}];(* formatting for gui element where user chooses \
cel files to be analyzed *)
(* DialogInput is used because it blocks the kernel from moving \
forward until the dialog is closed *)
DialogInput[{analysisfiles,
Button["I'm finished selecting files",
DialogReturn[]]},
WindowTitle -> "Choose the CEL files you want to analyze",
WindowSize -> {400, 400},
WindowElements -> "VerticalScrollBar"]
Comments and questions about Code Snippet 1 above:
Notice how the custom control allows multiple files to be chosen by clicking the "Select All" checkbox under a category, and also if files are already chosen, the control allows multiple files to be unchosen by clicking the "Deselect All" checkbox. This is the behavior that I want.
Notice how execution of Code Snippet 1 always produces the "Null", "Null" output in the notebook. I believe this is because the Dynamic statements controlling the "SelectAll" and "Deselect All" behavior do not have a semicolon after them. If I use a semicolon, the Dynamic statements are suppressed and the "Select All"/"Deselect All" functionality does not work anymore.
Q1. How can I maintain the desired behavior without producing the "Null", "Null" output?
- Because I am using the code above inside a custom palette, I really would like to place Code Snippet 1 inside DynamicModule. Unfortunately, this completely destroys the "Select All" and "Unselect All" behavior that I really need to preserve.
Consider what happens when you place code snippet 1 inside a DynamicModule
Code Snippet 2: (desired functionality of code snippet 1 destroyed)
celdatafiles = {"GSM15432", "GSM98765", "GSM34521", "GSM65912",
Style["Select All", Bold, Red],
Style["Unselect All", Bold, Red]};(* arbitrary test data *)
celChooser[celdatafiles_] :=
DynamicModule[{expsym, contsym, expcheckbox, contcheckbox,
celoptions, expchips, contchips, analysisfiles},
expsym = ConstantArray[False, Length[celdatafiles]];
contsym = ConstantArray[False, Length[celdatafiles]];
expcheckbox =
Table[With[{i = i}, Checkbox[Dynamic[expsym[[i]]]]], {i, 1,
Length[expsym]}];
contcheckbox =
Table[With[{i = i}, Checkbox[Dynamic[contsym[[i]]]]], {i, 1,
Length[contsym]}];
celoptions =
MapThread[List, {celdatafiles, expcheckbox, contcheckbox}];
(* BEGIN CODE to add control over Select All and Unselect All \
functionality *)
Dynamic[
Which[expsym[[-2]] == True \[And]
expsym[[-1]] == False, (expsym[[1 ;; (Length[expsym] - 2)]] =
ConstantArray[True, (Length[expsym] - 2)];
expsym[[-2]] = False),
expsym[[-2]] == False \[And]
expsym[[-1]] == True, (expsym[[1 ;; (Length[expsym] - 2)]] =
ConstantArray[False, (Length[expsym] - 2)];
expsym[[-1]] = False)]](*
do NOT use semicolon at end of statement,
because it affects display updating *)
(* control code for Select All and UnSelect All functionality *)
Dynamic[Which[
contsym[[-2]] == True \[And]
contsym[[-1]] ==
False, (contsym[[1 ;; (Length[contsym] - 2)]] =
ConstantArray[True, (Length[contsym] - 2)];
contsym[[-2]] = False),
contsym[[-2]] == False \[And]
contsym[[-1]] == True, (contsym[[1 ;; (Length[contsym] - 2)]] =
ConstantArray[False, (Length[contsym] - 2)];
contsym[[-1]] = False)]]
expchips = Dynamic[Pick[celdatafiles, expsym, True]];(*
grab experimental chips that were selected *)
contchips = Dynamic[Pick[celdatafiles, contsym, True]];(*
grab control chips that were selected *)
analysisfiles =
TableForm[celoptions, TableAlignments -> Center,
TableHeadings -> {None,
Map[Style[#, Bold, Blue] &, {"File Name", "Experimental?",
"Control?"}]}];(*
formatting for gui element where user chooses cel files to be \
analyzed *)
(* DialogInput is used because it blocks the kernel from moving \
forward until the dialog is closed *)
DialogInput[{analysisfiles,
Button["I'm finished selecting files",
DialogReturn[]]},
WindowTitle -> "Choose the CEL files you want to analyze",
WindowSize -> {400, 400},
WindowElements -> "VerticalScrollBar"]]
celChooser[celdatafiles]
Comments and questions about Code Snippet 2:
- If you run code snippet 2, you notice the following things:
A. The "Select All" and "Unselect All" functionality no longer works.
Q2. Why does placing this code inside DynamicModule break the behavior I need?
Q3. I feel like I'm wrestling with Mathematica (and I'm not winning!), so is there an alternative approach I should be trying to get the "Select All"/"Unselect All" functionality to work properly inside DynamicModule.
B. Code snippet 2 produces a Tag Times error, which I believe is also do to the Dynamic[Which .....] statement not having a semicolon after it.
In conclusion, how can I maintain the behavior I am after while inside a DynamicModule? Thanks!