scide: LookupDialog - redo lookup on classes after partial lookup
[supercollider.git] / SCClassLibrary / Common / GUI / osx / scide_scapp / Base / SCView.sc
blob75e49959fb09567cae7f8bfb3a527470c70ab3ed
1 SCView {  // abstract class
2         classvar <>currentDrag, <>currentDragString;
3         classvar <>globalKeyDownAction, <>globalKeyUpAction;
5         var dataptr, <parent, <>action, <background;
6         var <>mouseDownAction, <>mouseUpAction, <>mouseOverAction, <>mouseMoveAction;
7         var <>keyDownAction, <>keyUpAction, <>keyTyped, <> keyModifiersChangedAction;
8         var <>beginDragAction, <>canReceiveDragHandler, <>receiveDragHandler;
9         var <>onClose;
11         *implementsClass { ^this.name.asString[2..].asSymbol }
13         *new { arg parent, bounds;
14                 ^super.new.init(parent, bounds);
15         }
17         *viewClass { ^this }
19         *paletteExample { arg parent, bounds;
20                 ^this.new(parent, bounds);
21         }
23         init { arg argParent, argBounds;
24                 parent = argParent.asView; // actual view
25                 background = Color.clear;
26                         // call asView again because parent by this point might be a FlowView
27                 this.prInit(parent.asView, argBounds.asRect, this.class.viewClass);
28                 argParent.add(this);//maybe window or viewadapter
29         }
31         asView { ^this }
33         bounds {
34                 ^this.getProperty(\bounds, Rect.new)
35         }
36         bounds_ { arg rect;
37                 this.setProperty(\bounds, rect)
38         }
40         visible {
41                 ^this.getProperty(\visible)
42         }
43         visible_ { arg bool;
44                 this.setProperty(\visible, bool)
45         }
47         enabled {
48                 ^this.getProperty(\enabled)
49         }
50         enabled_ { arg bool;
51                 this.setProperty(\enabled, bool)
52         }
54         canFocus {
55                 ^this.getProperty(\canFocus)
56         }
57         canFocus_ { arg bool;
58                 this.setProperty(\canFocus, bool)
59         }
61         focus { arg flag=true;
62                 _SCView_Focus
63                 ^this.primitiveFailed
64         }
66         hasFocus {
67                 _SCView_HasFocus
68                 ^this.primitiveFailed
69         }
71         focusColor_ { |color|
72                 this.setProperty(\focusColor, color)
73         }
74         focusColor {
75                 ^this.getProperty(\focusColor, Color.new)
76         }
78         id {
79                 ^this.getProperty(\id)
80         }
81         id_ { arg id;
82                 this.setProperty(\id, id)
83         }
85         dragLabel_ { arg string;
86                 this.setProperty(\dragLabel, string)
87         }
89         refresh {
90                 _SCView_Refresh
91                 ^this.primitiveFailed
92         }
94         findByID { arg id;
95                 _SCView_FindByID
96                 ^this.primitiveFailed
97         }
99         isClosed { ^dataptr.isNil }
100         notClosed { ^dataptr.notNil }
101         remove {
102                 if(dataptr.notNil) {
103                         parent.prRemoveChild(this);
104                         this.prRemove;
105                         this.prClose;
106                 } {
107                         "SCView-remove : this view already removed.".debug(this);
108                 }
109         }
110         /*
111         resize behaviour in an SCCompositeView:
112                 1  2  3
113                 4  5  6
114                 7  8  9
116                 1 - fixed to left, fixed to top
117                 2 - horizontally elastic, fixed to top
118                 3 - fixed to right, fixed to top
120                 4 - fixed to left, vertically elastic
121                 5 - horizontally elastic, vertically elastic
122                 6 - fixed to right, vertically elastic
124                 7 - fixed to left, fixed to bottom
125                 8 - horizontally elastic, fixed to bottom
126                 9 - fixed to right, fixed to bottom
127         */
129         resize {
130                 ^this.getProperty(\resize)
131         }
133         resize_ { arg resize;
134                 this.setProperty(\resize, resize)
135         }
137         background_ { arg color;
138                 background = color;
139                 this.setProperty(\background, color)
140         }
142         addAction { arg func, selector=\action;
143                 this.perform(selector.asSetter, this.perform(selector).addFunc(func));
144         }
146         removeAction { arg func, selector=\action;
147                 this.perform(selector.asSetter, this.perform(selector).removeFunc(func));
148         }
150         mouseDown { arg x, y, modifiers, buttonNumber, clickCount;
151                 mouseDownAction.value(this, x, y, modifiers, buttonNumber, clickCount);
152         }
154         mouseUp { arg x, y, modifiers;
155                 mouseUpAction.value(this, x, y, modifiers)
156         }
158         mouseMove { arg x, y, modifiers;
159                 mouseMoveAction.value(this, x, y, modifiers)
160         }
162         mouseOver { arg x, y;
163                 mouseOverAction.value(this, x, y);
164         }
166         keyDown { arg char, modifiers, unicode, keycode;
167                 globalKeyDownAction.value(this, char, modifiers, unicode, keycode);
168                 this.handleKeyDownBubbling(this, char, modifiers, unicode, keycode);
169         }
171         keyModifiersChanged { arg modifiers;
172                 this.handleKeyModifiersChangedBubbling(this, modifiers)
173         }
175         handleKeyModifiersChangedBubbling { arg view, modifiers;
176                 var result;
177                 // nil from keyDownAction --> pass it on
178                 if (keyModifiersChangedAction.isNil) {
179 //                      this.defaultKeyDownAction(char, modifiers, unicode, keycode);
180                         result = nil;
181                 } {
182                         result = keyModifiersChangedAction.value(view, modifiers);
183                 };
184                 if(result.isNil) {
185                         // call keydown action of parent view
186                         parent.handleKeyModifiersChangedBubbling(view, modifiers);
187                 };
188         }
190         defaultKeyDownAction { ^nil }
192         handleKeyDownBubbling { arg view, char, modifiers, unicode, keycode;
193                 var result;
194                 // nil from keyDownAction --> pass it on
195                 if (keyDownAction.isNil) {
196                         result = this.defaultKeyDownAction(char, modifiers, unicode, keycode);
197                 } {
198                         result = keyDownAction.value(view, char, modifiers, unicode, keycode);
199                 };
200                 if(result.isNil) {
201                         // call keydown action of parent view
202                         parent.handleKeyDownBubbling(view, char, modifiers, unicode, keycode);
203                 };
204         }
206         // sc.solar addition
207         keyUp { arg char, modifiers, unicode, keycode;
208                 this.keyTyped = char;
209                 // always call global keydown action first
210                 globalKeyUpAction.value(this, char, modifiers, unicode, keycode);
211                 this.handleKeyUpBubbling(this, char, modifiers, unicode, keycode);
212         }
214         defaultKeyUpAction { ^nil }
216         handleKeyUpBubbling { arg view, char, modifiers, unicode, keycode;
217                 var result;
218                 // nil from keyDownAction --> pass it on
219                 if (keyUpAction.isNil) {
220                         result = this.defaultKeyUpAction(char, modifiers, unicode, keycode);
221                 } {
222                         result = keyUpAction.value(view, char, modifiers, unicode, keycode);
223                 };
224                 if(result.isNil) {
225                         // call keydown action of parent view
226                         parent.handleKeyUpBubbling(view, char, modifiers, unicode, keycode);
227                 };
228         }
230         beginDrag {
231                 currentDrag = if (beginDragAction.notNil)
232                  {
233                         beginDragAction.value(this)
234                 } {
235                         this.defaultGetDrag
236                 };
237                 currentDragString = currentDrag.asCompileString;
238         }
240         defaultGetDrag { ^nil }
242         canReceiveDrag {
243                 ^if(canReceiveDragHandler.notNil) {
244                         canReceiveDragHandler.value(this)
245                 } {
246                         this.defaultCanReceiveDrag
247                 }
248         }
249         defaultCanReceiveDrag { ^false }
250         receiveDrag { |x, y|
251                 if(receiveDragHandler.notNil) {
252                         receiveDragHandler.value(this, x, y)
253                 } {
254                         this.defaultReceiveDrag(x, y)
255                 };
256                 currentDrag = currentDragString = nil;
257         }
259         // get the view parent tree up to the SCTopView
260         getParents {
261                 var parents, view;
262                 view = this;
263                 parents = List.new;
264                 while( {(view = view.asView.parent).notNil}, { parents.add(view)});
265                 ^parents
266         }
268         doAction {
269                 action.value(this);
270         }
272         properties {
273                 ^#[\bounds, \visible, \enabled, \canFocus, \resize, \background,
274                                 \minWidth, \maxWidth, \minHeight, \maxHeight, \focusColor]
275         }
277         getPropertyList {
278                 ^this.properties.collect( { arg name;
279                         [name, this.perform(name)]
280                 });
281         }
283         setPropertyList { arg list;
284                 list.do( { arg item;
285                         var name, value;
286                         #name, value = item;
287                         this.perform(name.asSetter, value);
288                 });
289         }
291         // private
292         prInit { arg argParent, argBounds, argViewClass;
293                 _SCView_New
294                 ^this.primitiveFailed
295         }
297         prClose { dataptr = nil; onClose.value(this); }
298         prRemove {
299                 _SCView_Remove
300                 ^this.primitiveFailed
301         }
302         setProperty { arg key, value;
303                 _SCView_SetProperty
304                 ^this.primitiveFailed
305         }
306         getProperty { arg key, value;
307                 _SCView_GetProperty
308                 ^this.primitiveFailed
309         }
310         setPropertyWithAction { arg symbol, obj;
311                 // setting some properties may need to have the action called.
312                 if (this.setProperty(symbol, obj), {
313                         // setProperty returns true if action needs to be called.
314                         this.doAction;
315                 });
316         }
318 //      *importDrag {
319 //              // this is called when an NSString is the drag object
320 //              // from outside of the SC app
321 //              // we compile it to an SCObject.
322 //              currentDragString = currentDrag;
323 //              currentDrag = currentDrag.interpret;
324 //      }
326         absoluteBounds {
327                 ^this.getProperty(\absoluteBounds, Rect.new)
328         }
331 SCContainerView : SCView { // abstract class
333         var <children, <decorator;
335         add { arg child;
336                 children = children.add(child);
337                 if (decorator.notNil, { decorator.place(child); });
338         }
340         init { arg argParent, argBounds;
341                 super.init(argParent, argBounds);
342         }
344         removeAll {
345                 children.copy.do { |child| child.remove };
346         }
348         addFlowLayout { arg margin, gap;
349                 this.decorator_( FlowLayout( this.bounds.moveTo(0, 0), margin, gap ) );
350                 ^this.decorator;
351                 }
353         decorator_ { arg decor;
354                 decor.bounds = decor.bounds.moveTo(0, 0);
355                 decor.reset;
356                 decorator = decor;
357         }
359         prRemoveChild { arg child;
360                 children.remove(child);
361                 // ... decorator should re-place all
362         }
364         //bounds_  ... replace all
366         prClose {
367                 super.prClose;
368                 children.do( { arg item; item.prClose });
369         }
373 SCCompositeView : SCContainerView {
376 SCTopView : SCCompositeView {
378         // created by SCWindow
379         handleKeyModifiersChangedBubbling { arg view, modifiers;
380                 keyModifiersChangedAction.value(view, modifiers);
381         }
382         handleKeyDownBubbling { arg view, char, modifiers, unicode, keycode;
383                 var currentAppModal, window;
384                 keyDownAction.value(view, char, modifiers, unicode, keycode);
385         }
386         handleKeyUpBubbling { arg view, char, modifiers, unicode, keycode;
387                 keyUpAction.value(view, char, modifiers, unicode, keycode);
388         }
390         //only in construction mode, handled internally
391         canReceiveDrag { ^currentDrag.isKindOf(Class)}
392 //      remove { this.removeAll }
394         findWindow {
395                 SCWindow.allWindows.do { |win|
396                         if(win.view == this) {
397                                 ^win
398                         }
399                 }
400         }
402         /* construction mode */
404         constructionGrid_ { arg point;
405                 this.setProperty( \constructionGrid, point );
406         }
408         constructionGrid {
409                 ^this.getProperty( \constructionGrid, Point.new );
410         }
412         enableConstructionGrid_ { arg flag;
413                 this.setProperty( \enableConstructionGrid, flag );
414         }
416         enableConstructionGrid {
417                 ^this.getProperty( \enableConstructionGrid );
418         }
420         //private called from lang
421         setConstructionMode { |flag|
422                 this.setProperty( \setConstructionMode, flag )
423         }
425         defaultReceiveDrag { |x, y|
426                 var win, view;
427                 win = this.findWindow;
428                 view = currentDrag.paletteExample(win, Rect(x, y, 140, 24)).enabled_(false);
429                 view.keyDownAction_( { |view, char, modifiers, unicode, keycode|
430                         if(keycode == 51) {
431                                 view.remove;
432                         }
433                 });
434         }
437 SCScrollTopView : SCTopView {
438         var <autohidesScrollers = true, <hasHorizontalScroller = true, <hasVerticalScroller = true;
439         var <autoScrolls = true;
441         autohidesScrollers_ { |bool|
442                 autohidesScrollers = bool;
443                 this.setProperty(\setAutohidesScrollers, bool);
444         }
446         hasHorizontalScroller_ { |bool|
447                 hasHorizontalScroller = bool;
448                 this.setProperty(\setHasHorizontalScroller, bool);
449         }
451         hasVerticalScroller_ { |bool|
452                 hasVerticalScroller = bool;
453                 this.setProperty(\setHasVerticalScroller, bool);
454         }
456         visibleOrigin_ { arg point;
457                 this.setProperty( \clipViewOrigin, point );
458         }
460         visibleOrigin { ^this.getProperty( \clipViewOrigin, Point.new );}
462         autoScrolls_ { |bool|
463                 autoScrolls = bool;
464                 this.setProperty(\setAutoScrolls, bool);
465         }
467         innerBounds {
468                 ^this.getProperty(\innerBounds, Rect.new)
469         }
471         bounds {
472                 var     bounds = this.absoluteBounds;
473                 this.getParents.do( { |parent|
474                         bounds = bounds.moveBy(parent.bounds.left.neg, parent.bounds.top.neg)
475                 });
476                 ^bounds
477         }
479 //      handleKeyModifiersChangedBubbling { arg view, modifiers;
480 //              var result;
481 //              // nil from keyDownAction --> pass it on
482 //              if (keyModifiersChangedAction.isNil) {
483 //                      result = nil;
484 //              } {
485 //                      result = keyModifiersChangedAction.value(view, modifiers);
486 //              };
487 //              if(result.isNil) {
488 //                      // call keydown action of parent view
489 //                      parent.handleKeyModifiersChangedBubbling(view, modifiers);
490 //              };
491 //      }
493 //      handleKeyDownBubbling { arg view, char, modifiers, unicode, keycode;
494 //              var result;
495 //              // nil from keyDownAction --> pass it on
496 //              if (keyDownAction.isNil) {
497 //                      result = this.defaultKeyDownAction(char, modifiers, unicode, keycode);
498 //              } {
499 //                      result = keyDownAction.value(view, char, modifiers, unicode, keycode);
500 //              };
501 //              if(result.isNil) {
502 //                      // call keydown action of parent view
503 //                      parent.handleKeyDownBubbling(view, char, modifiers, unicode, keycode);
504 //              };
505 //      }
507 //      handleKeyUpBubbling { arg view, char, modifiers, unicode, keycode;
508 //              var result;
509 //              // nil from keyDownAction --> pass it on
510 //              if (keyUpAction.isNil) {
511 //                      result = this.defaultKeyUpAction(char, modifiers, unicode, keycode);
512 //              } {
513 //                      result = keyUpAction.value(view, char, modifiers, unicode, keycode);
514 //              };
515 //              if(result.isNil) {
516 //                      // call keydown action of parent view
517 //                      parent.handleKeyUpBubbling(view, char, modifiers, unicode, keycode);
518 //              };
519 //      }
523 SCScrollView : SCScrollTopView {
524         var <hasBorder = false;
526         hasBorder_ { arg bool = true;
527                 this.setProperty(\border, bool);
528         }
530         init { |argParent, argBounds|
531                 super.init(argParent, argBounds);
532         }
534         handleKeyModifiersChangedBubbling { arg view, modifiers;
535                 var result;
536                 // nil from keyDownAction --> pass it on
537                 if (keyModifiersChangedAction.isNil) {
538                         result = nil;
539                 } {
540                         result = keyModifiersChangedAction.value(view, modifiers);
541                 };
542                 if(result.isNil) {
543                         // call keydown action of parent view
544                         parent.handleKeyModifiersChangedBubbling(view, modifiers);
545                 };
546         }
548         handleKeyDownBubbling { arg view, char, modifiers, unicode, keycode;
549                 var result;
550                 // nil from keyDownAction --> pass it on
551                 if (keyDownAction.isNil) {
552                         result = this.defaultKeyDownAction(char, modifiers, unicode, keycode);
553                 } {
554                         result = keyDownAction.value(view, char, modifiers, unicode, keycode);
555                 };
556                 if(result.isNil) {
557                         // call keydown action of parent view
558                         parent.handleKeyDownBubbling(view, char, modifiers, unicode, keycode);
559                 };
560         }
562         handleKeyUpBubbling { arg view, char, modifiers, unicode, keycode;
563                 var result;
564                 // nil from keyDownAction --> pass it on
565                 if (keyUpAction.isNil) {
566                         result = this.defaultKeyUpAction(char, modifiers, unicode, keycode);
567                 } {
568                         result = keyUpAction.value(view, char, modifiers, unicode, keycode);
569                 };
570                 if(result.isNil) {
571                         // call keydown action of parent view
572                         parent.handleKeyUpBubbling(view, char, modifiers, unicode, keycode);
573                 };
574         }
578 SCLayoutView : SCContainerView {
579         properties { ^super.properties ++ #[\spacing] }
581         spacing {
582                 ^this.getProperty(\spacing, 0)
583         }
584         spacing_ { arg distance;
585                 this.setProperty(\spacing, distance)
586         }
587         setProperty { |key, value|
588                 super.setProperty(key, value);
589         }
592 SCHLayoutView : SCLayoutView {}
593 SCVLayoutView : SCLayoutView {}
596 SCControlView : SCView { // abstract class
599 SCSliderBase : SCControlView {
601         var <>shift_scale = 100.0, <>ctrl_scale = 10.0, <>alt_scale = 0.1;
603         getScale { |modifiers|
604                 ^case
605                          { modifiers & 131072 == 131072 } { shift_scale }
606                          { modifiers & 262144 == 262144 } { ctrl_scale }
607                          { modifiers & 524288 == 524288 } { alt_scale }
608                          { 1 };
609         }
611         knobColor {
612                 ^this.getProperty(\knobColor, Color.new)
613         }
614         knobColor_ { arg color;
615                 this.setProperty(\knobColor, color)
616         }
618         step_ { arg stepSize;
619         //      this.setPropertyWithAction(\step, stepSize); // action really needed?
620                 this.setProperty(\step, stepSize);
621         }
623         step {
624                 ^this.getProperty(\step)
625         }
627         properties {
628                 ^super.properties ++ #[\knobColor, \step]
629         }
633 SCSlider : SCSliderBase {
635         value {
636                 ^this.getProperty(\value)
637         }
638         value_ { arg val;
639                 this.setProperty(\value, val);
640         }
641         valueAction_ { arg val;
642                 this.setPropertyWithAction(\value, val);
643         }
645         increment { |zoom=1| ^this.valueAction = this.value + (max(this.step, this.pixelStep) * zoom) }
646         decrement { |zoom=1| ^this.valueAction = this.value - (max(this.step, this.pixelStep) * zoom) }
648         pixelStep {
649                 var bounds = this.bounds;
650                 ^(bounds.width.max(bounds.height) - this.thumbSize).reciprocal
651         }
653         defaultKeyDownAction { arg char, modifiers, unicode, keycode;
654                 var zoom = this.getScale(modifiers);
656                 // standard keydown
657                         // rand could also use zoom factors
658                 if (char == $r, { this.valueAction = 1.0.rand; ^this });
659                 if (char == $n, { this.valueAction = 0.0; ^this });
660                 if (char == $x, { this.valueAction = 1.0; ^this });
661                 if (char == $c, { this.valueAction = 0.5; ^this });
663                 if (char == $], { this.increment(zoom); ^this });
664                 if (char == $[, { this.increment(zoom); ^this });
665                 if (unicode == 16rF700, { this.increment(zoom); ^this });
666                 if (unicode == 16rF703, { this.increment(zoom); ^this });
667                 if (unicode == 16rF701, { this.decrement(zoom); ^this });
668                 if (unicode == 16rF702, { this.decrement(zoom); ^this });
670                 ^nil            // bubble if it's an invalid key
671         }
673         defaultGetDrag {
674                 ^this.value
675         }
676         defaultCanReceiveDrag {
677                 ^currentDrag.isNumber
678         }
679         defaultReceiveDrag {
680                 this.valueAction = currentDrag;
681         }
683         thumbSize {
684                 ^this.getProperty(\thumbSize, 12);
685         }
686         thumbSize_ { arg size;
687                 this.setProperty(\thumbSize, size);
688         }
690         properties {
691                 ^super.properties ++ #[\thumbSize];
692         }
695 SCRangeSlider : SCSliderBase {
697         *paletteExample { arg parent, bounds;
698                 var v;
699                 v = this.new(parent, bounds);
700                 v.lo = 0.2;
701                 v.hi = 0.7;
702                 ^v
703         }
705         lo {
706                 ^this.getProperty(\lo)
707         }
708         lo_ { arg val;
709                 this.setProperty(\lo, val);
710         }
711         activeLo_ { arg val;
712                 this.setPropertyWithAction(\lo, val);
713         }
714         hi {
715                 ^this.getProperty(\hi)
716         }
717         hi_ { arg val;
718                 this.setProperty(\hi, val);
719         }
720         activeHi_ { arg val;
721                 this.setPropertyWithAction(\hi, val);
722         }
723         range {
724                 ^this.getProperty(\range)
725         }
726         range_ { arg val;
727                 this.setProperty(\range, val);
728         }
729         activeRange_ { arg val;
730                 this.setPropertyWithAction(\range, val);
731         }
733         setSpan { arg lo, hi;
734                 this.lo = lo;
735                 this.hi = hi;
736         }
738         setSpanActive { arg lo, hi;
739                 this.setSpan( lo, hi );
740                 this.doAction;
741         }
743         setDeviation { arg deviation, average;
744                         var lo = ( 1 - deviation ) * average;
745                         this.setSpan(lo, lo + deviation);
746         }
748         properties {
749                 ^super.properties ++ #[\lo, \hi]
750         }
752         pixelStep {
753                 var bounds = this.bounds;
754                 ^(bounds.width.max(bounds.height)).reciprocal
755         }
757         increment { |zoom=1|
758                 var inc = (max(this.step, this.pixelStep) * zoom);
759                 var newHi = (this.hi + inc);
760                 if (newHi > 1) {
761                         inc = 1 - this.hi;
762                         newHi = 1;
763                 };
764                 this.lo_(this.lo + inc).activeHi_(newHi);
765         }
767         decrement { |zoom=1|
768                 var inc = (max(this.step, this.pixelStep) * zoom);
769                 var newLo = (this.lo - inc);
770                 if (newLo < 0) {
771                         inc =  this.lo;
772                         newLo = 0;
773                 };
774                 this.lo_(newLo).activeHi_(this.hi - inc);
775         }
777         defaultKeyDownAction { arg char, modifiers, unicode;
778                 var a, b;
779                 var zoom = this.getScale(modifiers);
780                 // standard keydown
781                 if (char == $r, {
782                         a = 1.0.rand;
783                         b = 1.0.rand;
784                         this.activeLo_(min(a, b));
785                         this.activeHi_(max(a, b));
786                         ^this
787                 });
788                 if (char == $n, { this.activeLo_(0.0); this.activeHi_(0.0); ^this });
789                 if (char == $x, { this.activeLo_(1.0); this.activeHi_(1.0); ^this });
790                 if (char == $c, { this.activeLo_(0.5); this.activeHi_(0.5); ^this });
791                 if (char == $a, { this.activeLo_(0.0); this.activeHi_(1.0); ^this });
792                 if (unicode == 16rF700, { this.increment(zoom); ^this });
793                 if (unicode == 16rF703, { this.increment(zoom); ^this });
794                 if (unicode == 16rF701, { this.decrement(zoom); ^this });
795                 if (unicode == 16rF702, { this.decrement(zoom); ^this });
796                 ^nil            // bubble if it's an invalid key
797         }
798         defaultGetDrag { ^Point(this.lo, this.hi) }
799         defaultCanReceiveDrag {
800                 ^currentDrag.isKindOf(Point);
801         }
802         defaultReceiveDrag {
803                 // changed to x, y instead of lo, hi
804                 this.lo = currentDrag.x;
805                 this.hi = currentDrag.y;
806                 this.doAction
807         }
810 SC2DSlider : SCSliderBase {
811         *implementsClass { ^'Slider2D' }
812         x {
813                 ^this.getProperty(\x)
814         }
815         x_ { arg val;
816                 this.setProperty(\x, val);
817         }
818         activex_ { arg val;
819                 this.setPropertyWithAction(\x, val);
820         }
821         y {
822                 ^this.getProperty(\y)
823         }
824         y_ { arg val;
825                 this.setProperty(\y, val);
826         }
827         activey_ { arg val;
828                 this.setPropertyWithAction(\y, val);
829         }
831         setXY { arg x, y;
832                 this.x = x;
833                 this.y = y;
834         }
836         setXYActive { arg x, y;
837                 this.setXY( x, y );
838                 this.doAction;
839         }
841         properties {
842                 ^super.properties ++ #[\x, \y]
843         }
845         pixelStepX { ^(this.bounds.width).reciprocal }
846         pixelStepY { ^(this.bounds.height).reciprocal }
848         incrementY { |zoom=1| ^this.y = this.y + (this.pixelStepY * zoom) }
849         decrementY { |zoom=1| ^this.y = this.y - (this.pixelStepY * zoom) }
850         incrementX { |zoom=1| ^this.x = this.x + (this.pixelStepX * zoom) }
851         decrementX { |zoom=1| ^this.x = this.x - (this.pixelStepX * zoom) }
853         defaultKeyDownAction { arg char, modifiers, unicode, keycode;
854                 var zoom = this.getScale(modifiers);
855                 // standard keydown
856                 if (char == $r, { this.x = 1.0.rand; this.y = 1.0.rand; ^this });
857                 if (char == $n, { this.x = 0.0; this.y = 0.0; ^this });
858                 if (char == $x, { this.x = 1.0; this.y = 1.0; ^this });
859                 if (char == $c, { this.x = 0.5; this.y = 0.5; ^this });
860                 if (unicode == 16rF700, { this.incrementY(zoom); ^this });
861                 if (unicode == 16rF703, { this.incrementX(zoom); ^this });
862                 if (unicode == 16rF701, { this.decrementY(zoom); ^this });
863                 if (unicode == 16rF702, { this.decrementX(zoom); ^this });
864                 ^nil            // bubble if it's an invalid key
865         }
866         defaultGetDrag {
867                 ^Point(this.x, this.y)
868         }
869         defaultCanReceiveDrag {
870                 ^currentDrag.isKindOf(Point);
871         }
872         defaultReceiveDrag {
873                 this.setXYActive(currentDrag.x, currentDrag.y);
874         }
877 SC2DTabletSlider : SC2DSlider {
878         *implementsClass { ^'TabletSlider2D' }
879 //      var <>mouseDownAction, <>mouseUpAction;
881         mouseDown { arg x, y, pressure, tiltx, tilty, deviceID,
882                          buttonNumber, clickCount, absoluteZ, rotation;
883                 mouseDownAction.value(this, x, y, pressure, tiltx, tilty, deviceID,
884                         buttonNumber, clickCount, absoluteZ, rotation);
885         }
886         mouseUp { arg x, y, pressure, tiltx, tilty, deviceID,
887                         buttonNumber, clickCount, absoluteZ, rotation;
888                 mouseUpAction.value(this, x, y, pressure, tiltx, tilty, deviceID,
889                         buttonNumber, clickCount, absoluteZ, rotation);
890         }
891         doAction { arg x, y, pressure, tiltx, tilty, deviceID,
892                         buttonNumber, clickCount, absoluteZ, rotation;
893                 action.value(this, x, y, pressure, tiltx, tilty, deviceID,
894                         buttonNumber, clickCount, absoluteZ, rotation);
895         }
898 SCButton : SCControlView {
899         var <font, <states;
901         *paletteExample { arg parent, bounds;
902                 var v;
903                 v = this.new(parent, bounds);
904                 v.states = [
905                         ["Push", Color.black, Color.red],
906                         ["Pop", Color.white, Color.blue]];
907                 ^v
908         }
910         value {
911                 ^this.getProperty(\value)
912         }
913         value_ { arg val;
914                 this.setProperty(\value, val);
915         }
916         valueAction_ { arg val;
917                 this.setPropertyWithAction(\value, val);
918         }
920         doAction { arg modifiers;
921                 action.value(this, modifiers);
922         }
924         defaultKeyDownAction { arg char, modifiers, unicode;
925                 if (char == $ , { this.valueAction = this.value + 1; ^this });
926                 if (char == $\r, { this.valueAction = this.value + 1; ^this });
927                 if (char == $\n, { this.valueAction = this.value + 1; ^this });
928                 if (char == 3.asAscii, { this.valueAction = this.value + 1; ^this });
929                 ^nil            // bubble if it's an invalid key
930         }
932         font_ { arg argFont;
933                 font = argFont;
934                 this.setProperty(\font, font)
935         }
937         states_ { arg array;
938                 states = array;
939                 this.setProperty(\states, states);
940         }
942         properties {
943                 ^super.properties ++ #[\value, \font, \states]
944         }
946         defaultGetDrag {
947                 ^this.value
948         }
949         defaultCanReceiveDrag {
950                 ^currentDrag.isNumber or: { currentDrag.isKindOf(Function) };
951         }
952         defaultReceiveDrag {
953                 if (currentDrag.isNumber) {
954                         this.valueAction = currentDrag;
955                 } {
956                         this.action = currentDrag;
957                 };
958         }
962 SCPopUpMenu : SCControlView {
963         var <font, <items;
965         *paletteExample { arg parent, bounds;
966                 var v;
967                 v = this.new(parent, bounds);
968                 v.items = #["linear", "exponential", "sine", "welch", "squared", "cubed"];
969                 ^v
970         }
972         value {
973                 ^this.getProperty(\value)
974         }
975         value_ { arg val;
976                 this.setProperty(\value, val);
977         }
978         valueAction_ { arg val;
979                 this.setPropertyWithAction(\value, val);
980         }
982         defaultKeyDownAction { arg char, modifiers, unicode;
983                 if (char == $ , { this.valueAction = this.value + 1; ^this });
984                 if (char == $\r, { this.valueAction = this.value + 1; ^this });
985                 if (char == $\n, { this.valueAction = this.value + 1; ^this });
986                 if (char == 3.asAscii, { this.valueAction = this.value + 1; ^this });
987                 if (unicode == 16rF700, { this.valueAction = this.value - 1; ^this });
988                 if (unicode == 16rF703, { this.valueAction = this.value + 1; ^this });
989                 if (unicode == 16rF701, { this.valueAction = this.value + 1; ^this });
990                 if (unicode == 16rF702, { this.valueAction = this.value - 1; ^this });
991                 ^nil            // bubble if it's an invalid key
992         }
993         font_ { arg argFont;
994                 font = argFont;
995                 this.setProperty(\font, font)
996         }
997         items_ { arg array;
998                 items = array;
999                 this.setProperty(\items, items);
1000         }
1002         item {
1003                 ^items[this.value]
1004         }
1006         stringColor {
1007                 ^this.getProperty(\stringColor, Color.new)
1008         }
1009         stringColor_ { arg color;
1010                 this.setProperty(\stringColor, color)
1011         }
1013         properties {
1014                 ^super.properties ++ #[\value, \font, \items, \stringColor]
1015         }
1017         defaultGetDrag {
1018                 ^this.value
1019         }
1020         defaultCanReceiveDrag {
1021                 ^currentDrag.isNumber;
1022         }
1023         defaultReceiveDrag {
1024                 this.valueAction = currentDrag;
1025         }
1030 SCStaticTextBase : SCView {
1031         var <string, <font, <object, <>setBoth=true;
1033         font_ { arg argFont;
1034                 font = argFont;
1035                 this.setProperty(\font, font)
1036         }
1038         string_ { arg argString;
1039                 string = argString.asString;
1040                 this.setProperty(\string, string)
1041         }
1042         align_ { arg align;
1043                 this.setProperty(\align, align)
1044         }
1046         stringColor {
1047                 ^this.getProperty(\stringColor, Color.new)
1048         }
1049         stringColor_ { arg color;
1050                 this.setProperty(\stringColor, color)
1051         }
1053         object_ { arg obj;
1054                 object = obj;
1055                 if (setBoth) { this.string = object.asString(80); };
1056         }
1058         properties {
1059                 ^super.properties ++ #[\string, \font, \stringColor]
1060         }
1063 SCStaticText : SCStaticTextBase {
1064         *paletteExample { arg parent, bounds;
1065                 var v;
1066                 v = this.new(parent, bounds);
1067                 v.string = "The lazy brown fox";
1068                 ^v
1069         }
1073 SCNumberBoxOld : SCStaticTextBase {
1074         var <> keyString, <>step=1, <>scroll_step=1;
1075         var <>typingColor, <>normalColor;
1076         var <>clipLo = -inf, <>clipHi = inf, hit, inc=1.0, <>scroll=true;
1077         var <>shift_scale = 100.0, <>ctrl_scale = 10.0, <>alt_scale = 0.1;
1079         getScale { |modifiers|
1080                 ^case
1081                          { modifiers & 131072 == 131072 } { shift_scale }
1082                          { modifiers & 262144 == 262144 } { ctrl_scale }
1083                          { modifiers & 524288 == 524288 } { alt_scale }
1084                          { 1 };
1085         }
1087         *paletteExample { arg parent, bounds;
1088                 var v;
1089                 v = this.new(parent, bounds);
1090                 v.value = 123.456;
1091                 ^v
1092         }
1094         init { arg argParent, argBounds;
1095                 typingColor = Color.red;
1096                 normalColor = Color.black;
1097                 background = Color.white;
1098                 parent = argParent.asView; // actual view
1099                 this.prInit(parent.asView, argBounds.asRect, this.class.viewClass);
1100                 argParent.add(this);//maybe window or viewadapter
1101         }
1103         increment { arg mul=1; this.valueAction = this.value + (step*mul); }
1104         decrement { arg mul=1; this.valueAction = this.value - (step*mul); }
1106         defaultKeyDownAction { arg char, modifiers, unicode;
1107                 var zoom = this.getScale(modifiers);
1109                 // standard chardown
1110                 if (unicode == 16rF700, { this.increment(zoom); ^this });
1111                 if (unicode == 16rF703, { this.increment(zoom); ^this });
1112                 if (unicode == 16rF701, { this.decrement(zoom); ^this });
1113                 if (unicode == 16rF702, { this.decrement(zoom); ^this });
1115                 if ((char == 3.asAscii) || (char == $\r) || (char == $\n), { // enter key
1116                         if (keyString.notNil, { // no error on repeated enter
1117                                 this.valueAction_(keyString.asFloat);
1118                         });
1119                         ^this
1120                 });
1121                 if (char == 127.asAscii, { // delete key
1122                         keyString = nil;
1123                         this.string = object.asString;
1124                         this.stringColor = normalColor;
1125                         ^this
1126                 });
1127                 if (char.isDecDigit || "+-.eE".includes(char), {
1128                         if (keyString.isNil, {
1129                                 keyString = String.new;
1130                                 this.stringColor = typingColor;
1131                         });
1132                         keyString = keyString.add(char);
1133                         this.string = keyString;
1134                         ^this
1135                 });
1139                 ^nil            // bubble if it's an invalid key
1140         }
1142         value { ^object }
1143         value_ { arg val;
1144                 keyString = nil;
1145                 this.stringColor = normalColor;
1146                 object = val !? { val.clip(clipLo, clipHi) };
1147                 this.string = object.asString;
1148         }
1149         valueAction_ { arg val;
1150                 var prev;
1151                 prev = object;
1152                 this.value = val !? { val.clip(clipLo, clipHi) };
1153                 if (object != prev, { this.doAction });
1154         }
1156         boxColor {
1157                 this.deprecated(thisMethod, SCView.findMethod(\background));
1158                 ^this.background;
1159         }
1160         boxColor_ { arg color;
1161                 this.deprecated(thisMethod, SCView.findMethod(\background_));
1162                 this.background_(color)
1163         }
1165         properties {
1166                 ^super.properties ++ #[\boxColor]
1167         }
1168         defaultGetDrag {
1169                 ^object.asFloat
1170         }
1171         defaultCanReceiveDrag {
1172                 ^currentDrag.isNumber;
1173         }
1174         defaultReceiveDrag {
1175                 this.valueAction = currentDrag;
1176         }
1178         mouseDown { arg x, y, modifiers, buttonNumber, clickCount;
1179                 hit = Point(x, y);
1180                 if (scroll == true, { inc = this.getScale(modifiers) });
1181                 mouseDownAction.value(this, x, y, modifiers, buttonNumber, clickCount)
1182         }
1184         mouseMove { arg x, y, modifiers;
1185                 var direction;
1186                 if (scroll == true, {
1187                         direction = 1.0;
1188                                 // horizontal or vertical scrolling:
1189                         if ( (x - hit.x) < 0 or: { (y - hit.y) > 0 }) { direction = -1.0; };
1191                         this.valueAction = (this.value + (inc * this.scroll_step * direction));
1192                         hit = Point(x, y);
1193                 });
1194                 mouseMoveAction.value(this, x, y, modifiers);
1195         }
1196         mouseUp {
1197                 inc=1
1198         }
1201 SCListView : SCControlView {
1202         var <font, <items, <>enterKeyAction;
1204         *paletteExample { arg parent, bounds;
1205                 var v;
1206                 v = this.new(parent, bounds);
1207                 v.items = #["linear", "exponential", "sine", "welch", "squared", "cubed"];
1208                 ^v
1209         }
1211         init { arg argParent, argBounds;
1212                 parent = argParent.asView; // actual view
1213                         // call asView again because parent by this point might be a FlowView
1214                 this.prInit(parent.asView, argBounds.asRect, this.class.viewClass);
1215                 argParent.add(this);//maybe window or viewadapter
1216                 this.items = []; // trick to draw right in scrollviews
1217         }
1219         item {
1220                 ^items[this.value]
1221         }
1222         value {
1223                 ^this.getProperty(\value)
1224         }
1225         value_ { arg val;
1226                 this.setProperty(\value, val);
1227         }
1228         valueAction_ { arg val;
1229                 this.setPropertyWithAction(\value, val);
1230         }
1232         defaultKeyDownAction { arg char, modifiers, unicode;
1233                 var index;
1234                 if (char == $ , { this.valueAction = this.value + 1; ^this });
1235                 if (char == $\r, { this.enterKeyAction.value(this); ^this });
1236                 if (char == $\n, { this.enterKeyAction.value(this); ^this });
1237                 if (char == 3.asAscii, { this.enterKeyAction.value(this); ^this });
1238                 if (unicode == 16rF700, { this.valueAction = this.value - 1; ^this });
1239                 if (unicode == 16rF703, { this.valueAction = this.value + 1; ^this });
1240                 if (unicode == 16rF701, { this.valueAction = this.value + 1; ^this });
1241                 if (unicode == 16rF702, { this.valueAction = this.value - 1; ^this });
1242                 if (char.isAlpha, {
1243                         char = char.toUpper;
1244                         index = items.detectIndex( { |item| item.asString.at(0).toUpper >= char });
1245                         if (index.notNil, {
1246                                 this.valueAction = index
1247                         });
1248                         ^this
1249                 });
1250                 ^nil            // bubble if it's an invalid key
1251         }
1252         font_ { arg argFont;
1253                 font = argFont;
1254                 this.setProperty(\font, font)
1255         }
1256         items_ { arg array;
1257                 items = array;
1258                 this.setProperty(\items, items);
1259         }
1261         colors_ { arg incolors;
1262                 this.setProperty(\itemColors, incolors);
1263         }
1265         colors {
1266                 ^this.getProperty(\itemColors, {Color.new}!items.size);
1267         }
1269         stringColor {
1270                 ^this.getProperty(\stringColor, Color.new)
1271         }
1272         stringColor_ { arg color;
1273                 this.setProperty(\stringColor, color)
1274         }
1276         selectedStringColor {
1277                 ^this.getProperty(\selectedStringColor, Color.new)
1278         }
1279         selectedStringColor_ { arg color;
1280                 this.setProperty(\selectedStringColor, color)
1281         }
1283         hiliteColor {
1284                 ^this.getProperty(\hiliteColor, Color.new)
1285         }
1286         hiliteColor_ { arg color;
1287                 this.setProperty(\hiliteColor, color)
1288         }
1290         properties {
1291                 ^super.properties ++ #[\value, \font, \items, \stringColor, \align, \itemColors]
1292         }
1294         defaultGetDrag {
1295                 ^this.value
1296         }
1297         defaultCanReceiveDrag {
1298                 ^currentDrag.isNumber;
1299         }
1300         defaultReceiveDrag {
1301                 this.valueAction = currentDrag;
1302         }
1306 SCDragView : SCStaticTextBase {
1308         *paletteExample { arg parent, bounds;
1309                 var v;
1310                 v = this.new(parent, bounds);
1311                 v.object = \something;
1312                 ^v
1313         }
1314         defaultGetDrag {
1315                 ^object
1316         }
1319 SCDragSource : SCDragView {
1323 SCDragSink : SCDragView {
1324         defaultCanReceiveDrag { ^true;  }
1325         defaultReceiveDrag {
1326                 this.object = currentDrag;
1327                 this.doAction;
1328         }
1331 SCDragBoth : SCDragSink {
1332         defaultGetDrag { ^object }
1336 SCUserView : SCView {
1337         var <>drawFunc;
1338 //      var <>mouseBeginTrackFunc, <>mouseTrackFunc, <>mouseEndTrackFunc;
1339         var < clearOnRefresh = true;
1340         var < drawingEnabled = true;
1342         init { |argParent, argBounds|
1343                 super.init(argParent, argBounds);
1344         }
1346         draw {
1347                 drawFunc.value(this) ;
1348         }
1350         clearDrawing {
1351                         this.setProperty(\clearDrawing);
1352         }
1354         mousePosition {
1355                 this.deprecated(thisMethod);
1356                 ^this.getProperty(\mousePosition, Point.new)
1357         }
1359         clearOnRefresh_ { |bool|
1360                 clearOnRefresh = bool;
1361                 this.setProperty(\clearOnRefresh, bool);                        }
1363         animate_ { |bool|
1364                 this.setProperty(\animate, bool);
1365         }
1367         frame {
1368                 ^this.getProperty(\frame);
1369         }
1371         frameRate {
1372                 ^this.getProperty(\frameRate);
1373         }
1375         drawingEnabled_ { |bool|
1376                 drawingEnabled = bool;
1377                 this.setProperty(\drawingEnabled, bool);        }
1379         /* backwards compatibility */
1380         keyDownFunc_ { |action|
1381                 "SCUserView:keyDownFunc deprecated, use SCUserView:keyDownAction".warn;
1382                 keyDownAction = action;
1383         }
1385         keyDownFunc {
1386                 "SCUserView:keyDownFunc deprecated, use SCUserView:keyDownAction".warn;
1387                 ^keyDownAction
1388         }
1390         mouseBeginTrackFunc_ { |action|
1391                 "SCUserView:mouseBeginTrackFunc deprecated, use SCUserView:mouseDownAction".warn;
1392                 mouseDownAction = action;
1393         }
1394         mouseBeginTrackFunc {
1395                 "SCUserView:mouseBeginTrackFunc deprecated, use SCUserView:mouseDownAction".warn;
1396                 ^mouseDownAction;
1397         }
1399         mouseTrackFunc_ { |action|
1400                 "SCUserView:mouseTrackFunc deprecated, use SCUserView:mouseMoveAction".warn;
1401                 mouseMoveAction = action;
1402         }
1403         mouseTrackFunc {
1404                 "SCUserView:mouseTrackFunc deprecated, use SCUserView:mouseMoveAction".warn;
1405                 ^mouseMoveAction;
1406         }
1408         mouseEndTrackFunc_ { |action|
1409                 "SCUserView:mouseEndTrackFunc deprecated, use SCUserView:mouseUpAction".warn;
1410                 mouseUpAction = action;
1411         }
1413         mouseEndTrackFunc {
1414                 "SCUserView:mouseEndTrackFunc deprecated, use SCUserView:mouseUpAction".warn;
1415                 ^mouseUpAction;
1416         }
1422 //SCFuncUserView : SCUserView {
1423 //      var <>keyDownFunc, <>drawFunc;
1424 //      var <>mouseBeginTrackFunc, <>mouseTrackFunc, <>mouseEndTrackFunc;
1426 //      draw { drawFunc.value(this) }
1427 //      mouseBeginTrack { arg x, y, modifiers;
1428 //              mouseBeginTrackFunc.value(this, x, y, modifiers);
1429 //      }
1430 //      mouseTrack { arg x, y, modifiers;
1431 //              mouseTrackFunc.value(this, x, y, modifiers);
1432 //      }
1433 //      mouseEndTrack { arg x, y, modifiers;
1434 //              mouseEndTrackFunc.value(this, x, y, modifiers);
1435 //      }
1436 //      keyDown { arg key, modifiers, unicode;
1437 //              keyDownFunc.value(this, key, modifiers, unicode)
1438 //      }
1441 //by jt v.0.22
1442 SCMultiSliderView : SCView {
1444         var <>metaAction;
1445 //      var <>mouseUpAction;
1446         var <>size ;
1447         var <gap;
1448         var <editable = true;
1449         var <elasticMode = 0;
1451         draw {}
1452         mouseBeginTrack { arg x, y, modifiers;}
1453         mouseTrack { arg x, y, modifiers;       }
1454         mouseEndTrack { arg x, y, modifiers;
1455                 mouseUpAction.value(this);
1456         }
1457         properties {
1458                 ^super.properties ++ #[\value, \thumbSize, \fillColor, \strokeColor, \xOffset, \x, \y, \showIndex, \drawLines, \drawRects, \selectionSize, \startIndex, \referenceValues, \thumbWidth, \absoluteX, \isFilled, \step, \elasticResizeMode]
1459         }
1463         elasticMode_ { arg mode;
1464                 elasticMode =mode;
1465                 this.setProperty(\elasticResizeMode, mode);
1466         }
1468         step_ { arg stepSize;
1469                 this.setPropertyWithAction(\step, stepSize);
1470         }
1472         step {
1473                 ^this.getProperty(\step)
1474         }
1476         value { //returns array
1477                 ^this.getProperty(\value, Array.newClear(this.size))
1478         }
1479         value_ { arg val;
1480                 this.size = val.size;
1481                 this.setProperty(\value, val)
1482         }
1484         valueAction_ { arg val;
1485                 this.size = val.size;
1486                 this.setPropertyWithAction(\value, val);
1487         }
1489         reference { //returns array
1490                 ^this.getProperty(\referenceValues, Array.newClear(this.size))
1491         }
1492         reference_ { arg val;
1493                 //this.size = val.size;
1494                 this.setProperty(\referenceValues, val)
1495         }
1496         index { //returns selected index
1497                 ^this.getProperty(\x)
1498         }
1499         index_ { arg inx;
1500                 this.setProperty(\x, inx)
1501         }
1502         isFilled_ { arg abool;
1503                 this.setProperty(\isFilled, abool);
1504         }
1505         xOffset_ { arg aval;
1506                 this.setProperty(\xOffset, aval);
1507         }
1508         gap_ { arg inx;
1509                 gap = inx;
1510                 this.setProperty(\xOffset, inx)
1511         }
1513         startIndex_ { arg val; this.setProperty( \startIndex, val )}
1515         selectionSize {
1516                 ^this.getProperty(\selectionSize)
1517         }
1518         selectionSize_ { arg aval;
1519                 this.setProperty(\selectionSize, aval)
1520         }
1521         currentvalue { //returns value of selected index
1522                 ^this.getProperty(\y)
1523         }
1524         fillColor_ { arg acolor;
1525                 this.setProperty(\fillColor, acolor)
1526         }
1527         strokeColor_ { arg acolor;
1528                 this.setProperty(\strokeColor, acolor)
1529         }
1530         colors_ { arg strokec, fillc;
1531                 this.strokeColor_(strokec);
1532                 this.fillColor_(fillc);
1533         }
1534         currentvalue_ { arg iny;
1535                 this.setProperty(\y, iny)
1536         }
1537         showIndex_ { arg abool;
1538                 this.setProperty(\showIndex, abool)
1539                 }
1540         drawLines { arg abool;
1541                 this.setProperty(\drawLines, abool)
1542         }
1543         drawLines_ { arg abool;
1544                 this.drawLines(abool)
1545         }
1546         drawRects_ { arg abool;
1547                 this.setProperty(\drawRects, abool)
1548         }
1549         readOnly_ { arg val;
1550                 editable = val.not;
1551                 this.setProperty(\readOnly, val);
1552         }
1553         editable_ { arg val;
1554                 editable = val;
1555                 this.setProperty(\readOnly, editable.not);
1556         }
1557         thumbSize_ { arg val;
1558                 this.setProperty(\thumbSize, val)
1559         }
1560         indexThumbSize_ { arg val;
1561                 this.setProperty(\indexThumbSize, val)
1562         }
1563         valueThumbSize_ { arg val;
1564                 this.setProperty(\valueThumbSize, val)
1565         }
1566         indexIsHorizontal_ { arg val;
1567                 this.setProperty(\isHorizontal, val);
1568         }
1569         defaultCanReceiveDrag { ^true; }
1570         defaultReceiveDrag {
1571                 if(currentDrag.at(0).isSequenceableCollection, {
1572                         this.value_(currentDrag.at(0));
1573                         this.reference_(currentDrag.at(1));
1574                 }, {
1575                         this.value_(currentDrag);
1576                 });
1577         }
1578         defaultGetDrag {
1579                 var setsize, vals, rvals, outval;
1580                 rvals = this.reference;
1581                 vals = this.value;
1582                 if(this.selectionSize > 1, {
1583                         vals = vals.copyRange(this.index, this.selectionSize + this.index);});
1584                 if(rvals.isNil, {
1585                         ^vals
1586                 }, {
1587                 if(this.selectionSize > 1, {
1588                         rvals = rvals.copyRange(this.index, this.selectionSize + this.index);});
1589                         outval = outval.add(vals);
1590                         outval = outval.add(rvals);
1591                 });
1592                 ^outval
1593         }
1595         defaultKeyDownAction { arg key, modifiers, unicode;
1596                 //modifiers.postln; 16rF702
1597                 if (unicode == 16rF703, { this.index = this.index + 1; ^this });
1598                 if (unicode == 16rF702, { this.index = this.index - 1; ^this });
1599                 if (unicode == 16rF700, { this.gap = this.gap + 1; ^this });
1600                 if (unicode == 16rF701, { this.gap = this.gap - 1; ^this });
1601                 ^nil            // bubble if it's an invalid key
1602         }
1604         *paletteExample { arg parent, bounds;
1605                 var example;
1606                 example = this.new(parent, bounds).valueThumbSize_(2);
1607                 ^example
1608         }
1610         doMetaAction {
1611                 metaAction.value(this)
1612         } //on ctrl click
1615 SCEnvelopeView : SCView {
1616         var connection, <>allConnections, doOnce;
1617 //      var <>mouseUpAction;
1618         var <>items;
1619         var < fixedSelection = false;
1620         var <>metaAction;
1621         var <>size ;
1622         var <editable = true;
1623         var <curves = \linear;
1624         var <gridOn, <gridColor, <grid;
1626         init { arg argParent, argBounds;
1627                 super.init(argParent, argBounds);
1628                 gridOn = false;
1629                 gridColor = Color(0, 0, 0.8, 0.3);
1630                 grid = Point(0.1, 0.1);
1631         }
1633         draw {}
1634         mouseBeginTrack { arg x, y, modifiers;}
1635         mouseTrack { arg x, y, modifiers;       }
1636         mouseEndTrack { arg x, y, modifiers;
1637                 mouseUpAction.value(this);
1638         }
1640         grid_ { arg point;
1641                 this.setProperty(\setGrid, [point.x, point.y]);
1642                 grid = point;
1643         }
1645         gridOn_ { arg bool;
1646                 this.setProperty(\showGrid, bool);
1647                 gridOn = bool;
1648         }
1650         gridColor_ { arg color;
1651                 this.setProperty(\setGridColor, color);
1652                 gridColor = color;
1653         }
1655         properties {
1656                 ^super.properties ++ #[\value, \thumbSize, \fillColor, \strokeColor, \xOffset, \x, \y, \showIndex, \drawLines, \drawRects, \selectionSize, \startIndex, \thumbWidth, \absoluteX, \isFilled, \step, \setCurve, \setCurves, \showGrid, setGridColor, \setGrid]
1657         }
1659         step_ { arg stepSize;
1660                 this.setPropertyWithAction(\step, stepSize);
1661         }
1663         step {
1664                 ^this.getProperty(\step)
1665         }
1667         valueAction_ { arg val;
1668                 this.value_(val);
1669                 this.doAction;
1670         }
1672         currentvalue { //returns value of selected index
1673                 ^this.getProperty(\y)
1674         }
1675         currentvalue_ { arg iny;
1676                 this.setProperty(\y, iny)
1677         }
1679         strokeColor_ { arg acolor;
1680                 this.setProperty(\strokeColor, acolor)
1681         }
1682         colors_ { arg strokec, fillc;
1683                 this.strokeColor_(strokec);
1684                 this.fillColor_(fillc);
1685         }
1687         drawLines { arg abool;
1688                 this.setProperty(\drawLines, abool)
1689         }
1690         drawLines_ { arg abool;
1691                 this.drawLines(abool)
1692         }
1693         drawRects_ { arg abool;
1694                 this.setProperty(\drawRects, abool)
1695         }
1697         defaultCanReceiveDrag { ^true; }
1699     defaultKeyDownAction { arg key, modifiers, unicode;
1700                 (modifiers==10617090).if { // shift key
1701                         (this.index > 1.neg).if {
1702                         if (unicode == 16rF703, { this.x = this.value[0][this.index] + this.step; ^this });
1703                         if (unicode == 16rF702, { this.x = this.value[0][this.index] - this.step; ^this });
1704                         };
1705                 } {
1706                         if (unicode == 16rF703, { this.selectIndex((this.index+1)%this.size) ^this });
1707                         if (unicode == 16rF702, { this.selectIndex((this.index-1)%this.size) ^this });
1708                 };
1709                 (this.index > 1.neg).if {
1710                    if (unicode == 16rF700, { this.y = this.value[1][this.index] + this.step; ^this });
1711                    if (unicode == 16rF701, { this.y = this.value[1][this.index] - this.step; ^this });
1712                 };
1713         ^nil        // bubble if it's an invalid key
1714     }
1716         doMetaAction {
1717                 metaAction.value(this)
1718         } //on ctrl click
1720         value_ { arg val;
1721                 if(val.at(1).size != val.at(0).size, {
1722                         // otherwise its a fatal crash
1723                         Error("SCEnvelopeView got mismatched times/levels arrays").throw;
1724                 });
1725                 this.size = val.at(0).size;
1726                 this.setProperty(\value, val)
1727         }
1728         setString { arg index, astring;
1729                 //items = items.add(astring);
1730                 this.setProperty(\string, [index, astring])
1731         }
1733         strings_ { arg astrings;
1734                 astrings.do( { arg str, i;
1735                         this.setString(i, str);
1736                 });
1737         }
1738         value {
1739                 var ax, ay, axy;
1740                 ax = Array.newClear(this.size);
1741                 ay = Array.newClear(this.size);
1742                 axy = Array.with(ax, ay);
1743                 ^this.getProperty(\value, axy)
1744         }
1746         setThumbHeight { arg index, height;
1747                 this.setProperty(\thumbHeight, [index, height]);
1748         }
1749         thumbHeight_ { arg height;
1750                 this.setThumbHeight(-1, height);
1751         }
1752         setThumbWidth { arg index, width;
1753                 this.setProperty(\thumbWidth, [index, width]);
1754         }
1755         thumbWidth_ { arg width;
1756                 this.setThumbWidth(-1, width);
1757         }
1758         setThumbSize { arg index, size;
1759                 this.setProperty(\thumbSize, [index, size]);
1760         }
1761         thumbSize_ { arg size;
1762                 this.setThumbSize(-1, size);
1763         }
1764         setFillColor { arg index, color;
1765                 this.setProperty(\fillColor, [index, color]);
1766         }
1767         fillColor_ { arg color;
1768                 this.setFillColor(-1, color);
1769         }
1771         curves_ { arg inCurves;
1772                 var curveNumbers;
1773                 var shapeNum, curveNum=0;
1774                 curves = inCurves;
1775                 if(curves.isKindOf(Array)) {
1776                         curveNumbers = curves.collect { |it|
1777                                 shapeNum = this.shapeNumber(it);
1778                                 if(shapeNum == 5) {
1779                                         curveNum = it;
1780                                 } {
1781                                         curveNum = 0;
1782                                 };
1783                                 [shapeNum, curveNum]
1784                         };
1785 //                      this.debug(curveNumbers);
1786                         this.prSetCurves(curveNumbers);
1787                 } {
1788                         shapeNum = this.shapeNumber(curves);
1789                                 if(shapeNum == 5) {
1790                                         curveNum = curves;
1791                                 } {
1792                                         curveNum = 0;
1793                                 };
1794                         this.prSetCurve([-1, shapeNum, curveNum]);
1795                 }
1796         }
1798         setEnv { arg env, minValue, maxValue, minTime, maxTime;
1799                 var times, levels;
1800                 var spec;
1802                 times = Array.newClear(env.times.size + 1);
1803                 times[0] = 0;
1804                 for(1, env.times.size, { arg i;
1805                         times[i] = times[i-1] + env.times[i-1];
1806                 });
1807                 maxTime = maxTime ? times.last;
1808                 minTime = minTime ? 0;
1809                 levels = env.levels;
1810                 minValue = minValue ? levels.minItem;
1811                 maxValue = maxValue ? levels.maxItem;
1813                 levels = levels.linlin(minValue, maxValue, 0, 1);
1814                 times = times.linlin(minTime, maxTime, 0, 1);
1816                 this.value_([times.asFloat, levels.asFloat]);
1817                 this.curves_(env.curves);
1819         }
1821         editEnv { arg env, minValue, maxValue, duration;
1822                 var vals, levels, times, lastTime = 0;
1823                 vals = this.value;
1824                 levels = vals[0].linlin(0, 1, minValue, maxValue);
1825                 times = vals[1].collect { |it|
1826                         var out;
1827                         out = it - lastTime;
1828                         lastTime = it;
1829                         out
1830                 };
1831                 env.times_(times);
1832                 env.levels_(levels);
1833                 env.curves_(this.curves);
1834         }
1836         asEnv { arg env, minValue, maxValue, duration;
1837                 var vals, levels, times, lastTime = 0;
1838                 vals = this.value;
1839                 levels = vals[0].linlin(0, 1, minValue, maxValue);
1840                 times = vals[1].collect { |it|
1841                         var out;
1842                         out = it - lastTime;
1843                         lastTime = it;
1844                         out
1845                 };
1846                 env.times_(times);
1847                 env.levels_(levels);
1848                 env.curves_(this.curves);
1849                 ^Env(levels, times, this.curves);
1850         }
1852         *paletteExample { arg parent, bounds;
1853                 ^this.new(parent, bounds).setEnv(Env([0.1, 0.3, 0.4, 0.01], [0.3, 1, 3]));
1854         }
1856         prSetCurves { |arr|
1857                 this.setProperty(\setCurves, arr);
1858         }
1860         prSetCurve { |arr|
1861 //              this.debug([\setCurves, arr]);
1862                 this.setProperty(\setCurve, arr);
1863         }
1865         shapeNumber { arg shapeName;
1866                 var shape;
1867                 shape = Env.shapeNames.at(shapeName);
1868                 if (shape.notNil) { ^shape } {^5};
1869         }
1871         connect { arg from, aconnections;
1872                 this.setProperty(\connect, [from, aconnections.asFloat]);
1873         }
1875         select { arg index; //this means no refresh;
1876                 this.setProperty(\setIndex, index);
1877         }
1878         selectIndex { arg index; //this means that the view will be refreshed
1879                 this.setProperty(\selectedIndex, index);
1880         }
1881         x {                                             //returns selected x
1882                 ^this.getProperty(\x);
1883         }
1884         y {
1885                 ^this.getProperty(\y);
1886         }
1887         x_ { arg ax;
1888                 this.setProperty(\x, ax);
1889         }
1890         y_ { arg ay;
1891                 this.setProperty(\y, ay);
1892         }
1893         index {
1894                 ^this.getProperty(\selectedIndex)
1895         }
1896         lastIndex {
1897                 ^this.getProperty(\lastIndex)
1898         }
1900         setEditable { arg index, boolean;
1901                 this.setProperty(\editable, [index, boolean]);
1902         }
1904         editable_ { arg boolean;
1905                 this.setEditable(-1, boolean);
1906         }
1908         selectionColor_ { arg acolor;
1909                 this.setProperty(\selectionColor, acolor)
1910         }
1911         defaultGetDrag {
1912                 ^this.value
1913         }
1914         defaultReceiveDrag {
1915                 if(currentDrag.isString, {
1916                         this.addValue;
1917                         items = items.insert(this.lastIndex + 1, currentDrag);
1918                         this.strings_(items);
1919                 }, {
1920                         this.value_(currentDrag);
1921                 });
1922         }
1924         addValue { arg xval, yval;
1925                 var arr, arrx, arry, aindx;
1926                 arr = this.value;
1927                 arrx = arr@0;
1928                 arry = arr@1;
1929                 arrx.do { |val, i|
1930                         if(val>xval and: aindx.isNil) {
1931                                 aindx = i;
1932                         }
1933                 };
1934 //              this.debug(aindx);
1935                 arrx = arrx.insert(aindx , xval);
1936                 arry = arry.insert(aindx , yval);
1937                 this.value_([arrx, arry]);
1938         }
1940         fixedSelection_ { arg bool;
1941                 fixedSelection =  bool;
1942                 this.setProperty(\setFixedSelection, bool);
1943         }
1946 //including keydown by Heiko:
1947 // bug fixed in SCRangeSlider-receiveDrag
1948 // bug fixed in SCView-getPropertyList
1949 // allowing children in SCContainerView and parent in SCView to be accessed
1950 // globalKeyDownAction as classvar for all Views
1951 // KeyDownAction for all Views
1952 // bug fixed in SCNumberBox-defaultKeyDownAction
1953 // passing keydown up the tree
1954 // consuming keydown in function
1955 // added keyup
1956 // and SCMultiSlider by jan t.
1957 // added customizable drag handlers, cx