GUI layout help

hi

I am wondering if there is a way to create a GUI layout like the one in the mockup
Pantaila-argazkia_2022-07-26_13-07-45
attached.

So far I am just using a FlowLayout, just dumpling all the widgets there and using w.view.decorator.nextLine; to create new rows. But I want to have in some cases two buttons one on top each other in between other widgets (see mockup, it will be easier to understand, it is marked in red).

I thought I could use a VLayout or GridLayout but I dont see how to get what I want. I tried to use GridLayout which allows some widgets to span across several cells in the grid but I get very weird results with buttons resizing themselves in strange ways. Is there any in depth tutorial of GUI creation in Supercollider? I could not find any…

Note that set of widgets is controlling a sample, potentially the window will contain up to a dozen of sets of widgets. I hope I made myself clear.

thanks

enrike

FlowLayout is over, don’t bother with it.

With Qt layouts, you put layouts within layouts to define relationships.

HLayout(
    DragSink(),  // or whatever it is
    // the entire VLayout becomes one entry in the row
    VLayout(
        button1 = Button(),  // maybe set a fixedSize
        button2 = Button()
    ),
    slider1 = Slider().orientation_(\vertical),
    slider2 = Slider().orientation_(\vertical),
    ... and repeat the pattern
)

hjh

ok. I see… but how do I control the space between the widgets? I cannot see a way to “compress” all the widgets to use as little space as possible. For eg:


(
w = Window().front;
w.layout = HLayout(	
	Button().states_([
		["blah", Color.white, Color.black],
		["blah", Color.black, Color.red]
	])
	.fixedSize_(100@100),  
	// the entire VLayout becomes one entry in the row
	VLayout(
		Button().states_([
			[">", Color.green, Color.black],
			["<", Color.red, Color.black]
		]).fixedSize_(20@40),  
		Button().states_([
			["-", Color.green, Color.black],
			["o", Color.red, Color.black]
		]).fixedSize_(20@40),
	),
	Slider().orientation_(\vertical).fixedSize_(15@100),
	Slider().orientation_(\vertical).fixedSize_(15@100),	
)
)

thanks

Not sure where it is documented but layouts have two properties to control that:
margins and spacing
e.g.

VLayout(...).margins_(0).spacing_(0)

You can insert “nil” into a layout to work like a qt spacer, e.g.

(
var win, lay = (), layout;
win = Window.new("test");

lay[\1] = HLayout(Button(), Button());
lay[\2] = HLayout(Button(), nil, Button());
lay[\3] = HLayout(Button(), Button(), nil);
layout = VLayout(lay[\1], lay[\2], lay[\3]);
win.layout_(layout);
win.front;
)

margins_(10).spacing_(0) make no difference as far as I can see

(
w = Window().front;
w.layout = HLayout(	
	Button().states_([
		["blah", Color.white, Color.black],
		["blah", Color.black, Color.red]
	])
	.fixedSize_(100@100),  // or whatever it is
	// the entire VLayout becomes one entry in the row
	VLayout(
		Button().states_([// maybe set a fixedSize
			[">", Color.green, Color.black],
			["<", Color.red, Color.black]
		]).fixedSize_(20@40),  
		Button().states_([
			["-", Color.green, Color.black],
			["o", Color.red, Color.black]
		]).fixedSize_(20@40),
	).margins_(10).spacing_(0),
	Slider().orientation_(\vertical).fixedSize_(15@100),
	Slider().orientation_(\vertical).fixedSize_(15@100),	
).margins_(0).spacing_(0)
)

mmm… I think I am going to go back to my stone-age style GUI with al widgets the same height stacked one after another into a flowlayout. It is too much headache for such a detail.

Not sure about the interaction between a Window and Layout but using a View instead of a Window as the parent I think gets what you’re going after…nevertheless this is how I would go about it…

(
var view = View().layout_(HLayout(	
	Button().states_([
		["blah", Color.white, Color.black],
		["blah", Color.black, Color.red]
	])
	.fixedSize_(100@100),  // or whatever it is
	// the entire VLayout becomes one entry in the row
	VLayout(
		Button().states_([// maybe set a fixedSize
			[">", Color.green, Color.black],
			["<", Color.red, Color.black]
		]).fixedSize_(20@40),  
		Button().states_([
			["-", Color.green, Color.black],
			["o", Color.red, Color.black]
		]).fixedSize_(20@40),
	).margins_(3).spacing_(0),
	Slider().orientation_(\vertical).fixedSize_(15@100),
	Slider().orientation_(\vertical).fixedSize_(15@100),
).margins_(0).spacing_(0)
);
view.front
)

yes it does!! now I have to find out the right way to integrate this in my code.

thanks!

For completeness, something similar with “nil” instead of fixed size (but nothing wrong with the other solution!)

(
var view = View().layout_(HLayout(	
	nil,
	Button().states_([
		["blah", Color.white, Color.black],
		["blah", Color.black, Color.red]
	]), 
	nil,
	// the entire VLayout becomes one entry in the row
	VLayout(
		nil,
		Button().states_([// maybe set a fixedSize
			[">", Color.green, Color.black],
			["<", Color.red, Color.black]
		]),
		Button().states_([
			["-", Color.green, Color.black],
			["o", Color.red, Color.black]
		]),
		nil
	),
	nil,
	Slider().orientation_(\vertical),
	nil,
	Slider().orientation_(\vertical),
	nil
)
);
view.front
)

or if you don’t like the sliders resizing

(
var view = View().layout_(HLayout(	
	nil,
	Button().states_([
		["blah", Color.white, Color.black],
		["blah", Color.black, Color.red]
	]), 
	nil,
	// the entire VLayout becomes one entry in the row
	VLayout(
		nil,
		Button().states_([// maybe set a fixedSize
			[">", Color.green, Color.black],
			["<", Color.red, Color.black]
		]),
		Button().states_([
			["-", Color.green, Color.black],
			["o", Color.red, Color.black]
		]),
		nil
	),
	nil,
	VLayout(nil, Slider().orientation_(\vertical), nil),
	nil,
	VLayout(nil, Slider().orientation_(\vertical), nil),
	nil
)
);
view.front
)

or perhaps you want to keep the blah button close to the arrows:

(
var view = View().layout_(HLayout(	
	nil,
	Button().states_([
		["blah", Color.white, Color.black],
		["blah", Color.black, Color.red]
	]), 
	// the entire VLayout becomes one entry in the row
	VLayout(
		nil,
		Button().states_([// maybe set a fixedSize
			[">", Color.green, Color.black],
			["<", Color.red, Color.black]
		]),
		Button().states_([
			["-", Color.green, Color.black],
			["o", Color.red, Color.black]
		]),
		nil
	),
	nil,
	VLayout(nil, Slider().orientation_(\vertical), nil),
	nil,
	VLayout(nil, Slider().orientation_(\vertical), nil),
	nil
)
);
view.front;
)

anyway…you get the idea :slight_smile:

Hello there,

Fixing a View’s size inside a Layout seems to force the whole layout to have a fixed sized too… I think this should be avoided inside a Layout.

Furthermore, Buttons have a low maxWidth and maxHeight which renders horribly when resizing the views.

Here, I fixed those two problems, and now, you can use margins and spacing to adjust your interface :

(
w = Window().front;
w.layout = HLayout(	
	
	Button().states_([
		["blah", Color.white, Color.black],
		["blah", Color.black, Color.red]
	]).maxWidth_(9999).maxHeight_(9999),
	
	VLayout(
		Button().states_([// maybe set a fixedSize
			[">", Color.green, Color.black],
			["<", Color.red, Color.black]
		]).maxWidth_(9999).maxHeight_(9999),
		Button().states_([
			["-", Color.green, Color.black],
			["o", Color.red, Color.black]
		]).maxWidth_(9999).maxHeight_(9999)
	).margins_(0).spacing_(5),
	
	Slider().orientation_(\vertical),
	
	Slider().orientation_(\vertical)
	
).margins_(10).spacing_(5)
)