This helpfile is part of a GUI tutorial.
It is the third part of a beginner's introduction to SuperCollider's GUI system. First part covers creating a window, while second part talks about interfacing a synth with a GUI interface.
This tutorial presents different interfaces you might need to construct when working with SuperCollider's system, and discuss their particularities. If you need a more detailed tutorial about the basics of view composition, you should read GUI: Interfacing an instrument with a View first.
SuperCollider implements different GUI components that allow you to compose complex softwares interfaces.
The list of those components is available in the documentation, by selecting Browse > GUI > Views.
You can see those components as some base building blocks allowing you to construct a greater structure.
This is the simplest example about view composition: a Slider, a TextField and a StaticText. Not much to say here, the code mostly speaks for itself. The only thing to remember is to have the Slider and the TextField update each other accordingly when edited.
Please note that this example is 'unsafe': there is no mechanism preventing to enter high values inside the TextField: any float number is valid. You are still responsible to clip values to the correct range when using a TextField. Entering a non-valid number in the TextField will set the value to 0.0 (because converting a non-float String with .asFloat
returns 0.0).
This example is the continuation of the previous one, and explains why UI components shouldn't be directly responsible for the action they ultimately perform. It also talks briefly about focus and keyboard input response.
One of the common mistake when starting using SuperCollider's GUI system is to use a View's action function as if it was effectively the function responsible for modifying the software. Even if it works reliably if there is only one View associated with the algorithm, this tends to decrease code readability. When several Views are tied to the same algorithm, this almost always introduces issues, as one can see in the previous example.
The next example shows how to centralize the algorithm in a single Function, which is responsible for applying the modification to the software, then update the Views accordingly. In this context, View's action functions are only responsible to convert the data they provide to the right format, then to call the centralizing function.
Here, several views are using the updateValue
function to modify the value. This function also updates every views at once. What's interesting is that the function clips the value if it was out of bounds: this is preventing users to specify a wrong value when using the TextField. This will clip any wrong value, regardless of its origin.
Both the Slider and the TextField have really small action functions: they only convert the value to the right format, then call updateValue
. Beside readability, we only need to modify updateValue
if we have to change the algorithm. View's action
functions aren't concerned by any changes once set.
In this particular example, I also implement a switch statement which allows the window to respond to keyboard inputs. Since both Slider and TextField natively respond to keyboard inputs events, we have to manipulate Views focus to specify the context of the events.
An interface that provides a simple tab system, like one would find in a web browser, allowing to switch between several web pages.
To do this, we can combine two simple building blocks: some Buttons, and a StackLayout.
A StackLayout allows to insert several graphical contexts on top of each other, as you would pile some drawings on top of each other. You can chose to only display one of them, or all of them, in which case you can see a view under another view. This is similar to the layer system you can find in drawing softwares.
This example demonstrate how to toggle a views visibility as one would use a window minimize function.
This is possible because a layout redraws its children when their visibility is modified.
The window is first split vertically in two: a main view, and a small menu that 'contains' hidden views. This menu is only visible when it is non-empty.
For each of our subviews (in our example, a MultiSliderView and a StaticText), we are creating two Buttons: one that hides the view, and is situated in the same layout as the view it is hiding, and one inside the menu, that displays it back. They control the views visibility, and they also control the visibility of the menu.