← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~nomeata/widelands/rip-temp-ware-target into lp:widelands

 

Joachim Breitner has proposed merging lp:~nomeata/widelands/rip-temp-ware-target into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)


A merge request as requested.
-- 
https://code.launchpad.net/~nomeata/widelands/rip-temp-ware-target/+merge/39687
Your team Widelands Developers is requested to review the proposed merge of lp:~nomeata/widelands/rip-temp-ware-target into lp:widelands.
=== added file 'pics/stock_policy_button_dontstock.png'
Binary files pics/stock_policy_button_dontstock.png	1970-01-01 00:00:00 +0000 and pics/stock_policy_button_dontstock.png	2010-10-30 15:03:54 +0000 differ
=== added file 'pics/stock_policy_button_normal.png'
Binary files pics/stock_policy_button_normal.png	1970-01-01 00:00:00 +0000 and pics/stock_policy_button_normal.png	2010-10-30 15:03:54 +0000 differ
=== added file 'pics/stock_policy_button_prefer.png'
Binary files pics/stock_policy_button_prefer.png	1970-01-01 00:00:00 +0000 and pics/stock_policy_button_prefer.png	2010-10-30 15:03:54 +0000 differ
=== added file 'pics/stock_policy_button_remove.png'
Binary files pics/stock_policy_button_remove.png	1970-01-01 00:00:00 +0000 and pics/stock_policy_button_remove.png	2010-10-30 15:03:54 +0000 differ
=== added file 'pics/ware_list_bg_selected.png'
Binary files pics/ware_list_bg_selected.png	1970-01-01 00:00:00 +0000 and pics/ware_list_bg_selected.png	2010-10-30 15:03:54 +0000 differ
=== modified file 'src/economy/economy.cc'
--- src/economy/economy.cc	2010-09-05 21:25:25 +0000
+++ src/economy/economy.cc	2010-10-30 15:03:54 +0000
@@ -54,7 +54,7 @@
 	m_ware_target_quantities   = new Target_Quantity[nr_wares  .value()];
 	for (Ware_Index i = Ware_Index::First(); i < nr_wares; ++i) {
 		Target_Quantity tq;
-		tq.temporary = tq.permanent =
+		tq.permanent =
 			tribe.get_ware_descr(i)->default_target_quantity();
 		tq.last_modified = 0;
 		m_ware_target_quantities[i.value()] = tq;
@@ -62,7 +62,7 @@
 	m_worker_target_quantities = new Target_Quantity[nr_workers.value()];
 	for (Ware_Index i = Ware_Index::First(); i < nr_workers; ++i) {
 		Target_Quantity tq;
-		tq.temporary = tq.permanent =
+		tq.permanent =
 			tribe.get_worker_descr(i)->default_target_quantity();
 		tq.last_modified = 0;
 		m_worker_target_quantities[i.value()] = tq;
@@ -343,7 +343,7 @@
 
 /**
  * Set the target quantities for the given Ware_Index to the
- * numbers given in permanent and temporary. Also update the last
+ * numbers given in permanent. Also update the last
  * modification time.
  *
  * This is called from Cmd_ResetTargetQuantity and Cmd_SetTargetQuantity
@@ -351,11 +351,9 @@
 void Economy::set_ware_target_quantity
 	(Ware_Index const ware_type,
 	 uint32_t   const permanent,
-	 uint32_t   const temporary,
 	 Time       const mod_time)
 {
 	Target_Quantity & tq = m_ware_target_quantities[ware_type.value()];
-	tq.temporary = temporary;
 	tq.permanent = permanent;
 	tq.last_modified = mod_time;
 }
@@ -364,11 +362,9 @@
 void Economy::set_worker_target_quantity
 	(Ware_Index const ware_type,
 	 uint32_t   const permanent,
-	 uint32_t   const temporary,
 	 Time       const mod_time)
 {
 	Target_Quantity & tq = m_worker_target_quantities[ware_type.value()];
-	tq.temporary = temporary;
 	tq.permanent = permanent;
 	tq.last_modified = mod_time;
 }
@@ -410,11 +406,6 @@
 
 	m_wares.remove(id, count);
 
-	Target_Quantity & tq = m_ware_target_quantities[id.value()];
-	tq.temporary =
-		tq.temporary <= tq.permanent + count ?
-		tq.permanent : tq.temporary - count;
-
 	// TODO: remove from global player inventory?
 }
 
@@ -429,11 +420,6 @@
 
 	m_workers.remove(id, count);
 
-	Target_Quantity & tq = m_worker_target_quantities[id.value()];
-	tq.temporary =
-		tq.temporary <= tq.permanent + count ?
-		tq.permanent : tq.temporary - count;
-
 	// TODO: remove from global player inventory?
 }
 
@@ -535,7 +521,7 @@
 
 bool Economy::needs_ware(Ware_Index const ware_type) const {
 	size_t const nr_supplies = m_supplies.get_nrsupplies();
-	uint32_t const t = ware_target_quantity(ware_type).temporary;
+	uint32_t const t = ware_target_quantity(ware_type).permanent;
 	uint32_t quantity = 0;
 	for (size_t i = 0; i < nr_supplies; ++i)
 		if (upcast(WarehouseSupply const, warehouse_supply, &m_supplies[i])) {
@@ -549,7 +535,7 @@
 
 bool Economy::needs_worker(Ware_Index const worker_type) const {
 	size_t const nr_supplies = m_supplies.get_nrsupplies();
-	uint32_t const t = worker_target_quantity(worker_type).temporary;
+	uint32_t const t = worker_target_quantity(worker_type).permanent;
 	uint32_t quantity = 0;
 	for (size_t i = 0; i < nr_supplies; ++i)
 		if (upcast(WarehouseSupply const, warehouse_supply, &m_supplies[i])) {

=== modified file 'src/economy/economy.h'
--- src/economy/economy.h	2010-05-29 19:29:35 +0000
+++ src/economy/economy.h	2010-10-30 15:03:54 +0000
@@ -50,29 +50,14 @@
 	///
 	/// This affects the result of \ref needs_ware and thereby the demand checks
 	/// in production programs. A ware type is considered to be needed if there
-	/// are less than the temporary target quantity stored in warehouses in the
+	/// are less than the permanent target quantity stored in warehouses in the
 	/// economy.
 	///
-	/// The temporary quantity will be decreased when a ware of the type is
-	/// consumed, but not below the permanent quantity. This allows the
-	/// following use case:
-	///   The player has built up a lot of economic infrastructure but lacks
-	///   mines. Then he discovers a mountain. He plans to expand to the
-	///   mountain and build some mines. Therefore he anticipates that he will
-	///   soon need 10 picks. Suppose that he has the target quantity (both
-	///   permanent and temporary) for pick set to 2. He sets the temporary
-	///   target quantity for pick to 12.  For each pick that is consumed in the
-	///   economy, the target quantity for pick drops back 1 step, until it
-	///   reaches the permanent level of 2. So when the player has built his
-	///   mines and used his 10 picks, the targe quantity setting for pick is
-	///   what it was before he changed it. That is the rationale for the name
-	///   "temporary".
-	///
 	/// The last_modified time is used to determine which setting to use when
 	/// economies are merged. The setting that was modified most recently will
 	/// be used for the merged economy.
 	struct Target_Quantity {
-		uint32_t permanent, temporary;
+		uint32_t permanent;
 		Time     last_modified;
 	};
 
@@ -100,8 +85,8 @@
 	void remove_flag(Flag &);
 	Flag & get_arbitrary_flag();
 
-	void set_ware_target_quantity  (Ware_Index, uint32_t, uint32_t, Time);
-	void set_worker_target_quantity(Ware_Index, uint32_t, uint32_t, Time);
+	void set_ware_target_quantity  (Ware_Index, uint32_t, Time);
+	void set_worker_target_quantity(Ware_Index, uint32_t, Time);
 
 	void    add_wares  (Ware_Index, uint32_t count = 1);
 	void remove_wares  (Ware_Index, uint32_t count = 1);

=== modified file 'src/economy/economy_data_packet.cc'
--- src/economy/economy_data_packet.cc	2010-01-04 03:32:50 +0000
+++ src/economy/economy_data_packet.cc	2010-10-30 15:03:54 +0000
@@ -27,7 +27,7 @@
 #include "logic/player.h"
 
 
-#define CURRENT_ECONOMY_VERSION 2
+#define CURRENT_ECONOMY_VERSION 3
 
 namespace Widelands {
 
@@ -43,7 +43,8 @@
 					while (Time const last_modified = fr.Unsigned32()) {
 						char const * const type_name = fr.CString();
 						uint32_t const permanent = fr.Unsigned32();
-						uint32_t const temporary = fr.Unsigned32();
+						if (version <= 2)
+							fr.Unsigned32();
 						if (Ware_Index i = tribe.ware_index(type_name)) {
 							if
 								(tribe.get_ware_descr(i)->default_target_quantity()
@@ -61,7 +62,6 @@
 									throw game_data_error
 										(_("duplicated entry for %s"), type_name);
 								tq.permanent         = permanent;
-								tq.temporary         = temporary;
 								tq.last_modified     = last_modified;
 							}
 						} else if ((i = tribe.worker_index(type_name))) {
@@ -81,7 +81,6 @@
 									throw game_data_error
 										(_("duplicated entry for %s"), type_name);
 								tq.permanent         = permanent;
-								tq.temporary         = temporary;
 								tq.last_modified     = last_modified;
 							}
 						} else
@@ -115,7 +114,6 @@
 			fw.Unsigned32(last_modified);
 			fw.CString(tribe.get_ware_descr(i)->name());
 			fw.Unsigned32(tq.permanent);
-			fw.Unsigned32(tq.temporary);
 		}
 	}
 	for (Ware_Index i = tribe.get_nrworkers(); i.value();) {
@@ -126,7 +124,6 @@
 			fw.Unsigned32(last_modified);
 			fw.CString(tribe.get_worker_descr(i)->name());
 			fw.Unsigned32(tq.permanent);
-			fw.Unsigned32(tq.temporary);
 		}
 	}
 	fw.Unsigned32(0); //  terminator

=== modified file 'src/logic/playercommand.cc'
--- src/logic/playercommand.cc	2010-06-16 20:10:55 +0000
+++ src/logic/playercommand.cc	2010-10-30 15:03:54 +0000
@@ -700,10 +700,10 @@
 	(int32_t const _duetime, Player_Number const _sender,
 	 uint32_t const _economy,
 	 Ware_Index const _ware_type,
-	 uint32_t const _permanent, uint32_t const _temporary)
+	 uint32_t const _permanent)
 	:
 	Cmd_ChangeTargetQuantity(_duetime, _sender, _economy, _ware_type),
-	m_permanent(_permanent), m_temporary(_temporary)
+	m_permanent(_permanent)
 {}
 
 void Cmd_SetWareTargetQuantity::execute(Game & game)
@@ -713,10 +713,10 @@
 		(economy  () < player.get_nr_economies() and
 		 ware_type() < player.tribe().get_nrwares())
 		player.get_economy_by_number(economy())->set_ware_target_quantity
-			(ware_type(),  m_permanent, m_temporary, duetime());
+			(ware_type(),  m_permanent, duetime());
 }
 
-#define PLAYER_CMD_SETWARETARGETQUANTITY_VERSION 1
+#define PLAYER_CMD_SETWARETARGETQUANTITY_VERSION 2
 
 void Cmd_SetWareTargetQuantity::Write
 	(FileWrite & fw, Editor_Game_Base & egbase, Map_Map_Object_Saver & mos)
@@ -724,7 +724,6 @@
 	fw.Unsigned16(PLAYER_CMD_SETWARETARGETQUANTITY_VERSION);
 	Cmd_ChangeTargetQuantity::Write(fw, egbase, mos);
 	fw.Unsigned32(m_permanent);
-	fw.Unsigned32(m_temporary);
 }
 
 void Cmd_SetWareTargetQuantity::Read
@@ -732,10 +731,11 @@
 {
 	try {
 		uint16_t const packet_version = fr.Unsigned16();
-		if (packet_version == PLAYER_CMD_SETWARETARGETQUANTITY_VERSION) {
+		if (packet_version <= PLAYER_CMD_SETWARETARGETQUANTITY_VERSION) {
 			Cmd_ChangeTargetQuantity::Read(fr, egbase, mol);
 			m_permanent = fr.Unsigned32();
-			m_temporary = fr.Unsigned32();
+			if (packet_version == 1)
+				fr.Unsigned32();
 		} else
 			throw game_data_error
 				(_("unknown/unhandled version %u"), packet_version);
@@ -747,16 +747,16 @@
 Cmd_SetWareTargetQuantity::Cmd_SetWareTargetQuantity(StreamRead & des)
 	:
 	Cmd_ChangeTargetQuantity(des),
-	m_permanent             (des.Unsigned32()),
-	m_temporary             (des.Unsigned32())
-{}
+	m_permanent             (des.Unsigned32())
+{
+	if (cmdserial() == 1) des.Unsigned32();
+}
 
 void Cmd_SetWareTargetQuantity::serialize(StreamWrite & ser)
 {
 	ser.Unsigned8 (PLCMD_SETWARETARGETQUANTITY);
 	Cmd_ChangeTargetQuantity::serialize(ser);
 	ser.Unsigned32(m_permanent);
-	ser.Unsigned32(m_temporary);
 }
 
 
@@ -779,7 +779,7 @@
 		int32_t const count =
 			tribe.get_ware_descr(ware_type())->default_target_quantity();
 		player.get_economy_by_number(economy())->set_ware_target_quantity
-			(ware_type(),  count, count, 0);
+			(ware_type(),  count, 0);
 	}
 }
 
@@ -822,10 +822,10 @@
 	(int32_t const _duetime, Player_Number const _sender,
 	 uint32_t const _economy,
 	 Ware_Index const _ware_type,
-	 uint32_t const _permanent, uint32_t const _temporary)
+	 uint32_t const _permanent)
 	:
 	Cmd_ChangeTargetQuantity(_duetime, _sender, _economy, _ware_type),
-	m_permanent(_permanent), m_temporary(_temporary)
+	m_permanent(_permanent)
 {}
 
 void Cmd_SetWorkerTargetQuantity::execute(Game & game)
@@ -835,10 +835,10 @@
 		(economy  () < player.get_nr_economies() and
 		 ware_type() < player.tribe().get_nrwares())
 		player.get_economy_by_number(economy())->set_worker_target_quantity
-			(ware_type(),  m_permanent, m_temporary, duetime());
+			(ware_type(),  m_permanent, duetime());
 }
 
-#define PLAYER_CMD_SETWORKERTARGETQUANTITY_VERSION 1
+#define PLAYER_CMD_SETWORKERTARGETQUANTITY_VERSION 2
 
 void Cmd_SetWorkerTargetQuantity::Write
 	(FileWrite & fw, Editor_Game_Base & egbase, Map_Map_Object_Saver & mos)
@@ -846,7 +846,6 @@
 	fw.Unsigned16(PLAYER_CMD_SETWORKERTARGETQUANTITY_VERSION);
 	Cmd_ChangeTargetQuantity::Write(fw, egbase, mos);
 	fw.Unsigned32(m_permanent);
-	fw.Unsigned32(m_temporary);
 }
 
 void Cmd_SetWorkerTargetQuantity::Read
@@ -854,10 +853,11 @@
 {
 	try {
 		uint16_t const packet_version = fr.Unsigned16();
-		if (packet_version == PLAYER_CMD_SETWORKERTARGETQUANTITY_VERSION) {
+		if (packet_version <= PLAYER_CMD_SETWORKERTARGETQUANTITY_VERSION) {
 			Cmd_ChangeTargetQuantity::Read(fr, egbase, mol);
 			m_permanent = fr.Unsigned32();
-			m_temporary = fr.Unsigned32();
+			if (packet_version == 1)
+				fr.Unsigned32();
 		} else
 			throw game_data_error
 				(_("unknown/unhandled version %u"), packet_version);
@@ -869,16 +869,16 @@
 Cmd_SetWorkerTargetQuantity::Cmd_SetWorkerTargetQuantity(StreamRead & des)
 	:
 	Cmd_ChangeTargetQuantity(des),
-	m_permanent             (des.Unsigned32()),
-	m_temporary             (des.Unsigned32())
-{}
+	m_permanent             (des.Unsigned32())
+{
+	if (cmdserial() == 1) des.Unsigned32();
+}
 
 void Cmd_SetWorkerTargetQuantity::serialize(StreamWrite & ser)
 {
 	ser.Unsigned8 (PLCMD_SETWORKERTARGETQUANTITY);
 	Cmd_ChangeTargetQuantity::serialize(ser);
 	ser.Unsigned32(m_permanent);
-	ser.Unsigned32(m_temporary);
 }
 
 
@@ -901,7 +901,7 @@
 		int32_t const count =
 			tribe.get_ware_descr(ware_type())->default_target_quantity();
 		player.get_economy_by_number(economy())->set_worker_target_quantity
-			(ware_type(),  count, count, 0);
+			(ware_type(),  count, 0);
 	}
 }
 

=== modified file 'src/logic/playercommand.h'
--- src/logic/playercommand.h	2010-05-29 18:46:13 +0000
+++ src/logic/playercommand.h	2010-10-30 15:03:54 +0000
@@ -273,7 +273,7 @@
 	Cmd_SetWareTargetQuantity
 		(int32_t duetime, Player_Number sender,
 		 uint32_t economy, Ware_Index index,
-		 uint32_t permanent, uint32_t temporary);
+		 uint32_t permanent);
 
 	//  Write/Read these commands to/from a file (for savegames).
 	void Write(FileWrite &, Editor_Game_Base &, Map_Map_Object_Saver  &);
@@ -287,7 +287,7 @@
 	virtual void serialize (StreamWrite &);
 
 private:
-	uint32_t m_permanent, m_temporary;
+	uint32_t m_permanent;
 };
 
 struct Cmd_ResetWareTargetQuantity : public Cmd_ChangeTargetQuantity {
@@ -317,7 +317,7 @@
 	Cmd_SetWorkerTargetQuantity
 		(int32_t duetime, Player_Number sender,
 		 uint32_t economy, Ware_Index index,
-		 uint32_t permanent, uint32_t temporary);
+		 uint32_t permanent);
 
 	//  Write/Read these commands to/from a file (for savegames).
 	void Write(FileWrite &, Editor_Game_Base &, Map_Map_Object_Saver  &);
@@ -331,7 +331,7 @@
 	virtual void serialize (StreamWrite &);
 
 private:
-	uint32_t m_permanent, m_temporary;
+	uint32_t m_permanent;
 };
 
 struct Cmd_ResetWorkerTargetQuantity : public Cmd_ChangeTargetQuantity {

=== modified file 'src/wui/stock_menu.cc'
--- src/wui/stock_menu.cc	2010-06-16 20:29:34 +0000
+++ src/wui/stock_menu.cc	2010-10-30 15:03:54 +0000
@@ -45,24 +45,24 @@
 			 (this, 0, 0, g_gr->get_picture(PicMod_UI, "pics/but1.png"));
 	set_center_panel(tabs);
 
-	m_all_wares = new WaresDisplay(tabs, 0, 0, plr.player().tribe());
+	m_all_wares = new WaresDisplay(tabs, 0, 0, plr.player().tribe(), WaresDisplay::WARE, false);
 	tabs->add
 		("total_wares", g_gr->get_picture(PicMod_UI, pic_tab_wares),
 		 m_all_wares, _("Wares (total)"));
 
-	m_all_workers = new WaresDisplay(tabs, 0, 0, plr.player().tribe());
+	m_all_workers = new WaresDisplay(tabs, 0, 0, plr.player().tribe(), WaresDisplay::WORKER, false);
 	tabs->add
 		("workers_total", g_gr->get_picture(PicMod_UI, pic_tab_workers),
 		 m_all_workers, _("Workers (total)"));
 
-	m_warehouse_wares = new WaresDisplay(tabs, 0, 0, plr.player().tribe());
+	m_warehouse_wares = new WaresDisplay(tabs, 0, 0, plr.player().tribe(), WaresDisplay::WARE, false);
 	tabs->add
 		("wares_in_warehouses",
 		 g_gr->get_picture (PicMod_UI, pic_tab_wares_warehouse),
 		 m_warehouse_wares, _("Wares in warehouses")
 	);
 
-	m_warehouse_workers = new WaresDisplay(tabs, 0, 0, plr.player().tribe());
+	m_warehouse_workers = new WaresDisplay(tabs, 0, 0, plr.player().tribe(), WaresDisplay::WORKER, false);
 	tabs->add
 		("workers_in_warehouses",
 		 g_gr->get_picture(PicMod_UI, pic_tab_workers_warehouse),
@@ -99,8 +99,7 @@
 		waresdisplay->add_warelist
 			(type == WaresDisplay::WARE ?
 			 player.get_economy_by_number(i)->get_wares() :
-			 player.get_economy_by_number(i)->get_workers(),
-			 type);
+			 player.get_economy_by_number(i)->get_workers());
 }
 
 /**
@@ -125,7 +124,7 @@
 		{
 			waresdisplay->add_warelist
 				(type == WaresDisplay::WARE ?
-				 (*it)->get_wares() : (*it)->get_workers(), type);
+				 (*it)->get_wares() : (*it)->get_workers());
 		}
 	}
 }

=== modified file 'src/wui/transport_ui.cc'
--- src/wui/transport_ui.cc	2010-05-28 09:48:37 +0000
+++ src/wui/transport_ui.cc	2010-10-30 15:03:54 +0000
@@ -28,6 +28,9 @@
 #include "ui_basic/button.h"
 #include "ui_basic/tabpanel.h"
 #include "ui_basic/unique_window.h"
+#include "wui/waresdisplay.h"
+
+#include <boost/lexical_cast.hpp>
 
 using Widelands::Economy;
 using Widelands::Editor_Game_Base;
@@ -36,506 +39,241 @@
 using Widelands::Ware_Index;
 using Widelands::Worker_Descr;
 
+
+static const char pic_tab_wares[] = "pics/menu_tab_wares.png";
+static const char pic_tab_workers[] = "pics/menu_tab_workers.png";
+
 struct Economy_Options_Window : public UI::UniqueWindow {
 	Economy_Options_Window(Interactive_GameBase & parent, Economy & economy)
 		:
 		UI::UniqueWindow
 			(&parent, "economy_options", &economy.m_optionswindow_registry, 0, 0,
 			 _("Economy options")),
-		m_tabpanel(*this, economy)
+		m_tabpanel(this, 0, 0, g_gr->get_picture(PicMod_UI, "pics/but1.png"))
 	{
 		set_center_panel(&m_tabpanel);
-	}
 
-	virtual void think() {
-		Interactive_GameBase const & igbase =
-			ref_cast<Interactive_GameBase, UI::Panel>(*get_parent());
-		Widelands::Player_Number const owner =
-			m_tabpanel.economy().owner().player_number();
-		if (not igbase.can_see(owner))
-			die();
-		bool const can_act = igbase.can_act(owner);
-		for
-			(Ware_Type_Box * b =
-			 	dynamic_cast<Ware_Type_Box *>
-			 		(m_tabpanel.m_ware_target_quantities.get_first_child());
-			 b;
-			 b = dynamic_cast<Ware_Type_Box *>(b->get_next_sibling()))
-		{
-			Ware_Index const i = b->ware_type;
-			Economy::Target_Quantity const & tq =
-				m_tabpanel.economy().ware_target_quantity(i);
-			b->decrease_permanent.set_enabled(can_act and 1 < tq.permanent);
-			b->increase_permanent.set_enabled(can_act);
-			b->decrease_temporary.set_enabled(can_act and 1 < tq.temporary);
-			b->increase_temporary.set_enabled(can_act);
-			b->reset             .set_enabled(can_act and tq.last_modified);
-		}
-		for
-			(Worker_Type_Box * b =
-			 	dynamic_cast<Worker_Type_Box *>
-			 		(m_tabpanel.m_worker_target_quantities.get_first_child());
-			 b;
-			 b = dynamic_cast<Worker_Type_Box *>(b->get_next_sibling()))
-		{
-			Ware_Index const i = b->worker_type;
-			Economy::Target_Quantity const & tq =
-				m_tabpanel.economy().worker_target_quantity(i);
-			b->decrease_permanent.set_enabled(can_act and 1 < tq.permanent);
-			b->increase_permanent.set_enabled(can_act);
-			b->decrease_temporary.set_enabled(can_act and 1 < tq.temporary);
-			b->increase_temporary.set_enabled(can_act);
-			b->reset             .set_enabled(can_act and tq.last_modified);
-		}
+		m_tabpanel.add("wares",
+			g_gr->get_picture(PicMod_UI, pic_tab_wares),
+			new Economy_Options_Ware_Panel(&m_tabpanel, parent, economy),
+			_("Wares"));
+		m_tabpanel.add("workers",
+			g_gr->get_picture(PicMod_UI, pic_tab_workers),
+			new Economy_Options_Worker_Panel(&m_tabpanel, parent, economy),
+			_("Wares"));
 	}
 
 private:
-	struct Ware_Type_Box : public UI::Panel {
-		Ware_Type_Box
-			(UI::Box               &       parent,
-			 Ware_Index              const _ware_type,
-			 Item_Ware_Descr const &       _descr)
-			:
-			UI::Panel  (&parent, 0, 0, 420, 24),
-			decrease_permanent(*this),
-			increase_permanent(*this),
-			decrease_temporary(*this),
-			increase_temporary(*this),
-			reset             (*this),
-			ware_type         (_ware_type),
-			descr             (_descr)
-		{}
-
-		virtual void draw(RenderTarget & dst) {
-			dst.blit(Point(0, 0), descr.icon());
-			UI::g_fh->draw_string
-				(dst,
-				 UI_FONT_NAME, UI_FONT_SIZE_SMALL, UI_FONT_CLR_FG, UI_FONT_CLR_BG,
-				 Point(26, 12),
-				 descr.descname());
-			Economy::Target_Quantity const & tq =
-				economy().ware_target_quantity(ware_type);
-			char buffer[32];
-			sprintf(buffer, "%u", tq.permanent);
-			UI::g_fh->draw_string
-				(dst,
-				 UI_FONT_NAME, UI_FONT_SIZE_SMALL, UI_FONT_CLR_FG, UI_FONT_CLR_BG,
-				 Point(188, 12),
-				 buffer,
-				 UI::Align_CenterRight);
-			sprintf(buffer, "%u", tq.temporary);
-			UI::g_fh->draw_string
-				(dst,
-				 UI_FONT_NAME, UI_FONT_SIZE_SMALL, UI_FONT_CLR_FG, UI_FONT_CLR_BG,
-				 Point(278, 12),
-				 buffer,
-				 UI::Align_CenterRight);
-			UI::Panel::draw(dst);
-		}
-
-		Economy & economy() const {
-			return
-				ref_cast<Tab_Panel, UI::Panel>
-					(*ref_cast<UI::Box, UI::Panel>(*get_parent()).get_parent())
-				.economy();
-		}
-
-		struct Decrease_Permanent : public UI::Button {
-			Decrease_Permanent(Ware_Type_Box & parent) :
-				UI::Button
-					(&parent, "decr_permanent_target_quantity", 190, 0, 24, 24,
-					 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
-					 g_gr->get_picture(PicMod_UI, "pics/scrollbar_down.png"),
-					 _("Decrease permanent target quantity"),
-					 true)
-			{
-				set_repeating(true);
-			}
-			void clicked() {
-				Ware_Type_Box const & parent =
-					ref_cast<Ware_Type_Box, UI::Panel>(*get_parent());
-				Economy & e = parent.economy();
-				Ware_Index const ware_type = parent.ware_type;
-				Economy::Target_Quantity const & tq =
-					e.ware_target_quantity(ware_type);
-				assert(tq.permanent <= tq.temporary);
-				if (1 < tq.permanent) {
-					Widelands::Player & player = e.owner();
-					Game & game = ref_cast<Game, Editor_Game_Base>(player.egbase());
-					game.send_player_command
-						(*new Widelands::Cmd_SetWareTargetQuantity
-						 	(game.get_gametime(), player.player_number(),
-						 	 player.get_economy_number(&e), ware_type,
-						 	 tq.permanent - 1, tq.temporary));
-				}
-			}
-		} decrease_permanent;
-
-		struct Increase_Permanent : public UI::Button {
-			Increase_Permanent(Ware_Type_Box & parent) :
-				UI::Button
-					(&parent, "incr_permanent_target_quantity", 214, 0, 24, 24,
-					 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
-					 g_gr->get_picture(PicMod_UI, "pics/scrollbar_up.png"),
-					 _("Increase permanent target quantity"))
-			{
-				set_repeating(true);
-			}
-			void clicked() {
-				Ware_Type_Box const & parent =
-					ref_cast<Ware_Type_Box, UI::Panel>(*get_parent());
-				Economy & e = parent.economy();
-				Ware_Index const ware_type = parent.ware_type;
-				Economy::Target_Quantity const & tq =
-					e.ware_target_quantity(ware_type);
-				assert(tq.permanent <= tq.temporary);
-				uint32_t const new_permanent = tq.permanent + 1;
-				Widelands::Player & player = e.owner();
-				Game & game = ref_cast<Game, Editor_Game_Base>(player.egbase());
-				game.send_player_command
-					(*new Widelands::Cmd_SetWareTargetQuantity
-					 	(game.get_gametime(), player.player_number(),
-					 	 player.get_economy_number(&e), ware_type,
-					 	 new_permanent, std::max(new_permanent, tq.temporary)));
-			}
-		} increase_permanent;
-
-		struct Decrease_Temporary : public UI::Button {
-			Decrease_Temporary(Ware_Type_Box & parent) :
-				UI::Button
-					(&parent, "decr_temp_target_quantity", 280, 0, 24, 24,
-					 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
-					 g_gr->get_picture(PicMod_UI, "pics/scrollbar_down.png"),
-					 _("Decrease temporary target quantity"))
-			{
-				set_repeating(true);
-			}
-			void clicked() {
-				Ware_Type_Box const & parent =
-					ref_cast<Ware_Type_Box, UI::Panel>(*get_parent());
-				Economy & e = parent.economy();
-				Ware_Index const ware_type = parent.ware_type;
-				Economy::Target_Quantity const & tq =
-					e.ware_target_quantity(ware_type);
-				assert(tq.permanent <= tq.temporary);
-				if (1 < tq.temporary) {
-					uint32_t const new_temporary = tq.temporary - 1;
-					Widelands::Player & player = e.owner();
-					Game & game = ref_cast<Game, Editor_Game_Base>(player.egbase());
-					game.send_player_command
-						(*new Widelands::Cmd_SetWareTargetQuantity
-						 	(game.get_gametime(), player.player_number(),
-						 	 player.get_economy_number(&e), ware_type,
-						 	 std::min(tq.permanent, new_temporary), new_temporary));
-				}
-			}
-		} decrease_temporary;
-
-		struct Increase_Temporary : public UI::Button {
-			Increase_Temporary(Ware_Type_Box & parent) :
-				UI::Button
-					(&parent, "incr_temp_target_quantity",  304, 0, 24, 24,
-					 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
-					 g_gr->get_picture(PicMod_UI, "pics/scrollbar_up.png"),
-					 _("Increase temporary target quantity"))
-			{
-				set_repeating(true);
-			}
-			void clicked() {
-				Ware_Type_Box const & parent =
-					ref_cast<Ware_Type_Box, UI::Panel>(*get_parent());
-				Economy & e = parent.economy();
-				Ware_Index const ware_type = parent.ware_type;
-				Economy::Target_Quantity const & tq =
-					e.ware_target_quantity(ware_type);
-				assert(tq.permanent <= tq.temporary);
-				Widelands::Player & player = e.owner();
-				Game & game = ref_cast<Game, Editor_Game_Base>(player.egbase());
-				game.send_player_command
-					(*new Widelands::Cmd_SetWareTargetQuantity
-					 	(game.get_gametime(), player.player_number(),
-					 	 player.get_economy_number(&e), ware_type,
-					 	 tq.permanent, tq.temporary + 1));
-			}
-		} increase_temporary;
-
-		struct Reset : UI::Button {
-			Reset(Ware_Type_Box & parent) :
-				UI::Button
-					(&parent, "reset_target_quantity",  330, 0, 90, 24,
-					 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
-					 _("Reset"),
-					 _("Reset target quantity to default value"))
-			{}
-			void clicked() {
-				Ware_Type_Box const & parent =
-					ref_cast<Ware_Type_Box, UI::Panel>(*get_parent());
-				Economy & e = parent.economy();
-				Widelands::Player & player = e.owner();
-				Game & game = ref_cast<Game, Editor_Game_Base>(player.egbase());
-				game.send_player_command
-					(*new Widelands::Cmd_ResetWareTargetQuantity
-					 	(game.get_gametime(), player.player_number(),
-					 	 player.get_economy_number(&e), parent.ware_type));
-			}
-		} reset;
-
-		Ware_Index              const ware_type;
-		Item_Ware_Descr const &       descr;
-	};
-
-	struct Worker_Type_Box : public UI::Panel {
-		Worker_Type_Box
-			(UI::Box            &       parent,
-			 Ware_Index           const _worker_type,
-			 Worker_Descr const &       _descr)
-			:
-			UI::Panel  (&parent, 0, 0, 420, 24),
-			decrease_permanent(*this),
-			increase_permanent(*this),
-			decrease_temporary(*this),
-			increase_temporary(*this),
-			reset             (*this),
-			worker_type       (_worker_type),
-			descr             (_descr)
-		{}
-
-		virtual void draw(RenderTarget & dst) {
-			dst.blit(Point(0, 0), descr.icon());
-			UI::g_fh->draw_string
-				(dst,
-				 UI_FONT_NAME, UI_FONT_SIZE_SMALL, UI_FONT_CLR_FG, UI_FONT_CLR_BG,
-				 Point(26, 12),
-				 descr.descname());
-			Economy::Target_Quantity const & tq =
-				economy().worker_target_quantity(worker_type);
-			char buffer[32];
-			sprintf(buffer, "%u", tq.permanent);
-			UI::g_fh->draw_string
-				(dst,
-				 UI_FONT_NAME, UI_FONT_SIZE_SMALL, UI_FONT_CLR_FG, UI_FONT_CLR_BG,
-				 Point(188, 12),
-				 buffer,
-				 UI::Align_CenterRight);
-			sprintf(buffer, "%u", tq.temporary);
-			UI::g_fh->draw_string
-				(dst,
-				 UI_FONT_NAME, UI_FONT_SIZE_SMALL, UI_FONT_CLR_FG, UI_FONT_CLR_BG,
-				 Point(278, 12),
-				 buffer,
-				 UI::Align_CenterRight);
-			UI::Panel::draw(dst);
-		}
-
-		Economy & economy() const {
-			return
-				ref_cast<Tab_Panel, UI::Panel>
-					(*ref_cast<UI::Box, UI::Panel>(*get_parent()).get_parent())
-				.economy();
-		}
-
-		struct Decrease_Permanent : public UI::Button {
-			Decrease_Permanent(Worker_Type_Box & parent) :
-				UI::Button
-					(&parent, "decr_perm_target_quantity",  190, 0, 24, 24,
-					 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
-					 g_gr->get_picture(PicMod_UI, "pics/scrollbar_down.png"),
-					 _("Decrease permanent target quantity"),
-					 true)
-			{
-				set_repeating(true);
-			}
-			void clicked() {
-				Worker_Type_Box const & parent =
-					ref_cast<Worker_Type_Box, UI::Panel>(*get_parent());
-				Economy & e = parent.economy();
-				Ware_Index const worker_type = parent.worker_type;
-				Economy::Target_Quantity const & tq =
-					e.worker_target_quantity(worker_type);
-				assert(tq.permanent <= tq.temporary);
-				if (1 < tq.permanent) {
-					Widelands::Player & player = e.owner();
-					Game & game = ref_cast<Game, Editor_Game_Base>(player.egbase());
-					game.send_player_command
-						(*new Widelands::Cmd_SetWorkerTargetQuantity
-						 	(game.get_gametime(), player.player_number(),
-						 	 player.get_economy_number(&e), worker_type,
-						 	 tq.permanent - 1, tq.temporary));
-				}
-			}
-		} decrease_permanent;
-
-		struct Increase_Permanent : public UI::Button {
-			Increase_Permanent(Worker_Type_Box & parent) :
-				UI::Button
-					(&parent, "incr_perm_target_quantity",  214, 0, 24, 24,
-					 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
-					 g_gr->get_picture(PicMod_UI, "pics/scrollbar_up.png"),
-					 _("Increase permanent target quantity"))
-			{
-				set_repeating(true);
-			}
-			void clicked() {
-				Worker_Type_Box const & parent =
-					ref_cast<Worker_Type_Box, UI::Panel>(*get_parent());
-				Economy & e = parent.economy();
-				Ware_Index const worker_type = parent.worker_type;
-				Economy::Target_Quantity const & tq =
-					e.worker_target_quantity(worker_type);
-				assert(tq.permanent <= tq.temporary);
-				uint32_t const new_permanent = tq.permanent + 1;
-				Widelands::Player & player = e.owner();
-				Game & game = ref_cast<Game, Editor_Game_Base>(player.egbase());
-				game.send_player_command
-					(*new Widelands::Cmd_SetWorkerTargetQuantity
-					 	(game.get_gametime(), player.player_number(),
-					 	 player.get_economy_number(&e), worker_type,
-					 	 new_permanent, std::max(new_permanent, tq.temporary)));
-			}
-		} increase_permanent;
-
-		struct Decrease_Temporary : public UI::Button {
-			Decrease_Temporary(Worker_Type_Box & parent) :
-				UI::Button
-					(&parent, "decr_temp_target_quantity",  280, 0, 24, 24,
-					 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
-					 g_gr->get_picture(PicMod_UI, "pics/scrollbar_down.png"),
-					 _("Decrease temporary target quantity"))
-			{
-				set_repeating(true);
-			}
-			void clicked() {
-				Worker_Type_Box const & parent =
-					ref_cast<Worker_Type_Box, UI::Panel>(*get_parent());
-				Economy & e = parent.economy();
-				Ware_Index const worker_type = parent.worker_type;
-				Economy::Target_Quantity const & tq =
-					e.worker_target_quantity(worker_type);
-				assert(tq.permanent <= tq.temporary);
-				if (1 < tq.temporary) {
-					uint32_t const new_temporary = tq.temporary - 1;
-					Widelands::Player & player = e.owner();
-					Game & game = ref_cast<Game, Editor_Game_Base>(player.egbase());
-					game.send_player_command
-						(*new Widelands::Cmd_SetWorkerTargetQuantity
-						 	(game.get_gametime(), player.player_number(),
-						 	 player.get_economy_number(&e), worker_type,
-						 	 std::min(tq.permanent, new_temporary), new_temporary));
-				}
-			}
-		} decrease_temporary;
-
-		struct Increase_Temporary : public UI::Button {
-			Increase_Temporary(Worker_Type_Box & parent) :
-				UI::Button
-					(&parent, "incr_temp_target_quantity",  304, 0, 24, 24,
-					 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
-					 g_gr->get_picture(PicMod_UI, "pics/scrollbar_up.png"),
-					 _("Increase temporary target quantity"))
-			{
-				set_repeating(true);
-			}
-			void clicked() {
-				Worker_Type_Box const & parent =
-					ref_cast<Worker_Type_Box, UI::Panel>(*get_parent());
-				Economy & e = parent.economy();
-				Ware_Index const worker_type = parent.worker_type;
-				Economy::Target_Quantity const & tq =
-					e.worker_target_quantity(worker_type);
-				assert(tq.permanent <= tq.temporary);
-				Widelands::Player & player = e.owner();
-				Game & game = ref_cast<Game, Editor_Game_Base>(player.egbase());
-				game.send_player_command
-					(*new Widelands::Cmd_SetWorkerTargetQuantity
-					 	(game.get_gametime(), player.player_number(),
-					 	 player.get_economy_number(&e), worker_type,
-					 	 tq.permanent, tq.temporary + 1));
-			}
-		} increase_temporary;
-
-		struct Reset : UI::Button {
-			Reset(Worker_Type_Box & parent) :
-				UI::Button
-					(&parent, "reset_target_quantity",  330, 0, 90, 24,
-					 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
-					 _("Reset"),
-					 _("Reset target quantity to default value"))
-			{}
-			void clicked() {
-				Worker_Type_Box const & parent =
-					ref_cast<Worker_Type_Box, UI::Panel>(*get_parent());
-				Economy & e = parent.economy();
-				Widelands::Player & player = e.owner();
-				Game & game = ref_cast<Game, Editor_Game_Base>(player.egbase());
-				game.send_player_command
-					(*new Widelands::Cmd_ResetWorkerTargetQuantity
-					 	(game.get_gametime(), player.player_number(),
-					 	 player.get_economy_number(&e), parent.worker_type));
-			}
-		} reset;
-
-		Ware_Index           const worker_type;
-		Worker_Descr const &       descr;
-	};
-
-	struct Tab_Panel : public UI::Tab_Panel {
-		Tab_Panel(Economy_Options_Window & parent, Economy & _economy) :
-			UI::Tab_Panel
-				(&parent, 0, 0, g_gr->get_picture(PicMod_UI, "pics/but1.png")),
-			m_ware_target_quantities  (*this, _economy.owner().tribe()),
-			m_worker_target_quantities(*this, _economy.owner().tribe()),
-			m_economy(_economy)
-		{
-			add
-				("wares", g_gr->get_picture(PicMod_UI, "pics/genstats_nrwares.png"),
-				 &m_ware_target_quantities,
-				 _("Ware type target quantities"));
-			add
-				("workers",
-				 g_gr->get_picture(PicMod_UI, "pics/genstats_nrworkers.png"),
-				 &m_worker_target_quantities,
-				 _("Worker type target quantities"));
-			layout();
-		}
-
-		Economy & economy() const {return m_economy;}
-
-		struct Ware_Target_Quantities : public UI::Box {
-			Ware_Target_Quantities
-				(Tab_Panel & parent, Widelands::Tribe_Descr const & tribe)
-				:
-				UI::Box
-					(&parent, 0, 0, UI::Box::Vertical,
-					 g_gr->get_xres() - 80, g_gr->get_yres() - 100)
-			{
-				Ware_Index const nr_wares = tribe.get_nrwares();
-				for (Ware_Index i = Ware_Index::First(); i < nr_wares; ++i) {
-					Item_Ware_Descr const & descr = *tribe.get_ware_descr(i);
-					if (descr.has_demand_check())
-						add(new Ware_Type_Box(*this, i, descr), UI::Box::AlignTop);
-				}
-				set_scrolling(true);
-			}
-		} m_ware_target_quantities;
-		struct Worker_Target_Quantities : public UI::Box {
-			Worker_Target_Quantities
-				(Tab_Panel & parent, Widelands::Tribe_Descr const & tribe)
-				:
-				UI::Box
-					(&parent, 0, 0, UI::Box::Vertical,
-					 g_gr->get_xres() - 80, g_gr->get_yres() - 100)
-			{
-				Ware_Index const nr_workers = tribe.get_nrworkers();
-				for (Ware_Index i = Ware_Index::First(); i < nr_workers; ++i) {
-					Worker_Descr const & descr = *tribe.get_worker_descr(i);
-					if (descr.has_demand_check())
-						add(new Worker_Type_Box(*this, i, descr), UI::Box::AlignTop);
-				}
-				set_scrolling(true);
-			}
-		} m_worker_target_quantities;
-		Economy & m_economy;
-	} m_tabpanel;
+	UI::Tab_Panel m_tabpanel;
+
+	struct TargetWaresDisplay : public AbstractWaresDisplay {
+		typedef AbstractWaresDisplay::wdType wdType;
+
+		TargetWaresDisplay
+			(UI::Panel * const parent,
+			 int32_t const x, int32_t const y,
+			 Widelands::Tribe_Descr const & tribe,
+			 wdType type,
+			 bool selectable,
+			 Economy & economy):
+			 AbstractWaresDisplay(parent, x, y, tribe, type, selectable) ,
+			 m_economy(economy)
+		{
+			Ware_Index nr_wares = m_economy.owner().tribe().get_nrwares();
+			for (Ware_Index i = Ware_Index::First(); i < nr_wares; ++i) {
+				if (not m_economy.owner().tribe().get_ware_descr(i)->has_demand_check()) {
+					hide_ware(i);
+				}
+			}
+		}
+	protected:
+		std::string info_for_ware(Widelands::Ware_Index const ware) {
+			return boost::lexical_cast<std::string>(
+				get_type() == WaresDisplay::WORKER
+				? m_economy.worker_target_quantity(ware).permanent
+				: m_economy.ware_target_quantity(ware).permanent
+			);
+		}
+	private:
+		Economy & m_economy;
+	};
+
+
+	/**
+	 * Wraps the wares display together with some buttons
+	 */
+	struct Economy_Options_Ware_Panel : UI::Box {
+		bool m_can_act;
+		TargetWaresDisplay m_display;
+		Economy & m_economy;
+
+		Economy_Options_Ware_Panel(UI::Panel * parent, Interactive_GameBase & igbase, Economy & economy) :
+			UI::Box(parent, 0, 0, UI::Box::Vertical),
+			m_can_act(igbase.can_act(economy.owner().player_number())),
+			m_display(this, 0, 0, economy.owner().tribe(), WaresDisplay::WARE, m_can_act,economy),
+			m_economy(economy)
+		{
+			add(&m_display, UI::Box::AlignLeft, true);
+
+			UI::Box *buttons = new UI::Box(this, 0, 0, UI::Box::Horizontal);
+			add(buttons, UI::Box::AlignLeft);
+				
+			#define ADD_WARE_BUTTON(callback, text, tooltip)                          \
+				buttons->add(new UI::Callback_Button(                             \
+					buttons, #callback,                                       \
+					0, 0, 34, 34,                                             \
+					g_gr->get_picture(PicMod_UI,"pics/but4.png"),             \
+					boost::bind(&Economy_Options_Ware_Panel::callback, this), \
+					text, tooltip, m_can_act)                                 \
+				, UI::Box::AlignCenter);                                          \
+			
+			ADD_WARE_BUTTON(increase_target, "+", _("Increase target"))
+			ADD_WARE_BUTTON(decrease_target, "-", _("Decrease target"))
+			ADD_WARE_BUTTON(reset_target, "R", _("Reset to default"))
+		}
+
+		void decrease_target() {
+			Widelands::Ware_Index nritems = m_economy.owner().tribe().get_nrwares();
+
+			for (Widelands::Ware_Index id = Widelands::Ware_Index::First();
+	                    id < nritems; ++id) {
+				if (m_display.ware_selected(id)) {
+					Economy::Target_Quantity const & tq =
+						m_economy.ware_target_quantity(id);
+					if (1 < tq.permanent) {
+						Widelands::Player & player = m_economy.owner();
+						Game & game = ref_cast<Game, Editor_Game_Base>(player.egbase());
+						game.send_player_command
+							(*new Widelands::Cmd_SetWareTargetQuantity
+								(game.get_gametime(), player.player_number(),
+								 player.get_economy_number(&m_economy), id,
+								 tq.permanent - 1));
+					}
+				}
+                        }
+		}
+
+		void increase_target() {
+			Widelands::Ware_Index nritems = m_economy.owner().tribe().get_nrwares();
+
+			for (Widelands::Ware_Index id = Widelands::Ware_Index::First();
+	                    id < nritems; ++id) {
+				if (m_display.ware_selected(id)) {
+					Economy::Target_Quantity const & tq =
+						m_economy.ware_target_quantity(id);
+					Widelands::Player & player = m_economy.owner();
+					Game & game = ref_cast<Game, Editor_Game_Base>(player.egbase());
+					game.send_player_command
+						(*new Widelands::Cmd_SetWareTargetQuantity
+							(game.get_gametime(), player.player_number(),
+							 player.get_economy_number(&m_economy), id,
+							 tq.permanent + 1));
+				}
+                        }
+		}
+
+		void reset_target() {
+			Widelands::Ware_Index nritems = m_economy.owner().tribe().get_nrwares();
+
+			for (Widelands::Ware_Index id = Widelands::Ware_Index::First();
+	                    id < nritems; ++id) {
+				if (m_display.ware_selected(id)) {
+					Widelands::Player & player = m_economy.owner();
+					Game & game = ref_cast<Game, Editor_Game_Base>(player.egbase());
+					game.send_player_command
+						(*new Widelands::Cmd_ResetWareTargetQuantity
+							(game.get_gametime(), player.player_number(),
+							 player.get_economy_number(&m_economy), id));
+				}
+                        }
+		}
+	};
+	struct Economy_Options_Worker_Panel : UI::Box {
+		bool m_can_act;
+		TargetWaresDisplay m_display;
+		Economy & m_economy;
+
+		Economy_Options_Worker_Panel(UI::Panel * parent, Interactive_GameBase & igbase, Economy & economy) :
+			UI::Box(parent, 0, 0, UI::Box::Vertical),
+			m_can_act(igbase.can_act(economy.owner().player_number())),
+			m_display(this, 0, 0, economy.owner().tribe(), WaresDisplay::WORKER, m_can_act,economy),
+			m_economy(economy)
+		{
+			add(&m_display, UI::Box::AlignLeft, true);
+
+			UI::Box *buttons = new UI::Box(this, 0, 0, UI::Box::Horizontal);
+			add(buttons, UI::Box::AlignLeft);
+				
+			#define ADD_WORKER_BUTTON(callback, text, tooltip)                          \
+				buttons->add(new UI::Callback_Button(                               \
+					buttons, #callback,                                         \
+					0, 0, 34, 34,                                               \
+					g_gr->get_picture(PicMod_UI,"pics/but4.png"),               \
+					boost::bind(&Economy_Options_Worker_Panel::callback, this), \
+					text, tooltip, m_can_act)                                   \
+				, UI::Box::AlignCenter);                                            \
+			
+			ADD_WORKER_BUTTON(increase_target, "+", _("Increase target"))
+			ADD_WORKER_BUTTON(decrease_target, "-", _("Decrease target"))
+			ADD_WORKER_BUTTON(reset_target, "R", _("Reset to default"))
+		}
+
+
+		void decrease_target() {
+			Widelands::Ware_Index nritems = m_economy.owner().tribe().get_nrworkers();
+
+			for (Widelands::Ware_Index id = Widelands::Ware_Index::First();
+	                    id < nritems; ++id) {
+				if (m_display.ware_selected(id)) {
+					Economy::Target_Quantity const & tq =
+						m_economy.worker_target_quantity(id);
+					if (1 < tq.permanent) {
+						Widelands::Player & player = m_economy.owner();
+						Game & game = ref_cast<Game, Editor_Game_Base>(player.egbase());
+						game.send_player_command
+							(*new Widelands::Cmd_SetWorkerTargetQuantity
+								(game.get_gametime(), player.player_number(),
+								 player.get_economy_number(&m_economy), id,
+								 tq.permanent - 1));
+					}
+				}
+                        }
+		}
+
+		void increase_target() {
+			Widelands::Ware_Index nritems = m_economy.owner().tribe().get_nrworkers();
+
+			for (Widelands::Ware_Index id = Widelands::Ware_Index::First();
+	                    id < nritems; ++id) {
+				if (m_display.ware_selected(id)) {
+					Economy::Target_Quantity const & tq =
+						m_economy.worker_target_quantity(id);
+					Widelands::Player & player = m_economy.owner();
+					Game & game = ref_cast<Game, Editor_Game_Base>(player.egbase());
+					game.send_player_command
+						(*new Widelands::Cmd_SetWorkerTargetQuantity
+							(game.get_gametime(), player.player_number(),
+							 player.get_economy_number(&m_economy), id,
+							 tq.permanent + 1));
+				}
+                        }
+		}
+
+		void reset_target() {
+			Widelands::Ware_Index nritems = m_economy.owner().tribe().get_nrworkers();
+			for (Widelands::Ware_Index id = Widelands::Ware_Index::First();
+	                    id < nritems; ++id) {
+				if (m_display.ware_selected(id)) {
+					Widelands::Player & player = m_economy.owner();
+					Game & game = ref_cast<Game, Editor_Game_Base>(player.egbase());
+					game.send_player_command
+						(*new Widelands::Cmd_ResetWorkerTargetQuantity
+							(game.get_gametime(), player.player_number(),
+							 player.get_economy_number(&m_economy), id));
+				}
+                        }
+		}
+	};
 };
 
 

=== modified file 'src/wui/warehousewindow.cc'
--- src/wui/warehousewindow.cc	2010-10-29 22:01:38 +0000
+++ src/wui/warehousewindow.cc	2010-10-30 15:03:54 +0000
@@ -41,8 +41,7 @@
 	WarehouseWaresDisplay(UI::Panel * parent, uint32_t width, Interactive_GameBase &, Warehouse &, wdType type);
 
 protected:
-	virtual void draw_ware(RenderTarget& dst, Widelands::Ware_Index ware, uint32_t stock);
-	virtual bool handle_mousepress(Uint8 btn, int32_t x, int32_t y);
+	virtual void draw_ware(RenderTarget& dst, Widelands::Ware_Index ware);
 
 private:
 	Interactive_GameBase & m_igbase;
@@ -52,19 +51,17 @@
 WarehouseWaresDisplay::WarehouseWaresDisplay
 	(UI::Panel* parent, uint32_t width, Interactive_GameBase & igbase, Warehouse& wh, wdType type)
 :
-WaresDisplay(parent, 0, 0, wh.owner().tribe()),
+WaresDisplay(parent, 0, 0, wh.owner().tribe(), type, true),
 m_igbase(igbase),
 m_warehouse(wh)
 {
 	set_inner_size(width, 0);
-	add_warelist
-		(type == WORKER ? m_warehouse.get_workers() : m_warehouse.get_wares(),
-		 type);
+	add_warelist(type == WORKER ? m_warehouse.get_workers() : m_warehouse.get_wares());
 }
 
-void WarehouseWaresDisplay::draw_ware(RenderTarget& dst, Widelands::Ware_Index ware, uint32_t stock)
+void WarehouseWaresDisplay::draw_ware(RenderTarget& dst, Widelands::Ware_Index ware)
 {
-	WaresDisplay::draw_ware(dst, ware, stock);
+	WaresDisplay::draw_ware(dst, ware);
 
 	Warehouse::StockPolicy policy = m_warehouse.get_stock_policy(get_type() == WORKER, ware);
 	PictureID picid;
@@ -81,34 +78,74 @@
 	dst.blit(ware_position(ware), picid);
 }
 
-bool WarehouseWaresDisplay::handle_mousepress(Uint8 btn, int32_t x, int32_t y)
+/**
+ * Wraps the wares display together with some buttons
+ */
+struct WarehouseWaresPanel : UI::Box {
+	WarehouseWaresPanel(UI::Panel * parent, uint32_t width, Interactive_GameBase &, Warehouse &, WaresDisplay::wdType type);
+
+	void set_policy(Warehouse::StockPolicy);
+private:
+	WarehouseWaresDisplay m_display;
+	Interactive_GameBase & m_gb;
+	Warehouse & m_wh;
+	WaresDisplay::wdType m_type;
+
+};
+
+WarehouseWaresPanel::WarehouseWaresPanel(UI::Panel * parent, uint32_t width, Interactive_GameBase & gb, Warehouse & wh, WaresDisplay::wdType type) :
+	UI::Box(parent, 0, 0, UI::Box::Vertical),
+	m_display(this, width, gb, wh, type),
+	m_gb(gb),
+	m_wh(wh),
+	m_type(type)
 {
-	if (btn == SDL_BUTTON_LEFT) {
-		Widelands::Ware_Index ware = ware_at_point(x, y);
-		if (!ware)
-			return false;
-
-		if (m_igbase.can_act(m_warehouse.owner().player_number())) {
-			Warehouse::StockPolicy policy = m_warehouse.get_stock_policy(get_type() == WORKER, ware);
-			Warehouse::StockPolicy newpolicy;
-
-			switch(policy) {
-			case Warehouse::SP_Normal: newpolicy = Warehouse::SP_Prefer; break;
-			case Warehouse::SP_Prefer: newpolicy = Warehouse::SP_DontStock; break;
-			case Warehouse::SP_DontStock: newpolicy = Warehouse::SP_Remove; break;
-			default: newpolicy = Warehouse::SP_Normal; break;
+	add(&m_display, UI::Box::AlignLeft, true);
+
+	UI::Box *buttons = new UI::Box(this, 0, 0, UI::Box::Horizontal);
+	add(buttons, UI::Box::AlignLeft);
+		
+	if (m_gb.can_act(m_wh.owner().player_number())) {
+#define ADD_POLICY_BUTTON(policy, policyname, tooltip)                    \
+        	buttons->add(new UI::Callback_Button(                     \
+			buttons, #policy,                                 \
+			0, 0, 34, 34,                                     \
+			g_gr->get_picture(PicMod_UI,"pics/but4.png"),     \
+			g_gr->get_picture(PicMod_Game,                    \
+		              "pics/stock_policy_button_" #policy ".png"),\
+			boost::bind(&WarehouseWaresPanel::set_policy,     \
+			            this, Warehouse::SP_##policyname),    \
+			tooltip)                                          \
+		, UI::Box::AlignCenter);                                  \
+	
+		ADD_POLICY_BUTTON(normal, Normal, _("Normal policy"))
+		ADD_POLICY_BUTTON(prefer, Prefer, _("Preferably store selected wares here"))
+		ADD_POLICY_BUTTON(dontstock, DontStock, _("Do not store selected wares here"))
+		ADD_POLICY_BUTTON(remove, Remove, _("Remove selected wares from here"))
+	}
+}
+
+/**
+ * Add Buttons policy buttons
+ */
+void WarehouseWaresPanel::set_policy(Warehouse::StockPolicy newpolicy) {
+	bool is_workers = m_type == WaresDisplay::WORKER;
+	Widelands::Ware_Index nritems =
+	                   is_workers ? m_wh.owner().tribe().get_nrworkers() :
+				        m_wh.owner().tribe().get_nrwares();
+	if (m_gb.can_act(m_wh.owner().player_number())) {
+	       for (Widelands::Ware_Index id = Widelands::Ware_Index::First();
+	            id < nritems; ++id) {
+			if (m_display.ware_selected(id)) {
+				m_gb.game().send_player_command
+					(*new Widelands::Cmd_SetStockPolicy
+						(m_gb.game().get_gametime(),
+						 m_wh.owner().player_number(),
+						 m_wh, is_workers,
+						 id, newpolicy));
 			}
-
-			m_igbase.game().send_player_command
-				(*new Widelands::Cmd_SetStockPolicy
-					(m_igbase.game().get_gametime(), m_warehouse.owner().player_number(),
-					 m_warehouse, get_type() == WORKER, ware, newpolicy));
 		}
-
-		return true;
 	}
-
-	return WaresDisplay::handle_mousepress(btn, x, y);
 }
 
 
@@ -149,8 +186,8 @@
 void Warehouse_Window::make_wares_tab
 	(WaresDisplay::wdType type, PictureID tabicon, const std::string & tooltip)
 {
-	WaresDisplay * display = new WarehouseWaresDisplay(get_tabs(), Width, igbase(), warehouse(), type);
-	get_tabs()->add("wares", tabicon, display, tooltip);
+	WarehouseWaresPanel * panel = new WarehouseWaresPanel(get_tabs(), Width, igbase(), warehouse(), type);
+	get_tabs()->add("wares", tabicon, panel, tooltip);
 }
 
 /**

=== modified file 'src/wui/waresdisplay.cc'
--- src/wui/waresdisplay.cc	2010-10-30 09:18:16 +0000
+++ src/wui/waresdisplay.cc	2010-10-30 15:03:54 +0000
@@ -28,11 +28,14 @@
 #include "logic/worker.h"
 
 #include <cstdio>
+#include <boost/lexical_cast.hpp>
 
-WaresDisplay::WaresDisplay
+AbstractWaresDisplay::AbstractWaresDisplay
 	(UI::Panel * const parent,
 	 int32_t const x, int32_t const y,
-	 Widelands::Tribe_Descr const & tribe)
+	 Widelands::Tribe_Descr const & tribe,
+	 wdType type,
+	 bool selectable)
 	:
 	// Size is set when add_warelist is called, as it depends on the m_type.
 	UI::Panel(parent, x, y, 0, 0),
@@ -42,23 +45,29 @@
 		(this,
 		 0, get_inner_h() - 25, get_inner_w(), 20,
 		 _("Stock"), UI::Align_Center),
-	m_type (WORKER)
-
-{
-}
-
-
-WaresDisplay::~WaresDisplay()
-{
-	remove_all_warelists();
-}
-
-
-bool WaresDisplay::handle_mousemove
+	m_type (type),
+	m_selected(m_type == WORKER ? m_tribe.get_nrworkers()
+	                            : m_tribe.get_nrwares(), false),
+	m_hidden  (m_type == WORKER ? m_tribe.get_nrworkers()
+	                            : m_tribe.get_nrwares(), false),
+	m_selectable(selectable)				    
+{
+	// 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();
+
+	// 25 is height of m_curware text
+	set_desired_size(columns * (WARE_MENU_PIC_WIDTH  +     3) + 1,
+	                 rows    * (WARE_MENU_PIC_HEIGHT + 8 + 3) + 1 + 25);
+}
+
+
+bool AbstractWaresDisplay::handle_mousemove
 	(Uint8, int32_t const x, int32_t const y, int32_t, int32_t)
 {
-	assert(m_warelists.size());
-
 	Widelands::Ware_Index const index = ware_at_point(x, y);
 
 	m_curware.set_text
@@ -73,11 +82,28 @@
 	return true;
 }
 
+bool AbstractWaresDisplay::handle_mousepress
+	(Uint8 btn, int32_t const x, int32_t const y)
+{
+	if (btn == SDL_BUTTON_LEFT) {
+		Widelands::Ware_Index ware = ware_at_point(x, y);
+		if (!ware)
+			return false;
+
+		if (m_selectable) {
+			toggle_ware(ware);
+		}
+		return true;
+	}
+
+	return UI::Panel::handle_mousepress(btn, x, y);
+}
+
 /**
  * Returns the index of the ware under the given coordinates, or
  * WareIndex::Null() if the given point is outside the range.
  */
-Widelands::Ware_Index WaresDisplay::ware_at_point(int32_t x, int32_t y) const
+Widelands::Ware_Index AbstractWaresDisplay::ware_at_point(int32_t x, int32_t y) const
 {
 	if (x < 0 || y < 0)
 		return Widelands::Ware_Index::Null();
@@ -86,43 +112,17 @@
 	unsigned int i = x / (WARE_MENU_PIC_WIDTH + 4);
 	unsigned int j = y / (WARE_MENU_PIC_HEIGHT + 8 + 3);
 	if (i < icons_order().size() && j < icons_order()[i].size()) {
-		return icons_order()[i][j];
+		Widelands::Ware_Index ware = icons_order()[i][j];
+		if (not m_hidden[ware]) {
+			return ware;
+		}
 	}
 
 	return Widelands::Ware_Index::Null();
 }
 
 
-/*
-===============
-add a ware list to be displayed in this WaresDisplay
-===============
-*/
-void WaresDisplay::add_warelist
-	(Widelands::WareList const & wares, wdType const type)
-{
-	//  If you register something twice, it is counted twice. Not my problem.
-	m_warelists.push_back(&wares);
-	m_type = type;
-
-	update_desired_size();
-}
-
-void WaresDisplay::update_desired_size()
-{
-	// 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();
-
-	// 25 is height of m_curware text
-	set_desired_size(columns * (WARE_MENU_PIC_WIDTH  +     3) + 1,
-	                 rows    * (WARE_MENU_PIC_HEIGHT + 8 + 3) + 1 + 25);
-}
-
-void WaresDisplay::layout()
+void AbstractWaresDisplay::layout()
 {
 	m_curware.set_pos(Point(0, get_inner_h() - 25));
 	m_curware.set_size(get_inner_w(), 20);
@@ -133,7 +133,7 @@
 }
 
 
-void WaresDisplay::draw(RenderTarget & dst)
+void AbstractWaresDisplay::draw(RenderTarget & dst)
 {
 	Widelands::Ware_Index number = 
 		m_type == WORKER ? 
@@ -146,18 +146,13 @@
 		 id < number;
 		 ++id, ++totid)
 	{
-		uint32_t totalstock = 0;
-		for
-			(Widelands::Ware_Index i = Widelands::Ware_Index::First();
-			 i.value() < m_warelists.size();
-			 ++i)
-			totalstock += m_warelists[i]->stock(id);
+		if (m_hidden[id]) continue;
 
-		draw_ware(dst, id, totalstock);
+		draw_ware(dst, id);
 	}
 }
 
-Widelands::Tribe_Descr::WaresOrder const & WaresDisplay::icons_order() const
+Widelands::Tribe_Descr::WaresOrder const & AbstractWaresDisplay::icons_order() const
 {
 	switch(m_type) {
 		case WARE:
@@ -169,7 +164,7 @@
 	}
 }
 
-Widelands::Tribe_Descr::WaresOrderCoords const & WaresDisplay::icons_order_coords() const
+Widelands::Tribe_Descr::WaresOrderCoords const & AbstractWaresDisplay::icons_order_coords() const
 {
 	switch(m_type) {
 		case WARE:
@@ -182,7 +177,7 @@
 }
 
 
-Point WaresDisplay::ware_position(Widelands::Ware_Index const id) const
+Point AbstractWaresDisplay::ware_position(Widelands::Ware_Index const id) const
 {
 	Point p(2,2);
 	p.x += icons_order_coords()[id].first  * (WARE_MENU_PIC_WIDTH + 3);
@@ -197,16 +192,18 @@
 Draw one ware icon + additional information.
 ===============
 */
-void WaresDisplay::draw_ware
+void AbstractWaresDisplay::draw_ware
 	(RenderTarget        &       dst,
-	 Widelands::Ware_Index const id,
-	 uint32_t              const stock)
+	 Widelands::Ware_Index const id)
 {
 	Point p = ware_position(id);
 
 	//  draw a background
 	const PictureID picid =
-		g_gr->get_picture(PicMod_Game, "pics/ware_list_bg.png");
+		g_gr->get_picture(PicMod_Game,
+			ware_selected(id) ?  "pics/ware_list_bg_selected.png"
+			                  :  "pics/ware_list_bg.png"
+		);
 	uint32_t w, h;
 	g_gr->get_picture_size(picid, w, h);
 
@@ -224,14 +221,69 @@
 		(Rect(pos + Point(0, WARE_MENU_PIC_HEIGHT), WARE_MENU_PIC_WIDTH, 8),
 		 RGBColor(0, 0, 0));
 
-	char buffer[32];
-	snprintf(buffer, sizeof(buffer), "%i", stock);
-
 	UI::g_fh->draw_string
 		(dst,
 		 UI_FONT_ULTRASMALL,
 		 UI_FONT_SMALL_CLR,
 		 p + Point(WARE_MENU_PIC_WIDTH, WARE_MENU_PIC_HEIGHT - 4),
-		 buffer,
+		 info_for_ware(id),
 		 UI::Align_Right);
 }
+
+// Wares highlighting/selecting
+void AbstractWaresDisplay::select_ware(Widelands::Ware_Index ware) {
+	m_selected[ware] = true;
+}
+void AbstractWaresDisplay::unselect_ware(Widelands::Ware_Index ware) {
+	m_selected[ware] = false;
+}
+bool AbstractWaresDisplay::ware_selected(Widelands::Ware_Index ware) {
+	return	m_selected[ware];
+}
+
+// Wares hiding
+void AbstractWaresDisplay::hide_ware(Widelands::Ware_Index ware) {
+	m_hidden[ware] = true;
+}
+void AbstractWaresDisplay::unhide_ware(Widelands::Ware_Index ware) {
+	m_hidden[ware] = false;
+}
+bool AbstractWaresDisplay::ware_hidden(Widelands::Ware_Index ware) {
+	return	m_hidden[ware];
+}
+
+WaresDisplay::WaresDisplay
+	(UI::Panel * const parent,
+	 int32_t const x, int32_t const y,
+	 Widelands::Tribe_Descr const & tribe,
+	 wdType type,
+	 bool selectable) :
+	 AbstractWaresDisplay(parent, x, y, tribe, type, selectable)
+{}
+
+WaresDisplay::~WaresDisplay()
+{
+	remove_all_warelists();
+}
+
+std::string WaresDisplay::info_for_ware(Widelands::Ware_Index ware) {
+	uint32_t totalstock = 0;
+	for
+		(Widelands::Ware_Index i = Widelands::Ware_Index::First();
+		 i.value() < m_warelists.size();
+		 ++i)
+		totalstock += m_warelists[i]->stock(ware);
+	return boost::lexical_cast<std::string>(totalstock);
+}
+
+/*
+===============
+add a ware list to be displayed in this WaresDisplay
+===============
+*/
+void WaresDisplay::add_warelist
+	(Widelands::WareList const & wares)
+{
+	//  If you register something twice, it is counted twice. Not my problem.
+	m_warelists.push_back(&wares);
+}

=== modified file 'src/wui/waresdisplay.h'
--- src/wui/waresdisplay.h	2010-10-30 09:14:05 +0000
+++ src/wui/waresdisplay.h	2010-10-30 15:03:54 +0000
@@ -35,33 +35,52 @@
 }
 
 /*
-class WaresDisplay
+class AbstractWaresDisplay
 ------------------
-Panel that displays the contents of a WareList.
+Panel that displays wares or workers with some string
 */
-struct WaresDisplay : public UI::Panel {
+struct AbstractWaresDisplay : public UI::Panel {
 	enum wdType {
 		WORKER,
 		WARE
 	};
 
-	WaresDisplay
+	AbstractWaresDisplay
 		(UI::Panel * const parent,
-		 int32_t const x, int32_t const y, Widelands::Tribe_Descr const &);
-	virtual ~WaresDisplay();
+		 int32_t const x, int32_t const y,
+		 Widelands::Tribe_Descr const &,
+		 wdType type,
+		 bool selectable);
 
 	bool handle_mousemove
 		(Uint8 state, int32_t x, int32_t y, int32_t xdiff, int32_t ydiff);
 
-	void add_warelist(Widelands::WareList const &, wdType);
-	void remove_all_warelists();
+	bool handle_mousepress(Uint8 btn, int32_t x, int32_t y);
+
+
+	// Wares may be selected (highlighted)
+	void select_ware(Widelands::Ware_Index);
+	void unselect_ware(Widelands::Ware_Index);
+	bool ware_selected(Widelands::Ware_Index);
+	void toggle_ware(Widelands::Ware_Index ware) {
+		if (ware_selected(ware))
+			unselect_ware(ware);
+		else
+			select_ware(ware);
+	}
+
+	// Wares may be hidden
+	void hide_ware(Widelands::Ware_Index);
+	void unhide_ware(Widelands::Ware_Index);
+	bool ware_hidden(Widelands::Ware_Index);
 
 	Widelands::Ware_Index ware_at_point(int32_t x, int32_t y) const;
 	wdType get_type() const {return m_type;}
 
 protected:
 	virtual void layout();
-	virtual void update_desired_size();
+
+	virtual std::string info_for_ware(Widelands::Ware_Index const) = 0;
 
 	Widelands::Tribe_Descr::WaresOrder const & icons_order() const;
 	Widelands::Tribe_Descr::WaresOrderCoords const & icons_order_coords() const;
@@ -69,15 +88,45 @@
 	virtual void draw(RenderTarget &);
 	virtual void draw_ware
 		(RenderTarget &,
-		 Widelands::Ware_Index,
-		 uint32_t stock);
+		 Widelands::Ware_Index);
 
 private:
 	typedef std::vector<Widelands::WareList const *> vector_type;
+	typedef std::vector<bool> selection_type;
 
 	Widelands::Tribe_Descr const & m_tribe;
+	wdType              m_type;
 	UI::Textarea        m_curware;
-	wdType              m_type;
+	selection_type      m_selected;
+	selection_type      m_hidden;
+	bool		    m_selectable;
+};
+
+/*
+class WaresDisplay
+------------------
+Panel that displays the contents of a WareList.
+*/
+struct WaresDisplay : public AbstractWaresDisplay {
+	typedef AbstractWaresDisplay::wdType wdType;
+
+	WaresDisplay
+		(UI::Panel * const parent,
+		 int32_t const x, int32_t const y,
+		 Widelands::Tribe_Descr const &,
+		 wdType type,
+		 bool selectable);
+
+	virtual ~WaresDisplay();
+
+	void add_warelist(Widelands::WareList const &);
+	void remove_all_warelists();
+
+protected:
+	virtual std::string info_for_ware(Widelands::Ware_Index const);
+
+private:
+	typedef std::vector<Widelands::WareList const *> vector_type;
 	vector_type         m_warelists;
 };
 


Follow ups