This is a question regarding scripting. I would like to have a button "toggle" between two states; revealing a widget A, then hiding a widget A, then revealing a widget A, etc. but don't know what the script for that would look like. And speculatively, would it be possible to add other elements so that the button might cycle between revealing widget A, to revealing widget B, to revealing widget C, then back to hiding them all? Thanks in advance!
The first example is very straightforward: widgets have a .toggle[] method. If you call it with a single argument it will alternate the value of their .show attribute between "none" and the string specified ("solid", "transparent", or "invert"):
on click do a.toggle["solid"] end
You can see more examples of .toggle[] in the release notes.
Cycling through displaying several different widgets is a bit more complicated.
One approach would be to test the .show attributes of widgets, find which one is currently visible, and then set the .show attributes of all the widgets in a group in order to advance to the "next" selection. The main issue here is it's very ugly and inconvenient to add more widgets to the cycle:
on click do if "solid"~a.show a.show:c.show:"none" b.show:"solid" elseif "solid"~b.show b.show:a.show:"none" c.show:"solid" else c.show:b.show:"none" a.show:"solid" end end
We can reduce repetition and make maintenance a bit easier by making a list of widgets of interest, scanning for them in a loop, and using an index modulo the length of the list to pick the next item:
on click do cycle:a,b,c current:0 each wid index in cycle if "solid"~wid.show current:index end end cycle..show:"none" cycle[(count cycle)%1+current].show:"solid" end
If we want to get really clever, there's also a "vector-oriented" way to handle that search instead of an each-loop. In general, multiplying a list of integers [0,n) by a length-n list containing zeroes and a single one will "mask out" the index of the one:
(0,1,2,3)*(1,0,0,0) # (0,0,0,0) (0,1,2,3)*(0,1,0,0) # (0,1,0,0) (0,1,2,3)*(0,0,1,0) # (0,0,2,0) (0,1,2,3)*(0,0,0,1) # (0,0,0,3)
So we could compute "current" like so:
Giving a complete script as follows:
on click do cycle:a,b,c current:sum(range count cycle)*"solid"=cycle..show cycle..show:"none" cycle[(count cycle)%1+current].show:"solid" end
If you want to include "don't show anything" in the cycle, you can add a "0" dummy element to the list of widgets; 0.show will always be 0, which is not equal to the string "show", and attempting to set the .show property of a number is likewise harmless:
on click do cycle:0,a,b,c current:sum(range count cycle)*"solid"=cycle..show cycle..show:"none" cycle[(count cycle)%1+current].show:"solid" end
Does that answer the question?
Edit: one more note: depending on what you're trying to do it might be worth considering using a slider widget instead of a button; Sliders naturally represent choosing between a range of integers, which could represent an index into a list:
on change val do cycle:0,a,b,c cycle..show:"none" cycle[val].show:"solid" end
See also, the enum contraption.