1 TaskProxyGui : JITGui {
3 var <nameBut, <playBut, <pauseBut, <srcBut, <envBut;
4 var <envirGui, <usedKeys;
6 setDefaults { |options|
8 minSize = 250 @ (skin.buttonHeight * (numItems + 1) + (numItems.sign * 4));
9 if (parent.notNil) { skin = skin.copy.put(\margin, 0@0) };
10 // "% - minSize: %\n".postf(this.class, minSize);
14 var height = skin.buttonHeight;
15 var lineWidth = zone.bounds.width - (skin.margin.y * 2);
16 var width = lineWidth * 0.62 / 4;
17 var nameWidth = lineWidth * 0.38;
18 var zoneMargin = if ( (numItems > 0) or: { parent.isKindOf(Window.implClass) }) { skin.margin } { 0@0 };
20 zone.decorator = FlowLayout(zone.bounds, zoneMargin, skin.gap);
22 nameBut = Button(zone, Rect(0,0, nameWidth, height))
26 [" ", skin.fontColor, skin.onColor]
28 .keyDownAction_({ |btn, char|
30 if (char.ascii == 127) {
32 object.class.all.removeAt(btn.states.first.first.asSymbol);
37 playBut = Button(zone, Rect(0,0, width, height))
41 [" >", skin.fontColor, skin.offColor],
42 [" _", skin.fontColor, skin.onColor ],
43 [" |", skin.fontColor, skin.offColor ]
45 .action_({ |but| var string;
47 if (History.started) {
48 // historical action, sets cmdLine and gets recorded.
49 string = object.asCompileString
50 ++ [".play;", ".play;", ".stop;" ][but.value];
51 thisProcess.interpreter.cmdLine_(string)
52 .interpretPrintCmdLine;
54 // a-historical, but faster
55 [ { object.play }, { object.play }, { object.stop } ][but.value].value
61 pauseBut = Button(zone, Rect(0,0, width, height))
65 ["paus", skin.fontColor, skin.onColor],
66 ["rsum", skin.fontColor, skin.offColor]
68 .action_({ |but| var string;
70 if (History.started) { // "// historical".postln;
71 string = object.asCompileString
72 ++ [".resume;", ".pause;" ][but.value];
73 thisProcess.interpreter.cmdLine_(string)
74 .interpretPrintCmdLine;
75 } { // "// faster".postln;
76 [ { object.resume },{ object.pause } ][but.value].value
82 srcBut = Button(zone, Rect(0,0, width, height))
86 ["src", skin.fontColor, skin.offColor],
87 ["src", skin.fontColor, skin.onColor]
90 this.openDoc(this.srcString);
91 but.value_(object.hasSource.binaryValue)
94 envBut = Button(zone, Rect(0,0, width, height))
98 ["env", skin.fontColor, skin.offColor],
99 ["env", skin.fontColor, skin.onColor]
101 .action_({ |but, mod|
103 this.class.new(object, max(object.envir.size, 8), nil, 400@20);
105 if (object.envir.isNil) {
106 this.openDoc(this.editString)
108 this.openDoc(this.editStrings)
111 but.value_(object.hasEnvir.binaryValue)
114 if (numItems > 0) { this.makeEnvirGui(lineWidth, height) };
118 makeEnvirGui { |lineWidth, height|
119 zone.decorator.nextLine.shift(0, 2);
122 try { this.object.envir },
125 Rect(0, 20, lineWidth, numItems * height),
130 accepts { |obj| ^obj.isNil or: { obj.isKindOf(this.class.observedClass) } }
136 ^(playState: 0, hasSource: 0, hasEnvir: 0, canPause: 0, isPaused: 0)
140 isPlaying: object.isPlaying, // == proxy is playing now or will play
141 isActive: object.isActive, // == really does something right now
142 hasSource: object.source.notNil, // has a source
143 hasEnvir: object.envir.notNil, // has an envir
144 canPause: object.canPause,
145 isPaused: object.isPaused
146 ).collect(_.binaryValue)
147 .put(\name, object.key)
148 .put(\object, object);
152 var newState = this.getState;
155 // compare newState and prevState, update gui items as needed
156 if (newState == prevState) { ^this };
158 if (newState[\object].isNil) {
159 prevState = newState;
160 zone.visible_(false);
164 if (newState[\name] != prevState[\name]) { // name
166 nameBut.states_(nameBut.states.collect(_.put(0, object.key.asString))).refresh;
169 playState = newState[\isPlaying] * 2 - newState[\isActive];
170 newState.put(\playState, playState);
172 if (playState != prevState[\playState]) {
173 // stopped/playing/ended
174 // 0 is stopped, 1 is active, 2 is playing but waiting:
175 playBut.value_(playState).refresh;
177 if (newState[\hasSource] != prevState[\hasSource]) {
178 srcBut.value_(newState[\hasSource]).refresh;
180 if (newState[\hasEnvir] != prevState[\hasEnvir]) { // has envir
181 envBut.value_(newState[\hasEnvir]).refresh;
183 if (newState[\canPause] != prevState[\canPause]) {
184 pauseBut.visible_(newState[\canPause] > 0).refresh;
187 if (newState[\isPaused] != prevState[\isPaused]) {
188 pauseBut.value_(newState[\isPaused]).refresh;
191 // object_ does checkUpdate!
192 if (envirGui.notNil) {
193 envirGui.object_(if (object.isNil) { nil } { object.envir });
198 clear { object = nil; this.checkUpdate }
201 ^this.class.observedClass.asString
202 ++ "(" + object.key.asCompileString + ","
203 + object.source.asCompileString + ");\n"
207 var keyText = if (edKey.isNil) {
210 edKey.asCompileString + ","
211 + object.envir[edKey].asCompileString
214 ^(this.class.observedClass.asString
215 ++ "(" + object.key.asCompileString
216 + ").set(" + keyText + ");\n"
220 editStrings { |edKeys|
221 edKeys = edKeys ? this.getUsedKeys;
222 ^edKeys.collect (this.editString(_))
226 if (object.envir.isNil) { ^[] };
227 ^usedKeys = object.envir.keys.rejectAs(_ == \self, Array).sort;
230 openDoc { |strings, bounds|
231 var doc = strings.join.newTextWindow("edit me");
232 try { doc.bounds_(bounds ? Rect(0, 400, 400, 200)) };
237 TdefGui : TaskProxyGui {
238 *observedClass { ^Tdef }
241 PdefGui : TaskProxyGui {
242 *observedClass { ^Pdef }
245 TaskProxyAllGui :JITGui {
246 var <filtBut, <filTextV, <edits, <tpGui;
247 var <>prefix = "", <>filtering = false;
248 var <names, <keysRotation=0;
251 *new { |numItems = 16, parent, bounds, makeSkip = true, options = #[]|
252 ^super.new(this.observedClass.all, numItems, parent, bounds, makeSkip, options );
255 // options could include a TdefGui with EnvirGui ...
256 makeViews { |options|
258 if (parent.isKindOf(Window.implClass)) {
259 parent.name = this.class.observedClass.name ++ ".all";
262 filtBut = Button(zone, Rect(0,0, 80, skin.headHeight))
264 .states_([["all"], ["filt"]])
266 this.filtering_(btn.value > 0);
269 filTextV = TextView(zone, Rect(60,0, 80, skin.headHeight))
271 .enterInterpretsSelection_(false)
273 .keyDownAction_({ |txvw, char, mod, uni, keycode|
274 var str = txvw.string;
275 if (str == "") { str = nil };
276 this.prefix_(txvw.string);
279 edits = Array.fill(numItems, {
280 this.class.tpGuiClass.new(
283 bounds: Rect(0,0, zone.bounds.width - 16, skin.buttonHeight),
288 parent.view.decorator.left_(zone.bounds.right - 12)
289 .top_(zone.bounds.top + skin.headHeight);
291 scroller = EZScroller(parent,
292 Rect(0, 0, 12, numItems * skin.buttonHeight),
294 { |sc| keysRotation = sc.value.asInteger.max(0) }
297 scroller.slider.resize_(3);
299 // if (options.includes(\edit)) {
300 // editZone = CompositeView.new(parent,)
306 var overflow, tooMany;
308 names = object.keys.as(Array);
313 names = names.reject { |name| name.asString.includes($_) };
315 names = names.select { |name| name.asString.contains(prefix) };
318 overflow = (names.size - numItems).max(0);
320 scroller.visible_(true);
321 scroller.numItems_(names.size);
322 scroller.value_(keysRotation ? overflow);
323 names = names.drop(keysRotation).keep(numItems);
325 scroller.visible_(false);
327 edits.do { |edit, i| edit.object_(object[names[i]]) };
328 if (tpGui.notNil) { tpGui.checkUpdate };
334 *observedClass { ^Pdefn }
336 accepts { |obj| ^obj.isNil or: { obj.isKindOf(this.class.observedClass) } }
339 // get all the state I need to know of the object I am watching
340 ^(object: object, source: try { object.source })
344 var newState = this.getState;
345 zone.visible_(newState[\object].notNil);
347 if (newState[\object] != prevState[\object]) {
348 // zone.visible_(newState[\object].notNil);
349 this.name_(this.getName);
351 if (newState[\source] != prevState[\source]) {
352 if (csView.textField.hasFocus.not) {
353 csView.value_(object);
355 try { csView.textField.string_(object.asCode) };
361 TdefAllGui : TaskProxyAllGui {
362 *observedClass { ^Tdef }
363 *tpGuiClass { ^TdefGui }
367 minSize = 260 @ (numItems + 1 * 20);
371 PdefAllGui : TaskProxyAllGui {
372 *observedClass { ^Pdef }
373 *tpGuiClass { ^PdefGui }
377 minSize = 260 @ (numItems + 1 * 20);
381 PdefnAllGui : TaskProxyAllGui {
382 *observedClass { ^Pdefn }
383 *tpGuiClass { ^PdefnGui }
387 minSize = 260 @ (numItems + 1 * 20);