SCCompositeView


A view that contains other views.




grouping by background color

(

w = SCWindow.new;


c = SCCompositeView(w,Rect(0,0,300,300));


a = SC2DSlider(c,Rect(0,0,100,100));

b = SC2DSlider(c,Rect(100,100,100,100));


c.background = Gradient(Color.rand,Color.rand);


w.front;

)


By default, coordinates are relative to (0, 0) in the window. That might not be immediately intuitive, but historically it's the way the CompositeView has always worked in SuperCollider. See the discussion of the relativeOrigin flag, immediately following, if you want to position child views relative to the CompositeView's origin.


(

w = SCWindow.new;


c = SCCompositeView(w,Rect(50,0,300,300));  // .relativeOrigin_(false), i.e. default


a = SC2DSlider(c,Rect(50,0,100,100));

b = SC2DSlider(c,Rect(150,100,100,100));


c.background = Gradient(Color.rand,Color.rand);


w.front;

)


c.bounds_(Rect(100,0,100,200));

c.resize_(5);


relativeOrigin_

If this flag is set to true, views are placed relative to the upper left corner of the CompositeView.


(

w = SCWindow.new;


c = SCCompositeView(w,Rect(50,0,300,300)).relativeOrigin_(true);

a = SC2DSlider(c,Rect(0,0,100,100)); // actually displays at (50, 0)

b = SC2DSlider(c,Rect(100,100,100,100));


c.background = Gradient(Color.rand,Color.rand);


w.front;

)


Note: if you place a CompositeView with absolute coordinates (relativeOrigin = false) inside another CompositeView using relative coordinates (relativeOrigin = true), the child CompositeView's absolute coordinates override the relative position indicated by the parent. This is easily handled if you're specifying the coordinates yourself, but if you're using a decorator (see below), the child will display in the wrong place. When using a decorator on a relative origin CompositeView, you should not place absolute origin CompositeViews inside it.


keydown bubbling


Note that the keyDown action is assigned to the CompositeView. If c and d do not have keyDown actions themselves, the event is passed to b, the parent.

(

w = SCWindow.new;


c = SCCompositeView(w,Rect(0,0,500,500));

c.background = Color.yellow(alpha: 0.3);


a = SC2DSlider(c,Rect(0,0,100,100));

b = SC2DSlider(c,Rect(100,100,100,100));


w.front;


c.keyDownAction = {

"keydown bubbled up to c".postln;

};


//d is on window w,  not on composite view c

d = SC2DSlider(w,Rect(200,200,100,100));

d.background = Color.black;

)

click on the different views and hit keys on the keyboard.




decorators

a 'decorator' object can be set to handle layout management.  all views added to the CompositeView will now be placed by the decorator.


(

a = SCWindow.new;


b = SCCompositeView(a,Rect(0,0,500,500)).relativeOrigin_(false);

b.decorator = FlowLayout(b.bounds);


// adding views to b automatically use the decorator

// no need to use parent.decorator.place

c = SC2DSlider(b,Rect(0,0,100,100)); // size matters

d = SC2DSlider(b,Rect(0,0,100,100)); // origin doesn't


a.front;

)


If you set the CompositeView's relativeOrigin to true, the bounds that you give to the FlowLayout should originate at (0,0). In this case, be careful not to put absolute origin CompositeViews inside a relative origin CompositeView that has a decorator.


(

a = SCWindow.new;


b = SCCompositeView(a,Rect(0,0,500,500)).relativeOrigin_(true);

b.decorator = FlowLayout(Rect(0, 0, 500, 500));


c = SC2DSlider(b,Rect(0,0,100,100)); // size matters

d = SC2DSlider(b,Rect(0,0,100,100)); // origin doesn't


a.front;

)




hiding / swapping

(

var colors = [Color.blue,Color.red, Color.green];

a = SCWindow.new;

q = 3;


e = SCButton(a,Rect(0,0,160,20));


e.states = Array.fill(q,{ arg i;

[i.asString,Color.white,colors.wrapAt(i)]

});


e.action = { arg butt;

p.visible = false;

p = c.at(butt.value);

p.visible = true;

};


c = Array.fill(q,{ arg i;

b = SCCompositeView(a,Rect(0,25,300,300));

b.decorator = FlowLayout(b.bounds);

c = SC2DSlider(b,Rect(0,0,100,100))

.background_(colors.wrapAt(i));

c.x = 1.0.rand;

d = SC2DSlider(b,Rect(0,0,100,100))

.background_(colors.wrapAt(i));

d.y = 1.0.rand;

b.visible = false;

b

});


p = c.at(0); // previous

p.visible = true; // show first one


a.front;


)


removing

(

w = SCWindow.new;

c = SCCompositeView(w,Rect(0,0,300,300));

a = SC2DSlider(c,Rect(0,0,100,100));

b = SC2DSlider(c,Rect(100,100,100,100));

c.background = Gradient(Color.rand,Color.rand);

w.front;

)



a.remove;

c.refresh;



resize contraints


resize behaviour is specified by an integer:

1  2  3

4  5  6

7  8  9

1 - fixed to left, fixed to top

2 - horizontally elastic, fixed to top

3 - fixed to right, fixed to top

4 - fixed to left, vertically elastic

5 - horizontally elastic, vertically elastic

6 - fixed to right, vertically elastic

7 - fixed to left, fixed to bottom

8 - horizontally elastic, fixed to bottom

9 - fixed to right, fixed to bottom


// resize behaviours

(

var a;

a =  { |i|

var w, b, x;

i = i + 1;

w = SCWindow("resize:"+i, Rect(10 + (i * 110), 300, 100, 80));

b = w.view.bounds;

x = SCCompositeView(w, w.view.bounds)

.background_(Color.rand)

.resize_(i);

x.decorator = FlowLayout(x.bounds).gap_(0.0 @ 0.0);


{

var t;

t = SCStaticText(x, Rect(0, 0, 40, 40))

.background_(Color.rand)

.resize_(i)

.string_(i)

.font_(Font("Helvetica", 26));

}.dup;

w.front;

w.onClose = { a.do(_.close) };



} ! 9;

)





(

w = SCWindow.new;


c = SCCompositeView(w,Rect(0,0,300,300));

c.background = Gradient(Color.rand,Color.rand);


c.resize = 5; // elastic


a = SC2DSlider(c,Rect(0,0,100,100));

a.resize = 1; // fixed


b = SC2DSlider(c,Rect(100,100,100,100));

b.resize = 2; // x elastic

b.setProperty(\minWidth,30); // up to a point

b.setProperty(\maxWidth,200);

w.front;


)

(bug: composite view should get limited by it's contents' limitations)

(other bug: SC2DSlider should not draw its right edge to the left of its left edge)