3 classvar <>compactRatio=0.87;
5 var <knobView, <numberView, <unitView, <>controlSpec,
6 popUp=false, knobSize,unitWidth, gap;
9 *new { arg parent, bounds, label, controlSpec, action, initVal,
10 initAction=false, labelWidth=60, knobSize,
11 unitWidth=0, labelHeight=20, layout=\vert, gap, margin;
13 ^super.new.init(parent, bounds, label, controlSpec, action,
14 initVal, initAction, labelWidth, knobSize,
15 unitWidth, labelHeight, layout, gap, margin)
18 init { arg parentView, bounds, label, argControlSpec, argAction, initVal,
19 initAction, labelWidth, argKnobSize,argUnitWidth,
20 labelHeight, argLayout, argGap, argMargin;
22 var labelBounds, numBounds, unitBounds,knobBounds;
26 this.prMakeMarginGap(parentView, argMargin, argGap);
28 unitWidth = argUnitWidth;
30 bounds.isNil.if{bounds = 50@90};
32 knobSize = argKnobSize ;
34 // if no parent, then pop up window
35 # view,bounds = this.prMakeView( parentView,bounds);
38 labelSize=labelWidth@labelHeight;
40 // calculate bounds of all subviews
41 # labelBounds,numBounds,knobBounds, unitBounds
42 = this.prSubViewBounds(innerBounds, label.notNil, unitWidth>0);
45 label.notNil.if{ //only add a label if desired
46 labelView = GUI.staticText.new(view, labelBounds);
47 labelView.string = label;
50 (unitWidth>0).if{ //only add a unitLabel if desired
51 unitView = GUI.staticText.new(view, unitBounds);
54 knobView = GUI.knob.new(view, knobBounds);
55 numberView = GUI.numberBox.new(view, numBounds);
57 // set view parameters and actions
58 controlSpec = argControlSpec.asSpec;
59 (unitWidth>0).if{unitView.string = " "++controlSpec.units.asString};
60 initVal = initVal ? controlSpec.default;
63 numberStep = controlSpec.step;
64 if (numberStep == 0) {
65 numberStep = controlSpec.guessNumberStep
67 // controlSpec wants a step, so zooming in with alt is disabled.
68 numberView.alt_scale = 1.0;
69 knobView.alt_scale = 1.0;
71 numberView.step = numberStep;
72 numberView.scroll_step = numberStep;
75 if((controlSpec.minval + controlSpec.maxval)==0){knobView.centered=true};
78 this.valueAction_(controlSpec.map(knobView.value));
81 if (controlSpec.step != 0) {
82 knobView.step = (controlSpec.step / (controlSpec.maxval - controlSpec.minval));
85 knobView.receiveDragHandler = { arg slider;
86 slider.valueAction = controlSpec.unmap(GUI.view.currentDrag);
89 knobView.beginDragAction = { arg slider;
90 controlSpec.map(slider.value)
93 numberView.action = { this.valueAction_(numberView.value) };
96 this.valueAction_(initVal);
101 this.prSetViewParams;
103 // just set, no action
105 value = controlSpec.constrain(val);
106 numberView.value = value.round(round);
107 knobView.value = controlSpec.unmap(value);
110 valueAction_ { arg val;
115 doAction { action.value(this) }
117 set { arg label, spec, argAction, initVal, initAction = false;
118 labelView.notNil.if { labelView.string = label.asString };
119 spec.notNil.if { controlSpec = spec.asSpec };
120 argAction.notNil.if { action = argAction };
121 initVal = initVal ? value ? controlSpec.default;
124 this.valueAction_(initVal);
126 this.value_(initVal);
130 centered_ { arg bool; knobView.centered_(bool) }
132 centered{ ^knobView.centered }
135 setColors{arg stringBackground,stringColor,numBackground,
136 numStringColor,numNormalColor,numTypingColor,knobColors,background;
138 stringBackground.notNil.if{
139 labelView.notNil.if{labelView.background_(stringBackground)};
140 unitView.notNil.if{unitView.background_(stringBackground)};};
141 stringColor.notNil.if{
142 labelView.notNil.if{labelView.stringColor_(stringColor)};
143 unitView.notNil.if{unitView.stringColor_(stringColor)};};
144 numBackground.notNil.if{
145 numberView.background_(numBackground);};
146 numNormalColor.notNil.if{
147 numberView.normalColor_(numNormalColor);};
148 numTypingColor.notNil.if{
149 numberView.typingColor_(numTypingColor);};
150 numStringColor.notNil.if{
151 numberView.stringColor_(numStringColor);};
152 knobColors.notNil.if{
153 knobView.color_(knobColors);};
154 background.notNil.if{
155 view.background=background;};
162 labelView.notNil.if{labelView.font=font};
163 unitView.notNil.if{unitView.font=font};
164 numberView.font=font;
167 ///////Private methods ///////
169 prSetViewParams{ // sets resize and alignment for different layouts
174 labelView.resize_(5);
175 unitView.notNil.if{unitView.resize_(9)};
176 numberView.resize_(8);
180 numberView.resize_(5);
182 numberView.resize_(5);
186 popUp.if{view.resize_(2)};
189 labelView.notNil.if{labelView.resize_(2)};
190 unitView.notNil.if{unitView.resize_(6)};
191 numberView.resize_(5);
192 popUp.if{view.resize_(2)};
195 labelView.notNil.if{labelView.resize_(2).align_(\center)};
196 unitView.notNil.if{unitView.resize_(6)};
197 numberView.resize_(5);
198 popUp.if{view.resize_(2)};
201 labelView.notNil.if{labelView.resize_(4).align_(\right)};
202 unitView.notNil.if{unitView.resize_(6)};
203 numberView.resize_(5);
205 popUp.if{view.resize_(2)};
210 prSubViewBounds{arg rect, hasLabel, hasUnit; // calculate subview bounds
211 var numBounds,labelBounds,knobBounds, unitBounds,knobHeight, numHeight;
212 var gap1, gap2, gap3, tmp, labelH, unitH;
216 (rect.height<= (labelSize.y*2)).if{labelSize.y=rect.height/2};
218 numHeight=labelSize.y;
222 knobSize.isNil.if{knobSize=( ((rect.height/compactRatio)-margin.x)@(rect.height))};
223 knobSize=(knobSize.x-margin.x)@(knobSize.y.min(rect.height));
224 hasUnit.not.if{ gap2 = 0@0; unitWidth = 0};
225 labelBounds = Rect(0,0,rect.width-knobSize.x-gap3.x,labelSize.y); //to left
227 unitBounds = Rect(labelBounds.width-unitWidth,labelSize.y+gap1.y,
228 unitWidth, rect.height-labelSize.y-gap1.y);
230 numBounds = Rect(0,labelSize.y+gap1.y,
231 labelBounds.width-gap2.x-unitBounds.width,rect.height-labelSize.y-gap1.y);
234 unitBounds = Rect(labelBounds.width-unitWidth,0,
235 unitWidth, rect.height);
237 numBounds = Rect(0,0,
238 labelBounds.width-gap2.x-unitBounds.width,rect.height);
241 knobBounds=knobSize.asRect.moveTo(rect.width-knobSize.x,0);
244 knobSize.isNil.if{knobSize=( ((rect.height/compactRatio)-margin.x)@(rect.height))};
245 knobSize=(knobSize.x-margin.x)@(knobSize.y.min(rect.height));
246 knobBounds=knobSize.asRect.moveTo(rect.width-knobSize.x,0);
247 hasUnit.not.if{ gap2 = 0@0; unitWidth = 0};
248 hasLabel.not.if{ gap1 = 0@0; labelSize.x = 0};
249 labelBounds = (labelSize.x@rect.height).asRect;
250 unitBounds = (unitWidth@rect.height).asRect
251 .moveTo(rect.width-knobBounds.width-gap2.x-unitWidth,0);
252 numBounds = Rect.newSides(labelSize.x+gap1.x,0,unitBounds.left-gap2.x,rect.height);
255 hasUnit.not.if{ gap3 = 0@0; unitWidth = 0};
256 hasLabel.not.if{ gap1 = 0@0; labelSize.y = 0};
259 knobSize=( ((rect.height-labelSize.y-numHeight-gap1.y-gap2.y)/compactRatio)
260 @(rect.height-labelSize.y-numHeight-gap1.y-gap2.y))
262 knobSize=((knobSize.x).min(rect.width))
263 @(knobSize.y.min(rect.height-labelSize.y-numHeight-gap1.y-gap2.y));
265 labelBounds = (rect.width@labelSize.y).asRect;
266 knobBounds=knobSize.asRect.moveTo(0,labelSize.y+gap1.y);
268 numBounds = Rect(0,rect.height-numHeight,rect.width-unitWidth-gap3.x, numHeight);
270 unitBounds = Rect(rect.width-unitWidth,rect.height-numHeight,unitWidth,numHeight);
274 hasUnit.not.if{ gap3 = 0@0; unitWidth = 0};
275 hasLabel.not.if{ gap1 = 0@0; labelSize.y = 0};
278 knobSize=( ((rect.height-labelSize.y-numHeight-gap1.y-gap2.y)/compactRatio)
279 @(rect.height-labelSize.y-numHeight-gap1.y-gap2.y))
281 knobSize=((knobSize.x).min(rect.width))
282 @(knobSize.y.min(rect.height-labelSize.y-numHeight-gap1.y-gap2.y));
285 labelBounds = (rect.width@labelSize.y).asRect;
286 knobBounds=knobSize.asRect.moveTo(0,labelSize.y+gap1.y);
287 knobBounds=knobBounds.moveBy((rect.width-knobBounds.width)/2,0);
288 numBounds = Rect(0,rect.height-numHeight,rect.width-unitWidth-gap3.x, numHeight);
290 unitBounds = Rect(rect.width-unitWidth,rect.height-numHeight,unitWidth,numHeight);
294 ((knobBounds.height<0)||(knobBounds.width<0)).if{knobBounds=knobBounds.height_(0).width_(0)};
296 ^[labelBounds, numBounds, knobBounds, unitBounds].collect{arg v; v.moveBy(margin.x,margin.y)}