Chapter 14. The border layout manager


Creating a border with an optional title
Setting the border title

The border layout manager draws a border around a display element. The grid layout manager handles containers with many elements, and also has the means to draw borders around them. The grid layout manager has many options and settings, while the border layout manager is dedicated and optimized for this specific task, and is faster than the grid layout manager for this specific use case. The LibCXX Windows Library uses the border layout manager to draw buttons and keyboard input focus borders.

The border layout manager has an option of adding a title to the border. This visual frames related display elements, and gives them a title.

** Copyright 2017 Double Precision, Inc.
** See COPYING for distribution information.

#include "config.h"
#include <x/mpobj.H>
#include <x/exception.H>
#include <x/destroy_callback.H>
#include <x/ref.H>
#include <x/obj.H>
#include <x/w/main_window.H>
#include <x/w/gridlayoutmanager.H>
#include <x/w/gridfactory.H>
#include <x/w/borderlayoutmanager.H>
#include <x/w/label.H>

#include <string>
#include <iostream>
#include <sstream>
#include <utility>

#include "close_flag.H"

static void create_main_window(const x::w::main_window &mw)
	x::w::gridlayoutmanager glm=mw->get_layoutmanager();

	// Two sample containers with the border layout manager. One of them
	// will have a title.
	// Even though the rest of the two containers are identical, the
	// title results in that one being slightly taller. For better
	// visual appearance, align all elements in row 0 at the bottom.
	glm->row_alignment(0, x::w::valign::bottom);

	x::w::gridfactory f=glm->append_row();

	x::w::new_borderlayoutmanager nblm
		 (const x::w::factory &f)
			 f->create_label("Border layout manager");

	// We're just creating a simple label inside each border. Usually
	// an entire container gets created inside the border, but we just
	// have a label. Change the default padding between the border and
	// its element to 10 millimeters. This makes the container bigger,
	// for demo purposes.

	f->create_container([](const auto &){}, nblm);

	// Create the 2nd one with the title. We can use the same
	// new_borderlayoutmanager, just set the title.


	f->create_container([](const auto &){}, nblm);

void borderlayoutmanager()
	x::destroy_callback::base::guard guard;

	auto close_flag=close_flag_ref::create();

	auto main_window=x::w::main_window::create(create_main_window);




		  const auto &ignore)


	x::mpcobj<bool>::lock lock{close_flag->flag};

	// update_title() updates the existing border's title.

	const char *titles[2]={"Hello", "World"};

	while (!lock.wait_for(std::chrono::seconds(1), [&] { return *lock; }))
		std::swap(titles[0], titles[1]);

		// We want the container in row 0, column 1 of the main window's
		// grid.

		x::w::gridlayoutmanager glm=main_window->get_layoutmanager();

		x::w::container frame_with_border=glm->get(0, 1);

		// This container uses the border layout manager.
		x::w::borderlayoutmanager blm=

		// And update the border's title.

int main(int argc, char **argv)
	try {
	} catch (const x::exception &e)
	return 0;

Creating a border with an optional title

Passing an x::w::new_borderlayoutmanager to a factory's create_container() creates a container with a x::w::borderlayoutmanager.

x::w::new_borderlayoutmanager's constructor's parameter is a callable object or a lambda. The lambda receives one parameter, a factory. The callable object must use the factory to create exactly one display element:

x::w::new_borderlayoutmanager nblm{
    (const x::w::factory &f)
        x::w::new_gridlayoutmanager nglm;

                               (const x::w::container &c)
                                    // ...

This is the typical way to create a border. The lambda uses the factory to create a container that uses the grid layout manager, then proceeds to initialize the grid. The border layout manager draws a border around a display element, but this diplay element could be a container of other display elements.

After setting any needed options in the x::w::new_borderlayoutmanager, create_container() creates the container with the border layout manager:

x::w::container c=f->create_container([](const auto &){}, nblm);

create_container() takes the x::w::new_borderlayoutmanager and constructs a new container with the border layout manager, and calls the lambda to create the display element with the border. As always, create_container() invokes the creator lambda to initialize the contents of the new container. However x::w::new_borderlayoutmanager's lambda already did pretty much the entire job. In the case of the border layout manager the creator lambda is usually empty; or perhaps it show()'s the new container.