Automatically reflow UI elements when a View size is exceeded or resized

Hi All.

I’m looking to have UI elements (Buttons) inside a HLayout automatically wrap to the next line when their position exceeds the width of a View - either when the buttons are created or when the View / Window is resized.

In the past I’ve either used decorators with addFlowLayout or bounds coordinate positioning. However, I was hoping for a simpler way using the HLayouts / VLayouts. I’ve looked everywhere but can’t find an example showing this behaviour.

Any help would be greatly appreciated.

Thanks,
Christian

(
var win, cview, buts;

// Window
win = Window.new(bounds: Rect(100, 100, 800, 200));
win.front;

// Container
cview = View(parent: win, bounds: Rect(0, 0, 800, 200));
cview.resize = 5;

// Buttons
buts = { Button().fixedWidth_(80); } ! 10;

// Layouts
cview.layout = HLayout(
	*buts
);
cview.layout.margins = 5 ! 4;
cview.layout.spacing = 5;

)

AFAIK there is no method to do this but you can use .onResize to calculate the layout like this:

(
var win, cview, buts, calcLayout;

// Window
win = Window.new(bounds: Rect(100, 100, 800, 200));
win.front;

// Container
cview = View(parent: win, bounds: Rect(0, 0, 800, 200));
cview.resize = 5;

// Buttons
// nil ensures buttons are left aligned, remove nil if you want buttons to be centered
buts = { Button().fixedWidth_(80) } ! 10 ++ [nil]; 

calcLayout = { VLayout(*buts.clump((cview.bounds.width / 85).floor).collect{|n|HLayout(*n)}) };

// Layouts
cview.layout = calcLayout.();
cview.layout.margins = 5;
cview.layout.spacing = 5;
cview.onResize_{cview.layout = calcLayout.()}
)

Thanks for that Thor.

That’s a very nice solution and given me an excellent head start for what I need. Much appreciated!

1 Like