← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/csite_improvement into lp:widelands

 

cghislai has proposed merging lp:~widelands-dev/widelands/csite_improvement into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #580905 in widelands: "write building status in a different font color for construction sites"
  https://bugs.launchpad.net/widelands/+bug/580905
  Bug #722087 in widelands: "hard to empty warehouse"
  https://bugs.launchpad.net/widelands/+bug/722087
  Bug #803284 in widelands: "While building, show range of the building on construction site"
  https://bugs.launchpad.net/widelands/+bug/803284
  Bug #1108083 in widelands: "Construction site window does not display specific building name"
  https://bugs.launchpad.net/widelands/+bug/1108083
  Bug #1132238 in widelands: "Open buildingwindow after closing of constructionsitewindow when construction has finished"
  https://bugs.launchpad.net/widelands/+bug/1132238

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/csite_improvement/+merge/174623

This contains a bunch of improvements not all related to construction sites
- Colored string for production efficiency and trends
- Anchored selection for ware selection in warehouses/economy settings
- Range building shown for construction sites
- Building name shown in construction site windows
- Building window opened when construction site window was open when build finishes
-- 
https://code.launchpad.net/~widelands-dev/widelands/csite_improvement/+merge/174623
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/csite_improvement into lp:widelands.
=== modified file 'src/constants.h'
--- src/constants.h	2013-07-13 14:32:49 +0000
+++ src/constants.h	2013-07-14 16:56:24 +0000
@@ -80,9 +80,11 @@
 #define PROSA_FONT_CLR_FG    RGBColor(255, 255,   0)
 
 /// Colors for good/ok/bad
-#define UI_FONT_CLR_BAD_HEX   "ff0000"
-#define UI_FONT_CLR_OK_HEX   "ffff00"
-#define UI_FONT_CLR_GOOD_HEX   "325b1f"
+#define UI_FONT_CLR_BRIGHT_HEX    "fff666"
+#define UI_FONT_CLR_DARK_HEX      "a39013"
+#define UI_FONT_CLR_BAD_HEX       "bb0000"
+#define UI_FONT_CLR_OK_HEX        "ffe11e"
+#define UI_FONT_CLR_GOOD_HEX      "55ff46"
 //@}
 
 /** \name Text colors

=== modified file 'src/logic/building.h'
--- src/logic/building.h	2013-07-14 10:38:26 +0000
+++ src/logic/building.h	2013-07-14 16:56:24 +0000
@@ -183,7 +183,7 @@
 	virtual bool burn_on_destroy();
 	virtual void destroy(Editor_Game_Base &);
 
-	void show_options(Interactive_GameBase &, bool avoid_fastclick = false);
+	void show_options(Interactive_GameBase &, bool avoid_fastclick = false, Point pos = Point(- 1, - 1));
 	void hide_options();
 	void refresh_options(Interactive_GameBase &);
 

=== modified file 'src/logic/constructionsite.cc'
--- src/logic/constructionsite.cc	2013-07-14 10:38:26 +0000
+++ src/logic/constructionsite.cc	2013-07-14 16:56:24 +0000
@@ -35,6 +35,8 @@
 #include "worker.h"
 
 #include "constructionsite.h"
+#include <wui/interactive_base.h>
+#include <wui/interactive_gamebase.h>
 
 namespace Widelands {
 
@@ -87,13 +89,11 @@
 {
 	unsigned int percent = (get_built_per64k() * 100) >> 16;
 
-	std::string clr = UI_FONT_CLR_OK_HEX;
-	if (percent <= 25) clr = UI_FONT_CLR_BAD_HEX;
-	else if (percent >= 75) clr = UI_FONT_CLR_GOOD_HEX;
-
-	std::string perc_s = (boost::format("<font color=%s>%i</font>") % clr % percent).str();
-
-	return (boost::format(_("%s%% built")) % perc_s.c_str()).str();
+
+	std::string perc_s =
+		(boost::format("<font color=%1$s>%2$i%% built</font>") % UI_FONT_CLR_DARK_HEX % percent).str();
+
+	return perc_s;
 }
 
 /*
@@ -183,6 +183,13 @@
 			builder->reset_tasks(ref_cast<Game, Editor_Game_Base>(egbase));
 			builder->set_location(&b);
 		}
+		if (m_optionswindow) {
+			Point window_position = m_optionswindow->get_pos();
+			hide_options();
+			Interactive_GameBase & igbase =
+				ref_cast<Interactive_GameBase, Interactive_Base>(*egbase.get_ibase());
+			b.show_options(igbase, false, window_position);
+		}
 	}
 }
 

=== modified file 'src/logic/productionsite.cc'
--- src/logic/productionsite.cc	2013-05-25 09:30:35 +0000
+++ src/logic/productionsite.cc	2013-07-14 16:56:24 +0000
@@ -18,6 +18,8 @@
  */
 
 #include <libintl.h>
+#include <cstdio>
+#include <boost/format.hpp>
 
 #include "helper.h"
 #include "i18n.h"
@@ -243,20 +245,21 @@
 	for (uint32_t i = nr_working_positions; i;)
 		nr_workers += m_working_positions[--i].worker ? 1 : 0;
 	if (!nr_workers)
-		return _("(not occupied)");
+		 return
+			(boost::format("<font color=%s>%s</font>") % UI_FONT_CLR_BAD_HEX % _("(not occupied)")).str();
 	else if (uint32_t const nr_requests = nr_working_positions - nr_workers) {
 		char buffer[1000];
 		snprintf
 			(buffer, sizeof(buffer), "%s",
 			 ngettext("Worker missing", "Workers missing", nr_requests));
-		return buffer;
+		return (boost::format("<font color=%s>%s</font>") % UI_FONT_CLR_BAD_HEX % buffer).str();
 	}
 
 	if (m_statistics_changed)
 		calc_statistics();
 
 	if (m_is_stopped)
-		return _("(stopped)");
+		return (boost::format("<font color=%s>%s</font>") % UI_FONT_CLR_BRIGHT_HEX % _("(stopped)")).str();
 
 	return m_statistics_buffer;
 }
@@ -315,20 +318,42 @@
 				++lastOk;
 		}
 	}
-	uint8_t const percOk = (ok * 100) / STATISTICS_VECTOR_LENGTH;
-	uint8_t const lastPercOk = (lastOk * 100) / (STATISTICS_VECTOR_LENGTH / 2);
-
-	const std::string trend =
-		lastPercOk > percOk ? "+" : lastPercOk < percOk ? "-" : "=";
+	// Somehow boost::format doesn't handle correctly uint8_t in this case
+	unsigned int percOk = (ok * 100) / STATISTICS_VECTOR_LENGTH;
+	unsigned int lastPercOk = (lastOk * 100) / (STATISTICS_VECTOR_LENGTH / 2);
+
+	std::string color;
+	if (percOk < 33)
+		color = UI_FONT_CLR_BAD_HEX;
+	else if (percOk < 66)
+		color = UI_FONT_CLR_OK_HEX;
+	else
+		color = UI_FONT_CLR_GOOD_HEX;
+	const std::string perc_str =
+		(boost::format("<font color=%1$s>%2$i%%</font>") % color % percOk).str();
+
+	std::string trend;
+	if (lastPercOk > percOk) {
+		color = UI_FONT_CLR_GOOD_HEX;
+		trend = "+";
+	} else if (lastPercOk < percOk) {
+		color = UI_FONT_CLR_BAD_HEX;
+		trend = "-";
+	} else {
+		color = UI_FONT_CLR_BRIGHT_HEX;
+		trend = "=";
+	}
+	const std::string trend_str =
+		(boost::format("<font color=%s>%s</font>") % color % trend).str();
 
 	if (0 < percOk and percOk < 100)
 		snprintf
 			(m_statistics_buffer, sizeof(m_statistics_buffer),
-			 "%d%% %s", percOk, trend.c_str());
+			 "%s %s", perc_str.c_str(), trend_str.c_str());
 	else
 		snprintf
 			(m_statistics_buffer, sizeof(m_statistics_buffer),
-			 "%d%%",    percOk);
+			 "%s", perc_str.c_str());
 
 	m_last_stat_percent = percOk;
 

=== modified file 'src/logic/productionsite.h'
--- src/logic/productionsite.h	2013-04-22 20:15:00 +0000
+++ src/logic/productionsite.h	2013-07-14 16:56:24 +0000
@@ -256,7 +256,7 @@
 	Input_Queues m_input_queues; ///< input queues for all inputs
 	std::vector<bool>        m_statistics;
 	bool                     m_statistics_changed;
-	char                     m_statistics_buffer[40];
+	char                     m_statistics_buffer[128];
 	char                     m_result_buffer   [213];
 	uint8_t                  m_last_stat_percent;
 	bool                     m_is_stopped;

=== modified file 'src/ui_basic/window.h'
--- src/ui_basic/window.h	2013-02-09 23:18:23 +0000
+++ src/ui_basic/window.h	2013-07-14 16:56:24 +0000
@@ -87,7 +87,6 @@
 	bool handle_mousemove
 		(Uint8 state, int32_t mx, int32_t my, int32_t xdiff, int32_t ydiff);
 	bool handle_alt_drag (int32_t mx, int32_t my);
-
 protected:
 	virtual void layout();
 	virtual void update_desired_size();

=== modified file 'src/wui/building_ui.cc'
--- src/wui/building_ui.cc	2013-07-09 05:53:39 +0000
+++ src/wui/building_ui.cc	2013-07-14 16:56:24 +0000
@@ -28,7 +28,7 @@
  * Create the building's options window if necessary and bring it to
  * the top to be seen by the player.
  */
-void Building::show_options(Interactive_GameBase & igbase, bool avoid_fastclick)
+void Building::show_options(Interactive_GameBase & igbase, bool avoid_fastclick, Point pos)
 {
 	if (m_optionswindow) {
 		if (m_optionswindow->is_minimal())
@@ -42,6 +42,9 @@
 		// get properly initialized
 		m_optionswindow->think();
 	}
+	if (pos.x >= 0 && pos.y >= 0) {
+		m_optionswindow->set_pos(pos);
+	}
 }
 
 /**

=== modified file 'src/wui/buildingwindow.cc'
--- src/wui/buildingwindow.cc	2013-07-13 15:58:52 +0000
+++ src/wui/buildingwindow.cc	2013-07-14 16:56:24 +0000
@@ -23,6 +23,7 @@
 #include "graphic/image.h"
 #include "graphic/rendertarget.h"
 #include "interactive_player.h"
+#include "logic/constructionsite.h"
 #include "logic/dismantlesite.h"
 #include "logic/maphollowregion.h"
 #include "logic/militarysite.h"
@@ -88,6 +89,14 @@
 
 	show_workarea();
 
+	if (is_a(Widelands::ConstructionSite, &m_building)) {
+		upcast(Widelands::ConstructionSite, csite, &m_building);
+		char cs_title[256];
+		// Show name in parenthesis as it may take all width already
+		sprintf(cs_title, _("(%s)"), csite->building().descname().c_str());
+		set_title(cs_title);
+	}
+
 	set_fastclick_panel(this);
 }
 
@@ -515,7 +524,13 @@
 	if (m_workarea_job_id)
 		return; // already shown, nothing to be done
 
-	const Workarea_Info & workarea_info = m_building.descr().m_workarea_info;
+	Workarea_Info workarea_info;
+	if (is_a(Widelands::ConstructionSite, &m_building)) {
+		upcast(Widelands::ConstructionSite, csite, &m_building);
+		workarea_info = csite->building().m_workarea_info;
+	} else {
+		workarea_info = m_building.descr().m_workarea_info;
+	}
 	if (workarea_info.size() == 0)
 		return; // building has no workarea
 

=== modified file 'src/wui/waresdisplay.cc'
--- src/wui/waresdisplay.cc	2013-03-01 23:12:08 +0000
+++ src/wui/waresdisplay.cc	2013-07-14 16:56:24 +0000
@@ -63,8 +63,12 @@
 	m_hidden
 		(m_type == Widelands::wwWORKER ? m_tribe.get_nrworkers()
 	                          : m_tribe.get_nrwares(), false),
+	m_in_selection
+		(m_type == Widelands::wwWORKER ? m_tribe.get_nrworkers()
+	                          : m_tribe.get_nrwares(), false),
 	m_selectable(selectable),
 	m_horizontal(horizontal),
+	m_selection_anchor(Widelands::Ware_Index::Null()),
 	m_callback_function(callback_function)
 {
 	//resize the configuration of our wares if they won't fit in the current window
@@ -104,6 +108,9 @@
 		 .c_str()
 		 :
 		 "");
+	if (m_selection_anchor) {
+		update_anchor_selection(x, y);
+	}
 	return true;
 }
 
@@ -117,6 +124,10 @@
 
 		if (m_selectable) {
 			toggle_ware(ware);
+			// mouserelase may be skipped sometimes here
+			if (!m_selection_anchor) {
+				m_selection_anchor = ware;
+			}
 		}
 		return true;
 	}
@@ -124,6 +135,32 @@
 	return UI::Panel::handle_mousepress(btn, x, y);
 }
 
+bool AbstractWaresDisplay::handle_mouserelease(Uint8 btn, int32_t x, int32_t y)
+{
+	if (btn == SDL_BUTTON_LEFT) {
+		if (m_selection_anchor) {
+			Widelands::Ware_Index const number = m_type == Widelands::wwWORKER ? 
+				m_tribe.get_nrworkers() : m_tribe.get_nrwares();
+			for (Widelands::Ware_Index i = Widelands::Ware_Index::First();
+					i < number; ++i) {
+				if (!m_in_selection[i]) {
+					continue;
+				}
+				if (ware_selected(m_selection_anchor)) {
+					select_ware(i);
+				} else {
+					unselect_ware(i);
+				}
+			}
+			m_selection_anchor = Widelands::Ware_Index::Null();
+			std::fill(m_in_selection.begin(), m_in_selection.end(), false);
+			return true;
+		}
+	}
+	return UI::Panel::handle_mouserelease(btn, x, y);
+}
+
+
 /**
  * Returns the index of the ware under the given coordinates, or
  * WareIndex::Null() if the given point is outside the range.
@@ -151,6 +188,62 @@
 	return Widelands::Ware_Index::Null();
 }
 
+void AbstractWaresDisplay::update_anchor_selection(int32_t x, int32_t y)
+{
+	if (!m_selection_anchor || x < 0 || y < 0) {
+		return;
+	}
+
+	std::fill(m_in_selection.begin(), m_in_selection.end(), false);
+	Point pos0 = ware_position(m_selection_anchor);
+	int32_t x0 = pos0.x + 3; // Make sure the anchor row/col is selected in reverse order
+	int32_t y0 = pos0.y + 3;
+
+	unsigned int i0 = x0 / (WARE_MENU_PIC_WIDTH + 4);
+	unsigned int j0 = y0 / (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + 3);
+	unsigned int i = x / (WARE_MENU_PIC_WIDTH + 4);
+	unsigned int j = y / (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + 3);
+	unsigned int s;
+	if (m_horizontal) {
+		s = i0;
+		i0 = j0;
+		j0 = s;
+		s = i;
+		i = j;
+		j = s;
+	}
+
+	// Ensure topleft to bottomright
+	if (i0 > i) {
+		s = i0;
+		i0 = i;
+		i = s;
+	}
+	if (j0 > j) {
+		s = j0;
+		j0 = j;
+		j = s;
+	}
+
+	for (unsigned int cur_i = i0; cur_i <= i; cur_i++) {
+		if (cur_i >= icons_order().size()) {
+			continue;
+		}
+		for (unsigned cur_j = j0; cur_j <= j; cur_j++) {
+			if (cur_j >= icons_order()[cur_i].size()) {
+				continue;
+			}
+			Widelands::Ware_Index ware = icons_order()[cur_i][cur_j];
+			if (m_hidden[ware]) {
+				continue;
+			}
+			m_in_selection[ware] = true;
+		}
+	}
+	update();
+}
+
+
 
 void AbstractWaresDisplay::layout()
 {
@@ -241,9 +334,18 @@
 {
 	Point p = ware_position(id);
 
+	bool draw_selected = m_selected[id];
+	if (m_selection_anchor) {
+		if (ware_selected(m_selection_anchor)) {
+			draw_selected |= m_in_selection[id];
+		} else {
+			draw_selected &= !m_in_selection[id];
+		}
+	}
+	
 	//  draw a background
 	const Image* bgpic =
-		g_gr->images().get(ware_selected(id) ?  "pics/ware_list_bg_selected.png" :  "pics/ware_list_bg.png");
+		g_gr->images().get(draw_selected ?  "pics/ware_list_bg_selected.png" :  "pics/ware_list_bg.png");
 	uint16_t w = bgpic->width();
 
 	dst.blit(p, bgpic);
@@ -378,3 +480,4 @@
 			}
 	return ret;
 }
+

=== modified file 'src/wui/waresdisplay.h'
--- src/wui/waresdisplay.h	2013-02-09 22:51:15 +0000
+++ src/wui/waresdisplay.h	2013-07-14 16:56:24 +0000
@@ -58,6 +58,7 @@
 		(uint8_t state, int32_t x, int32_t y, int32_t xdiff, int32_t ydiff);
 
 	bool handle_mousepress(uint8_t btn, int32_t x, int32_t y);
+	bool handle_mouserelease(Uint8 btn, int32_t x, int32_t y);
 
 
 	// Wares may be selected (highlighted)
@@ -100,13 +101,17 @@
 	typedef std::vector<const Widelands::WareList *> vector_type;
 	typedef std::vector<bool> selection_type;
 
+	void update_anchor_selection(int32_t x, int32_t y);
+
 	const Widelands::Tribe_Descr & m_tribe;
 	Widelands::WareWorker m_type;
 	UI::Textarea        m_curware;
 	selection_type      m_selected;
 	selection_type      m_hidden;
+	selection_type		m_in_selection;
 	bool                m_selectable;
 	bool                m_horizontal;
+	Widelands::Ware_Index m_selection_anchor;
 	boost::function<void(Widelands::Ware_Index, bool)> m_callback_function;
 };
 


Follow ups