Chapter 4. Word-wrapping labels

Index

Preserving window positions
Hello World!

This example follows up on the hello world program. It uses a create_label() overload to create a label that word-wraps its text to the given width. A word-wrapping label gets created by setting x::w::label_config's widthmm value.

See the section called “Building example programs” for more information on building this example:

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

#include "config.h"
#include "close_flag.H"

#include <x/exception.H>
#include <x/destroy_callback.H>
#include <x/config.H>

#include <x/w/main_window.H>
#include <x/w/screen_positions.H>
#include <x/w/gridlayoutmanager.H>
#include <x/w/gridfactory.H>
#include <x/w/label.H>
#include <x/w/text_param_literals.H>
#include <x/w/font_literals.H>
#include <string>
#include <iostream>

// This is the creator lambda, that gets passed to create_mainwindow() below,
// factored out for readability.

void create_mainwindow(const x::w::main_window &main_window)
{
	x::w::rgb light_yellow{
		x::w::rgb::maximum,
		x::w::rgb::maximum,
		(x::w::rgb_component_t)(x::w::rgb::maximum * .75)},

		blue{0, 0, x::w::rgb::maximum},

		black{};

	main_window->set_background_color(light_yellow);

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

	x::w::gridfactory factory=layout->append_row();

	x::w::label_config config;

	config.widthmm=100.0; // Initial text width is 100 millimeters

	// Optional parameter, alignment:
	config.alignment=x::w::halign::center;

	factory->create_label({
		 blue,
		"underline"_decoration,
		"serif; point_size=24; weight=bold"_font,

	        "Lorem ipsum\n",

		"no"_decoration,
		"sans serif; point_size=12"_font,
		black,

		"dolor sit amet, consectetur adipisicing elit, "
		"sed do eiusmod tempor incididunt ut labore et dolore mana "
		"aliqua. Ut enim ad minim veniam, quis nostrud exercitation "
		"ullamco laboris nisi ut aliquip ex ea commodo consequat. "
		"Duis aute irure dolor in reprehenderit in voluptate velit "
		"esse cillum dolore eu fugiat nulla pariatur. "
		"Excepteur sint occaecat cupidatat non proident, "
		"sunt in culpa qui officia deserunt mollit anim id est "
		"laborum."
	  }, config);
}

void wordwrap()
{
	x::destroy_callback::base::guard guard;

	auto close_flag=close_flag_ref::create();

	// Configuration filename where we save the window's position.

	std::string configfile=
		x::configdir("wordwraplabel@examples.w.libcxx.com")
		+ "/windows";

	// Load the saved window position.
	//
	// x::w::screen_positions captures the position and size of
	// main_windows. If the configuration file exists, the previously
	// captured positions and sizes of main_windows get loaded. Nothing
	// happens if the file does not exist.
	x::w::screen_positions pos{configfile};

	// It's possible to capture more than one main_window's position and
	// size, and save it. Each main_window must have a unique label, that
	// identifies the stored position.
	//
	// Creating a new main_window with an optional screen_position and
	// a label ends up reopening the window (eventually, when it gets
	// show()n) in its former position and size (hopefully).
	//
	// This has no effect if no memorized position was loaded from the
	// the configuration (which includes the situation where the
	// configuration file does not exist).

	auto main_window=
		x::w::main_window::create(pos, "main", create_mainwindow);

	main_window->on_disconnect([]
				   {
					   _exit(1);
				   });

	guard(main_window->connection_mcguffin());

	main_window->set_window_title("Hello world!");
	main_window->set_window_class("main", "wordwraplabel@examples.w.libcxx.com");
	main_window->on_delete
		([close_flag]
		 (THREAD_CALLBACK,
		  const x::w::busy &ignore)
		 {
			 close_flag->close();
		 });

	main_window->show_all();

	close_flag->wait();

	// Before terminating the most recent window position and save
	// needs to be saved into a screen_positions object:

	main_window->save(pos);

	// In this case we're using the initial screen_positions that were
	// loaded from the configuration file. Specifying an existing label
	// replaces the existing saved position with the same label.
	//
	// It's also possible to default-construct a new screen_positions,
	// and use it.
	//
	// Multiple main_windows must have a unique label, each.
	//
	// Finally, the screen_positions gets save()d into the configuration
	// file, for next time:

	pos.save(configfile);
}

int main(int argc, char **argv)
{
	try {
		wordwrap();
	} catch (const x::exception &e)
	{
		e->caught();
		exit(1);
	}
	return 0;
}

Notes:

wordwraplabel.C also demonstrates several other formatting options for the text parameter:

Preserving window positions

Running wordwraplabel.C again should open its window in the same position where it was previously, This stickiness needs some additional coding, and the actual behavior may vary depending upon the display screen's window manager, the ultimate judge where new windows open and how big they are.

#include <x/config.H>
#include <x/w/screen_positions.H>

std::string configfile=
   x::configdir("wordwraplabel@examples.w.libcxx.com")
		+ "/windows";

x::w::screen_positions pos;

// ...

main_window->save(pos);
pos->save(configfile);

x::w::main_window's save() gets called before the program ends. This records the window's last known position on the screen in the x::w::screen_positions. More than one window's position may be recorded, and a unique label associaties each position with its window. Each main window that gets created by the application (if there's more than one) has a unique identifying label which serves as the window's identifier. The application may put more than one window's position in the container, by using a unique identifier for each window. x::w::screen_positions's save() saves all positions in a file. This example program uses LibCXX's base library's x::configdir function to initialize a configuration directory for wordwraplabel's use, where the window's position get saved.

x::w::screen_positions pos{configfile};

auto main_window=
    x::w::main_window::create(pos, "main",
                              [&]
                              (const x::w::main_window)
                              {
                                 // ...

Reopening a window in the same position is a two-step process:

  • Passing a filename to x::w::screen_positions's constructor reads the previously saved positions from the file, if the file exists.

  • The x::w::screen_positions object and the application-assigned label for the main window gets passed to the overloaded main window create()or. The above example passes main for the label.

The named window's position that was saved the last time wordwraplabel ran, the same position and size gets set for the new window. The same label gets used to record the window's position, by its save() method.

Note

It's possible that application windows will open in their last known position even without explicitly saving them this way. Some window managers try to remember application windows, and open them in the same location. It's also possible that an application's requested window position gets ignored by the window manager, and the application window still opens in some other location on the screen.

Some display elements also use a x::w::screen_positions to save and restore their appearance. See the section called “Preserving table columns' widths” for an example.