diff --git a/changelog b/changelog index 3070900e60b..9a9fd37b3e6 100644 --- a/changelog +++ b/changelog @@ -166,6 +166,7 @@ Version 1.11.0-svn: * Stop showing a unit's potential moves before moving in a move & attack, rather than after (more consistent with regular movement) * Changed: Made the id for a tooltip and helptip mandatory. + * Added: Helper code to assist in widget placement. * Whiteboard: * Fixed bug #19626: segfaults on window resize * Fixed bug #19369: Using planning mode can cause losing ability to move my units diff --git a/po/wesnoth-lib/POTFILES.in b/po/wesnoth-lib/POTFILES.in index 082ca8730a3..d94e6dc82fc 100644 --- a/po/wesnoth-lib/POTFILES.in +++ b/po/wesnoth-lib/POTFILES.in @@ -12,6 +12,9 @@ src/gui/auxiliary/iterator/iterator.cpp src/gui/auxiliary/iterator/walker_grid.cpp src/gui/auxiliary/iterator/walker_widget.cpp src/gui/auxiliary/log.cpp +src/gui/auxiliary/placer.cpp +src/gui/auxiliary/placer/horizontal_list.cpp +src/gui/auxiliary/placer/vertical_list.cpp src/gui/auxiliary/tips.cpp src/gui/auxiliary/widget_definition/button.cpp src/gui/auxiliary/widget_definition.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 339183f56c0..210bf7707ff 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -418,6 +418,9 @@ set(wesnoth-main_SRC gui/auxiliary/iterator/walker_grid.cpp gui/auxiliary/iterator/walker_widget.cpp gui/auxiliary/log.cpp + gui/auxiliary/placer.cpp + gui/auxiliary/placer/horizontal_list.cpp + gui/auxiliary/placer/vertical_list.cpp gui/auxiliary/old_markup.cpp gui/auxiliary/timer.cpp gui/auxiliary/tips.cpp diff --git a/src/SConscript b/src/SConscript index c46e564a75d..0bebedf75a7 100644 --- a/src/SConscript +++ b/src/SConscript @@ -262,6 +262,9 @@ wesnoth_sources = Split(""" gui/auxiliary/iterator/walker_grid.cpp gui/auxiliary/iterator/walker_widget.cpp gui/auxiliary/log.cpp + gui/auxiliary/placer.cpp + gui/auxiliary/placer/horizontal_list.cpp + gui/auxiliary/placer/vertical_list.cpp gui/auxiliary/old_markup.cpp gui/auxiliary/timer.cpp gui/auxiliary/tips.cpp diff --git a/src/gui/auxiliary/placer.cpp b/src/gui/auxiliary/placer.cpp new file mode 100644 index 00000000000..9ce18221ef2 --- /dev/null +++ b/src/gui/auxiliary/placer.cpp @@ -0,0 +1,49 @@ +/* $Id$ */ +/* + Copyright (C) 2012 by Mark de Wever + Part of the Battle for Wesnoth Project http://www.wesnoth.org/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +#define GETTEXT_DOMAIN "wesnoth-lib" + +#define ENUM_ENABLE_STREAM_OPERATORS_IMPLEMENTATION +#define ENUM_TYPE ::gui2::tplacer_ +#define ENUM_LIST \ +ENUM(horizontal, "horizontal"); \ +ENUM(vertical, "vertical"); \ + +#include "gui/auxiliary/placer.hpp" + +#include "gui/auxiliary/placer/horizontal_list.hpp" +#include "gui/auxiliary/placer/vertical_list.hpp" + +ENUM_DEFINE_STREAM_OPERATORS(::gui2::tplacer_::tgrow_direction) + +namespace gui2 { + +tplacer_* tplacer_::build( + const tgrow_direction grow_direction + , const unsigned parallel_items) +{ + switch(grow_direction) { + case horizontal : + return new implementation::tplacer_horizontal_list(parallel_items); + case vertical : + return new implementation::tplacer_vertical_list(parallel_items); + }; +} + +tplacer_::~tplacer_() +{ +} + +} // namespace gui2 diff --git a/src/gui/auxiliary/placer.hpp b/src/gui/auxiliary/placer.hpp new file mode 100644 index 00000000000..a711d9ad880 --- /dev/null +++ b/src/gui/auxiliary/placer.hpp @@ -0,0 +1,130 @@ +/* $Id$ */ +/* + Copyright (C) 2012 by Mark de Wever + Part of the Battle for Wesnoth Project http://www.wesnoth.org/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +/** + * @file + * Base class for the placement helper. + * + * Some items can create new child items and these items are placed in some way + * this code contains helpers for the placement by calculating the positions + * for the items and the best size for the children. + */ + +#ifndef GUI_AUXILIARY_PLACER_HPP_INCLUDED +#define GUI_AUXILIARY_PLACER_HPP_INCLUDED + +namespace gui2 { + +class tpoint; + +/** + * Base class for the placement helper. + * + * The normal operation for the usage of the class is: + * * Call @ref initialise(). + * * For every visible child item call @ref add_item() with the wanted size of + * the widget. + * Once this is done the required size for all children can be retrieved with + * @ref get_size(). It is also possible to place all children now. In order to + * do so loop again over all children in the same order as @ref add_item() and + * call @ref get_origin(). The @p index parameter is an increasing counter. + * + * @note The origins can only be retrieved after all items are added since the + * adding of a later item may influence a previous item. E.g. in a vertical + * list with two columns the position of the second column depends on the width + * of the first and a later row may have a wider column 1 as an earlier row. + */ +class tplacer_ +{ +public: + + /***** ***** Types. ***** *****/ + + /** The direction the placer should grow towards. */ + enum tgrow_direction + { + horizontal + , vertical + }; + + + /***** ***** Constructor, destructor, assignment. ***** *****/ + +public: + + /** + * Builder function. + * + * @pre @p parallel_items > 0 + * + * @param grow_direction The direction in which the items will be + * added. + * @param parallel_items The direction perpendicular towards the grow + * direction has a fixed number of items. This + * value sets that limit. For a list containing + * only horizontally or vertically placed items + * the value should be 1. + */ + static tplacer_* build( + const tgrow_direction grow_direction + , const unsigned parallel_items); + + virtual ~tplacer_(); + + + /***** ***** Operations. ***** *****/ + + /** + * Initialises the placer. + * + * When the placement needs to be calculated the state often needs to be + * reset, items are placed, removed or changed visibility causing the old + * placement to be invalid. + */ + virtual void initialise() = 0; + + /** + * Adds a item to be placed. + * + * @param size The required size for the item. + */ + virtual void add_item(const tpoint& size) = 0; + + /** + * Gets the required size of all items. + * + * @returns The required size. + */ + virtual tpoint get_size() const = 0; + + /** + * Gets the origin for an item. + * + * @param index The index of the item whose origin to return. + * The index is the index of the call to + * @ref add_item(). + * + * @returns The origin where to place the widget. + */ + virtual tpoint get_origin(const unsigned index) const = 0; +}; + +} // namespace gui2 + +#include "enumerate.tpp" + +ENUM_DECLARE_STREAM_OPERATORS(::gui2::tplacer_::tgrow_direction) + +#endif diff --git a/src/gui/auxiliary/placer/horizontal_list.cpp b/src/gui/auxiliary/placer/horizontal_list.cpp new file mode 100644 index 00000000000..0eada381c47 --- /dev/null +++ b/src/gui/auxiliary/placer/horizontal_list.cpp @@ -0,0 +1,89 @@ +/* $Id$ */ +/* + Copyright (C) 2012 by Mark de Wever + Part of the Battle for Wesnoth Project http://www.wesnoth.org/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +#define GETTEXT_DOMAIN "wesnoth-lib" + +#include "gui/auxiliary/placer/horizontal_list.hpp" + +#include "gui/widgets/helper.hpp" + +#include +#include + +namespace gui2 { + +namespace implementation { + +tplacer_horizontal_list::tplacer_horizontal_list(const unsigned maximum_rows) + : maximum_rows_(maximum_rows) + , rows_(maximum_rows, 0) + , columns_(1, std::make_pair(0, 0)) + , row_(0) + , column_(0) +{ + assert(maximum_rows_ > 0); +} + +void tplacer_horizontal_list::initialise() +{ + std::fill(rows_.begin(), rows_.end(), 0); + columns_.clear(); + columns_.push_back(std::make_pair(0, 0)); + row_ = 0; + column_ = 0; +} + +void tplacer_horizontal_list::add_item(const tpoint& size) +{ + if(size.x > columns_[column_].second) { + columns_[column_].second = size.x; + } + + if(size.y > rows_[row_]) { + rows_[row_]= size.y; + } + + ++row_; + if(row_ == maximum_rows_) { + row_ = 0; + ++column_; + + const int origin = columns_.back().first + columns_.back().second; + columns_.push_back(std::make_pair(origin, 0)); + } +} + +tpoint tplacer_horizontal_list::get_size() const +{ + const int width = columns_.back().first + columns_.back().second; + const int height = std::accumulate(rows_.begin(), rows_.end(), 0); + return tpoint(width, height); +} + +tpoint tplacer_horizontal_list::get_origin(const unsigned index) const +{ + const unsigned row = index % maximum_rows_; + const unsigned column = index / maximum_rows_; + + const int height = row == 0 + ? 0 + : std::accumulate(rows_.begin(), rows_.begin() + row, 0); + + return tpoint(columns_[column].first, height); +} + +} // namespace implementation + +} // namespace gui2 diff --git a/src/gui/auxiliary/placer/horizontal_list.hpp b/src/gui/auxiliary/placer/horizontal_list.hpp new file mode 100644 index 00000000000..23b6c0b89cf --- /dev/null +++ b/src/gui/auxiliary/placer/horizontal_list.hpp @@ -0,0 +1,95 @@ +/* $Id$ */ +/* + Copyright (C) 2012 by Mark de Wever + Part of the Battle for Wesnoth Project http://www.wesnoth.org/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +/** + * @file + * Placement helper for the horizontal list. + */ + +#ifndef GUI_AUXILIARY_PLACER_HORIZONTAL_LIST_HPP_INCLUDED +#define GUI_AUXILIARY_PLACER_HORIZONTAL_LIST_HPP_INCLUDED + +#include "gui/auxiliary/placer.hpp" + +#include + +namespace gui2 { + +namespace implementation { + +/** + * The placement class for a horizontal list. + * + * @see @ref tplacer_ for more information. + */ +class tplacer_horizontal_list + : public tplacer_ +{ + +public: + + /***** ***** Constructor, destructor, assignment. ***** *****/ + + explicit tplacer_horizontal_list(const unsigned maximum_rows); + + + /***** ***** Inherited operations. ***** *****/ + + virtual void initialise(); + + virtual void add_item(const tpoint& size); + + virtual tpoint get_size() const; + + virtual tpoint get_origin(const unsigned index) const; + + + /***** ***** Members. ***** *****/ + +private: + + /** + * The maximum number of rows to use. + * + * This value is determined by the @p parallel_items parameter of + * @ref tplacer_::build). + */ + unsigned maximum_rows_; + + /** Holds the heights of the rows. */ + std::vector rows_; + + /** + * Holds the column sizes + * + * The pair contains the following values: + * * first The origin of a column. + * * second The width of a column. + */ + std::vector > columns_; + + /** The row to add an item to. */ + unsigned row_; + + /** The column to add an item to. */ + unsigned column_; + +}; + +} // namespace implementation + +} // namespace gui2 + +#endif diff --git a/src/gui/auxiliary/placer/vertical_list.cpp b/src/gui/auxiliary/placer/vertical_list.cpp new file mode 100644 index 00000000000..e884225788b --- /dev/null +++ b/src/gui/auxiliary/placer/vertical_list.cpp @@ -0,0 +1,89 @@ +/* $Id$ */ +/* + Copyright (C) 2012 by Mark de Wever + Part of the Battle for Wesnoth Project http://www.wesnoth.org/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +#define GETTEXT_DOMAIN "wesnoth-lib" + +#include "gui/auxiliary/placer/vertical_list.hpp" + +#include "gui/widgets/helper.hpp" + +#include +#include + +namespace gui2 { + +namespace implementation { + +tplacer_vertical_list::tplacer_vertical_list(const unsigned maximum_columns) + : maximum_columns_(maximum_columns) + , rows_(1, std::make_pair(0, 0)) + , columns_(maximum_columns, 0) + , row_(0) + , column_(0) +{ + assert(maximum_columns_ > 0); +} + +void tplacer_vertical_list::initialise() +{ + rows_.clear(); + rows_.push_back(std::make_pair(0, 0)); + std::fill(columns_.begin(), columns_.end(), 0); + row_ = 0; + column_ = 0; +} + +void tplacer_vertical_list::add_item(const tpoint& size) +{ + if(size.x > columns_[column_]) { + columns_[column_] = size.x; + } + + if(size.y > rows_[row_].second) { + rows_[row_].second = size.y; + } + + ++column_; + if(column_ == maximum_columns_) { + column_ = 0; + ++row_; + + const int origin = rows_.back().first + rows_.back().second; + rows_.push_back(std::make_pair(origin, 0)); + } +} + +tpoint tplacer_vertical_list::get_size() const +{ + const int width = std::accumulate(columns_.begin(), columns_.end(), 0); + const int height = rows_.back().first + rows_.back().second; + return tpoint(width, height); +} + +tpoint tplacer_vertical_list::get_origin(const unsigned index) const +{ + const unsigned row = index / maximum_columns_; + const unsigned column = index % maximum_columns_; + + const int width = column == 0 + ? 0 + : std::accumulate(columns_.begin(), columns_.begin() + column, 0); + + return tpoint(width, rows_[row].first); +} + +} // namespace implementation + +} // namespace gui2 diff --git a/src/gui/auxiliary/placer/vertical_list.hpp b/src/gui/auxiliary/placer/vertical_list.hpp new file mode 100644 index 00000000000..8d389a41533 --- /dev/null +++ b/src/gui/auxiliary/placer/vertical_list.hpp @@ -0,0 +1,93 @@ +/* $Id$ */ +/* + Copyright (C) 2012 by Mark de Wever + Part of the Battle for Wesnoth Project http://www.wesnoth.org/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +/** + * @file + * Placement helper for the vertical list. + */ + +#ifndef GUI_AUXILIARY_PLACER_VERTICAL_LIST_HPP_INCLUDED +#define GUI_AUXILIARY_PLACER_VERTICAL_LIST_HPP_INCLUDED + +#include "gui/auxiliary/placer.hpp" + +#include + +namespace gui2 { + +namespace implementation { + +/** + * The placement class for a vertical list. + * + * @see @ref tplacer_ for more information. + */ +class tplacer_vertical_list + : public tplacer_ +{ +public: + + /***** ***** Constructor, destructor, assignment. ***** *****/ + + explicit tplacer_vertical_list(const unsigned maximum_columns); + + + /***** ***** Inherited operations. ***** *****/ + + virtual void initialise(); + + virtual void add_item(const tpoint& size); + + virtual tpoint get_size() const; + + virtual tpoint get_origin(const unsigned index) const; + + + /***** ***** Members. ***** *****/ + +private: + + /** + * The maximum number of colums to use. + * + * This value is determined by the @p parallel_items parameter of + * @ref tplacer_::build). + */ + unsigned maximum_columns_; + + /** + * Holds the row sizes + * + * The pair contains the following values: + * * first The origin of a row. + * * second The height of a row. + */ + std::vector > rows_; + + /** Holds the widths of the columns. */ + std::vector columns_; + + /** The row to add an item to. */ + unsigned row_; + + /** The column to add an item to. */ + unsigned column_; +}; + +} // namespace implementation + +} // namespace gui2 + +#endif