deprecate SCViewHolder-layRight
[supercollider.git] / SCClassLibrary / Common / GUI / osx / scide_scapp / SCInterfaceBuilder / SCIBToolboxWindow.sc
blobefb1ed67137d8531dd23e673798d6c3f4923661b
1 /*
2         SCIBToolboxWindow()
4         select view(s) and apple-drag between windows to copy
5         select view(s) and apple-drag inside a window, or press c, to copy
6         press delete to delete
8         by scott micheli-smith
9         sclang integration by jan trutzschler
11 SCIBPanelWindow
13         var <window,<userview,>parent,isSelected=false;
15         var selection,<selectedViews,views;
17         var <gridStep = 10,<gridOn = false,dragging,indent,multipleDragBy;
19         var resizeHandles,resizeFixed, dropX, dropY;
22         *new { |window, bounds| ^super.new.init(window, bounds) }
25         init { |win, bounds|
26                 window = win;
28                 views = window.view.children ? Array.new;
29                 this.makeUserview;
30                 window.constructionView = userview;
32         }
34         gridOn_ { |bool|
35                 gridOn = bool;
36                 window.refresh;
37         }
39         gridStep_ { |step|
40                 gridStep = step;
41                 this.debug(gridStep);
42                 if(gridOn, { window.refresh })
43         }
45         makeUserview {
46                 var w = window.bounds.width, h = window.bounds.height;
48                 userview !? { userview.remove };
49                 userview = SCConstructionView(window,Rect(0,0,w,h)).resize_(5);
51                 userview.beginDragAction = {
52                         var classes,rects;
54                         if ( selectedViews.size > 0,{
55                                 #classes, rects = flop(selectedViews.collect({ |view|
56                                         [ view.class, view.bounds ]
57                                 }));
59                                 SCIBMultipleDrag(classes,rects)
60                         })
61                 };
63                 userview.keyDownAction = { |v,c,m,u| this.panelSelect.keyDown(c,u) };
64                 userview.mouseDownAction = { |v,x,y| this.panelSelect.mouseDown(x,y) };
65                 userview.mouseUpAction = { |v,x,y| this.panelSelect.mouseUp };
67                 userview.mouseOverAction = { |v,x,y| dropX = x; dropY = y };
69                 userview.canReceiveDragHandler = {
70                         SCView.currentDrag.isKindOf( SCIBDrag )
71                 };
73                 userview.receiveDragHandler = {
74                         var addedViews = Array.new;
76                         SCView.currentDrag.do({ |class, rect|
77                                 rect = rect.moveBy( dropX, dropY );
78                                 addedViews = addedViews.add( class.paletteExample(window,rect).enabled_(false) );
79                         });
81                         views = views.addAll( addedViews );
83                         dragging = true;
84                         selectedViews = addedViews;
85                         indent = dropX@dropY - views.last.bounds.origin;
87                         this.makeUserview.updateResizeHandles;
88                         window.front.refresh;
90                         this.panelSelect
91                 };
93                 userview.mouseMoveAction = { |v,x,y| this.drag(x,y) };
94                 userview.focus;
96                 this.initDrawFunc
97         }
99         initDrawFunc {
100                 userview.drawFunc = {
101                         var b,n,h,w;
103                         if(gridOn,{
104                                 b = window.view.bounds;
105                                 h = b.height;
106                                 w = b.width;
108                                 Color.yellow(1,0.4).set;
110                                 n = h / gridStep;
111                                 (n-1).do({ |i| i=i+1*gridStep;
112                                         Pen.moveTo(0@i).lineTo(w@i).stroke;
113                                 });
115                                 n = w / gridStep;
116                                 (n-1).do({ |i| i=i+1*gridStep;
117                                         Pen.moveTo(i@0).lineTo(i@h).stroke;
118                                 })
119                         });
121                         Color.blue.set;
123                         if(isSelected,{
124                                 Pen.width_(4).strokeRect(window.bounds.moveTo(0,0));
125                         });
127                         selectedViews.do({ |v|
128                                 Pen.strokeRect(v.bounds)
129                         });
130                         Pen.width_(1);
132                         resizeHandles.do({ |r|
133                                 Pen.fillRect(r)
134                         });
136                         if(selection.notNil, {
137                                 Pen.strokeRect(selection.rect)
138                         });
140                 }
141         }
143         deselect {
144                 isSelected = false;
145                 window.refresh
146         }
148         updateResizeHandles { var r,d=4;
149                 resizeHandles = if( selectedViews.size == 1,{
150                         r = selectedViews.first.bounds;
151                         [ r.leftTop, r.rightTop, r.rightBottom, r.leftBottom ]
152                                 .collect({ |center| Rect.aboutPoint(center,d,d) })
153                 });
154                 window.refresh
155         }
157         panelSelect {
158                 isSelected = true;
159                 if(parent.notNil,
160                         { parent.panelSelect(this) })
161         }
164         setResizeFixed { |resizeHandle|
165                 var r = selectedViews.first.bounds,i = resizeHandles.indexOf(resizeHandle);
166                 resizeFixed=r.perform([ \rightBottom, \leftBottom, \leftTop, \rightTop ][i])
167         }
170         mouseDown { |x,y|
171                 var view,p,handle;
173                 p = x@y;
175                 if( resizeHandles.notNil and: {
176                         (handle = resizeHandles.detect({ |h| h.containsPoint(p) }) ).notNil
177                 },
178                 {
179                         this.setResizeFixed(handle)
180                 },
181                 {
182                         resizeFixed = nil;
183                         view = this.viewContainingPoint(p);
185                         dragging = view.notNil;
187                         if( dragging, {
188                                 indent = p - view.bounds.origin;
190                                 if( (selectedViews.size > 1) and:
191                                         { selectedViews.includes(view) },
192                                 {
193                                         multipleDragBy = view
194                                 },
195                                 {
196                                         multipleDragBy = nil;
197                                         selectedViews = [ view ]
198                                 })
199                         },{
200                                 selectedViews = [];
201                                 selection = SCIBAreaSelection(p)
202                         })
203                 });
204 //              this.debug(selectedViews);
205                 this.updateResizeHandles
206         }
208         drag { |x,y|
209                 var view,f,p=x@y;
210                 if( dragging, {
212                         if( resizeFixed.isNil,
213                         {
214                                 if(multipleDragBy.notNil,
215                                 {
216                                         f = p - ( multipleDragBy.bounds.origin + indent );
218                                         selectedViews.do({ |v|
219                                                 this.quantSetBounds(v,v.bounds.moveBy(f.x,f.y))
220                                         })
221                                 },{
222                                         view = selectedViews.first;
223                                         this.quantSetBounds(view,view.bounds.moveToPoint(p-indent));
225                                         this.updateResizeHandles
226                                 })
227                         },{
228                                 if(gridOn,{ p = p.round(gridStep) });
229                                 selectedViews.first.bounds = Rect.fromPoints(p,resizeFixed);
230                                 this.updateResizeHandles
231                         })
232                 },
233                 {
234                         selection.mouseDrag(p);
235                         selectedViews = views.select({ |view|
236                                 selection.selects(view.bounds)
237                         });
238                         window.refresh
239                 })
240         }
242         mouseUp { |x,y|
243                 if(selection.notNil,{
244                         selection = nil; window.refresh
245                 })
246         }
248         keyDown { |c,u|
249                 var newViews;
250                 case (
251                 // delete
252                 {u==127}, {
253                         if(selectedViews.isEmpty.not,{
254                                 selectedViews.do({ |v|
255                                         views.remove(v.remove);
256                                 });
257                                 selectedViews=[];
259                                 this.updateResizeHandles
260                         })
261                 },
262                 // clone
263                 {(c==$c) or: (c==$C)},{
264                         if(selectedViews.isEmpty.not,{
265                                 newViews=selectedViews.collect({ |v|
266                                         v.class.paletteExample(window,v.bounds.moveBy(40,40))
267                                 });
268                                 views=views++newViews;
269                                 selectedViews=newViews;
271                                 this.makeUserview.updateResizeHandles
272                         })
273                 })
274         }
277         quantSetBounds { |view,rect|
278                 view.bounds=if(gridOn,
279                         { rect.moveToPoint(rect.origin.round(gridStep)) },
280                         { rect })
281         }
284         viewContainingPoint { |point|
285 //              this.debug(views);
286                 views.do({ |view|
287                         if(view.bounds.containsPoint(point),
288                                 { ^view })
289                 })
290                 ^nil
291         }
293         asCompileString {
294                 var str = "";
295                 views.do({ |v| str = str ++ format("%.new(w,%);\n",v.class,v.bounds) });
296                 ^format( "(\nvar w = SCWindow.new(\"\",%).front;\n%\n)",window.bounds,str )
297         }
301 SCIBToolboxWindow
303         classvar shared;
304         var <window,viewPallatte,panels,selectedPanel, <gridStep=20, gridOn=false;
306         *front{
307                 if(shared.isNil){
308                         shared = SCIBToolboxWindow.new;
309                 }{
310                         shared.window.front;
311                 };
312                 ^shared
313         }
315         *new { ^super.new.init }
317         addWindow{|win|
318                 var panel;
319                 panel = SCIBPanelWindow.new(win).parent_(this);
320                 win.bounds = win.bounds.moveTo(window.bounds.left+window.bounds.width,window.bounds.height);
321 //              win.view.children.do{|it| it.enabled_(false)};
322                 panels = panels.add(panel);
323                 this.debug(this.gridStep);
324                 panel.gridOn_(gridOn).gridStep_(this.gridStep);
325         }
327         removeWindow{|win|
328                 var panel = SCIBPanelWindow.new(win).parent_(this), indx;
329                 win.view.children.copy.do{|it|
330                         it.enabled_(true);
331                         if(it.isKindOf(SCConstructionView)){it.remove;}
332                 };
333                 indx = this.findPanelIndexForWindow(win);
334                 if(indx.notNil){
335                         panels.removeAt(indx);
336                 }
337         }
339         findPanelIndexForWindow{|win|
340                 panels.do{|it,i|
341                         if(it.window == win){^i}
342                 };
343                 ^nil
344         }
346         enableGridWithSize{|flag, gridsize|
347                 gridOn = flag;
348                 gridStep = gridsize;
349                 panels.do({ |panel|
350                         panel.gridOn_(gridOn).gridStep_(gridStep);
351                 })
352         }
354         init
355         {
356                 var vh = 24, vw = 260,gridNB,gridBut;
358                 var height = 20 + 4 * (vh + 2) +2, os=0;
359                 var vw2 = div(vw,2);
361                 var funcButCol = Color.blue;
363                 window = SCWindow("IB",Rect(50,800,vw+8,height)).front
364                                         .onClose_({shared=nil});
365                 window.view.decorator = FlowLayout(window.view.bounds);
367                 panels = Array.new;
369                 SCButton(window,Rect(2,os,vw,vh)).states_([["New Window",nil,funcButCol]])
370                         .canFocus_(false).action = {
371                                 this.addWindow(SCWindow("pane",Rect(100,100,400,400)).front)
372                         };
374                 SCButton(window,Rect(2,os,vw,vh)).states_([ ["-> Code",nil,funcButCol]])
375                         .canFocus_(false).action_{ if ( selectedPanel.notNil,
376                                 {
377                                 Document("window construction code", selectedPanel.asSCIBCompileString);
378                         } )
379                         };
381                 SCButton(window,Rect(2,os,vw,vh)).states_([ ["Toggle Edit",nil,funcButCol]])
382                         .canFocus_(false).action = {
383                                 selectedPanel.window.toggleEditMode;
384                         };
386                 gridBut = SCButton(window,Rect(2,os,vw2-8,vh))
387                         .canFocus_(false).action_{ |v|
388                                 gridNB.visible = v.value == 1;
389                                 this.enableGridWithSize(v.value == 1, gridNB.value);
391                         }
392                         .states_([["Q On",nil,funcButCol],["Q Off",nil,funcButCol]]);
394                 gridNB = SCNumberBox(window,Rect(2+vw2,os,vw2,vh))
395                         .action_{ |v|
396                                 v.value = v.value.asInt.clip(3,40);
397                                 panels.do({ |panel| panel.gridStep = v.value })
398                         }
399                         .align_(\center).value_(10).visible_(false);
401                 viewPallatte = SCIBViewPallatte(window,Rect(2, 2, vw, (height - window.view.decorator.top)));
403         }
405         panelSelect { |panel|
406                 if( panel !== selectedPanel,{
407                         if(selectedPanel.notNil,{ selectedPanel.deselect });
408                         selectedPanel = panel
409                 })
410         }
413 SCIBViewPallatte
415 //      classvar <viewList;
416         var showExamples = false;
418         *new { |window,rect,parent|
419                 ^super.new.init(window,rect,parent)
420         }
422         init { |window,rect,parent|
423                 var x = rect.top, y = rect.left;
424                 var bW = rect.width, bH = rect.height, list, scroll;
425                 bH.postln;
426                 list = SCView.allSubclasses.reject{|it|
427                         (it.superclasses.indexOf(SCContainerView).notNil
428                         or: (it.name === 'SCContainerView')
429                         or: (it.name ==='SCStaticTextBase')
430                         or: (it.name === 'SCSliderBase')
431                         or: (it.name === 'SCControlView')
432                         or: (it.name === 'SCDragView'))
433                 };
434                 scroll = SCScrollView(window, Rect(0,0,bW-2, bH-34))
435                                         .resize_(5);
436                 scroll.decorator = FlowLayout(scroll.bounds.moveTo(0,0));
437                 list.do({ |class,i|
438                         var drag = SCIBPallatteDrag(class,Rect(0,0,100,20));
439                         SCDragSource(scroll,((bW*0.5)-12)@24)
440                                 .string_(class.asString).align_(\center).object_(drag);
441                         if(showExamples){
442                                 try{
443                                         class.paletteExample(scroll, Rect(0,0,(bW*0.5)-12,24));
444                                 }{
445                                         "no paletteExample found".warn;
446                                 };
447                                 scroll.decorator.nextLine;
448                         };
450                 })
451         }
453         //*initClass {
454 //              viewList = [
455 //                      SCButton,
456 //                      SCStaticText,
457 //                      SCNumberBox,
458 //                      SCSlider,
459 //                      SCRangeSlider,
460 //                      SCMultiSliderView,
461 //                      SCPopUpMenu,
462 //                      SC2DTabletSlider,
463 //                      SC2DSlider,
464 //                      SCTabletView,
465 //                      SCEnvelopeView,
466 //                      SCDragBoth,
467 //                      SCDragSink,
468 //                      SCDragSource,
469 //                      Knob,
470 //                      SCTextView,
471 //                      //SCMovieView
472 //              ];
473 //      }
476 SCIBAreaSelection
478         var click,round,<rect;
480         *new { |p,r| r !? { p = round(p,r) };
481                 ^super.newCopyArgs(p,r).mouseDrag(p)
482         }
484         mouseDrag { |drag|
485                 round !? { drag = round(drag,round) };
486                 rect = Rect.fromPoints(click,drag)
487         }
489         selects { |aRect|
490                 ^rect.intersects(aRect)
491         }
495 SCIBDrag { }
497 SCIBMultipleDrag : SCIBDrag
499         var classes,rects,minX, minY;
501         *new { |classes, rects|
502                 ^super.newCopyArgs( classes, rects ).init
503         }
505         init {
506                 minX = inf;
507                 minY = inf;
508                 rects.do({ |r|
509                         if ( r.left < minX, { minX = r.left });
510                         if ( r.top < minY, { minY = r.top })
511                 });
512                 minX = minX.neg;
513                 minY = minY.neg;
514         }
516         do { |func|
517                 classes.do({ |class,i|
518                         func.( class, rects[ i ].moveBy( minX, minY ), i )
519                 })
520         }
523 SCIBPallatteDrag : SCIBDrag
525         var class, rect;
527         *new { |class, rect|
528                 ^super.newCopyArgs( class, rect )
529         }
531         do { |func| func.(class,rect,0) }
533         asString { ^class.asString }