16 #define GETTEXT_DOMAIN "wesnoth-lib"
29 #define LOG_SCOPE_HEADER "grid [" + id() + "] " + __func__
30 #define LOG_HEADER LOG_SCOPE_HEADER + ':'
31 #define LOG_IMPL_HEADER "grid [" + grid.id() + "] " + __func__ + ':'
33 #define LOG_CHILD_SCOPE_HEADER \
34 "grid::child [" + (widget_ ? widget_->id() : "-") + "] " + __func__
35 #define LOG_CHILD_HEADER LOG_CHILD_SCOPE_HEADER + ':'
46 , row_grow_factor_(rows)
47 , col_grow_factor_(cols)
48 , children_(rows * cols)
50 connect_signal<event::REQUEST_PLACEMENT>(
52 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4),
66 unsigned result =
rows_;
75 const unsigned border_size)
87 << row <<
',' << col <<
"' will be replaced.";
102 std::unique_ptr<widget>
w,
116 if(
auto res =
g->swap_child(
id, std::move(
w),
true); res.get() != current_w) {
133 old->set_parent(new_parent);
136 w->set_visible(old->get_visible());
179 g->set_active(active);
210 if(
size.x <=
static_cast<int>(maximum_width)) {
220 if(
size.x <=
static_cast<int>(maximum_width)) {
239 if(
size.x <=
static_cast<int>(maximum_width)) {
244 const unsigned too_wide =
size.x - maximum_width;
245 unsigned reduced = 0;
246 for(std::size_t col = 0; col <
cols_; ++col) {
249 <<
" is too small to be reduced.";
253 const unsigned wanted_width =
col_width_[col] - (too_wide - reduced);
256 *
this, col, wanted_width);
262 <<
" pixels for column " << col <<
".";
265 reduced += reduction;
268 if(
size.x <=
static_cast<int>(maximum_width)) {
288 if(
size.y <=
static_cast<int>(maximum_height)) {
298 if(
size.y <=
static_cast<int>(maximum_height)) {
317 if(
size.y <=
static_cast<int>(maximum_height)) {
322 const unsigned too_high =
size.y - maximum_height;
323 unsigned reduced = 0;
324 for(std::size_t row = 0; row <
rows_; ++row) {
325 unsigned wanted_height =
row_height_[row] - (too_high - reduced);
335 <<
row_height_[row] <<
" want to reduce " << too_high
336 <<
" is too small to be reduced fully try 1 pixel.";
348 *
this, row, wanted_height);
354 <<
row_height_[row] <<
" want to reduce " << too_high
355 <<
" reduced " << reduction <<
" pixels.";
358 reduced += reduction;
361 if(
size.y <=
static_cast<int>(maximum_height)) {
369 <<
" resulting height " <<
size.y <<
".";
381 if (
get_window()->invalidate_layout_blocked()) {
388 if(
size.x >= best_size.x &&
size.y >= best_size.y) {
396 if(
size.y >= best_size.y) {
402 if(
size.x >= best_size.x &&
size.y >= best_size.y) {
438 for(
unsigned row = 0; row <
rows_; ++row) {
439 for(
unsigned col = 0; col <
cols_; ++col) {
453 for(
unsigned row = 0; row <
rows_; ++row) {
458 for(
unsigned col = 0; col <
cols_; ++col) {
509 if(best_size ==
size) {
514 if(best_size.x >
size.x || best_size.y >
size.y) {
516 std::stringstream out;
517 out <<
" Failed to place a grid, we have " <<
size <<
" space but we need " << best_size <<
" space.";
518 out <<
" This happened at a grid with the id '" <<
id() <<
"'";
520 while(pw !=
nullptr) {
521 out <<
" in a '" <<
typeid(*pw).name() <<
"' with the id '" << pw->
id() <<
"'";
532 if(
size.x > best_size.x) {
533 const unsigned w =
size.x - best_size.x;
534 unsigned w_size = std::accumulate(
538 <<
" will be divided amount " << w_size <<
" units in "
539 <<
cols_ <<
" columns.";
551 const unsigned w_normal =
w / w_size;
552 for(
unsigned i = 0;
i <
cols_; ++
i) {
560 if(
size.y > best_size.y) {
561 const unsigned h =
size.y - best_size.y;
562 unsigned h_size = std::accumulate(
565 <<
" will be divided amount " << h_size <<
" units in "
566 <<
rows_ <<
" rows.";
578 const unsigned h_normal =
h / h_size;
579 for(
unsigned i = 0;
i <
rows_; ++
i) {
634 return grid_implementation::find_at<widget>(
639 const bool must_be_active)
const
641 return grid_implementation::find_at<const widget>(
647 return grid_implementation::find<widget>(*
this,
id, must_be_active);
652 return grid_implementation::find<const widget>(*
this,
id, must_be_active);
690 return std::make_unique<gui2::iteration::grid>(*
this);
719 <<
" may give unexpected problems.";
741 <<
" widget visible " <<
false <<
" returning 0,0.";
748 <<
" widget visible " <<
true <<
" returning " << best_size
762 origin.y += border_size_;
763 size.y -= border_size_;
766 size.y -= border_size_;
770 origin.x += border_size_;
771 size.x -= border_size_;
774 size.x -= border_size_;
781 if(
size <= best_size) {
783 <<
" in best size range setting widget to " << origin <<
" x "
797 if(maximum_size ==
point() ||
size <= maximum_size) {
800 <<
" in maximum size range setting widget to " << origin
801 <<
" x " <<
size <<
".";
808 point widget_size =
point(std::min(
size.x, best_size.x), std::min(
size.y, best_size.y));
809 point widget_orig = origin;
815 widget_size.y = std::min(
size.y, maximum_size.y);
817 widget_size.y =
size.y;
820 << best_size.y <<
" to " << widget_size.y <<
".";
829 widget_orig.y += (
size.y - widget_size.y) / 2;
834 widget_orig.y += (
size.y - widget_size.y);
839 << v_flag <<
"' specified.";
847 widget_size.x = std::min(
size.x, maximum_size.x);
849 widget_size.x =
size.x;
852 << best_size.x <<
" to " << widget_size.x <<
".";
860 widget_orig.x += (
size.x - widget_size.x) / 2;
865 widget_orig.x += (
size.x - widget_size.x);
867 <<
" horizontally aligned at the right.";
876 <<
" x " << widget_size <<
".";
886 widget_->layout_initialize(full_initialization);
893 return widget_->id();
903 result.y += border_size_;
905 result.y += border_size_;
908 result.x += border_size_;
910 result.x += border_size_;
941 ERR_GUI_G <<
"Cannot set horizontal alignment (grid cell specifies dynamic growth)";
946 ERR_GUI_G <<
"Cannot set vertical alignment (grid cell specifies dynamic growth)";
962 for(
unsigned row = 0; row <
rows_; ++row) {
963 for(
unsigned col = 0; col <
cols_; ++col) {
967 <<
" at origin " << orig <<
" with size " <<
size
1026 grid&
grid,
const unsigned row,
const unsigned maximum_height)
1029 unsigned required_height = 0;
1031 for(std::size_t x = 0; x <
grid.
cols_; ++x) {
1033 cell_request_reduce_height(cell, maximum_height);
1037 if(required_height == 0 ||
static_cast<std::size_t
>(
size.y)
1038 > required_height) {
1040 required_height =
size.y;
1045 <<
" returning " << required_height <<
".";
1047 return required_height;
1051 grid&
grid,
const unsigned column,
const unsigned maximum_width)
1054 unsigned required_width = 0;
1056 for(std::size_t y = 0; y <
grid.
rows_; ++y) {
1058 cell_request_reduce_width(cell, maximum_width);
1062 if(required_width == 0 ||
static_cast<std::size_t
>(
size.x)
1065 required_width =
size.x;
1070 <<
" returning " << required_width <<
".";
1072 return required_width;
1077 const unsigned maximum_height)
1079 assert(
child.widget_);
1085 child.widget_->request_reduce_height(maximum_height
1086 -
child.border_space().y);
1091 const unsigned maximum_width)
1093 assert(
child.widget_);
1099 child.widget_->request_reduce_width(maximum_width -
child.border_space().x);
Main class to show messages to the user.
bool fire(const ui_event event, widget &target)
Fires an event which has no extra parameters.
void place(point origin, point size)
Places the widget in the cell.
void layout_initialize(const bool full_initialization)
Forwards grid::layout_initialize to the cell.
void set_border_size(const unsigned border_size)
void set_widget(std::unique_ptr< widget > widget)
Acquires an owning reference to the given widget.
void set_flags(const unsigned flags)
const std::string & id() const
Returns the id of the widget/.
point get_best_size() const
Returns the best size for the cell.
const widget * get_widget() const
std::unique_ptr< widget > free_widget()
Releases widget from ownership by this child and returns it in the form of a new shared_ptr.
point border_space() const
Returns the space needed for the border.
unsigned get_flags() const
bool can_wrap() const
Returns the can_wrap for the cell.
std::unique_ptr< widget > widget_
Pointer to the widget.
void set_active(const bool active)
Activates all children.
virtual void impl_draw_children() override
See widget::impl_draw_children.
virtual bool has_widget(const widget &widget) const override
See widget::has_widget.
void request_placement(dispatcher &dispatcher, const event::ui_event event, bool &handled, bool &halt)
Attempts to lay out the grid without laying out the entire window.
virtual point calculate_best_size() const override
See widget::calculate_best_size.
std::unique_ptr< widget > swap_child(const std::string &id, std::unique_ptr< widget > w, const bool recurse, widget *new_parent=nullptr)
Exchanges a child in the grid.
bool disable_click_dismiss() const override
See widget::disable_click_dismiss.
static const unsigned HORIZONTAL_GROW_SEND_TO_CLIENT
static const unsigned HORIZONTAL_ALIGN_RIGHT
const grid::child & get_child(const unsigned row, const unsigned col) const
Gets the grid child in the specified cell.
virtual void place(const point &origin, const point &size) override
See widget::place.
void reduce_height(const unsigned maximum_height)
Tries to reduce the height of a container.
virtual void set_visible_rectangle(const SDL_Rect &rectangle) override
See widget::set_visible_rectangle.
virtual iteration::walker_ptr create_walker() override
See widget::create_walker.
unsigned add_row(const unsigned count=1)
Adds a row to end of the grid.
const widget * get_widget(const unsigned row, const unsigned col) const
Returns the widget in the selected cell.
void reduce_width(const unsigned maximum_width)
Tries to reduce the width of a container.
static const unsigned HORIZONTAL_MASK
point recalculate_best_size()
Recalculates the best size.
std::vector< child > children_
The child items.
static const unsigned VERTICAL_ALIGN_BOTTOM
static const unsigned BORDER_TOP
std::vector< unsigned > col_width_
The column widths in the grid.
void set_cols(const unsigned cols)
static const unsigned VERTICAL_ALIGN_CENTER
virtual widget * find_at(const point &coordinate, const bool must_be_active) override
See widget::find_at.
void set_rows(const unsigned rows)
static const unsigned VERTICAL_GROW_SEND_TO_CLIENT
widget * find(const std::string_view id, const bool must_be_active) override
See widget::find.
static const unsigned BORDER_BOTTOM
static const unsigned BORDER_RIGHT
static const unsigned HORIZONTAL_ALIGN_CENTER
void remove_child(const unsigned row, const unsigned col)
Removes and frees a widget in a cell.
grid(const unsigned rows=0, const unsigned cols=0)
void set_child_alignment(widget *widget, unsigned set_flag, unsigned mode_mask)
Modifies the widget alignment data of a child cell containing a specific widget.
void layout(const point &origin)
Layouts the children in the grid.
unsigned cols_
The number of grid columns.
static const unsigned VERTICAL_MASK
void set_rows_cols(const unsigned rows, const unsigned cols)
Wrapper to set_rows and set_cols.
std::vector< unsigned > col_grow_factor_
The grow factor for all columns.
std::vector< unsigned > row_height_
The row heights in the grid.
static const unsigned VERTICAL_ALIGN_TOP
static const unsigned BORDER_LEFT
void set_child(std::unique_ptr< widget > widget, const unsigned row, const unsigned col, const unsigned flags, const unsigned border_size)
Sets a child in the grid.
virtual void set_origin(const point &origin) override
See widget::set_origin.
virtual void demand_reduce_height(const unsigned maximum_height) override
See widget::demand_reduce_height.
virtual bool can_wrap() const override
See widget::can_wrap.
virtual void layout_children() override
See widget::layout_children.
virtual void layout_initialize(const bool full_initialization) override
See widget::layout_initialize.
virtual void request_reduce_width(const unsigned maximum_width) override
See widget::request_reduce_width.
std::vector< unsigned > row_grow_factor_
The grow factor for all rows.
virtual void request_reduce_height(const unsigned maximum_height) override
See widget::request_reduce_height.
unsigned rows_
The number of grid rows.
static const unsigned HORIZONTAL_ALIGN_LEFT
virtual void demand_reduce_width(const unsigned maximum_width) override
See widget::demand_reduce_width.
void defer_region(const rect ®ion)
Defer rendering of a particular region to next frame.
This file contains the definitions for the gui2::event::message class.
#define LOG_CHILD_SCOPE_HEADER
Helper for header for the grid.
Define the common log macros for the gui toolkit.
Defines the exception classes for the layout algorithm.
#define log_scope2(domain, description)
void point(int x, int y)
Draw a single point.
ui_event
The event sent to the dispatcher.
std::unique_ptr< class walker_base > walker_ptr
void set_single_child(grid &grid, std::unique_ptr< widget > widget)
Sets the single child in a grid.
lg::log_domain log_gui_layout("gui/layout")
map_location coordinate
Contains an x and y coordinate used for starting positions in maps.
std::size_t size(std::string_view str)
Length in characters of a UTF-8 string.
The message callbacks hold a reference to a message.
static unsigned column_request_reduce_width(grid &grid, const unsigned column, const unsigned maximum_width)
Helper function to do the resizing of a column.
static void cell_request_reduce_width(grid::child &child, const unsigned maximum_width)
Helper function to do the resizing of a widget.
static void cell_request_reduce_height(grid::child &child, const unsigned maximum_height)
Helper function to do the resizing of a widget.
static unsigned row_request_reduce_height(grid &grid, const unsigned row, const unsigned maximum_height)
Helper function to do the resizing of a row.
Exception thrown when the height resizing has failed.
Exception thrown when the width resizing has failed.