HelpBrowser: path box becomes a more conventional search box
[supercollider.git] / SCClassLibrary / JITLib / GUI / NdefParamGui.sc
bloba1b5b18df9a1aa36399b2818c375cd2d401d543a
1 // list of named params - if single number, show EZSlider,
2 // else show EZText
4 NdefParamGui : EnvirGui {
5         var <drags;
7         setDefaults {
8                 defPos = 530@660;
9                 minSize = 320 @ (numItems * skin.buttonHeight);
11                 if (parent.notNil) { skin = skin.copy.margin = 0@0; };
12         }
14         accepts { |obj|
15                 ^obj.isNil or: { obj.isKindOf(NodeProxy) };
16         }
18                 // could be smarter:
19                 // accepts strings, numbers, ... what else?
20         dragAction { |i|
21                 ^{      arg drag;
22                         var key = prevState[\editKeys][i];
23                         var dragged = drag.object;
24                         if (dragged.isKindOf(String)) { dragged = dragged.interpret };
25                         if (dragged.notNil) {
26                                 if(dragged.isKindOf(NodeProxy)) {
27                                         drag.string = "->" + dragged.key;
28                                         object.map(key, dragged);
29                                         this.checkUpdate;
30                                 } {
31                                         if (dragged.isKindOf(SimpleNumber)) {
32                                                 object.set(key, dragged);
33                                         };
34                                 }
35                         }
36                 }
37         }
39         makeViews {
40                 var sinkWidth = 40;
41                 var height = skin.buttonHeight;
43                 specs = ();
44                 replaceKeys = ();
45                 prevState = ( settings: [], overflow: 0, keysRotation: 0, editKeys: []);
47                 labelWidth = zone.bounds.width * 0.15;
49                 #drags, valFields = { |i|
50                         var drag, field;
52                         try { // QT temp fix.
53                                 drag = DragBoth(zone, Rect(0, 0, sinkWidth, skin.buttonHeight))
54                                 .string_("-").align_(\center)
55                                 .visible_(false)
56                                 .font_(font);
57                         };
58                         drag.action_(this.dragAction(i));
60                         field = CompositeView(zone, Rect(0, 0, bounds.width - sinkWidth - 20, height))
61                         .resize_(2)
62                         .background_(skin.background);
64                         [drag, field];
66                 }.dup(numItems).flop;
68                 widgets = nil.dup(numItems); // keep EZGui types here
70                 zone.decorator.reset.shift(zone.bounds.width - 16, 0);
72                 scroller = EZScroller(zone,
73                         Rect(0, 0, 12, numItems * height),
74                         numItems, numItems,
75                         { |sc|
76                                 keysRotation = sc.value.asInteger.max(0);
77                                 prevState.put(\dummy, \dummy);
78                         }
79                 ).visible_(false);
80                 scroller.slider.resize_(3);
81         }
83         getState {
84                 var settings, newKeys, overflow;
86                 if (object.isNil) {
87                         ^(name: 'anon', settings: [], editKeys: [], overflow: 0, keysRotation: 0)
88                 };
90                 settings = object.getKeysValues;
91                 newKeys = settings.collect(_[0]);
93                 overflow = (newKeys.size - numItems).max(0);
94                 keysRotation = keysRotation.clip(0, overflow);
95                 newKeys = newKeys.drop(keysRotation).keep(numItems);
97                 ^(object: object, editKeys: newKeys, settings: settings,
98                         overflow: overflow, keysRotation: keysRotation)
99         }
101         checkUpdate {
102                 var newState = this.getState;
104                 if (newState == prevState) {
105                         ^this
106                 };
108                 if (object.isNil) {
109                         prevState = newState;
110                         ^this.clearFields(0);
111                 };
113                 if (newState[\overflow] > 0) {
114                         scroller.visible_(true);
115                         scroller.numItems_(newState[\settings].size);
116                         scroller.value_(newState[\keysRotation]);
118                 } {
119                         scroller.visible_(false);
120                 };
122                 if (newState[\editKeys] == prevState[\editKeys]) {
123                         this.setByKeys(newState[\editKeys], newState[\settings]);
124                 } {
125                         this.setByKeys(newState[\editKeys], newState[\settings]);
126                         if (newState[\overflow] == 0) { this.clearFields(newState[\editKeys].size) };
127                 };
129                 prevState = newState;
130         }
132 //      clearFields { (object.size .. valFields.size).do(this.clearField(_)) }
135         setByKeys { |newKeys, newSettings|
137                 var prevSettings = prevState[\settings] ? [];
138                 var newVal, oldVal, oldKey;
140                 newKeys.do { |newKey, i|
142                         newVal = newSettings.detect { |pair| pair[0] == newKey };
143                         if (newVal.notNil) { newVal = newVal[1] };
145                         oldKey = prevState[\editKeys][i];
146                         if (oldKey.notNil) {
147                                 oldVal = prevSettings.detect(_[0] == oldKey);
148                                 if (oldVal.notNil) { oldVal = oldVal[1] };
149                         };
150                         if (oldKey != newKey or: { oldVal != newVal }) {
151                         //      "val for % has changed: %\n".postf(key, newval);
152                                 this.setField(i, newKey, newVal, newKey == oldKey);
153                         };
154                 };
155         }
157         setFunc { |key|
158                 ^{ |sl| object.set(key, sl.value) }
159         }
161         clearField { |index|
162                 var area = valFields[index];
163                 try {
164                         drags[index].visible_(false);
165                         area.children.copy.do { |view| view.remove };
166                         area.background_(skin.background);
167                         area.refresh;
168                         widgets[index] = nil;
169                 };
170         }
172         setField { |index, key, value, sameKey = false|
173                 var area = valFields[index];
174                 var widget = widgets[index];
176         //      [replaceKeys, key].postcs;
177                 if (replaceKeys[key].notNil) {
178                         area.background_(skin.hiliteColor);
179                 } {
180                         area.background_(skin.background);
181                 };
182                 try { // QT temp fix.
183                         if (value.isKindOf(NodeProxy)) {
184                                 drags[index].object_(value).string_("->" ++ value.key);
185                         } {
186                                 drags[index].object_(nil).string_("-");
187                         };
188                                         // dodgy - defer should go away eventually.
189                                         // needed for defer in setToSlider...
190                         { drags[index].visible_(true) }.defer(0.05);
191                 };
192                 if (value.isKindOf(SimpleNumber) ) {
193                         this.setToSlider(index, key, value, sameKey);
194                         ^this
195                 };
197                 this.setToText(index, key, value, sameKey);
198         }