GUI2: refactored styled_widget canvas initialization process

Back in 515f450432 I attempted to optimize this, but I didn't do it right. Since I didn't
define a move ctor for canvas, that std::move call was useless and the copy ctor was being called
anyway. Though, that change wasn't a total waste. It still reduced the number of canvases created
from (I think) 3 to 2, since the code was no longer going default-construction
and copy-assignment from the state struct.

These new changes completely remove the canvas object from the state struct. Nothing particularity
special was being done there, only a call to canvas::set_cfg. Instead, the canvas config is saved
in the state objects and then styled_widget initializes the canvas itself. This does mean there's
config copying going on here, sadly, but it's unavoidable given the current design.

This also removes the definition_load_configuration function from styled_widget. Its contents were
moved to the ctor. This ensures only the exact number of canvas objects needed are created. No
copying from the state objects, no reallocations. This also means we can delete the copy ctor (see
below).

A move ctor was added to canvas (though it admittedly isn't needed now since no canvas moving
occurs), and the copy ctor deleted.
This commit is contained in:
Charles Dang 2017-12-07 19:18:42 +11:00
parent 590501aa1e
commit dfa09cd9d9
6 changed files with 55 additions and 58 deletions

View File

@ -1374,6 +1374,21 @@ canvas::canvas()
{
}
canvas::canvas(canvas&& c)
: shapes_(std::move(c.shapes_))
, blur_depth_(c.blur_depth_)
, w_(c.w_)
, h_(c.h_)
, canvas_(std::move(c.canvas_))
, renderer_(c.renderer_)
, variables_(c.variables_)
, functions_(c.functions_)
, is_dirty_(c.is_dirty_)
{
// Needed to ensure the other object doesn't destroy our software renderer prematurely.
c.renderer_ = nullptr;
}
canvas::~canvas()
{
SDL_DestroyRenderer(renderer_);

View File

@ -87,6 +87,9 @@ public:
typedef std::shared_ptr<const shape> const_shape_ptr;
canvas();
canvas(const canvas&) = delete;
canvas(canvas&& c);
~canvas();
/**

View File

@ -43,13 +43,10 @@ namespace gui2
* @end{parent}{name="generic/"}
*
*/
state_definition::state_definition(const config& cfg) : canvas_()
state_definition::state_definition(const config& cfg)
: canvas_cfg_(cfg ? cfg.child("draw") : cfg)
{
const config& draw = *(cfg ? &cfg.child("draw") : &cfg);
VALIDATE(draw, _("No state or draw section defined."));
canvas_.set_cfg(draw);
VALIDATE(canvas_cfg_, _("No state or draw section defined."));
}
/*WIKI

View File

@ -17,8 +17,8 @@
#include "config.hpp"
#include "font/font_options.hpp"
#include "font/text.hpp"
#include "gui/core/canvas.hpp"
#include "gui/core/linked_group_definition.hpp"
#include <vector>
namespace gui2
@ -35,7 +35,7 @@ struct state_definition
{
explicit state_definition(const config& cfg);
canvas canvas_;
config canvas_cfg_;
};

View File

@ -16,16 +16,16 @@
#include "gui/widgets/styled_widget.hpp"
#include "formatter.hpp"
#include "formula/string_utils.hpp"
#include "gettext.hpp"
#include "gui/auxiliary/iterator/walker_widget.hpp"
#include "gui/core/log.hpp"
#include "gui/core/event/message.hpp"
#include "gui/core/log.hpp"
#include "gui/dialogs/tooltip.hpp"
#include "gui/widgets/settings.hpp"
#include "gui/widgets/window.hpp"
#include "hotkey/hotkey_item.hpp"
#include "formatter.hpp"
#include "gettext.hpp"
#include "sdl/rect.hpp"
#include "wml_exception.hpp"
@ -52,18 +52,28 @@ styled_widget::styled_widget(const implementation::builder_styled_widget& builde
, use_tooltip_on_label_overflow_(builder.use_tooltip_on_label_overflow)
, tooltip_(builder.tooltip)
, help_message_(builder.help)
, canvas_()
, config_(nullptr)
, config_(get_control(control_type, definition_))
, canvases_(config_->state.size()) // One canvas per state
, renderer_()
, text_maximum_width_(0)
, text_alignment_(PANGO_ALIGN_LEFT)
, text_ellipse_mode_(PANGO_ELLIPSIZE_END)
, shrunken_(false)
{
definition_load_configuration(control_type);
/*
* Fill in each canvas from the widget state definitons.
*
* Most widgets have a single canvas. However, some widgets such as toggle_panel
* and toggle_button have a variable canvas count determined by their definitions.
*/
for(unsigned i = 0; i < config_->state.size(); ++i) {
canvases_[i].set_cfg(config_->state[i].canvas_cfg_);
}
// Initialize all the canvas variables.
update_canvas();
// Enable hover behavior if a tooltip was provided.
// TODO: maybe don't duplicate this call with set_tooltip?
set_wants_mouse_hover(!tooltip_.empty());
connect_signal<event::SHOW_TOOLTIP>(std::bind(
@ -254,7 +264,7 @@ point styled_widget::calculate_best_size() const
void styled_widget::place(const point& origin, const point& size)
{
// resize canvasses
for(auto & canvas : canvas_)
for(auto & canvas : canvases_)
{
canvas.set_width(size.x);
canvas.set_height(size.y);
@ -360,7 +370,7 @@ void styled_widget::update_canvas()
const int max_height = get_text_maximum_height();
// set label in canvases
for(auto & canvas : canvas_)
for(auto & canvas : canvases_)
{
canvas.set_variable("text", wfl::variant(label_));
canvas.set_variable("text_markup", wfl::variant(use_markup_));
@ -421,25 +431,6 @@ void styled_widget::impl_draw_foreground(surface& /*frame_buffer*/
/* DO NOTHING */
}
void styled_widget::definition_load_configuration(const std::string& control_type)
{
assert(!config_);
set_config(get_control(control_type, definition_));
/**
* Fill in each canvas from the widget state definitons.
*
* Most widgets have a single canvas. However, some widgets such as toggle_panel
* and toggle_button have a variable canvas count determined by their definitions.
*/
for(const auto& widget_state : config_->state) {
canvas_.emplace_back(std::move(widget_state.canvas_));
}
update_canvas();
}
point styled_widget::get_best_text_size(point minimum_size, point maximum_size) const
{
log_scope2(log_gui_layout, LOG_SCOPE_HEADER);
@ -451,7 +442,7 @@ point styled_widget::get_best_text_size(point minimum_size, point maximum_size)
? text_maximum_width_
: maximum_size.x;
/*
/*
* NOTE: text rendering does *not* happen here. That happens in the text_shape
* canvas class. Instead, this just leverages the pango text rendering engine to
* calculate the area this widget will need to sucessfully render its text later.

View File

@ -14,10 +14,11 @@
#pragma once
#include "font/text.hpp"
#include "gui/core/canvas.hpp"
#include "gui/core/widget_definition.hpp"
#include "gui/core/window_builder.hpp"
#include "gui/widgets/widget.hpp"
#include "font/text.hpp" // We want the file in src/
namespace gui2
{
@ -77,7 +78,7 @@ public:
protected:
/** Returns the id of the state.
*
* The current state is also the index canvas_.
* The current state is also the index canvases_.
*/
virtual unsigned get_state() const = 0;
@ -248,13 +249,13 @@ public:
// const versions will be added when needed
std::vector<canvas>& get_canvases()
{
return canvas_;
return canvases_;
}
canvas& get_canvas(const unsigned index)
{
assert(index < canvas_.size());
return canvas_[index];
assert(index < canvases_.size());
return canvases_[index];
}
virtual void set_text_alignment(const PangoAlignment text_alignment);
@ -376,16 +377,6 @@ private:
*/
t_string help_message_;
/**
* Holds all canvas objects for a styled_widget.
*
* A styled_widget can have multiple states, which are defined in the classes
* inheriting from us. For every state there is a separate canvas, which is
* stored here. When drawing the state is determined and that canvas is
* drawn.
*/
std::vector<canvas> canvas_;
/**
* Contains the pointer to the configuration.
*
@ -398,14 +389,14 @@ private:
resolution_definition_ptr config_;
/**
* Loads the configuration of the widget.
* Holds all canvas objects for a styled_widget.
*
* Controls have their definition stored in a definition object. In order to
* determine sizes and drawing the widget this definition needs to be
* loaded. The member definition_ contains the name of the definition and
* function load the proper configuration.
* A styled_widget can have multiple states, which are defined in the classes
* inheriting from us. For every state there is a separate canvas, which is
* stored here. When drawing the state is determined and that canvas is
* drawn.
*/
void definition_load_configuration(const std::string& control_type);
std::vector<canvas> canvases_;
public:
/**