diff --git a/src/gui/core/canvas.cpp b/src/gui/core/canvas.cpp index 1f1717d0cc2..bdb0da0aa71 100644 --- a/src/gui/core/canvas.cpp +++ b/src/gui/core/canvas.cpp @@ -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_); diff --git a/src/gui/core/canvas.hpp b/src/gui/core/canvas.hpp index ca31906cb8b..40dd91925d0 100644 --- a/src/gui/core/canvas.hpp +++ b/src/gui/core/canvas.hpp @@ -87,6 +87,9 @@ public: typedef std::shared_ptr const_shape_ptr; canvas(); + canvas(const canvas&) = delete; + canvas(canvas&& c); + ~canvas(); /** diff --git a/src/gui/core/widget_definition.cpp b/src/gui/core/widget_definition.cpp index 4bed7dffdf6..da02ed6aa19 100644 --- a/src/gui/core/widget_definition.cpp +++ b/src/gui/core/widget_definition.cpp @@ -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 diff --git a/src/gui/core/widget_definition.hpp b/src/gui/core/widget_definition.hpp index 3f35fdf09b2..d3ea3a8c00f 100644 --- a/src/gui/core/widget_definition.hpp +++ b/src/gui/core/widget_definition.hpp @@ -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 namespace gui2 @@ -35,7 +35,7 @@ struct state_definition { explicit state_definition(const config& cfg); - canvas canvas_; + config canvas_cfg_; }; diff --git a/src/gui/widgets/styled_widget.cpp b/src/gui/widgets/styled_widget.cpp index c231d9bb843..8f50bd5e062 100644 --- a/src/gui/widgets/styled_widget.cpp +++ b/src/gui/widgets/styled_widget.cpp @@ -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(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. diff --git a/src/gui/widgets/styled_widget.hpp b/src/gui/widgets/styled_widget.hpp index d76ff6a2a56..e3371fe4d76 100644 --- a/src/gui/widgets/styled_widget.hpp +++ b/src/gui/widgets/styled_widget.hpp @@ -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& 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_; - /** * 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 canvases_; public: /**