adamdruppe / arsd

This is a collection of modules that I've released over the years. Most of them stand alone, or have just one or two dependencies in here, so you don't have to download this whole repo.
http://arsd-official.dpldocs.info/arsd.html
531 stars 128 forks source link

How to use GridLayout? #391

Closed aferust closed 1 year ago

aferust commented 1 year ago

Hello, is there any minimal example showing how to use gridlayout. I am confused with its constructor and setChildPosition.

adamdruppe commented 1 year ago

Yeah, it is a kinda weird api because it is designed for a visual designer thing that I haven't actually made yet.

The idea is that you define a virtual grid in the constructor of some size, add children, then setChildPosition stores the positions separately in terms of the virtual grid. You can do new things inline though:

        auto window = new Window();
        auto grid = new GridLayout(12, 12, window);
        auto h = cast(TextLabel) grid.setChildPosition(new TextLabel("Header!", TextAlignment.Center | TextAlignment.VerticalCenter, grid), 0,
        0, 12, 1);
        grid.setChildPosition(new TextLabel("Footer!", TextAlignment.Center | TextAlignment.VerticalCenter, grid), 0, 11, 12, 1);

        auto leftBar = new VerticalLayout(grid);
        grid.setChildPosition(leftBar, 0, 1, 2, 10);

        auto rightBar = new VerticalLayout(grid);
        grid.setChildPosition(rightBar, 10, 1, 2, 10);

        auto mainArea = grid.setChildPosition(new VerticalLayout(grid), 2, 1, 8, 10);

      // add stuff to mainArea, leftBar, and rightBar here

So the grid here divides the window into 12x12 evenly spaced boxes.

Then the first wild line is:

 auto h = cast(TextLabel) grid.setChildPosition(new TextLabel("Header!", TextAlignment.Center | TextAlignment.VerticalCenter, grid), 0, 0, 12, 1);

Which combines creating a text label and setting its position. You could also write it out:

 auto h = new TextLabel("Header!", TextAlignment.Center | TextAlignment.VerticalCenter, grid);

grid.setChildPosition(h, 0, 0, 12, 1);

Notice that you create the widget with the grid as a parent, then tell it where you want it in numbers. (In the combined one, I cast the return value back to the original type since that knowledge gets lost through the function call. I plan on fixing this api to be easier to use in a later version.)

The position here is x, y (0, 0) and then width of 12 blocks and height of 1 block. So it is in the upper left of the window and spans the whole width, then gets 1/12th (since the constructor defined it as a 12x12 grid) of the height.

The next line is very similar setting up a footer. The big difference is its position is (0, 11), 11 being the maximum y position for a thing with height 1 (y = 11 + height = 1 adds to 12, the height of the grid) meaning it is pinned to the bottom of the window.

leftBar and rightBar are a bit wider - width of 2 - but otherwise pin to the left and right side of the window by using x = 0 (left side) and x = 10 (10 + width of 2 = 12). These widgets are normal vertical layouts which you can add things to and have it stack them automatically, like in a default window.

Finally, the rest of the space goes to a mainArea, just positioning it so it doesn't overlap anything else. You have to do all the numbers yourself (again the idea was I'd make a gui layout tool that generates this code separately but i never did you you have to do it yourself). Then you can add stuff to that mainArea widget as children to be positioned inside.

Each setChildPosition call can also take a gravity argument which defines where to put an inner child widget that couldn't take the full space available. For example, it does the math and finds 1/12 of the space is 100 pixels, but the child in that postiion has maxWidth of 80. With Gravity.Center, it will center it in that block, leaving empty space around it. Gravity.North will put it at the top of the block, leaving empty space below, etc.

Note that the current GridLayout is underpowered compared to things like CSS and Qt, since it doesn't allow things to reflow if the window is too small. Again, I want to fix this in a later version but haven't had time to really get into it yet.

....I should probably copy/paste this into the docs.

aferust commented 1 year ago

Thank you, Adam. A simple designer would help a lot. I know it is not easy to write one.