widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #16912
[Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
Benedikt Straub has proposed merging lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands.
Commit message:
Users can define and save their own profiles of economy target quantities.
Redesigned the economy options menu.
WaresDisplays and will relayout themselves dynamically on fullscreen switch.
Requested reviews:
Widelands Developers (widelands-dev)
Related bugs:
Bug #1827696 in widelands: "Allow users to define their own economy default settings"
https://bugs.launchpad.net/widelands/+bug/1827696
For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/economy-target-profiles/+merge/366987
For each tribe, I added two profiles: "Efficiency" is equal to the changes proposed previously, and "Stockpile" is for people who, well, like to stockpile stuff. Additionally there is an unchangeable "Default" pseudo-profile that resets items to the default settings.
To apply a profile, select the items you wish to change and choose the profile from the dropdown. Use "Save" to save your current settings as a profile. The save window also allows you to delete profiles.
--
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands.
=== added file 'data/images/ui_basic/scrollbar_down_fast.png'
Binary files data/images/ui_basic/scrollbar_down_fast.png 1970-01-01 00:00:00 +0000 and data/images/ui_basic/scrollbar_down_fast.png 2019-05-06 13:53:16 +0000 differ
=== added file 'data/images/ui_basic/scrollbar_up_fast.png'
Binary files data/images/ui_basic/scrollbar_up_fast.png 1970-01-01 00:00:00 +0000 and data/images/ui_basic/scrollbar_up_fast.png 2019-05-06 13:53:16 +0000 differ
=== added directory 'data/tribes/economy_profiles'
=== added file 'data/tribes/economy_profiles/atlanteans'
--- data/tribes/economy_profiles/atlanteans 1970-01-01 00:00:00 +0000
+++ data/tribes/economy_profiles/atlanteans 2019-05-06 13:53:16 +0000
@@ -0,0 +1,89 @@
+# Automatically created by Widelands bzr9094[economy-target-profiles] (Debug)
+
+[Default]
+0=_"Efficiency"
+1=_"Stockpile"
+
+[0]
+blackroot_flour="1"
+atlanteans_bread="20"
+bread_paddle="0"
+buckets="0"
+coal="5"
+cornmeal="3"
+diamond="3"
+fire_tongs="1"
+fishing_net="2"
+gold="1"
+gold_ore="1"
+gold_thread="0"
+granite="10"
+hammer="0"
+hook_pole="0"
+hunting_bow="1"
+iron="5"
+iron_ore="1"
+milking_tongs="0"
+pick="1"
+planks="1"
+quartz="3"
+saw="0"
+scythe="0"
+shield_advanced="0"
+shield_steel="0"
+shovel="0"
+smoked_fish="5"
+smoked_meat="3"
+spidercloth="5"
+spider_silk="5"
+tabard="1"
+tabard_golden="0"
+trident_double="0"
+trident_heavy_double="0"
+trident_light="1"
+trident_long="0"
+trident_steel="0"
+atlanteans_horse="1"
+atlanteans_soldier="10"
+
+[1]
+blackroot_flour="20"
+atlanteans_bread="30"
+bread_paddle="1"
+buckets="2"
+coal="25"
+cornmeal="20"
+diamond="10"
+fire_tongs="1"
+fishing_net="2"
+gold="20"
+gold_ore="15"
+gold_thread="5"
+granite="30"
+hammer="2"
+hook_pole="1"
+hunting_bow="1"
+iron="25"
+iron_ore="20"
+milking_tongs="1"
+pick="3"
+planks="40"
+quartz="10"
+saw="2"
+scythe="1"
+shield_advanced="1"
+shield_steel="1"
+shovel="2"
+smoked_fish="40"
+smoked_meat="25"
+spidercloth="20"
+spider_silk="15"
+tabard="30"
+tabard_golden="1"
+trident_double="1"
+trident_heavy_double="1"
+trident_light="30"
+trident_long="1"
+trident_steel="1"
+atlanteans_horse="20"
+atlanteans_soldier="20"
=== added file 'data/tribes/economy_profiles/barbarians'
--- data/tribes/economy_profiles/barbarians 1970-01-01 00:00:00 +0000
+++ data/tribes/economy_profiles/barbarians 2019-05-06 13:53:16 +0000
@@ -0,0 +1,81 @@
+# Automatically created by Widelands bzr9094[economy-target-profiles] (Debug)
+
+[Default]
+0=_"Efficiency"
+1=_"Stockpile"
+
+[0]
+ax="1"
+ax_battle="0"
+ax_broad="0"
+ax_bronze="0"
+ax_sharp="0"
+ax_warriors="0"
+beer="0"
+beer_strong="1"
+blackwood="40"
+barbarians_bread="5"
+bread_paddle="0"
+cloth="10"
+coal="20"
+felling_ax="0"
+fire_tongs="1"
+fishing_rod="0"
+gold="1"
+gold_ore="1"
+granite="10"
+grout="1"
+hammer="1"
+helmet="0"
+helmet_mask="0"
+helmet_warhelm="0"
+hunting_spear="0"
+iron="5"
+iron_ore="5"
+kitchen_tools="0"
+meal="5"
+pick="1"
+ration="20"
+scythe="0"
+shovel="0"
+snack="0"
+barbarians_ox="1"
+barbarians_soldier="10"
+
+[1]
+ax="30"
+ax_battle="1"
+ax_broad="1"
+ax_bronze="1"
+ax_sharp="1"
+ax_warriors="1"
+beer="15"
+beer_strong="20"
+blackwood="45"
+barbarians_bread="25"
+bread_paddle="1"
+cloth="10"
+coal="25"
+felling_ax="5"
+fire_tongs="1"
+fishing_rod="1"
+gold="20"
+gold_ore="15"
+granite="30"
+grout="20"
+hammer="2"
+helmet="1"
+helmet_mask="1"
+helmet_warhelm="1"
+hunting_spear="1"
+iron="25"
+iron_ore="20"
+kitchen_tools="1"
+meal="15"
+pick="2"
+ration="30"
+scythe="1"
+shovel="1"
+snack="20"
+barbarians_ox="20"
+barbarians_soldier="20"
=== added file 'data/tribes/economy_profiles/empire'
--- data/tribes/economy_profiles/empire 1970-01-01 00:00:00 +0000
+++ data/tribes/economy_profiles/empire 2019-05-06 13:53:16 +0000
@@ -0,0 +1,89 @@
+# Automatically created by Widelands bzr9094[economy-target-profiles] (Debug)
+
+[Default]
+0=_"Efficiency"
+1=_"Stockpile"
+
+[0]
+armor="1"
+armor_chain="1"
+armor_gilded="1"
+armor_helmet="30"
+basket="1"
+beer="1"
+empire_bread="20"
+bread_paddle="0"
+cloth="15"
+coal="5"
+felling_ax="0"
+fire_tongs="1"
+fishing_rod="0"
+flour="20"
+gold="1"
+gold_ore="1"
+granite="10"
+hammer="0"
+hunting_spear="0"
+iron="5"
+iron_ore="3"
+kitchen_tools="0"
+marble="30"
+marble_column="10"
+meal="5"
+meat="20"
+pick="1"
+planks="1"
+ration="20"
+saw="0"
+scythe="0"
+shovel="0"
+spear="1"
+spear_advanced="1"
+spear_heavy="1"
+spear_war="1"
+spear_wooden="30"
+wool="10"
+empire_donkey="1"
+empire_soldier="10"
+
+[1]
+armor="1"
+armor_chain="1"
+armor_gilded="1"
+armor_helmet="30"
+basket="1"
+beer="20"
+empire_bread="30"
+bread_paddle="1"
+cloth="15"
+coal="25"
+felling_ax="3"
+fire_tongs="1"
+fishing_rod="1"
+flour="25"
+gold="20"
+gold_ore="15"
+granite="30"
+hammer="2"
+hunting_spear="1"
+iron="25"
+iron_ore="20"
+kitchen_tools="1"
+marble="35"
+marble_column="15"
+meal="20"
+meat="30"
+pick="2"
+planks="40"
+ration="25"
+saw="1"
+scythe="1"
+shovel="1"
+spear="1"
+spear_advanced="1"
+spear_heavy="1"
+spear_war="1"
+spear_wooden="30"
+wool="15"
+empire_donkey="20"
+empire_soldier="20"
=== added file 'data/tribes/economy_profiles/frisians'
--- data/tribes/economy_profiles/frisians 1970-01-01 00:00:00 +0000
+++ data/tribes/economy_profiles/frisians 2019-05-06 13:53:16 +0000
@@ -0,0 +1,93 @@
+# Automatically created by Widelands bzr9093[economy-target-profiles] (Debug)
+
+[Default]
+0=_"Efficiency"
+1=_"Stockpile"
+
+[0]
+clay="30"
+brick="40"
+bread_frisians="20"
+honey_bread="20"
+mead="15"
+fur="10"
+fur_garment="30"
+fur_garment_studded="2"
+fur_garment_golden="2"
+helmet_golden="2"
+sword_short="30"
+sword_long="2"
+sword_broad="2"
+sword_double="2"
+needles="1"
+basket="1"
+beer="1"
+bread_paddle="1"
+cloth="10"
+coal="20"
+felling_ax="0"
+fire_tongs="1"
+fish="20"
+fishing_net="2"
+gold="1"
+gold_ore="1"
+granite="10"
+hammer="1"
+helmet="0"
+hunting_spear="0"
+iron="5"
+iron_ore="3"
+kitchen_tools="0"
+meal="1"
+pick="1"
+ration="20"
+scythe="0"
+shovel="0"
+smoked_fish="20"
+smoked_meat="10"
+frisians_reindeer="1"
+frisians_soldier="10"
+
+[1]
+clay="35"
+brick="50"
+bread_frisians="30"
+honey_bread="30"
+mead="30"
+fur="20"
+fur_garment="30"
+fur_garment_studded="2"
+fur_garment_golden="2"
+helmet_golden="2"
+sword_short="30"
+sword_long="2"
+sword_broad="2"
+sword_double="2"
+needles="1"
+basket="1"
+beer="30"
+bread_paddle="1"
+cloth="10"
+coal="35"
+felling_ax="3"
+fire_tongs="2"
+fish="40"
+fishing_net="2"
+gold="20"
+gold_ore="15"
+granite="35"
+hammer="3"
+helmet="2"
+hunting_spear="1"
+iron="25"
+iron_ore="20"
+kitchen_tools="2"
+meal="10"
+pick="3"
+ration="30"
+scythe="2"
+shovel="5"
+smoked_fish="30"
+smoked_meat="20"
+frisians_reindeer="20"
+frisians_soldier="20"
=== modified file 'src/logic/filesystem_constants.h'
--- src/logic/filesystem_constants.h 2019-04-18 16:50:35 +0000
+++ src/logic/filesystem_constants.h 2019-05-06 13:53:16 +0000
@@ -78,4 +78,6 @@
/// Filesystem names for config
const std::string kConfigFile = "config";
+const std::string kEconomyProfilesDir = "tribes/economy_profiles";
+
#endif // end of include guard: WL_LOGIC_FILESYSTEM_CONSTANTS_H
=== modified file 'src/logic/map_objects/tribes/tribe_descr.cc'
--- src/logic/map_objects/tribes/tribe_descr.cc 2019-05-04 10:47:44 +0000
+++ src/logic/map_objects/tribes/tribe_descr.cc 2019-05-06 13:53:16 +0000
@@ -89,8 +89,6 @@
load_roads("busy", &busy_road_paths_);
items_table = table.get_table("wares_order");
- wares_order_coords_.resize(tribes_.nrwares());
- int columnindex = 0;
for (const int key : items_table->keys<int>()) {
std::vector<DescriptionIndex> column;
std::vector<std::string> warenames =
@@ -104,7 +102,6 @@
}
wares_.insert(wareindex);
column.push_back(wareindex);
- wares_order_coords_[wareindex] = std::make_pair(columnindex, rowindex);
} catch (const WException& e) {
throw GameDataError(
"Failed adding ware '%s: %s", warenames[rowindex].c_str(), e.what());
@@ -112,13 +109,10 @@
}
if (!column.empty()) {
wares_order_.push_back(column);
- ++columnindex;
}
}
items_table = table.get_table("workers_order");
- workers_order_coords_.resize(tribes_.nrworkers());
- columnindex = 0;
for (const int key : items_table->keys<int>()) {
std::vector<DescriptionIndex> column;
std::vector<std::string> workernames =
@@ -132,7 +126,6 @@
}
workers_.insert(workerindex);
column.push_back(workerindex);
- workers_order_coords_[workerindex] = std::make_pair(columnindex, rowindex);
const WorkerDescr& worker_descr = *tribes_.get_worker_descr(workerindex);
if (worker_descr.is_buildable() && worker_descr.buildcost().empty()) {
@@ -145,7 +138,6 @@
}
if (!column.empty()) {
workers_order_.push_back(column);
- ++columnindex;
}
}
@@ -423,38 +415,6 @@
return list->second.find(lowest)->second;
}
-void TribeDescr::resize_ware_orders(size_t maxLength) {
- bool need_resize = false;
-
- // Check if we actually need to resize.
- for (WaresOrder::iterator it = wares_order_.begin(); it != wares_order_.end(); ++it) {
- if (it->size() > maxLength) {
- need_resize = true;
- }
- }
-
- // Build new smaller wares_order.
- if (need_resize) {
- WaresOrder new_wares_order;
- for (WaresOrder::iterator it = wares_order_.begin(); it != wares_order_.end(); ++it) {
- new_wares_order.push_back(std::vector<Widelands::DescriptionIndex>());
- for (std::vector<Widelands::DescriptionIndex>::iterator it2 = it->begin();
- it2 != it->end(); ++it2) {
- if (new_wares_order.rbegin()->size() >= maxLength) {
- new_wares_order.push_back(std::vector<Widelands::DescriptionIndex>());
- }
- new_wares_order.rbegin()->push_back(*it2);
- wares_order_coords_[*it2].first = new_wares_order.size() - 1;
- wares_order_coords_[*it2].second = new_wares_order.rbegin()->size() - 1;
- }
- }
-
- // Remove old array.
- wares_order_.clear();
- wares_order_ = new_wares_order;
- }
-}
-
void TribeDescr::add_building(const std::string& buildingname) {
try {
DescriptionIndex index = tribes_.safe_building_index(buildingname);
=== modified file 'src/logic/map_objects/tribes/tribe_descr.h'
--- src/logic/map_objects/tribes/tribe_descr.h 2019-03-01 04:19:53 +0000
+++ src/logic/map_objects/tribes/tribe_descr.h 2019-05-06 13:53:16 +0000
@@ -149,22 +149,13 @@
}
using WaresOrder = std::vector<std::vector<Widelands::DescriptionIndex>>;
- using WaresOrderCoords = std::vector<std::pair<uint32_t, uint32_t>>;
const WaresOrder& wares_order() const {
return wares_order_;
}
- const WaresOrderCoords& wares_order_coords() const {
- return wares_order_coords_;
- }
const WaresOrder& workers_order() const {
return workers_order_;
}
- const WaresOrderCoords& workers_order_coords() const {
- return workers_order_coords_;
- }
-
- void resize_ware_orders(size_t maxLength);
const std::vector<std::string>& get_ship_names() const {
return ship_names_;
@@ -215,9 +206,7 @@
std::vector<DescriptionIndex> trainingsites_;
// Order and positioning of wares in the warehouse display
WaresOrder wares_order_;
- WaresOrderCoords wares_order_coords_;
WaresOrder workers_order_;
- WaresOrderCoords workers_order_coords_;
std::vector<Widelands::TribeBasicInfo::Initialization> initializations_;
=== modified file 'src/logic/map_objects/tribes/tribes.cc'
--- src/logic/map_objects/tribes/tribes.cc 2019-03-01 04:19:53 +0000
+++ src/logic/map_objects/tribes/tribes.cc 2019-05-06 13:53:16 +0000
@@ -340,14 +340,9 @@
// Calculate the trainingsites proportions.
postload_calculate_trainingsites_proportions();
- // Resize the configuration of our wares if they won't fit in the current window (12 = info label
- // size).
- // Also, do some final checks on the gamedata
- int number = (g_gr->get_yres() - 290) / (WARE_MENU_PIC_HEIGHT + WARE_MENU_PIC_PAD_Y + 12);
+ // Some final checks on the gamedata
for (DescriptionIndex i = 0; i < tribes_->size(); ++i) {
TribeDescr* tribe_descr = tribes_->get_mutable(i);
- tribe_descr->resize_ware_orders(number);
-
// Verify that the preciousness has been set for all of the tribe's wares
for (const DescriptionIndex wi : tribe_descr->wares()) {
if (tribe_descr->get_ware_descr(wi)->preciousness(tribe_descr->name()) == kInvalidWare) {
=== modified file 'src/logic/map_objects/tribes/ware_descr.h'
--- src/logic/map_objects/tribes/ware_descr.h 2019-02-27 19:00:36 +0000
+++ src/logic/map_objects/tribes/ware_descr.h 2019-05-06 13:53:16 +0000
@@ -33,10 +33,8 @@
class Image;
class LuaTable;
-#define WARE_MENU_PIC_WIDTH 24 //!< Default width for ware's menu icons
-#define WARE_MENU_PIC_HEIGHT 24 //!< Default height for ware's menu icons
-#define WARE_MENU_PIC_PAD_X 3 //!< Default padding between menu icons
-#define WARE_MENU_PIC_PAD_Y 4 //!< Default padding between menu icons
+constexpr int kWareMenuPicWidth = 24; //!< Default width for ware's menu icons
+constexpr int kWareMenuPicHeight = 24; //!< Default height for ware's menu icons
namespace Widelands {
=== modified file 'src/logic/playercommand.h'
--- src/logic/playercommand.h 2019-02-23 11:00:49 +0000
+++ src/logic/playercommand.h 2019-05-06 13:53:16 +0000
@@ -581,6 +581,7 @@
uint32_t permanent_;
};
+// TODO(Nordfriese): CmdResetWareTargetQuantity can be removed when we next break savegame compatibility
struct CmdResetWareTargetQuantity : public CmdChangeTargetQuantity {
CmdResetWareTargetQuantity() : CmdChangeTargetQuantity() {
}
@@ -629,6 +630,7 @@
uint32_t permanent_;
};
+// TODO(Nordfriese): CmdResetWorkerTargetQuantity can be removed when we next break savegame compatibility
struct CmdResetWorkerTargetQuantity : public CmdChangeTargetQuantity {
CmdResetWorkerTargetQuantity() : CmdChangeTargetQuantity() {
}
=== modified file 'src/wui/CMakeLists.txt'
--- src/wui/CMakeLists.txt 2019-05-04 15:37:33 +0000
+++ src/wui/CMakeLists.txt 2019-05-06 13:53:16 +0000
@@ -44,8 +44,10 @@
graphic
logic
logic_commands
+ logic_filesystem_constants
logic_map_objects
notifications
+ profile
ui_basic
wui_waresdisplay
)
=== modified file 'src/wui/economy_options_window.cc'
--- src/wui/economy_options_window.cc 2019-02-23 11:00:49 +0000
+++ src/wui/economy_options_window.cc 2019-05-06 13:53:16 +0000
@@ -19,36 +19,98 @@
#include "wui/economy_options_window.h"
+#include <memory>
+
#include <boost/lexical_cast.hpp>
#include "graphic/graphic.h"
#include "logic/editor_game_base.h"
+#include "logic/filesystem_constants.h"
#include "logic/map_objects/tribes/ware_descr.h"
#include "logic/map_objects/tribes/worker_descr.h"
#include "logic/player.h"
#include "logic/playercommand.h"
+#include "profile/profile.h"
#include "ui_basic/button.h"
+#include "ui_basic/editbox.h"
+#include "ui_basic/messagebox.h"
+#include "ui_basic/table.h"
static const char pic_tab_wares[] = "images/wui/buildings/menu_tab_wares.png";
static const char pic_tab_workers[] = "images/wui/buildings/menu_tab_workers.png";
+constexpr int kDesiredWidth = 216;
+
+static inline int32_t calc_hgap(int32_t columns, int32_t total_w) {
+ return (total_w - columns * kWareMenuPicWidth) / (columns - 1);
+}
+
EconomyOptionsWindow::EconomyOptionsWindow(UI::Panel* parent,
Widelands::Economy* economy,
bool can_act)
: UI::Window(parent, "economy_options", 0, 0, 0, 0, _("Economy options")),
+ main_box_(this, 0, 0, UI::Box::Vertical),
serial_(economy->serial()),
player_(&economy->owner()),
tabpanel_(this, UI::TabPanelStyle::kWuiDark),
- ware_panel_(new EconomyOptionsPanel(&tabpanel_, serial_, player_, can_act, Widelands::wwWARE)),
+ ware_panel_(new EconomyOptionsPanel(&tabpanel_, this, serial_, player_, can_act, Widelands::wwWARE, kDesiredWidth)),
worker_panel_(
- new EconomyOptionsPanel(&tabpanel_, serial_, player_, can_act, Widelands::wwWORKER)) {
- set_center_panel(&tabpanel_);
+ new EconomyOptionsPanel(&tabpanel_, this, serial_, player_, can_act, Widelands::wwWORKER, kDesiredWidth)),
+ dropdown_box_(this, 0, 0, UI::Box::Horizontal),
+ dropdown_(&dropdown_box_, 0, 0, 174, 200, 34, "", UI::DropdownType::kTextual, UI::PanelStyle::kWui) {
+ set_center_panel(&main_box_);
tabpanel_.add("wares", g_gr->images().get(pic_tab_wares), ware_panel_, _("Wares"));
tabpanel_.add("workers", g_gr->images().get(pic_tab_workers), worker_panel_, _("Workers"));
+
+ UI::Box* buttons = new UI::Box(this, 0, 0, UI::Box::Horizontal);
+ UI::Button* b = new UI::Button(buttons, "decrease_target_fast", 0, 0, 44, 28, UI::ButtonStyle::kWuiSecondary,
+ g_gr->images().get("images/ui_basic/scrollbar_down_fast.png"), _("Decrease target by 10"));
+ b->sigclicked.connect([this] { change_target(-10); });
+ buttons->add(b);
+ b->set_repeating(true);
+ buttons->add_space(8);
+ b = new UI::Button(buttons, "decrease_target", 0, 0, 44, 28, UI::ButtonStyle::kWuiSecondary,
+ g_gr->images().get("images/ui_basic/scrollbar_down.png"), _("Decrease target"));
+ b->sigclicked.connect([this] { change_target(-1); });
+ buttons->add(b);
+ b->set_repeating(true);
+ buttons->add_space(24);
+
+ b = new UI::Button(buttons, "increase_target", 0, 0, 44, 28, UI::ButtonStyle::kWuiSecondary,
+ g_gr->images().get("images/ui_basic/scrollbar_up.png"), _("Increase target"));
+ b->sigclicked.connect([this] { change_target(1); });
+ buttons->add(b);
+ b->set_repeating(true);
+ buttons->add_space(8);
+ b = new UI::Button(buttons, "increase_target_fast", 0, 0, 44, 28, UI::ButtonStyle::kWuiSecondary,
+ g_gr->images().get("images/ui_basic/scrollbar_up_fast.png"), _("Increase target by 10"));
+ b->sigclicked.connect([this] { change_target(10); });
+ buttons->add(b);
+ b->set_repeating(true);
+
+ dropdown_.set_tooltip(_("Profile to apply to the selected items"));
+ dropdown_box_.set_size(40, 20); // Prevent assert failures
+ dropdown_box_.add(&dropdown_, UI::Box::Resizing::kFullSize);
+ dropdown_.selected.connect([this] { reset_target(); });
+
+ b = new UI::Button(&dropdown_box_, "save_targets", 0, 0, 34, 34, UI::ButtonStyle::kWuiMenu,
+ g_gr->images().get("images/wui/menus/menu_save_game.png"), _("Save target settings"));
+ b->sigclicked.connect([this] { create_target(); });
+ dropdown_box_.add_space(8);
+ dropdown_box_.add(b);
+
+ main_box_.add(&tabpanel_, UI::Box::Resizing::kAlign, UI::Align::kCenter);
+ main_box_.add_space(8);
+ main_box_.add(buttons, UI::Box::Resizing::kAlign, UI::Align::kCenter);
+ main_box_.add_space(8);
+ main_box_.add(&dropdown_box_, UI::Box::Resizing::kAlign, UI::Align::kCenter);
+
economy->set_has_window(true);
economynotes_subscriber_ = Notifications::subscribe<Widelands::NoteEconomy>(
[this](const Widelands::NoteEconomy& note) { on_economy_note(note); });
+
+ read_targets();
}
EconomyOptionsWindow::~EconomyOptionsWindow() {
@@ -81,6 +143,20 @@
}
}
+void EconomyOptionsWindow::layout() {
+ int w, h;
+ tabpanel_.get_desired_size(&w, &h);
+ main_box_.set_desired_size(w, h + 78);
+ update_desired_size();
+ UI::Window::layout();
+}
+
+void EconomyOptionsWindow::EconomyOptionsPanel::update_desired_size() {
+ display_.set_hgap(std::max(3, calc_hgap(display_.get_extent().w, kDesiredWidth)));
+ Box::update_desired_size();
+ get_parent()->layout();
+}
+
EconomyOptionsWindow::TargetWaresDisplay::TargetWaresDisplay(UI::Panel* const parent,
int32_t const x,
int32_t const y,
@@ -129,42 +205,26 @@
* Wraps the wares/workers display together with some buttons
*/
EconomyOptionsWindow::EconomyOptionsPanel::EconomyOptionsPanel(UI::Panel* parent,
+ EconomyOptionsWindow* eco_window,
Widelands::Serial serial,
Widelands::Player* player,
bool can_act,
- Widelands::WareWorker type)
+ Widelands::WareWorker type,
+ int32_t min_w)
: UI::Box(parent, 0, 0, UI::Box::Vertical),
serial_(serial),
player_(player),
type_(type),
can_act_(can_act),
- display_(this, 0, 0, serial_, player_, type_, can_act_) {
+ display_(this, 0, 0, serial_, player_, type_, can_act_),
+ economy_options_window_(eco_window) {
add(&display_, UI::Box::Resizing::kFullSize);
+ display_.set_hgap(std::max(3, calc_hgap(display_.get_extent().w, min_w)));
+
if (!can_act_) {
return;
}
- UI::Box* buttons = new UI::Box(this, 0, 0, UI::Box::Horizontal);
- add(buttons);
-
- UI::Button* b = new UI::Button(buttons, "decrease_target", 0, 0, 34, 34,
- UI::ButtonStyle::kWuiMenu, "-", _("Decrease target"));
- b->sigclicked.connect(boost::bind(&EconomyOptionsPanel::change_target, this, -1));
- buttons->add(b);
- b->set_repeating(true);
- buttons->add_space(8);
-
- b = new UI::Button(buttons, "increase_target", 0, 0, 34, 34, UI::ButtonStyle::kWuiMenu, "+",
- _("Increase target"));
- b->sigclicked.connect(boost::bind(&EconomyOptionsPanel::change_target, this, 1));
- buttons->add(b);
- b->set_repeating(true);
- buttons->add_space(8);
-
- b = new UI::Button(
- buttons, "reset_target", 0, 0, 34, 34, UI::ButtonStyle::kWuiMenu, "R", _("Reset to default"));
- b->sigclicked.connect(boost::bind(&EconomyOptionsPanel::reset_target, this));
- buttons->add(b);
}
void EconomyOptionsWindow::EconomyOptionsPanel::set_economy(Widelands::Serial serial) {
@@ -172,7 +232,26 @@
display_.set_economy(serial);
}
-void EconomyOptionsWindow::EconomyOptionsPanel::change_target(int amount) {
+void EconomyOptionsWindow::change_target(int amount) {
+ if (tabpanel_.active() == 0) {
+ ware_panel_->change_target(amount);
+ } else {
+ worker_panel_->change_target(amount);
+ }
+}
+
+void EconomyOptionsWindow::reset_target() {
+ if (tabpanel_.active() == 0) {
+ ware_panel_->reset_target();
+ } else {
+ worker_panel_->reset_target();
+ }
+}
+
+void EconomyOptionsWindow::EconomyOptionsPanel::change_target(int delta) {
+ if (delta == 0) {
+ return;
+ }
Widelands::Economy* economy = player_->get_economy(serial_);
if (economy == nullptr) {
die();
@@ -186,35 +265,286 @@
const Widelands::Economy::TargetQuantity& tq = is_wares ?
economy->ware_target_quantity(index) :
economy->worker_target_quantity(index);
- // Don't allow negative new amount.
- if (amount >= 0 || -amount <= static_cast<int>(tq.permanent)) {
- if (is_wares) {
- game.send_player_command(*new Widelands::CmdSetWareTargetQuantity(
- game.get_gametime(), player_->player_number(), serial_, index,
- tq.permanent + amount));
+ // Don't allow negative new amount
+ const int old_amount = static_cast<int>(tq.permanent);
+ const int new_amount = std::max(0, old_amount + delta);
+ if (new_amount == old_amount) {
+ continue;
+ }
+ if (is_wares) {
+ game.send_player_command(*new Widelands::CmdSetWareTargetQuantity(
+ game.get_gametime(), player_->player_number(), serial_, index, new_amount));
+ } else {
+ game.send_player_command(*new Widelands::CmdSetWorkerTargetQuantity(
+ game.get_gametime(), player_->player_number(), serial_, index, new_amount));
+ }
+ }
+ }
+}
+
+void EconomyOptionsWindow::EconomyOptionsPanel::reset_target() {
+ Widelands::Game& game = dynamic_cast<Widelands::Game&>(player_->egbase());
+ const bool is_wares = type_ == Widelands::wwWARE;
+ const auto& items = is_wares ? player_->tribe().wares() : player_->tribe().workers();
+ const PredefinedTargets settings = economy_options_window_->get_selected_target();
+ for (const Widelands::DescriptionIndex& index : items) {
+ if (display_.ware_selected(index)) {
+ if (is_wares) {
+ game.send_player_command(*new Widelands::CmdSetWareTargetQuantity(
+ game.get_gametime(), player_->player_number(), serial_, index, settings.wares.at(index)));
+ } else {
+ game.send_player_command(*new Widelands::CmdSetWorkerTargetQuantity(
+ game.get_gametime(), player_->player_number(), serial_, index, settings.workers.at(index)));
+ }
+ }
+ }
+}
+
+void EconomyOptionsWindow::update_profiles(const std::string& select) {
+ dropdown_.clear();
+ for (const auto& pair : predefined_targets_) {
+ dropdown_.add(_(pair.first), pair.first, nullptr, pair.first == select);
+ }
+}
+
+struct SaveProfileWindow : public UI::Window {
+ void update_save_enabled() {
+ const std::string& text = profile_name_.text();
+ if (text.empty() || text == kDefaultEconomyProfile) {
+ save_.set_enabled(false);
+ save_.set_tooltip(text.empty() ? _("The profile name cannot be empty") :
+ _("The default profile cannot be overwritten"));
+ } else {
+ save_.set_enabled(true);
+ save_.set_tooltip(_("Save the profile under this name"));
+ }
+ }
+
+ void table_selection_changed() {
+ if (!table_.has_selection()) {
+ delete_.set_enabled(false);
+ delete_.set_tooltip("");
+ return;
+ }
+ const std::string& sel = table_[table_.selection_index()];
+ if (sel == kDefaultEconomyProfile) {
+ delete_.set_tooltip(_("The default profile cannot be deleted"));
+ delete_.set_enabled(false);
+ } else {
+ delete_.set_tooltip(_("Delete the selected profiles"));
+ delete_.set_enabled(true);
+ }
+ profile_name_.set_text(sel);
+ update_save_enabled();
+ }
+
+ void close(bool ok) {
+ end_modal(ok ? UI::Panel::Returncodes::kOk : UI::Panel::Returncodes::kBack);
+ die();
+ }
+
+ void update_table() {
+ table_.clear();
+ for (const auto& pair : economy_options_->get_predefined_targets()) {
+ table_.add(pair.first).set_string(0, _(pair.first));
+ }
+ layout();
+ }
+
+ void save() {
+ const std::string name = profile_name_.text();
+ assert(!name.empty());
+ assert(name != kDefaultEconomyProfile);
+ for (const auto& pair : economy_options_->get_predefined_targets()) {
+ if (pair.first == name) {
+ UI::WLMessageBox m(this, _("Overwrite?"),
+ _("A profile with this name already exists.\nDo you wish to replace it?"),
+ UI::WLMessageBox::MBoxType::kOkCancel);
+ if (m.run<UI::Panel::Returncodes>() != UI::Panel::Returncodes::kOk) {
+ return;
+ }
+ break;
+ }
+ }
+ economy_options_->do_create_target(name);
+ close(true);
+ }
+
+ void delete_selected() {
+ assert(table_.has_selection());
+ auto& map = economy_options_->get_predefined_targets();
+ const std::string& name = table_[table_.selection_index()];
+ assert(name != kDefaultEconomyProfile);
+ for (auto it = map.begin(); it != map.end(); ++it) {
+ if (it->first == name) {
+ map.erase(it);
+ break;
+ }
+ }
+ economy_options_->save_targets();
+ update_table();
+ }
+
+ explicit SaveProfileWindow(UI::Panel* parent, EconomyOptionsWindow* eco)
+ : UI::Window(parent, "save_economy_options_profile", 0, 0, 0, 0, _("Save Profile")),
+ economy_options_(eco),
+ main_box_(this, 0, 0, UI::Box::Vertical),
+ table_box_(&main_box_, 0, 0, UI::Box::Vertical),
+ table_(&table_box_, 0, 0, 460, 120, UI::PanelStyle::kWui),
+ buttons_box_(&main_box_, 0, 0, UI::Box::Horizontal),
+ profile_name_(&buttons_box_, 0, 0, 240, 0, 0, UI::PanelStyle::kWui),
+ save_(&buttons_box_, "save", 0, 0, 80, 34, UI::ButtonStyle::kWuiPrimary, _("Save")),
+ cancel_(&buttons_box_, "cancel", 0, 0, 80, 34, UI::ButtonStyle::kWuiSecondary, _("Cancel")),
+ delete_(&buttons_box_, "delete", 0, 0, 80, 34, UI::ButtonStyle::kWuiSecondary, _("Delete")) {
+ table_.add_column(200, _("Existing Profiles"));
+ update_table();
+
+ table_.selected.connect([this](uint32_t) { table_selection_changed(); });
+ profile_name_.changed.connect([this] { update_save_enabled(); });
+ profile_name_.ok.connect([this] { save(); });
+ profile_name_.cancel.connect([this] { close(false); });
+ save_.sigclicked.connect([this] { save(); });
+ cancel_.sigclicked.connect([this] { close(false); });
+ delete_.sigclicked.connect([this] { delete_selected(); });
+
+ table_box_.add(&table_, UI::Box::Resizing::kFullSize);
+ buttons_box_.add(&profile_name_, UI::Box::Resizing::kFullSize);
+ buttons_box_.add(&save_);
+ buttons_box_.add(&cancel_);
+ buttons_box_.add(&delete_);
+ main_box_.add(&table_box_, UI::Box::Resizing::kFullSize);
+ main_box_.add(&buttons_box_, UI::Box::Resizing::kFullSize);
+ set_center_panel(&main_box_);
+
+ table_selection_changed();
+ update_save_enabled();
+ }
+ ~SaveProfileWindow() {
+ }
+
+private:
+ EconomyOptionsWindow* economy_options_;
+ UI::Box main_box_;
+ UI::Box table_box_;
+ UI::Table<const std::string&> table_;
+ UI::Box buttons_box_;
+ UI::EditBox profile_name_;
+ UI::Button save_;
+ UI::Button cancel_;
+ UI::Button delete_;
+};
+
+void EconomyOptionsWindow::create_target() {
+ std::unique_ptr<SaveProfileWindow> s (new SaveProfileWindow(get_parent(), this));
+ s->run<UI::Panel::Returncodes>();
+}
+
+void EconomyOptionsWindow::do_create_target(const std::string& name) {
+ assert(!name.empty());
+ assert(name != kDefaultEconomyProfile);
+ const Widelands::Tribes& tribes = player_->egbase().tribes();
+ const Widelands::TribeDescr& tribe = player_->tribe();
+ Widelands::Economy* economy = player_->get_economy(serial_);
+ PredefinedTargets t;
+ for (Widelands::DescriptionIndex di : tribe.wares()) {
+ if (tribes.get_ware_descr(di)->has_demand_check(tribe.name())) {
+ t.wares[di] = economy->ware_target_quantity(di).permanent;
+ }
+ }
+ for (Widelands::DescriptionIndex di : tribe.workers()) {
+ if (tribes.get_worker_descr(di)->has_demand_check()) {
+ t.workers[di] = economy->worker_target_quantity(di).permanent;
+ }
+ }
+ predefined_targets_[name] = t;
+
+ save_targets();
+ update_profiles(name);
+}
+
+void EconomyOptionsWindow::save_targets() {
+ const Widelands::Tribes& tribes = player_->egbase().tribes();
+ Profile profile;
+
+ std::map<std::string, uint32_t> serials;
+ for (const auto& pair : predefined_targets_) {
+ if (pair.first != kDefaultEconomyProfile) {
+ serials.emplace(pair.first, serials.size());
+ }
+ }
+ Section& global_section = profile.create_section(kDefaultEconomyProfile.c_str());
+ for (const auto& pair : serials) {
+ global_section.set_string(std::to_string(pair.second).c_str(), pair.first);
+ }
+
+ for (const auto& pair : predefined_targets_) {
+ if (pair.first == kDefaultEconomyProfile) {
+ continue;
+ }
+ Section& section = profile.create_section(std::to_string(serials.at(pair.first)).c_str());
+ for (const auto& setting : pair.second.wares) {
+ section.set_natural(tribes.get_ware_descr(setting.first)->name().c_str(), setting.second);
+ }
+ for (const auto& setting : pair.second.workers) {
+ section.set_natural(tribes.get_worker_descr(setting.first)->name().c_str(), setting.second);
+ }
+ }
+
+ g_fs->ensure_directory_exists(kEconomyProfilesDir);
+ std::string complete_filename = kEconomyProfilesDir + g_fs->file_separator() + player_->tribe().name();
+ profile.write(complete_filename.c_str(), false);
+}
+
+void EconomyOptionsWindow::read_targets(const std::string& select) {
+ predefined_targets_.clear();
+ const Widelands::Tribes& tribes = player_->egbase().tribes();
+ const Widelands::TribeDescr& tribe = player_->tribe();
+
+ {
+ PredefinedTargets t;
+ for (Widelands::DescriptionIndex di : tribe.wares()) {
+ const Widelands::WareDescr* descr = tribes.get_ware_descr(di);
+ if (descr->has_demand_check(tribe.name())) {
+ t.wares.emplace(di, descr->default_target_quantity(tribe.name()));
+ }
+ }
+ for (Widelands::DescriptionIndex di : tribe.workers()) {
+ const Widelands::WorkerDescr* descr = tribes.get_worker_descr(di);
+ if (descr->has_demand_check()) {
+ t.workers.emplace(di, descr->default_target_quantity());
+ }
+ }
+ predefined_targets_.emplace(kDefaultEconomyProfile, t);
+ }
+
+ std::string complete_filename = kEconomyProfilesDir + g_fs->file_separator() + player_->tribe().name();
+ Profile profile;
+ profile.read(complete_filename.c_str());
+
+ Section* global_section = profile.get_section(kDefaultEconomyProfile);
+ if (global_section) {
+ std::map<std::string, std::string> serials;
+ while (Section::Value* v = global_section->get_next_val()) {
+ serials.emplace(std::string(v->get_name()), v->get_string());
+ }
+
+ for (const auto& pair : serials) {
+ Section* section = profile.get_section(pair.first);
+ PredefinedTargets t;
+ while (Section::Value* v = section->get_next_val()) {
+ const std::string name = std::string(v->get_name());
+ Widelands::DescriptionIndex di = tribes.ware_index(name);
+ if (di == Widelands::INVALID_INDEX) {
+ di = tribes.worker_index(name);
+ assert(di != Widelands::INVALID_INDEX);
+ t.workers.emplace(di, v->get_natural());
} else {
- game.send_player_command(*new Widelands::CmdSetWorkerTargetQuantity(
- game.get_gametime(), player_->player_number(), serial_, index,
- tq.permanent + amount));
+ t.wares.emplace(di, v->get_natural());
}
}
+ predefined_targets_.emplace(pair.second, t);
}
}
-}
-void EconomyOptionsWindow::EconomyOptionsPanel::reset_target() {
- Widelands::Game& game = dynamic_cast<Widelands::Game&>(player_->egbase());
- const bool is_wares = type_ == Widelands::wwWARE;
- const auto& items = is_wares ? player_->tribe().wares() : player_->tribe().workers();
- for (const Widelands::DescriptionIndex& index : items) {
- if (display_.ware_selected(index)) {
- if (is_wares) {
- game.send_player_command(*new Widelands::CmdResetWareTargetQuantity(
- game.get_gametime(), player_->player_number(), serial_, index));
- } else {
- game.send_player_command(*new Widelands::CmdResetWorkerTargetQuantity(
- game.get_gametime(), player_->player_number(), serial_, index));
- }
- }
- }
+ update_profiles(select);
}
=== modified file 'src/wui/economy_options_window.h'
--- src/wui/economy_options_window.h 2019-02-23 11:00:49 +0000
+++ src/wui/economy_options_window.h 2019-05-06 13:53:16 +0000
@@ -20,20 +20,48 @@
#ifndef WL_WUI_ECONOMY_OPTIONS_WINDOW_H
#define WL_WUI_ECONOMY_OPTIONS_WINDOW_H
+#include <map>
#include <memory>
+#include <string>
#include "economy/economy.h"
#include "logic/map_objects/tribes/tribe_descr.h"
#include "notifications/notifications.h"
#include "ui_basic/box.h"
+#include "ui_basic/dropdown.h"
#include "ui_basic/tabpanel.h"
#include "ui_basic/window.h"
#include "wui/waresdisplay.h"
+const std::string kDefaultEconomyProfile = "Default";
+
struct EconomyOptionsWindow : public UI::Window {
EconomyOptionsWindow(UI::Panel* parent, Widelands::Economy* economy, bool can_act);
~EconomyOptionsWindow();
+ struct PredefinedTargets {
+ using Targets = std::map<Widelands::DescriptionIndex, uint32_t>;
+ Targets wares;
+ Targets workers;
+ };
+
+ void create_target();
+ void do_create_target(const std::string&);
+ void save_targets();
+ void read_targets(const std::string& = kDefaultEconomyProfile);
+ void update_profiles(const std::string&);
+ std::map<std::string, PredefinedTargets>& get_predefined_targets() {
+ return predefined_targets_;
+ }
+ const PredefinedTargets& get_selected_target() const {
+ return predefined_targets_.at(dropdown_.get_selected());
+ }
+
+ void change_target(int amount);
+ void reset_target();
+
+ void layout() override;
+
private:
struct TargetWaresDisplay : public AbstractWaresDisplay {
TargetWaresDisplay(UI::Panel* const parent,
@@ -59,14 +87,17 @@
*/
struct EconomyOptionsPanel : UI::Box {
EconomyOptionsPanel(UI::Panel* parent,
+ EconomyOptionsWindow* eco_window,
Widelands::Serial serial,
Widelands::Player* player,
bool can_act,
- Widelands::WareWorker type);
+ Widelands::WareWorker type,
+ int32_t min_w);
void set_economy(Widelands::Serial serial);
void change_target(int amount);
void reset_target();
+ void update_desired_size() override;
private:
Widelands::Serial serial_;
@@ -74,17 +105,23 @@
Widelands::WareWorker type_;
bool can_act_;
TargetWaresDisplay display_;
+ EconomyOptionsWindow* economy_options_window_;
};
/// Actions performed when a NoteEconomyWindow is received.
void on_economy_note(const Widelands::NoteEconomy& note);
+ UI::Box main_box_;
Widelands::Serial serial_;
Widelands::Player* player_;
UI::TabPanel tabpanel_;
EconomyOptionsPanel* ware_panel_;
EconomyOptionsPanel* worker_panel_;
std::unique_ptr<Notifications::Subscriber<Widelands::NoteEconomy>> economynotes_subscriber_;
+
+ std::map<std::string, PredefinedTargets> predefined_targets_;
+ UI::Box dropdown_box_;
+ UI::Dropdown<std::string> dropdown_;
};
#endif // end of include guard: WL_WUI_ECONOMY_OPTIONS_WINDOW_H
=== modified file 'src/wui/inputqueuedisplay.cc'
--- src/wui/inputqueuedisplay.cc 2019-04-25 06:40:24 +0000
+++ src/wui/inputqueuedisplay.cc 2019-05-06 13:53:16 +0000
@@ -71,7 +71,7 @@
uint32_t priority_button_height = show_only ? 0 : 3 * PriorityButtonSize;
uint32_t image_height =
- show_only ? WARE_MENU_PIC_HEIGHT : std::max<int32_t>(WARE_MENU_PIC_HEIGHT, ph);
+ show_only ? kWareMenuPicHeight : std::max<int32_t>(kWareMenuPicHeight, ph);
total_height_ = std::max(priority_button_height, image_height) + 2 * Border;
@@ -91,7 +91,7 @@
*/
void InputQueueDisplay::max_size_changed() {
uint32_t pbs = show_only_ ? 0 : PriorityButtonSize;
- uint32_t ctrl_b_size = show_only_ ? 0 : 2 * WARE_MENU_PIC_WIDTH;
+ uint32_t ctrl_b_size = show_only_ ? 0 : 2 * kWareMenuPicWidth;
cache_size_ = queue_.get_max_size();
@@ -140,7 +140,7 @@
Vector2i point = Vector2i::zero();
point.x = Border + (show_only_ ? 0 : CellWidth + CellSpacing);
- point.y = Border + (total_height_ - 2 * Border - WARE_MENU_PIC_HEIGHT) / 2;
+ point.y = Border + (total_height_ - 2 * Border - kWareMenuPicHeight) / 2;
for (; nr_inputs_to_draw; --nr_inputs_to_draw, point.x += CellWidth + CellSpacing) {
dst.blitrect(Vector2i(point.x, point.y), icon_, Recti(0, 0, icon_->width(), icon_->height()),
@@ -240,12 +240,12 @@
return;
uint32_t x = Border;
- uint32_t y = Border + (total_height_ - 2 * Border - WARE_MENU_PIC_WIDTH) / 2;
+ uint32_t y = Border + (total_height_ - 2 * Border - kWareMenuPicWidth) / 2;
boost::format tooltip_format("%s<br><p><font size=%d bold=0>%s<br>%s</font></p>");
decrease_max_fill_ = new UI::Button(
- this, "decrease_max_fill", x, y, WARE_MENU_PIC_WIDTH, WARE_MENU_PIC_HEIGHT,
+ this, "decrease_max_fill", x, y, kWareMenuPicWidth, kWareMenuPicHeight,
UI::ButtonStyle::kWuiMenu, g_gr->images().get("images/ui_basic/scrollbar_left.png"),
(tooltip_format
/** TRANSLATORS: Button tooltip in in a building's wares input queue */
@@ -262,7 +262,7 @@
x = Border + (cache_size_ + 1) * (CellWidth + CellSpacing);
increase_max_fill_ = new UI::Button(
- this, "increase_max_fill", x, y, WARE_MENU_PIC_WIDTH, WARE_MENU_PIC_HEIGHT,
+ this, "increase_max_fill", x, y, kWareMenuPicWidth, kWareMenuPicHeight,
UI::ButtonStyle::kWuiMenu, g_gr->images().get("images/ui_basic/scrollbar_right.png"),
(tooltip_format
/** TRANSLATORS: Button tooltip in a building's wares input queue */
=== modified file 'src/wui/inputqueuedisplay.h'
--- src/wui/inputqueuedisplay.h 2019-04-23 14:53:35 +0000
+++ src/wui/inputqueuedisplay.h 2019-05-06 13:53:16 +0000
@@ -49,7 +49,7 @@
*/
class InputQueueDisplay : public UI::Panel {
public:
- enum { CellWidth = WARE_MENU_PIC_WIDTH, CellSpacing = 2, Border = 4, PriorityButtonSize = 10 };
+ enum { CellWidth = kWareMenuPicWidth, CellSpacing = 2, Border = 4, PriorityButtonSize = 10 };
InputQueueDisplay(UI::Panel* parent,
int32_t x,
=== modified file 'src/wui/waresdisplay.cc'
--- src/wui/waresdisplay.cc 2019-02-23 11:00:49 +0000
+++ src/wui/waresdisplay.cc 2019-05-06 13:53:16 +0000
@@ -35,8 +35,9 @@
#include "logic/map_objects/tribes/ware_descr.h"
#include "logic/map_objects/tribes/worker.h"
#include "logic/player.h"
+#include "ui_basic/window.h"
-const int WARE_MENU_INFO_SIZE = 12;
+constexpr int kWareMenuInfoSize = 12;
AbstractWaresDisplay::AbstractWaresDisplay(
UI::Panel* const parent,
@@ -46,7 +47,9 @@
Widelands::WareWorker type,
bool selectable,
boost::function<void(Widelands::DescriptionIndex, bool)> callback_function,
- bool horizontal)
+ bool horizontal,
+ int32_t hgap,
+ int32_t vgap)
: // Size is set when add_warelist is called, as it depends on the type_.
UI::Panel(parent, x, y, 0, 0),
tribe_(tribe),
@@ -57,6 +60,8 @@
selectable_(selectable),
horizontal_(horizontal),
+ hgap_(hgap),
+ vgap_(vgap),
selection_anchor_(Widelands::INVALID_INDEX),
callback_function_(callback_function) {
for (const Widelands::DescriptionIndex& index : indices_) {
@@ -67,22 +72,65 @@
curware_.set_text(_("Stock"));
- // Find out geometry from icons_order
- unsigned int columns = icons_order().size();
- unsigned int rows = 0;
- for (unsigned int i = 0; i < icons_order().size(); i++)
- if (icons_order()[i].size() > rows)
- rows = icons_order()[i].size();
+ graphic_resolution_changed_subscriber_ = Notifications::subscribe<GraphicResolutionChanged>(
+ [this](const GraphicResolutionChanged&) {
+ recalc_desired_size(true);
+ });
+
+ recalc_desired_size(false);
+}
+
+Widelands::Extent AbstractWaresDisplay::get_extent() const {
+ int16_t columns = 0;
+ int16_t rows = 0;
+ for (const auto& pair : icons_order_coords()) {
+ columns = std::max(columns, pair.second.x);
+ rows = std::max(rows, pair.second.y);
+ }
+ // We cound from 0 up
+ ++columns;
+ ++rows;
+
if (horizontal_) {
- unsigned int s = columns;
+ const int16_t s = columns;
columns = rows;
rows = s;
}
+ return Widelands::Extent(columns, rows);
+}
+
+void AbstractWaresDisplay::set_hgap(int32_t gap) {
+ hgap_ = gap;
+ recalc_desired_size(true);
+}
+
+void AbstractWaresDisplay::set_vgap(int32_t gap) {
+ vgap_ = gap;
+ recalc_desired_size(true);
+}
+
+void AbstractWaresDisplay::recalc_desired_size(bool relayout) {
+ relayout_icons_order_coords();
+
+ // Find out geometry from icons_order
+ const Widelands::Extent size = get_extent();
// 25 is height of curware_ text
set_desired_size(
- columns * (WARE_MENU_PIC_WIDTH + WARE_MENU_PIC_PAD_X) + 1,
- rows * (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + WARE_MENU_PIC_PAD_Y) + 1 + 25);
+ size.w * (kWareMenuPicWidth + hgap_) + 1,
+ size.h * (kWareMenuPicHeight + kWareMenuInfoSize + vgap_) + 1 + 25);
+
+ if (relayout) {
+ // Since we are usually stacked deep within other panels, we need to tell our highest parent window to relayout
+ UI::Panel* p = this;
+ while (p->get_parent()) {
+ p = p->get_parent();
+ if (dynamic_cast<UI::Window*>(p)) {
+ p->layout();
+ return;
+ }
+ }
+ }
}
bool AbstractWaresDisplay::handle_mousemove(uint8_t state, int32_t x, int32_t y, int32_t, int32_t) {
@@ -162,21 +210,33 @@
* DescriptionIndex::null() if the given point is outside the range.
*/
Widelands::DescriptionIndex AbstractWaresDisplay::ware_at_point(int32_t x, int32_t y) const {
- if (x < 0 || y < 0)
- return Widelands::INVALID_INDEX;
-
- unsigned int i = x / (WARE_MENU_PIC_WIDTH + WARE_MENU_PIC_PAD_X);
- unsigned int j = y / (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + WARE_MENU_PIC_PAD_Y);
+ // Graphical offset
+ x -= 2;
+ y -= 2;
+
+ if (x < 0 || y < 0) {
+ return Widelands::INVALID_INDEX;
+ }
+
+ int i = x / (kWareMenuPicWidth + hgap_);
+ int j = y / (kWareMenuPicHeight + kWareMenuInfoSize + vgap_);
+ if (kWareMenuPicWidth * (i + 1) + hgap_ * i < x ||
+ (kWareMenuPicHeight + kWareMenuInfoSize) * (j + 1) + vgap_ * j < y) {
+ // Not on the ware, but on the space between
+ return Widelands::INVALID_INDEX;
+ }
if (horizontal_) {
- unsigned int s = i;
+ int s = i;
i = j;
j = s;
}
- if (i < icons_order().size() && j < icons_order()[i].size()) {
- const Widelands::DescriptionIndex& ware = icons_order()[i][j];
- assert(hidden_.count(ware) == 1);
- if (!(hidden_.find(ware)->second)) {
- return ware;
+ for (const auto& pair : icons_order_coords()) {
+ if (pair.second.x == i && pair.second.y == j) {
+ assert(hidden_.count(pair.first) == 1);
+ if (!(hidden_.find(pair.first)->second)) {
+ return pair.first;
+ }
+ break;
}
}
@@ -199,15 +259,13 @@
Vector2i anchor_pos = ware_position(selection_anchor_);
// Add an offset to make sure the anchor line and column will be
// selected when selecting in topleft direction
- int32_t anchor_x = anchor_pos.x + WARE_MENU_PIC_WIDTH / 2;
- int32_t anchor_y = anchor_pos.y + WARE_MENU_PIC_HEIGHT / 2;
+ int32_t anchor_x = anchor_pos.x + kWareMenuPicWidth / 2;
+ int32_t anchor_y = anchor_pos.y + kWareMenuPicHeight / 2;
- unsigned int left_ware_idx = anchor_x / (WARE_MENU_PIC_WIDTH + WARE_MENU_PIC_PAD_X);
- unsigned int top_ware_idx =
- anchor_y / (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + WARE_MENU_PIC_PAD_Y);
- unsigned int right_ware_idx = x / (WARE_MENU_PIC_WIDTH + WARE_MENU_PIC_PAD_X);
- unsigned int bottoware_idx_ =
- y / (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + WARE_MENU_PIC_PAD_Y);
+ unsigned int left_ware_idx = anchor_x / (kWareMenuPicWidth + hgap_);
+ unsigned int top_ware_idx = anchor_y / (kWareMenuPicHeight + kWareMenuInfoSize + vgap_);
+ unsigned int right_ware_idx = x / (kWareMenuPicWidth + hgap_);
+ unsigned int bottoware_idx_ = y / (kWareMenuPicHeight + kWareMenuInfoSize + vgap_);
unsigned int tmp;
// Reverse col/row and anchor/endpoint if needed
@@ -271,26 +329,43 @@
NEVER_HERE();
}
-const Widelands::TribeDescr::WaresOrderCoords& AbstractWaresDisplay::icons_order_coords() const {
- switch (type_) {
- case Widelands::wwWARE:
- return tribe_.wares_order_coords();
- case Widelands::wwWORKER:
- return tribe_.workers_order_coords();
+const WaresOrderCoords& AbstractWaresDisplay::icons_order_coords() const {
+ assert(!order_coords_.empty());
+ return order_coords_;
+}
+
+void AbstractWaresDisplay::relayout_icons_order_coords() {
+ order_coords_.clear();
+ const int column_number = icons_order().size();
+ const int column_max_size = (g_gr->get_yres() - 290) / (kWareMenuPicHeight + vgap_ + kWareMenuInfoSize);
+
+ int16_t column_index_to_apply = 0;
+ for (int16_t column_index = 0; column_index < column_number; ++column_index) {
+ const std::vector<Widelands::DescriptionIndex>& column = icons_order().at(column_index);
+ const int row_number = column.size();
+ int16_t row_index_to_apply = 0;
+ for (int16_t row_index = 0; row_index < row_number; ++row_index) {
+ order_coords_.emplace(column.at(row_index), Widelands::Coords(column_index_to_apply, row_index_to_apply));
+ ++row_index_to_apply;
+ if (row_index_to_apply > column_max_size) {
+ row_index_to_apply = 0;
+ ++column_index_to_apply;
+ }
+ }
+ if (row_index_to_apply > 0) {
+ ++column_index_to_apply;
+ }
}
- NEVER_HERE();
}
Vector2i AbstractWaresDisplay::ware_position(Widelands::DescriptionIndex id) const {
Vector2i p(2, 2);
if (horizontal_) {
- p.x += icons_order_coords()[id].second * (WARE_MENU_PIC_WIDTH + WARE_MENU_PIC_PAD_X);
- p.y += icons_order_coords()[id].first *
- (WARE_MENU_PIC_HEIGHT + WARE_MENU_PIC_PAD_Y + WARE_MENU_INFO_SIZE);
+ p.x += icons_order_coords().at(id).y * (kWareMenuPicWidth + hgap_);
+ p.y += icons_order_coords().at(id).x * (kWareMenuPicHeight + vgap_ + kWareMenuInfoSize);
} else {
- p.x += icons_order_coords()[id].first * (WARE_MENU_PIC_WIDTH + WARE_MENU_PIC_PAD_X);
- p.y += icons_order_coords()[id].second *
- (WARE_MENU_PIC_HEIGHT + WARE_MENU_PIC_PAD_Y + WARE_MENU_INFO_SIZE);
+ p.x += icons_order_coords().at(id).x * (kWareMenuPicWidth + hgap_);
+ p.y += icons_order_coords().at(id).y * (kWareMenuPicHeight + vgap_ + kWareMenuInfoSize);
}
return p;
}
@@ -326,15 +401,15 @@
const Image* icon = type_ == Widelands::wwWORKER ? tribe_.get_worker_descr(id)->icon() :
tribe_.get_ware_descr(id)->icon();
- dst.blit(p + Vector2i((w - WARE_MENU_PIC_WIDTH) / 2, 1), icon);
+ dst.blit(p + Vector2i((w - kWareMenuPicWidth) / 2, 1), icon);
- dst.fill_rect(Recti(p + Vector2i(0, WARE_MENU_PIC_HEIGHT), w, WARE_MENU_INFO_SIZE),
+ dst.fill_rect(Recti(p + Vector2i(0, kWareMenuPicHeight), w, kWareMenuInfoSize),
info_color_for_ware(id));
std::shared_ptr<const UI::RenderedText> rendered_text =
UI::g_fh->render(as_waresinfo(info_for_ware(id)));
rendered_text->draw(dst, Vector2i(p.x + w - rendered_text->width() - 1,
- p.y + WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + 1 -
+ p.y + kWareMenuPicHeight + kWareMenuInfoSize + 1 -
rendered_text->height()));
}
=== modified file 'src/wui/waresdisplay.h'
--- src/wui/waresdisplay.h 2019-02-23 11:00:49 +0000
+++ src/wui/waresdisplay.h 2019-05-06 13:53:16 +0000
@@ -20,6 +20,7 @@
#ifndef WL_WUI_WARESDISPLAY_H
#define WL_WUI_WARESDISPLAY_H
+#include <memory>
#include <vector>
#include "logic/map_objects/tribes/tribe_descr.h"
@@ -36,6 +37,8 @@
struct WareList;
} // namespace Widelands
+using WaresOrderCoords = std::map<Widelands::DescriptionIndex, Widelands::Coords>;
+
/**
* Display wares or workers together with some string (typically a number)
* in the style of the @ref WarehouseWindow.
@@ -54,7 +57,9 @@
CLANG_DIAG_OFF("-Wunknown-pragmas") CLANG_DIAG_OFF("-Wzero-as-null-pointer-constant")
boost::function<void(Widelands::DescriptionIndex, bool)> callback_function = 0,
CLANG_DIAG_ON("-Wzero-as-null-pointer-constant")
- CLANG_DIAG_ON("-Wunknown-pragmas") bool horizontal = false);
+ CLANG_DIAG_ON("-Wunknown-pragmas") bool horizontal = false,
+ int32_t hgap = 3,
+ int32_t vgap = 4);
bool
handle_mousemove(uint8_t state, int32_t x, int32_t y, int32_t xdiff, int32_t ydiff) override;
@@ -74,6 +79,19 @@
return type_;
}
+ int32_t get_hgap() {
+ return hgap_;
+ }
+ int32_t get_vgap() {
+ return vgap_;
+ }
+ void set_hgap(int32_t);
+ void set_vgap(int32_t);
+
+ Widelands::Extent get_extent() const;
+
+ const WaresOrderCoords& icons_order_coords() const;
+
protected:
void layout() override;
@@ -82,7 +100,6 @@
virtual RGBColor info_color_for_ware(Widelands::DescriptionIndex);
const Widelands::TribeDescr::WaresOrder& icons_order() const;
- const Widelands::TribeDescr::WaresOrderCoords& icons_order_coords() const;
virtual Vector2i ware_position(Widelands::DescriptionIndex) const;
void draw(RenderTarget&) override;
virtual void draw_ware(RenderTarget&, Widelands::DescriptionIndex);
@@ -110,6 +127,13 @@
WareListSelectionType in_selection_; // Wares in temporary anchored selection
bool selectable_;
bool horizontal_;
+ int32_t hgap_;
+ int32_t vgap_;
+
+ WaresOrderCoords order_coords_;
+
+ void relayout_icons_order_coords();
+ void recalc_desired_size(bool);
/**
* The ware on which the mouse press has been performed.
@@ -117,6 +141,8 @@
*/
Widelands::DescriptionIndex selection_anchor_;
boost::function<void(Widelands::DescriptionIndex, bool)> callback_function_;
+
+ std::unique_ptr<Notifications::Subscriber<GraphicResolutionChanged>> graphic_resolution_changed_subscriber_;
};
/*
Follow ups
-
[Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: noreply, 2019-05-29
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: GunChleoc, 2019-05-29
-
[Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: bunnybot, 2019-05-29
-
[Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: bunnybot, 2019-05-29
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Benedikt Straub, 2019-05-29
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: GunChleoc, 2019-05-29
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Benedikt Straub, 2019-05-28
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: GunChleoc, 2019-05-26
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: GunChleoc, 2019-05-26
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Benedikt Straub, 2019-05-25
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: GunChleoc, 2019-05-25
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Benedikt Straub, 2019-05-25
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Benedikt Straub, 2019-05-25
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: GunChleoc, 2019-05-25
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: GunChleoc, 2019-05-25
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: GunChleoc, 2019-05-25
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Toni Förster, 2019-05-24
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: GunChleoc, 2019-05-17
-
[Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: bunnybot, 2019-05-17
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Toni Förster, 2019-05-16
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Benedikt Straub, 2019-05-16
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Toni Förster, 2019-05-16
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Benedikt Straub, 2019-05-16
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Toni Förster, 2019-05-15
-
[Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: bunnybot, 2019-05-15
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Benedikt Straub, 2019-05-14
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Toni Förster, 2019-05-14
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Benedikt Straub, 2019-05-14
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: GunChleoc, 2019-05-12
-
[Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: bunnybot, 2019-05-12
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Benedikt Straub, 2019-05-11
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Toni Förster, 2019-05-11
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Benedikt Straub, 2019-05-11
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Toni Förster, 2019-05-11
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Benedikt Straub, 2019-05-11
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Benedikt Straub, 2019-05-11
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Toni Förster, 2019-05-11
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Toni Förster, 2019-05-11
-
[Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: bunnybot, 2019-05-10
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Benedikt Straub, 2019-05-10
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: GunChleoc, 2019-05-10
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Benedikt Straub, 2019-05-10
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: GunChleoc, 2019-05-10
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Benedikt Straub, 2019-05-09
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Toni Förster, 2019-05-09
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Toni Förster, 2019-05-09
-
[Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: bunnybot, 2019-05-08
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Benedikt Straub, 2019-05-08
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: kaputtnik, 2019-05-08
-
Re: [Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: Benedikt Straub, 2019-05-08
-
[Merge] lp:~widelands-dev/widelands/economy-target-profiles into lp:widelands
From: bunnybot, 2019-05-06