diff --git a/projectfiles/VC12/wesnoth.vcxproj b/projectfiles/VC12/wesnoth.vcxproj
index 5305f1f00a863..7594c6acb3dd7 100644
--- a/projectfiles/VC12/wesnoth.vcxproj
+++ b/projectfiles/VC12/wesnoth.vcxproj
@@ -2581,6 +2581,14 @@
$(IntDir)Gui\Widgets\
$(IntDir)Gui\Widgets\
+
+ $(IntDir)Gui\Widgets
+ $(IntDir)Gui\Widgets
+ $(IntDir)Gui\Widgets
+ $(IntDir)Gui\Widgets
+ $(IntDir)Gui\Widgets
+ $(IntDir)Gui\Widgets
+
$(IntDir)Gui\Widgets\
$(IntDir)Gui\Widgets\
@@ -4344,6 +4352,7 @@
+
diff --git a/projectfiles/VC12/wesnoth.vcxproj.filters b/projectfiles/VC12/wesnoth.vcxproj.filters
index 194e8970eb663..335cb786e3597 100644
--- a/projectfiles/VC12/wesnoth.vcxproj.filters
+++ b/projectfiles/VC12/wesnoth.vcxproj.filters
@@ -1558,6 +1558,9 @@
Font
+
+ Gui\Widgets
+
@@ -3017,6 +3020,9 @@
Font
+
+ Gui\Widgets
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index bf31d70a5641b..6f29f6061d532 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -536,6 +536,7 @@ set(wesnoth-gui_widget_SRC
gui/widgets/scrollbar_container.cpp
gui/widgets/scrollbar_panel.cpp
gui/widgets/settings.cpp
+ gui/widgets/size_fixater.cpp
gui/widgets/slider.cpp
gui/widgets/spacer.cpp
gui/widgets/stacked_widget.cpp
diff --git a/src/SConscript b/src/SConscript
index 3bf33f508c436..7c0199bdbe8fe 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -466,6 +466,7 @@ wesnoth_sources = Split("""
gui/widgets/scrollbar_panel.cpp
gui/widgets/scrollbar.cpp
gui/widgets/settings.cpp
+ gui/widgets/size_fixater.cpp
gui/widgets/slider.cpp
gui/widgets/spacer.cpp
gui/widgets/stacked_widget.cpp
diff --git a/src/gui/widgets/container.hpp b/src/gui/widgets/container.hpp
index 3871ce3949916..6259e1042870d 100644
--- a/src/gui/widgets/container.hpp
+++ b/src/gui/widgets/container.hpp
@@ -85,7 +85,7 @@ class tcontainer_ : public tcontrol
/** See @ref twidget::demand_reduce_height. */
virtual void demand_reduce_height(const unsigned maximum_height) override;
-private:
+protected:
/** See @ref twidget::calculate_best_size. */
virtual tpoint calculate_best_size() const override;
diff --git a/src/gui/widgets/size_fixater.cpp b/src/gui/widgets/size_fixater.cpp
new file mode 100644
index 0000000000000..a1b1081773d05
--- /dev/null
+++ b/src/gui/widgets/size_fixater.cpp
@@ -0,0 +1,148 @@
+/*
+ Copyright (C) 2016 Jyrki Vesterinen
+ Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY.
+
+ See the COPYING file for more details.
+*/
+
+#define GETTEXT_DOMAIN "wesnoth-lib"
+
+#include "size_fixater.hpp"
+
+#include
+#include
+#include
+#include
+#include
+
+namespace gui2
+{
+
+REGISTER_WIDGET(size_fixater)
+
+void tsize_fixater::layout_children()
+{
+ assert(generator_ != nullptr);
+ assert(generator_->get_item_count() == 1);
+
+ generator_->item(0).layout_children();
+}
+
+void tsize_fixater::finalize(tbuilder_grid_const_ptr widget_builder)
+{
+ assert(generator_ != nullptr);
+
+ generator_->create_item(-1, widget_builder, string_map(), nullptr);
+
+ static const std::string id = "_content_grid";
+ grid().set_id(id);
+ twidget* old_grid = grid().swap_child(id, generator_, true);
+ delete old_grid;
+}
+
+tsize_fixater_definition::tsize_fixater_definition(const config& cfg) :
+ tcontrol_definition(cfg)
+{
+ DBG_GUI_P << "Parsing fixed size widget " << id << '\n';
+
+ load_resolutions(cfg);
+}
+
+/*WIKI
+ * @page = GUIWidgetDefinitionWML
+ * @order = 1_size_fixater
+ *
+ * == Size fixater ==
+ *
+ * A size fixater contains one child widget and forces it to have the specified size.
+ * This can be used, for example, when there are two list boxes in different rows of
+ * the same grid and it's desired that only one list box changes size when its
+ * contents change.
+ *
+ * A size fixater has no states.
+ * @begin{parent}{name="gui/"}
+ * @begin{tag}{name="size_fixater_definition"}{min=0}{max=-1}{super="generic/widget_definition"}
+ * @end{tag}{name="size_fixater_definition"}
+ * @end{tag}{name="gui/"}
+ */
+tsize_fixater_definition::tresolution::tresolution(const config& cfg) :
+ tresolution_definition_(cfg), grid(nullptr)
+{
+ const config& child = cfg.child("grid");
+ VALIDATE(child, _("No grid defined."));
+
+ grid = std::make_shared(child);
+}
+
+/*WIKI
+ * @page = GUIWidgetInstanceWML
+ * @order = 2_size_fixater
+ * @begin{parent}{name="gui/window/resolution/grid/row/column/"}
+ * @begin{tag}{name="size_fixater"}{min=0}{max=-1}{super="generic/widget_instance"}
+ * == Size fixater ==
+ *
+ * A size fixater contains one child widget and forces it to have the specified size.
+ * This can be used, for example, when there are two list boxes in different rows of
+ * the same grid and it's desired that only one list box changes size when its
+ * contents change.
+ *
+ * @begin{table}{config}
+ * widget & section & mandatory & The widget. $
+ * width & f_unsigned & mandatory & The width of the widget. $
+ * height & f_unsigned & mandatory & The height of the widget. $
+ * @end{table}
+ *
+ * The variables available are the same as for window resolution, see
+ * [[GuiToolkitWML#Resolution_2]] for the list of items.
+ * @end{tag}{name="size_fixater"}
+ * @end{parent}{name="gui/window/resolution/grid/row/column/"}
+ */
+
+namespace implementation
+{
+
+tbuilder_size_fixater::tbuilder_size_fixater(const config& cfg) :
+ tbuilder_control(cfg), width_(cfg["width"]), height_(cfg["height"]), content_(nullptr)
+{
+ VALIDATE(cfg.has_child("widget"), _("No widget defined."));
+ content_ = std::make_shared(cfg.child("widget"));
+}
+
+twidget* tbuilder_size_fixater::build() const
+{
+ tsize_fixater* widget = new tsize_fixater();
+
+ init_control(widget);
+
+ DBG_GUI_G << "Window builder: placed fixed size widget '" << id <<
+ "' with definition '" << definition << "'.\n";
+
+ auto conf = std::static_pointer_cast(widget->config());
+ assert(conf != nullptr);
+
+ widget->init_grid(conf->grid);
+
+ game_logic::map_formula_callable size = get_screen_size_variables();
+
+ const unsigned width = width_(size);
+ const unsigned height = height_(size);
+
+ VALIDATE(width > 0 && height > 0, _("Invalid size."));
+
+ widget->set_size(tpoint(width, height));
+
+ widget->finalize(content_);
+
+ return widget;
+}
+
+}
+
+}
\ No newline at end of file
diff --git a/src/gui/widgets/size_fixater.hpp b/src/gui/widgets/size_fixater.hpp
new file mode 100644
index 0000000000000..10f511d0e8ade
--- /dev/null
+++ b/src/gui/widgets/size_fixater.hpp
@@ -0,0 +1,136 @@
+/*
+ Copyright (C) 2016 Jyrki Vesterinen
+ Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY.
+
+ See the COPYING file for more details.
+*/
+
+#ifndef GUI_WIDGETS_SIZE_FIXATER_HPP_INCLUDED
+#define GUI_WIDGETS_SIZE_FIXATER_HPP_INCLUDED
+
+#include
+
+#include
+#include
+#include
+#include
+
+namespace gui2
+{
+
+ namespace implementation
+ {
+ struct tbuilder_size_fixater;
+ }
+
+ /* A fixed-size widget that wraps an arbitrary widget and forces it to the given size. */
+
+ class tsize_fixater : public tcontainer_
+ {
+ friend struct implementation::tbuilder_size_fixater;
+
+ public:
+ tsize_fixater() :
+ tcontainer_(1),
+ generator_(
+ tgenerator_::build(false, false, tgenerator_::independent, false))
+ {}
+
+ /** See @ref tcontrol::get_active. */
+ bool get_active() const override
+ {
+ return true;
+ }
+
+ /** See @ref tcontrol::get_state. */
+ unsigned get_state() const override
+ {
+ return 0;
+ }
+
+ /** See @ref twidget::layout_children. */
+ void layout_children() override;
+
+ void set_size(const tpoint& size)
+ {
+ size_ = size;
+ }
+
+ protected:
+ tpoint calculate_best_size() const override
+ {
+ return size_;
+ }
+
+ private:
+ tpoint size_;
+
+ /**
+ * Contains a pointer to the generator.
+ *
+ * The pointer is not owned by this class, it's stored in the content_grid_
+ * of the tcontainer_ base class and freed when its grid is freed.
+ */
+ tgenerator_* generator_;
+
+ /**
+ * Finishes the building initialization of the widget.
+ *
+ * @param widget_builder The builder to build the contents of the
+ * widget.
+ */
+ void finalize(tbuilder_grid_const_ptr widget_builder);
+
+ /** See @ref tcontrol::get_control_type. */
+ const std::string& get_control_type() const override
+ {
+ static const std::string control_type = "size_fixater";
+ return control_type;
+ }
+
+ /** See @ref tcontainer_::set_self_active. */
+ void set_self_active(const bool) override
+ {
+ // DO NOTHING
+ }
+ };
+
+ struct tsize_fixater_definition : public tcontrol_definition
+ {
+ explicit tsize_fixater_definition(const config& cfg);
+
+ struct tresolution : public tresolution_definition_
+ {
+ explicit tresolution(const config& cfg);
+
+ tbuilder_grid_ptr grid;
+ };
+ };
+
+ namespace implementation
+ {
+
+ struct tbuilder_size_fixater : public tbuilder_control
+ {
+ explicit tbuilder_size_fixater(const config& cfg);
+
+ using tbuilder_control::build;
+
+ twidget* build() const;
+
+ private:
+ tbuilder_grid_const_ptr content_;
+ tformula width_;
+ tformula height_;
+ };
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/src/gui/widgets/stacked_widget.cpp b/src/gui/widgets/stacked_widget.cpp
index 842f2197f8b91..efe1a91165476 100644
--- a/src/gui/widgets/stacked_widget.cpp
+++ b/src/gui/widgets/stacked_widget.cpp
@@ -16,11 +16,11 @@
#include "gui/widgets/stacked_widget.hpp"
-#include "gui/auxiliary/find_widget.hpp"
#include "gui/core/register_widget.hpp"
#include "gui/widgets/settings.hpp"
#include "gui/widgets/generator.hpp"
#include "gettext.hpp"
+#include "wml_exception.hpp"
#include "utils/functional.hpp"
@@ -57,42 +57,6 @@ void tstacked_widget::layout_children()
}
}
-namespace
-{
-
-/**
- * Swaps an item in a grid for another one.*/
-void swap_grid(tgrid* grid,
- tgrid* content_grid,
- twidget* widget,
- const std::string& id)
-{
- assert(content_grid);
- assert(widget);
-
- // Make sure the new child has same id.
- widget->set_id(id);
-
- // Get the container containing the wanted widget.
- tgrid* parent_grid = nullptr;
- if(grid) {
- parent_grid = find_widget(grid, id, false, false);
- }
- if(!parent_grid) {
- parent_grid = find_widget(content_grid, id, true, false);
- }
- parent_grid = dynamic_cast(parent_grid->parent());
- assert(parent_grid);
-
- // Replace the child.
- widget = parent_grid->swap_child(id, widget, false);
- assert(widget);
-
- delete widget;
-}
-
-} // namespace
-
void
tstacked_widget::finalize(std::vector widget_builder)
{
@@ -102,7 +66,11 @@ tstacked_widget::finalize(std::vector widget_builder)
{
generator_->create_item(-1, builder, empty_data, nullptr);
}
- swap_grid(nullptr, &grid(), generator_, "_content_grid");
+
+ static const std::string id = "_content_grid";
+ grid().set_id(id);
+ twidget* old_grid = grid().swap_child(id, generator_, true);
+ delete old_grid;
select_layer(-1);
}