Use REQUEST_PLACEMENT event to trigger partial relayout

It turned out that mordante had added that event for the same purpose,
avoiding unnecessary full relayouts.

Letting GUI2 event handling to route the event to the right widgets is
better than doing it manually.
This commit is contained in:
Jyrki Vesterinen 2017-04-01 21:13:04 +03:00
parent 14239c6911
commit d8c670654a
6 changed files with 42 additions and 47 deletions

View file

@ -28,6 +28,15 @@
namespace gui2
{
container_base::container_base(const unsigned canvas_count)
: styled_widget(canvas_count), grid_()
{
grid_.set_parent(this);
connect_signal<event::REQUEST_PLACEMENT>(
std::bind(&container_base::clear_layout_size, this),
event::dispatcher::back_pre_child);
}
SDL_Rect container_base::get_client_rect() const
{
return get_rectangle();

View file

@ -34,11 +34,7 @@ class container_base : public styled_widget
friend class debug_layout_graph;
public:
explicit container_base(const unsigned canvas_count)
: styled_widget(canvas_count), grid_()
{
grid_.set_parent(this);
}
explicit container_base(const unsigned canvas_count);
/**
* Returns the client rect.

View file

@ -44,6 +44,10 @@ grid::grid(const unsigned rows, const unsigned cols)
, col_grow_factor_(cols)
, children_(rows * cols)
{
connect_signal<event::REQUEST_PLACEMENT>(
std::bind(&grid::request_placement, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4),
event::dispatcher::back_pre_child);
}
grid::~grid()
@ -378,12 +382,13 @@ void grid::demand_reduce_height(const unsigned /*maximum_height*/)
/** @todo Implement. */
}
void grid::relayout()
void grid::request_placement(dispatcher&, const event::ui_event, bool& handled, bool&)
{
point size = get_size();
point best_size = calculate_best_size();
if(size.x >= best_size.x && size.y >= best_size.y) {
place(get_origin(), size);
handled = true;
return;
}
@ -398,6 +403,7 @@ void grid::relayout()
if(size.x >= best_size.x && size.y >= best_size.y) {
// Wrapping succeeded, we still fit vertically.
place(get_origin(), size);
handled = true;
return;
} else {
// Wrapping failed, we no longer fit.
@ -406,23 +412,10 @@ void grid::relayout()
}
}
// Not enough space, ask the parent grid for more.
// Throw away cached sizes of all parent widgets until the next grid.
widget* parent_widget = parent();
while(parent_widget != nullptr &&
dynamic_cast<grid*>(parent_widget) == nullptr)
{
parent_widget->clear_layout_size();
parent_widget = parent_widget->parent();
}
grid* parent = get_parent_grid();
if(parent != nullptr) {
parent->relayout();
} else {
get_window()->invalidate_layout();
}
/*
Not enough space.
Let the event flow higher up.
This is a pre-event handler, so the event flows upwards. */
}
point grid::recalculate_best_size()

View file

@ -220,13 +220,6 @@ public:
/** See @ref widget::demand_reduce_height. */
virtual void demand_reduce_height(const unsigned maximum_height) override;
/**
* Attempts to lay out the grid without laying out the entire window.
* If the grid needs to grow, asks the parent grid for more space, recursively.
* If the grid is the top-level grid, falls back to laying out the whole window.
*/
void relayout();
/**
* Recalculates the best size.
*
@ -241,6 +234,11 @@ private:
/** See @ref widget::calculate_best_size. */
virtual point calculate_best_size() const override;
/**
* Attempts to lay out the grid without laying out the entire window.
*/
void request_placement(dispatcher& dispatcher, const event::ui_event event, bool& handled, bool& halt);
public:
/** See @ref widget::can_wrap. */
virtual bool can_wrap() const override;

View file

@ -17,6 +17,7 @@
#include "gui/widgets/scrollbar_container_private.hpp"
#include "gui/auxiliary/find_widget.hpp"
#include "gui/core/event/message.hpp"
#include "gui/core/log.hpp"
#include "gui/core/layout_exception.hpp"
#include "gui/widgets/clickable_item.hpp"
@ -592,10 +593,9 @@ bool scrollbar_container::content_resize_request(const bool force_sizing)
== widget::visibility::invisible)) {
DBG_GUI_L << LOG_HEADER
<< " can't use horizontal scrollbar, ask grid.\n";
grid* grid = get_parent_grid();
assert(grid);
grid->relayout();
<< " can't use horizontal scrollbar, request placement.\n";
event::message message;
fire(event::REQUEST_PLACEMENT, *this, message);
return false;
}
}
@ -608,10 +608,9 @@ bool scrollbar_container::content_resize_request(const bool force_sizing)
== widget::visibility::invisible)) {
DBG_GUI_L << LOG_HEADER
<< " can't use vertical scrollbar, ask grid.\n";
grid* grid = get_parent_grid();
assert(grid);
grid->relayout();
<< " can't use vertical scrollbar, request placement.\n";
event::message message;
fire(event::REQUEST_PLACEMENT, *this, message);
return false;
}
}

View file

@ -259,15 +259,6 @@ public:
*/
virtual void layout_initialise(const bool full_initialisation);
/**
* Throws away @ref layout_size_.
*
* Use with care: this function does not recurse to child widgets.
*
* See @ref layout_algorithm for more information.
*/
void clear_layout_size() { set_layout_size(point()); }
/**
* Tries to reduce the width of a widget.
*
@ -455,6 +446,15 @@ protected:
void set_layout_size(const point& size);
const point& layout_size() const;
/**
* Throws away @ref layout_size_.
*
* Use with care: this function does not recurse to child widgets.
*
* See @ref layout_algorithm for more information.
*/
void clear_layout_size() { set_layout_size(point()); }
public:
void set_linked_group(const std::string& linked_group);