GUI2: When a label grows, attempt to only lay out the containing grid

This greatly improves responsiveness of the add-on manager (bug #25523).
This commit is contained in:
Jyrki Vesterinen 2017-03-21 22:47:12 +02:00 committed by Charles Dang
parent 27f2826703
commit 01035f0adc
6 changed files with 78 additions and 9 deletions

View file

@ -1,4 +1,6 @@
Version 1.13.7+dev:
* Performance:
* Greatly speeded up switching between add-ons in the add-on manager (bug #25523)
Version 1.13.7:
* AI:

View file

@ -20,6 +20,7 @@
#include "gui/core/log.hpp"
#include "gui/core/layout_exception.hpp"
#include "gui/widgets/styled_widget.hpp"
#include "gui/widgets/window.hpp"
#include <numeric>
@ -377,6 +378,43 @@ void grid::demand_reduce_height(const unsigned /*maximum_height*/)
/** @todo Implement. */
}
void grid::relayout()
{
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);
return;
}
recalculate_best_size();
if(size.y >= best_size.y) {
// We have enough space in the Y direction, but not in the X direction.
// Try wrapping the content.
request_reduce_width(size.x);
best_size = get_best_size();
if(size.x >= best_size.x && size.y >= best_size.y) {
// Wrapping succeeded, we still fit vertically.
place(get_origin(), size);
return;
} else {
// Wrapping failed, we no longer fit.
// Reset the sizes of child widgets.
layout_initialise(true);
}
}
// Not enough space, ask the parent grid for more.
grid* parent = get_parent_grid();
if(parent != nullptr) {
parent->relayout();
} else {
get_window()->invalidate_layout();
}
}
point grid::recalculate_best_size()
{
point best_size = calculate_best_size();

View file

@ -220,6 +220,13 @@ 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.
*

View file

@ -582,10 +582,11 @@ bool scrollbar_container::content_resize_request(const bool force_sizing)
== widget::visibility::invisible)) {
DBG_GUI_L << LOG_HEADER
<< " can't use horizontal scrollbar, ask window.\n";
window* window = get_window();
assert(window);
window->invalidate_layout();
<< " can't use horizontal scrollbar, ask grid.\n";
layout_initialise(true);
grid* grid = get_parent_grid();
assert(grid);
grid->relayout();
return false;
}
}
@ -598,10 +599,11 @@ bool scrollbar_container::content_resize_request(const bool force_sizing)
== widget::visibility::invisible)) {
DBG_GUI_L << LOG_HEADER
<< " can't use vertical scrollbar, ask window.\n";
window* window = get_window();
assert(window);
window->invalidate_layout();
<< " can't use vertical scrollbar, ask grid.\n";
layout_initialise(true);
grid* grid = get_parent_grid();
assert(grid);
grid->relayout();
return false;
}
}

View file

@ -14,6 +14,7 @@
#define GETTEXT_DOMAIN "wesnoth-lib"
#include "gui/widgets/grid.hpp"
#include "gui/widgets/settings.hpp"
#include "gui/widgets/window.hpp"
#include "gui/core/event/message.hpp"
@ -137,6 +138,16 @@ const window* widget::get_window() const
return dynamic_cast<const window*>(result);
}
grid* widget::get_parent_grid()
{
widget* result = parent_;
while(result && dynamic_cast<grid*>(result) == nullptr) {
result = result->parent_;
}
return result ? dynamic_cast<grid*>(result) : nullptr;
}
dialogs::modal_dialog* widget::dialog()
{
window* window = get_window();

View file

@ -32,6 +32,7 @@ namespace gui2
struct builder_widget;
namespace dialogs { class modal_dialog; }
class window;
class grid;
namespace iteration
{
@ -176,10 +177,18 @@ public:
* Get the parent window.
*
* @returns Pointer to parent window.
* @retval nullptr No parent window found.
* @retval nullptr No parent window found.
*/
window* get_window();
/**
* Get the parent grid.
*
* @returns Pointer to parent grid.
* @retval nullptr No parent grid found.
*/
grid* get_parent_grid();
/** The constant version of @ref get_window. */
const window* get_window() const;