3 var <sliderView, <numberView, <unitView, <>controlSpec,
4 popUp=false, numSize,numberWidth,unitWidth, gap;
7 *new { arg parent, bounds, label, controlSpec, action, initVal,
8 initAction=false, labelWidth=60, numberWidth=45,
9 unitWidth=0, labelHeight=20, layout=\horz, gap, margin;
11 ^super.new.init(parent, bounds, label, controlSpec, action,
12 initVal, initAction, labelWidth, numberWidth,
13 unitWidth, labelHeight, layout, gap, margin)
16 init { arg parentView, bounds, label, argControlSpec, argAction, initVal,
17 initAction, labelWidth, argNumberWidth,argUnitWidth,
18 labelHeight, argLayout, argGap, argMargin;
20 var labelBounds, numBounds, unitBounds,sliderBounds;
24 this.prMakeMarginGap(parentView, argMargin, argGap);
26 unitWidth = argUnitWidth;
27 numberWidth = argNumberWidth;
29 bounds.isNil.if{bounds = 350@20};
32 // if no parent, then pop up window
33 # view,bounds = this.prMakeView( parentView,bounds);
36 labelSize=labelWidth@labelHeight;
37 numSize = numberWidth@labelHeight;
39 // calculate bounds of all subviews
40 # labelBounds,numBounds,sliderBounds, unitBounds
41 = this.prSubViewBounds(innerBounds, label.notNil, unitWidth>0);
44 label.notNil.if{ //only add a label if desired
45 labelView = GUI.staticText.new(view, labelBounds);
46 labelView.string = label;
49 (unitWidth>0).if{ //only add a unitLabel if desired
50 unitView = GUI.staticText.new(view, unitBounds);
53 sliderView = GUI.slider.new(view, sliderBounds);
54 numberView = GUI.numberBox.new(view, numBounds);
56 // set view parameters and actions
58 controlSpec = argControlSpec.asSpec;
59 controlSpec.addDependant(this);
60 this.onClose = { controlSpec.removeDependant(this) };
61 (unitWidth>0).if{unitView.string = " "++controlSpec.units.asString};
62 initVal = initVal ? controlSpec.default;
66 this.valueAction_(controlSpec.map(sliderView.value));
69 sliderView.receiveDragHandler = { arg slider;
70 slider.valueAction = controlSpec.unmap(GUI.view.currentDrag);
73 sliderView.beginDragAction = { arg slider;
74 controlSpec.map(slider.value)
77 numberView.action = { this.valueAction_(numberView.value) };
79 numberStep = controlSpec.step;
80 if (numberStep == 0) {
81 numberStep = controlSpec.guessNumberStep
83 // controlSpec wants a step, so zooming in with alt is disabled.
84 numberView.alt_scale = 1.0;
85 sliderView.alt_scale = 1.0;
88 numberView.step = numberStep;
89 numberView.scroll_step = numberStep;
90 //numberView.scroll=true;
93 this.valueAction_(initVal);
98 if (labelView.notNil) {
99 labelView.mouseDownAction = {|view, x, y, modifiers, buttonNumber, clickCount|
100 if(clickCount == 2, {this.editSpec});
104 this.prSetViewParams;
109 value = controlSpec.constrain(val);
110 numberView.value = value.round(round);
111 sliderView.value = controlSpec.unmap(value);
114 valueAction_ { arg val;
119 doAction { action.value(this) }
121 set { arg label, spec, argAction, initVal, initAction = false;
122 labelView.notNil.if { labelView.string = label.asString };
123 spec.notNil.if { controlSpec = spec.asSpec };
124 argAction.notNil.if { action = argAction };
126 initVal = initVal ? value ? controlSpec.default;
129 this.valueAction_(initVal);
131 this.value_(initVal);
136 setColors{arg stringBackground,stringColor,sliderBackground,numBackground,
137 numStringColor,numNormalColor,numTypingColor,knobColor,background;
139 stringBackground.notNil.if{
140 labelView.notNil.if{labelView.background_(stringBackground)};
141 unitView.notNil.if{unitView.background_(stringBackground)};};
142 stringColor.notNil.if{
143 labelView.notNil.if{labelView.stringColor_(stringColor)};
144 unitView.notNil.if{unitView.stringColor_(stringColor)};};
145 numBackground.notNil.if{
146 numberView.background_(numBackground);};
147 numNormalColor.notNil.if{
148 numberView.normalColor_(numNormalColor);};
149 numTypingColor.notNil.if{
150 numberView.typingColor_(numTypingColor);};
151 numStringColor.notNil.if{
152 numberView.stringColor_(numStringColor);};
153 sliderBackground.notNil.if{
154 sliderView.background_(sliderBackground);};
156 sliderView.knobColor_(knobColor);};
157 background.notNil.if{
158 view.background=background;};
164 labelView.notNil.if{labelView.font=font};
165 unitView.notNil.if{unitView.font=font};
166 numberView.font=font;
169 ///////Private methods ///////
171 prSetViewParams{ // sets resize and alignment for different layouts
176 labelView.resize_(2);
177 unitView.notNil.if{unitView.resize_(3)};
178 numberView.resize_(3);
182 numberView.resize_(1);
184 numberView.resize_(2);
187 sliderView.resize_(5);
188 popUp.if{view.resize_(2)};
191 labelView.notNil.if{labelView.resize_(2)};
192 unitView.notNil.if{unitView.resize_(8)};
193 numberView.resize_(8);
194 sliderView.resize_(5);
195 popUp.if{view.resize_(4)};
198 labelView.notNil.if{labelView.resize_(4).align_(\right)};
199 unitView.notNil.if{unitView.resize_(6)};
200 numberView.resize_(6);
201 sliderView.resize_(5);
202 popUp.if{view.resize_(2)};
207 prSubViewBounds{arg rect, hasLabel, hasUnit; // calculate subview bounds
208 var numBounds,labelBounds,sliderBounds, unitBounds;
209 var gap1, gap2, gap3, tmp, labelH, unitH;
213 labelH=labelSize.y;// needed for \vert
214 unitH=labelSize.y; // needed for \vert
215 hasUnit.not.if{ gap3 = 0@0; unitWidth = 0};
220 hasLabel.if{ // with label
221 unitBounds = (unitWidth@labelSize.y)
222 .asRect.left_(rect.width-unitWidth);// view to right
223 numBounds = (numSize.x@labelSize.y)
224 .asRect.left_(rect.width-unitBounds.width-numberWidth-gap3.x); // view to right
225 labelBounds = (labelSize.x@labelSize.y)
226 .asRect.width_(numBounds.left-gap2.x); //adjust width
228 labelBounds = (0@labelSize.y).asRect; //just a dummy
229 numBounds = (numberWidth@labelSize.y).asRect; //view to left
231 unitBounds = Rect (numBounds.width+gap3.x, 0,
232 rect.width-numBounds.width-gap3.x,labelSize.y); //adjust to fit
234 unitBounds = Rect (0, 0,0,0); //no unitView
235 numBounds = (rect.width@labelSize.y).asRect; //view to left
239 sliderBounds = Rect( //adjust to fit
243 rect.height-numSize.y-gap1.y;
248 hasLabel.not.if{ gap1 = 0@0; labelSize.x = 0 ;};
249 hasLabel.not.if{labelH=0};
250 labelBounds = (rect.width@labelH).asRect; // to top
251 hasUnit.not.if{unitH=0};
252 unitBounds = (rect.width@unitH)
253 .asRect.top_(rect.height-labelSize.y); // to bottom
254 numBounds = (rect.width@labelSize.y)
255 .asRect.top_(rect.height-unitBounds.height-numSize.y-gap3.y); // to bottom
257 sliderBounds = Rect( //adjust to fit
259 labelBounds.height+gap1.y,
261 rect.height - labelBounds.height - unitBounds.height
262 - numBounds.height - gap1.y - gap2.y - gap3.y
267 hasLabel.not.if{ gap1 = 0@0; labelSize.x = 0 ;};
268 labelSize.y = rect.height;
269 labelBounds = (labelSize.x@labelSize.y).asRect; //to left
270 unitBounds = (unitWidth@labelSize.y).asRect.left_(rect.width-unitWidth); // to right
271 numBounds = (numSize.x@labelSize.y).asRect
272 .left_(rect.width-unitBounds.width-numSize.x-gap3.x);// to right
273 sliderBounds = Rect( // adjust to fit
274 labelBounds.width+gap1.x,
276 rect.width - labelBounds.width - unitBounds.width
277 - numBounds.width - gap1.x - gap2.x - gap3.x,
283 ^[labelBounds, numBounds, sliderBounds, unitBounds].collect{arg v; v.moveBy(margin.x,margin.y)}
286 update {arg changer, what ...moreArgs;
288 if(changer === controlSpec, {
289 oldValue = this.value;
290 this.value = oldValue;
291 if(this.value != oldValue, { this.doAction });
297 [labelView, sliderView, numberView, unitView].do({|view|
298 view.notNil.if({ view.enabled_(false).visible_(false)});
300 ezspec = EZControlSpecEditor(view, view.bounds.moveTo(0,0), controlSpec: controlSpec, layout: layout);
301 ezspec.labelView.mouseDownAction = {|view, x, y, modifiers, buttonNumber, clickCount|
302 if(clickCount == 2, {
304 [labelView, sliderView, numberView, unitView].do({|view|
305 view.notNil.if({ view.enabled_(true).visible_(true)});