Layout Managers

Usually, CSS is a sufficient and convenient way to indicate how to layout widgets within a container widget, and we recommend to get familiarized with CSS for basic layout and styling.

There are however several situations when CSS is not effective to create a layout, especially for complex web applications. In particular, when placing contents within a dialog it is often necessary to adjust its contents to available vertical space, and it is often desirable to distribute excess space to a particular widget while keeping other widgets to their preferred size. It is for these reasons that Wt has a comprehensive set of layout managers that use JavaScript to compute and apply layout management to children of a WContainerWidget.

Wt provides the typical box, grid or border layout management options and layout managers and CSS can safely be intermixed.

Box Layout

WVBoxLayout and WHBoxLayout provide respectively vertical and horizontal layout of widgets inside a WContainerWidget.

In a horizontal box layout, widgets are given an appropriate width based on available space in the container and layout rules, while all widgets get the same height. Similarly, in a vertical box layout, widgets are given appropriate heights based on available space in the container and layout rules, while all widgets get the same width.

In the example below, a WHBoxLayout with default padding (9 pixels) and spacing (6 pixels) is used to manage two child widgets. If no stretch factors have been specified, space is evenly distributed to all widgets.

Example
Item 1Item 2
source
#include <Wt/WContainerWidget.h>
#include <Wt/WHBoxLayout.h>
#include <Wt/WText.h>


auto container = std::make_unique<Wt::WContainerWidget>();
container->setStyleClass("yellow-box");

auto hbox = container->setLayout(std::make_unique<Wt::WHBoxLayout>());

std::unique_ptr<Wt::WText> item = std::make_unique<Wt::WText>("Item 1");
item->setStyleClass("green-box");
hbox->addWidget(std::move(item));

item = std::make_unique<Wt::WText>("Item 2");
item->setStyleClass("blue-box");
hbox->addWidget(std::move(item));

The coloring for this and the following examples are provided by a stylesheet that you need to load using WApplication::useStyleSheet():

CSS
.yellow-box {
    background-color: #ffffb4;
    border: 1px solid black;
    margin-top: 1ex;
    margin-bottom: 1ex;
}

.green-box {
    background-color: #c4ffb4;
    min-height: 30px;
    text-align: center;
    padding: 3px;
}

.blue-box {
    background-color: #65dae8;
    min-height: 30px;
    text-align: center;
    padding: 3px;
}

By giving Item 1 a non-zero stretch factor value of 1, Item 2 will only use its preferred width, and Item 1 consumes all excess space, as illustrated below.

Example
Item 1Item 2
source
#include <Wt/WContainerWidget.h>
#include <Wt/WHBoxLayout.h>
#include <Wt/WText.h>
#include <memory>


auto container = std::make_unique<Wt::WContainerWidget>();
container->setStyleClass("yellow-box");

auto hbox = container->setLayout(std::make_unique<Wt::WHBoxLayout>());

auto item = std::make_unique<Wt::WText>("Item 1");
item->setStyleClass("green-box");
hbox->addWidget(std::move(item), 1);

item = std::make_unique<Wt::WText>("Item 2");
item->setStyleClass("blue-box");
hbox->addWidget(std::move(item));

The preferred width of a widget is either based on its contents (which for text is the in some cases impractical assumption of putting all text on a single line), but can be further controlled using widget->setWidth() or CSS width settings.

The WVBoxLayout works in exactly the same way, but stacks children vertically.

Example
Item 1Item 2
source
#include <Wt/WContainerWidget.h>
#include <Wt/WText.h>
#include <Wt/WVBoxLayout.h>

auto container = std::make_unique<Wt::WContainerWidget>();
container->resize(150, 150);
container->setStyleClass("yellow-box centered");

auto vbox = container->setLayout(std::make_unique<Wt::WVBoxLayout>());

auto item = std::make_unique<Wt::WText>("Item 1");
item->setStyleClass("green-box");
vbox->addWidget(std::move(item));

item = std::make_unique<Wt::WText>("Item 2");
item->setStyleClass("blue-box");
vbox->addWidget(std::move(item));
Example
Item 1Item 2
source
#include <Wt/WContainerWidget.h>
#include <Wt/WText.h>
#include <Wt/WVBoxLayout.h>

auto container = std::make_unique<Wt::WContainerWidget>();
container->resize(150, 150);
container->setStyleClass("yellow-box centered");

auto vbox = container->setLayout(std::make_unique<Wt::WVBoxLayout>());

auto item = std::make_unique<Wt::WText>("Item 1");
item->setStyleClass("green-box");
vbox->addWidget(std::move(item), 1);

item = std::make_unique<Wt::WText>("Item 2");
item->setStyleClass("blue-box");
vbox->addWidget(std::move(item));

Layout managers may be arbitrarily nested, either directly, or indirectly through widget composition, to create complex layouts. Layout managers fully cooperate with CSS, honoring the CSS margins and paddings of children, but also those of intermediate widgets in complex layouts.

In the example below we nest a WHBoxLayout containing two items in a WVBoxLayout containing one other item.

Example
Item 1
Item 2Item 3
source
#include <Wt/WContainerWidget.h>
#include <Wt/WHBoxLayout.h>
#include <Wt/WText.h>
#include <Wt/WVBoxLayout.h>

auto container = std::make_unique<Wt::WContainerWidget>();
container->resize(200, 200);
container->setStyleClass("yellow-box centered");

auto vbox = container->setLayout(std::make_unique<Wt::WVBoxLayout>());

auto item = std::make_unique<Wt::WText>("Item 1");
item->setStyleClass("green-box");
vbox->addWidget(std::move(item), 1);

auto hbox = vbox->addLayout(std::make_unique<Wt::WHBoxLayout>());

item = std::make_unique<Wt::WText>("Item 2");
item->setStyleClass("green-box");
hbox->addWidget(std::move(item));

item = std::make_unique<Wt::WText>("Item 3");
item->setStyleClass("blue-box");
hbox->addWidget(std::move(item));

Top

Grid Layout

This layout manager organizes the contents of a WContainerWidget in a grid.

Like WBoxLayout, a stretch factor defined for rows or columns is used to distribute excess space. In the example below, row 1 and columns 1 and 2 are given a non-zero stretch factor.

Example
Item (0, 0)
Item (0, 1)
Item (0, 2)
Item (0, 3)
Item (1, 0)
Item (1, 1)
Item (1, 2)
Item (1, 3)
Item (2, 0)
Item (2, 1)
Item (2, 2)
Item (2, 3)
source
#include <Wt/WContainerWidget.h>
#include <Wt/WGridLayout.h>
#include <Wt/WText.h>


auto container = std::make_unique<Wt::WContainerWidget>();
container->setHeight(400);
container->setStyleClass("yellow-box");

auto grid = container->setLayout(std::make_unique<Wt::WGridLayout>());

for (int row = 0; row < 3; ++row) {
    for (int column = 0; column < 4; ++column) {
        Wt::WString cell = Wt::WString("Item ({1}, {2})").arg(row).arg(column);

        auto text = std::make_unique<Wt::WText>(cell);
        if (row == 1 || column == 1 || column == 2)
            text->setStyleClass("blue-box");
        else
            text->setStyleClass("green-box");

        grid->addWidget(std::move(text), row, column);
    }
}

grid->setRowStretch(1, 1);
grid->setColumnStretch(1, 1);
grid->setColumnStretch(2, 1);

Top

Border Layout

This is a layout manager that organizes the container space in up to 5 regions, with a central region consuming any excess space.

Any of the regions can be omitted.

Example
North item
West item
Center item
East item
South item
source
#include <Wt/WContainerWidget.h>
#include <Wt/WBorderLayout.h>
#include <Wt/WText.h>


auto container = std::make_unique<Wt::WContainerWidget>();
container->setHeight(400);
container->setStyleClass("yellow-box");

auto layout = container->setLayout(std::make_unique<Wt::WBorderLayout>());

const char *cell = "{1} item";

auto item = std::make_unique<Wt::WText>(Wt::WString(cell).arg("North"));
item->setStyleClass("green-box");
layout->addWidget(std::move(item), Wt::LayoutPosition::North);

item = std::make_unique<Wt::WText>(Wt::WString(cell).arg("West"));
item->setStyleClass("green-box");
layout->addWidget(std::move(item), Wt::LayoutPosition::West);

item = std::make_unique<Wt::WText>(Wt::WString(cell).arg("East"));
item->setStyleClass("green-box");
layout->addWidget(std::move(item), Wt::LayoutPosition::East);

item = std::make_unique<Wt::WText>(Wt::WString(cell).arg("South"));
item->setStyleClass("green-box");
layout->addWidget(std::move(item), Wt::LayoutPosition::South);

item = std::make_unique<Wt::WText>(Wt::WString(cell).arg("Center"));
item->setStyleClass("green-box");
layout->addWidget(std::move(item), Wt::LayoutPosition::Center);

Top