scel: install files to site-lisp/SuperCollider
[supercollider.git] / HelpSource / Classes / EZKnob.schelp
blob2011570ba7b71096e22b1542b69fe0503979ced2
1 class:: EZKnob
2 summary:: Wrapper class for label, knob, number box
3 categories:: GUI>EZ-GUI
4 related:: Classes/Knob, Classes/NumberBox, Classes/StaticText, Classes/CompositeView, Classes/EZGui
6 description::
7 EZKnob is wrapper class which creates an (optional) link::Classes/StaticText::, and a link::Classes/Knob:: plus a link::Classes/NumberBox::. If the parent is nil, then EZKnob will create its own window. See link::Classes/EZGui:: more options.
9 subsection:: Some Important Issues Regarding NumberBox
11 warning::
12 EZKnob replaces the EZKnob Quark, which is now called EZKnobOld.  It is encouraged to update your code. The two classes have different creation methods and approaches, particularly concerning the strong::dimensions:: (now strong::bounds::). To make the conversion process easier,  EZKnobOld has an instance method called convert which will post the equivallent creation code for the new EZKnob.
15 note::
16 Bounds: Make certain to choose bounds that are large enough to encompass the knob, the number box, and the label (if you use one), otherwise you may get confusing results. See the examples below.
19 classmethods::
21 method:: new
23 argument:: parent
24 The parent view or window. If the parent is nil, then EZKnob will create its own link::Classes/Window::, and place it conveniently on the screen if the bounds are a link::Classes/Point::. If the bounds are a link::Classes/Rect::, then the link::Classes/Rect:: determines the window bounds.
26 argument:: bounds
27 An instance of link::Classes/Rect:: or link::Classes/Point::. Default value is code::160@20::.  Make certain to choose bounds that are large enough to encompass the knob, the number box, and the label (if you use one), otherwise you may get confusing results. See the examples below.
29 argument:: label
30 The label. Default value is nil. If nil, then no link::Classes/StaticText:: is created.
32 argument:: controlSpec
33 The link::Classes/ControlSpec:: for scaling the value.  If the code::minVal + maxVal:: of the spec is 0, then code::centered:: will be set to true automatically.
35 argument:: action
36 A link::Classes/Function:: called when the value changes. The function is passed the EZKnob instance as its argument.
38 argument:: initVal
39 The value to initialize the knob and number box with. If nil, then it uses the link::Classes/ControlSpec::'s default value.
41 argument:: initAction
42 A link::Classes/Boolean:: indicating whether the action function should be called when setting the initial value. The default is false.
44 argument:: labelWidth
45 Number of pixels width for the label. default is 60. This is only valid for the code::\horz:: layout.
47 argument:: knobSize
48 An instance of link::Classes/Point::.  It will adjust itself to maximize the space use of code::width/height::. By default, it uses the maximum availabel height, and adjusts the withd accordingly.
50 argument:: unitWidth
51 Number of pixels width for the unit label. Default is 0. If 0, then no unitLabel is created.
53 argument:: labelHeight
54 Default is 20.
56 argument:: layout
57 code::\vert::, code::vert2::,  code::\line2::, or code::\horz::. default is code::\vert::.
59 argument:: gap
60 A link::Classes/Point::. By default, the view tries to get its parent's gap, otherwise it defaults to code::2@2::. Setting it overrides these.
62 argument:: margin
63 A link::Classes/Point::. This will inset the bounds occupied  by the subviews of view.
65 discussion::
66 code::
68 w=Window.new.front;
69 g = EZKnob( w,        // parent
70             50@90,    // bounds
71             " test ", // label
72             \freq,    // controlSpec
73             { |ez| (ez.value.asString ++" is the value of " ++ ez).postln } // action
75 g.setColors(Color.grey, Color.white)
78 // Simplest version, no parent view, so a window is created
80         g = EZKnob(label:" test ");
81         g.action_({ |ez| (ez.value.asString ++" is the value of " ++ ez).postln });
84 The contained views can be accessed via the EZKnob instance variables: code::labelView::, code::knobView::, code::numberView::.
87 instancemethods::
89 subsection:: Accessing Instance Variables
91 method:: numberView
92 Returns:: the code::numberView::
94 method:: knobView
95 Returns:: the code::knobView::
97 method:: labelView
98 Set/get the code::labelView::
100 method:: action
101 A function to be evaluated when the value changes. Te first argument will be the EZKnob.
102 argument:: arg1
103 An instance of link::Classes/Function:: or link::Classes/FunctionList::. Default value is code::nil::.
105 method:: value
106 The value of the knob
108 method:: centered
109 Sets/gets whether the knob is in centered mode. See link::Classes/Knob::.
111 method:: round
112 Rounds the values in the number box.
114 method:: controlSpec
115 An instance of link::Classes/ControlSpec:: for scaling the values.
117 method:: value
118 Gets/sets the list/menu to the index at value. Does not perform the action.
119 argument:: val
120 An link::Classes/Integer::.
122 method:: doAction
123 Performs the action at the current index and the global action.
125 method:: set
126 Set the args after creation. You can only set the label if it was not nil from the beginning.
128 method:: visible
129 Sets/gets if the component views are visible.
130 argument:: bool
131 An instance of link::Classes/Boolean::. Default is code::true::.
133 subsection:: Changing Appearance
135 method:: setColors
136 argument:: stringBackground
137 An instance of link::Classes/Color::. The code::background:: of the label and unit views.
138 argument:: stringColor
139 An instance of link::Classes/Color::. The code::stringColor:: of the label and unit views.
140 argument:: numBackground
141 An instance of link::Classes/Color::. The code::numColor:: of the number view.
142 argument:: numStringColor
143 An instance of link::Classes/Color::. The code::stringColor:: of the number view.
144 argument:: numNormalColor
145 An instance of link::Classes/Color::. The code::normalColor:: of the number view.
146 argument:: numTypingColor
147 An instance of link::Classes/Color::. The code::typingColor:: of the number view.
148 argument:: knobColor
149 An instance of link::Classes/Color::. The code::knobColor:: of the knob view.
150 argument:: background
151 An instance of link::Classes/Color::. The code::background:: of the enclosing view.
153 method:: font
154 Set the Font used by all the views.
155 argument:: font
156 An instance of link::Classes/Font::.
158 examples::
160 code::
161 (       // basic use
162         w=Window.new.front;
163         g=EZKnob(w, 50@90," test  ", \freq,{|a| a.value.postln});
164         g.setColors(Color.grey,Color.white);
168 // lots of knobs on on view
170 w=Window.new.front;
171 w.view.decorator=FlowLayout(w.view.bounds);
172 w.view.decorator.gap=2@2;
174 20.do{
175         EZKnob(w, 180@24," Freq ", \freq,unitWidth:30,initVal:6000.rand,layout:\horz)
176         .setColors(Color.grey,Color.white)
177         .font_(Font("Helvetica",11));
182 Window.closeAll  // use this to close all the windows
184 /////////////////////////////////////////////////////////////////
185 ////////// click these parentheses to see all features and layouts
188 m=nil;
189 m=2@2;          // comment this for no margin
191 /////////////////
192 /// Layout \line2
194 (               // all features, small font
195                 g=EZKnob(nil, 128@40," freq  ", \freq,unitWidth:20,layout:\line2, margin: m);
196                 g.setColors(Color.grey,Color.white,Color.grey,
197                         Color.white, Color.yellow,nil,nil, Color.grey(0.7));
198                 g.window.bounds = g.window.bounds.moveBy(-180,50);
199                 g.font_(Font("Helvetica",10));
202 (               // no unitView
203                 g=EZKnob(nil, 118@40," freq  ", \freq,unitWidth:0,layout:\line2, margin: m);
204                 g.setColors(Color.grey,Color.white,Color.grey,
205                         Color.white, Color.yellow,nil,nil, Color.grey(0.7));
206                 g.window.bounds = g.window.bounds.moveBy(-180, -40);
208 (               // no label, so use window name as label
209                 g=EZKnob(nil, 118@30, nil, \freq,labelWidth:100, unitWidth:20,layout:\line2, margin: m);
210                 g.setColors(Color.grey,Color.white,Color.grey,
211                         Color.white, Color.yellow,nil,nil, Color.grey(0.7));
212                 g.window.bounds = g.window.bounds.moveBy(-180, -130);
213                 g.window.name="Freq";
216 /////////////////
217 /// Layout \horz
220 (               // all features
221                 g=EZKnob(nil, 200@28," freq  ", \freq,unitWidth:30,layout:\horz, margin: m);
222                 g.setColors(Color.grey,Color.white,Color.grey,
223                         Color.white, Color.yellow,nil,nil, Color.grey(0.7));
224                 g.window.bounds = g.window.bounds.moveBy(0,50);
227 (               // no unitView
228                 g=EZKnob(nil, 160@28," freq  ", \freq,layout:\horz, margin: m);
229                 g.setColors(Color.grey,Color.white,Color.grey,
230                         Color.white, Color.yellow,nil,nil, Color.grey(0.7));
231                 g.window.bounds = g.window.bounds.moveBy(0, -30);
233 (               // no label, so use window name as label
234                 g=EZKnob(nil, 120@28, nil, \freq ,layout:\horz, margin: m);
235                 g.setColors(Color.grey,Color.white,Color.grey,
236                         Color.white, Color.yellow,nil,nil, Color.grey(0.7));
237                 g.window.bounds = g.window.bounds.moveBy(0, -110);
238                 g.window.name="Freq";
243 /////////////////
244 /// Layout \vert
246 (               // all features
247                 g=EZKnob(nil, 82@82," freq  ", \freq,unitWidth:18,layout:\vert, margin: m);
248                 g.setColors(Color.grey,Color.white,Color.grey,
249                         Color.white, Color.yellow,nil,nil, Color.grey(0.7));
250                 g.font_(Font("Helvetica", 10));
251                 g.window.bounds = g.window.bounds.moveBy(220,50);
254 (               // no unitView, with label
255                 g=EZKnob(nil, 70@90," freq  ", \freq,unitWidth:0,layout:\vert, margin: m);
256                 g.setColors(Color.grey,Color.white,Color.grey,
257                         Color.white, Color.yellow,nil,nil, Color.grey(0.7));
258                 g.window.bounds = g.window.bounds.moveBy(220,-90);
261 (               // no label
262                 g=EZKnob(nil, 120@60,nil, \freq, unitWidth:30,layout:\vert, margin: m);
263                 g.setColors(Color.grey,Color.white,Color.grey,
264                         Color.white, Color.yellow,nil,nil, Color.grey(0.7));
265                 g.window.bounds = g.window.bounds.moveBy(220,-230);
266                 g.window.name="Freq";
269 (               // no lablel, so use window name as label
270                 g=EZKnob(nil, 120@60,nil, \freq,unitWidth:0,layout:\vert, margin: m);
271                 g.setColors(Color.grey,Color.white,Color.grey,
272                         Color.white, Color.yellow,nil,nil, Color.grey(0.7));
273                 g.window.bounds = g.window.bounds.moveBy(220,-340);
274                 g.window.name="Freq";
278 /////////////////
279 /// Layout \vert2
281 (               // all features
282                 g=EZKnob(nil, 82@82," freq  ", \freq,unitWidth:18,layout:\vert2, margin: m);
283                 g.setColors(Color.grey,Color.white,Color.grey,
284                         Color.white, Color.yellow,nil,nil, Color.grey(0.7));
285                 g.font_(Font("Helvetica", 10));
286                 g.window.bounds = g.window.bounds.moveBy(350,50);
289 (               // no unitView, with label
290                 g=EZKnob(nil, 70@90," freq  ", \freq,unitWidth:0,layout:\vert2, margin: m);
291                 g.setColors(Color.grey,Color.white,Color.grey,
292                         Color.white, Color.yellow,nil,nil, Color.grey(0.7));
293                 g.window.bounds = g.window.bounds.moveBy(350,-90);
296 (               // no label
297                 g=EZKnob(nil, 120@60,nil, \freq, unitWidth:30,layout:\vert2, margin: m);
298                 g.setColors(Color.grey,Color.white,Color.grey,
299                         Color.white, Color.yellow,nil,nil, Color.grey(0.7));
300                 g.window.bounds = g.window.bounds.moveBy(350,-230);
301                 g.window.name="Freq";
304 (               // no lablel, so use window name as label
305                 g=EZKnob(nil, 120@60,nil, \freq,unitWidth:0,layout:\vert2, margin: m);
306                 g.setColors(Color.grey,Color.white,Color.grey,
307                         Color.white, Color.yellow,nil,nil, Color.grey(0.7));
308                 g.window.bounds = g.window.bounds.moveBy(350,-340);
309                 g.window.name="Freq";
318 ///////////////////////////////////////////////////////////////
319 ///////////////////////////////////////////////////////////////
322 // Sound example
324 // start server
325 s.waitForBoot({
327 var w, startButton, noteControl, cutoffControl, resonControl;
328 var balanceControl, ampControl;
329 var node, cmdPeriodFunc;
331 // define a synth
332 SynthDef("window-test", { arg note = 36, fc = 1000, rq = 0.25, bal=0, amp=0.4, gate = 1;
333                 var x;
334                 x = Mix.fill(4, {
335                         LFSaw.ar((note + {0.1.rand2}.dup).midicps, 0, 0.02)
336                 });
337                 x = RLPF.ar(x, fc, rq).softclip;
338                 x = RLPF.ar(x, fc, rq, amp).softclip;
339                 x = Balance2.ar(x[0], x[1], bal);
340                 x = x * EnvGen.kr(Env.cutoff, gate, doneAction: 2);
341                 Out.ar(0, x);
342         }, [0.1, 0.1, 0.1, 0.1, 0.1, 0]
343 ).add;
348 // make the window
349 w = Window("another control panel", Rect(20, 400, 230, 250));
350 w.front; // make window visible and front window.
351 w.view.decorator = FlowLayout(w.view.bounds);
352 w.view.decorator.gap=2@2;
354 // add a button to start and stop the sound.
355 startButton = Button(w, 75 @ 20);
356 startButton.states = [
357         ["Start", Color.black, Color.green(0.7)],
358         ["Stop", Color.white, Color.red(0.7)]
360 startButton.action = {|view|
361                 if (view.value == 1) {
362                         // start sound
363                         node = Synth( "window-test", [
364                                 "note", noteControl.value,
365                                 "fc", cutoffControl.value,
366                                 "rq", resonControl.value,
367                                 "bal", balanceControl.value,
368                                 "amp", ampControl.value.dbamp ]);
369                 } {
370                         // set gate to zero to cause envelope to release
371                         node.release; node = nil;
372                 };
375 // create controls for all parameters
376 w.view.decorator.nextLine;
377 noteControl = EZKnob(w, 220 @ 32, "Note ", ControlSpec(24, 60, \lin, 1, 36, \note),
378         {|ez| node.set( "note", ez.value )}, unitWidth:30,layout:\horz)
379                 .setColors(Color.grey,Color.white, Color.grey(0.7),Color.grey, Color.white, Color.yellow);
381 w.view.decorator.nextLine;
382 cutoffControl = EZKnob(w, 220 @ 32, "Cutoff ", ControlSpec(200, 5000, \exp,0.01,1000,\Hz),
383         {|ez| node.set( "fc", ez.value )}, unitWidth:30,layout:\horz)
384                 .setColors(Color.grey,Color.white, Color.grey(0.7),Color.grey, Color.white, Color.yellow);
386 w.view.decorator.nextLine;
387 resonControl = EZKnob(w, 220 @ 32, "Reson ", ControlSpec(0.1, 0.7,\lin,0.001,0.2,\rq),
388         {|ez| node.set( "rq", ez.value )}, unitWidth:30,layout:\horz)
389                 .setColors(Color.grey,Color.white, Color.grey(0.7),Color.grey, Color.white, Color.yellow);
391 w.view.decorator.nextLine;
392 balanceControl = EZKnob(w, 220 @ 32, "Balance ", \bipolar,
393         {|ez| node.set( "bal", ez.value )},  unitWidth:30,layout:\horz)
394                 .setColors(Color.grey,Color.white, Color.grey(0.7),Color.grey, Color.white, Color.yellow);
396 w.view.decorator.nextLine;
397 ampControl = EZKnob(w, 220 @ 32, "Amp ", \db,
398         {|ez| node.set( "amp", ez.value.dbamp )}, -6, unitWidth:30,layout:\horz)
399                 .setColors(Color.grey,Color.white, Color.grey(0.7),Color.grey, Color.white, Color.yellow);
402 // set start button to zero upon a cmd-period
403 cmdPeriodFunc = { startButton.value = 0; };
404 CmdPeriod.add(cmdPeriodFunc);
406 // stop the sound when window closes and remove cmdPeriodFunc.
407 w.onClose = {
408         node.free; node = nil;
409         CmdPeriod.remove(cmdPeriodFunc);
415 //////////////////////////////
416 // more examples
417 // these mimick the original  EZKnob layout and colors
420 w = Window("EZKnob", Rect(380,400,300,180)).front;
421 w.view.decorator = FlowLayout(w.view.bounds);
422 k = EZKnob(w, 42 @ 74, "Knob", action: { arg knb; knb.value.postln; }, margin:2@2, labelHeight:16);
423 k.view.background_(Color.grey.alpha_(0.4));
425 k.centered_(true)
426 k.value=0.5;
427 k.visible_(false)
428 k.visible_(true)
430 k.enabled_(false)
431 k.value = 0.1
432 k.enabled
433 k.enabled_(true)
434 k.value = 0.25
437 w = Window("EZKnob", Rect(380,400,300,180)).front;
438 w.view.decorator = FlowLayout(w.view.bounds, gap: 1@1);
439 StaticText(w, (42 * 4 + 3) @ 16).string_("EZKnob Cluster").background_(Color.blue(0.1,0.1));
440 w.view.decorator.nextLine;
441 a = [
442                 EZKnob(w, 42 @ 74, "knob 1", margin:2@2, labelHeight:16),
443                 EZKnob(w, 42 @ 74, "knob 2", controlSpec: \freq, margin:2@2, labelHeight:16),
444                 EZKnob(w, 42 @ 74, "knob 3", controlSpec: \pan, margin:2@2, labelHeight:16).round_(0.001),
445                 EZKnob(w, 42 @ 74, "knob 4", controlSpec: \rq, margin:2@2, labelHeight:16)
446         ];
447 a.do{arg a;a.view.background_(Color.grey.alpha_(0.4))};
449 // a now holds the array of knobs
451 a[0].value
452 a[3].value_(0.5)
453 a.collect(_.value );