Merge lp:~widelands-dev/widelands/csite_improvement into lp:widelands
- csite_improvement
- Merge into trunk
Status: | Merged | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 6654 | ||||||||||||||||||||
Proposed branch: | lp:~widelands-dev/widelands/csite_improvement | ||||||||||||||||||||
Merge into: | lp:widelands | ||||||||||||||||||||
Diff against target: |
599 lines (+260/-61) 11 files modified
src/constants.h (+5/-3) src/logic/building.h (+1/-1) src/logic/constructionsite.cc (+18/-11) src/logic/item_ware_descr.h (+2/-0) src/logic/productionsite.cc (+50/-25) src/logic/productionsite.h (+1/-1) src/ui_basic/table.cc (+4/-0) src/wui/building_ui.cc (+4/-1) src/wui/buildingwindow.cc (+10/-2) src/wui/waresdisplay.cc (+146/-15) src/wui/waresdisplay.h (+19/-2) |
||||||||||||||||||||
To merge this branch: | bzr merge lp:~widelands-dev/widelands/csite_improvement | ||||||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
SirVer | Approve | ||
Review via email: mp+174623@code.launchpad.net |
Commit message
Description of the change
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 of building shown for construction sites
- Building name shown in construction site windows
- Building window opened when construction site window was open and construction ended
SirVer (sirver) wrote : | # |
SirVer (sirver) wrote : | # |
Okay, a bunch of minor comments. I did not understand what the anchoring does - I would love to see some comments about this someplace.
SirVer (sirver) wrote : | # |
And I forgot to mention: I much appreciate you adding {} in more places while going over the code :). I find this so much more readable.
cghislai (charlyghislain) wrote : | # |
I loaclly merged the bug657285 branch in order to test this under opengl without crashing.
Everything works as intended.
SirVer (sirver) wrote : | # |
Lgtm. I fixed very small nits and merged this.
SirVer (sirver) wrote : | # |
Charly, could you go over the bugs and mark them fixed as appropriate?
Preview Diff
1 | === modified file 'src/constants.h' | |||
2 | --- src/constants.h 2013-07-16 00:37:26 +0000 | |||
3 | +++ src/constants.h 2013-07-21 14:41:26 +0000 | |||
4 | @@ -80,9 +80,11 @@ | |||
5 | 80 | #define PROSA_FONT_CLR_FG RGBColor(255, 255, 0) | 80 | #define PROSA_FONT_CLR_FG RGBColor(255, 255, 0) |
6 | 81 | 81 | ||
7 | 82 | /// Colors for good/ok/bad | 82 | /// Colors for good/ok/bad |
11 | 83 | #define UI_FONT_CLR_BAD_HEX "ff0000" | 83 | #define UI_FONT_CLR_BRIGHT_HEX "fffaaa" |
12 | 84 | #define UI_FONT_CLR_OK_HEX "ffff00" | 84 | #define UI_FONT_CLR_DARK_HEX "a39013" |
13 | 85 | #define UI_FONT_CLR_GOOD_HEX "325b1f" | 85 | #define UI_FONT_CLR_BAD_HEX "bb0000" |
14 | 86 | #define UI_FONT_CLR_OK_HEX "ffe11e" | ||
15 | 87 | #define UI_FONT_CLR_GOOD_HEX "00bb00" | ||
16 | 86 | //@} | 88 | //@} |
17 | 87 | 89 | ||
18 | 88 | /** \name Text colors | 90 | /** \name Text colors |
19 | 89 | 91 | ||
20 | === modified file 'src/logic/building.h' | |||
21 | --- src/logic/building.h 2013-07-16 10:17:53 +0000 | |||
22 | +++ src/logic/building.h 2013-07-21 14:41:26 +0000 | |||
23 | @@ -184,7 +184,7 @@ | |||
24 | 184 | virtual bool burn_on_destroy(); | 184 | virtual bool burn_on_destroy(); |
25 | 185 | virtual void destroy(Editor_Game_Base &); | 185 | virtual void destroy(Editor_Game_Base &); |
26 | 186 | 186 | ||
28 | 187 | void show_options(Interactive_GameBase &, bool avoid_fastclick = false); | 187 | void show_options(Interactive_GameBase &, bool avoid_fastclick = false, Point pos = Point(- 1, - 1)); |
29 | 188 | void hide_options(); | 188 | void hide_options(); |
30 | 189 | void refresh_options(Interactive_GameBase &); | 189 | void refresh_options(Interactive_GameBase &); |
31 | 190 | 190 | ||
32 | 191 | 191 | ||
33 | === modified file 'src/logic/constructionsite.cc' | |||
34 | --- src/logic/constructionsite.cc 2013-07-18 06:31:11 +0000 | |||
35 | +++ src/logic/constructionsite.cc 2013-07-21 14:41:26 +0000 | |||
36 | @@ -25,12 +25,14 @@ | |||
37 | 25 | #include "upcast.h" | 25 | #include "upcast.h" |
38 | 26 | #include "wexception.h" | 26 | #include "wexception.h" |
39 | 27 | 27 | ||
40 | 28 | #include "graphic/animation.h" | ||
41 | 29 | #include "economy/wares_queue.h" | 28 | #include "economy/wares_queue.h" |
42 | 30 | #include "game.h" | 29 | #include "game.h" |
43 | 30 | #include "graphic/animation.h" | ||
44 | 31 | #include "graphic/graphic.h" | 31 | #include "graphic/graphic.h" |
45 | 32 | #include "graphic/rendertarget.h" | 32 | #include "graphic/rendertarget.h" |
46 | 33 | #include "sound/sound_handler.h" | 33 | #include "sound/sound_handler.h" |
47 | 34 | #include "ui_basic/window.h" | ||
48 | 35 | #include "wui/interactive_gamebase.h" | ||
49 | 34 | #include "tribe.h" | 36 | #include "tribe.h" |
50 | 35 | #include "worker.h" | 37 | #include "worker.h" |
51 | 36 | 38 | ||
52 | @@ -86,14 +88,9 @@ | |||
53 | 86 | std::string ConstructionSite::get_statistics_string() | 88 | std::string ConstructionSite::get_statistics_string() |
54 | 87 | { | 89 | { |
55 | 88 | unsigned int percent = (get_built_per64k() * 100) >> 16; | 90 | unsigned int percent = (get_built_per64k() * 100) >> 16; |
64 | 89 | 91 | std::string perc_s = | |
65 | 90 | std::string clr = UI_FONT_CLR_OK_HEX; | 92 | (boost::format("<font color=%1$s>%2$i%% built</font>") % UI_FONT_CLR_DARK_HEX % percent).str(); |
66 | 91 | if (percent <= 25) clr = UI_FONT_CLR_BAD_HEX; | 93 | return perc_s; |
59 | 92 | else if (percent >= 75) clr = UI_FONT_CLR_GOOD_HEX; | ||
60 | 93 | |||
61 | 94 | std::string perc_s = (boost::format("<font color=%s>%i</font>") % clr % percent).str(); | ||
62 | 95 | |||
63 | 96 | return (boost::format(_("%s%% built")) % perc_s.c_str()).str(); | ||
67 | 97 | } | 94 | } |
68 | 98 | 95 | ||
69 | 99 | /* | 96 | /* |
70 | @@ -102,9 +99,11 @@ | |||
71 | 102 | ======= | 99 | ======= |
72 | 103 | */ | 100 | */ |
73 | 104 | WaresQueue & ConstructionSite::waresqueue(Ware_Index const wi) { | 101 | WaresQueue & ConstructionSite::waresqueue(Ware_Index const wi) { |
76 | 105 | container_iterate_const(Wares, m_wares, i) | 102 | container_iterate_const(Wares, m_wares, i) { |
77 | 106 | if ((*i.current)->get_ware() == wi) | 103 | if ((*i.current)->get_ware() == wi) { |
78 | 107 | return **i.current; | 104 | return **i.current; |
79 | 105 | } | ||
80 | 106 | } | ||
81 | 108 | throw wexception | 107 | throw wexception |
82 | 109 | ("%s (%u) (building %s) has no WaresQueue for %u", | 108 | ("%s (%u) (building %s) has no WaresQueue for %u", |
83 | 110 | name().c_str(), serial(), m_building->name().c_str(), wi.value()); | 109 | name().c_str(), serial(), m_building->name().c_str(), wi.value()); |
84 | @@ -183,6 +182,14 @@ | |||
85 | 183 | builder->reset_tasks(ref_cast<Game, Editor_Game_Base>(egbase)); | 182 | builder->reset_tasks(ref_cast<Game, Editor_Game_Base>(egbase)); |
86 | 184 | builder->set_location(&b); | 183 | builder->set_location(&b); |
87 | 185 | } | 184 | } |
88 | 185 | // Open the new building window if needed | ||
89 | 186 | if (m_optionswindow) { | ||
90 | 187 | Point window_position = m_optionswindow->get_pos(); | ||
91 | 188 | hide_options(); | ||
92 | 189 | Interactive_GameBase & igbase = | ||
93 | 190 | ref_cast<Interactive_GameBase, Interactive_Base>(*egbase.get_ibase()); | ||
94 | 191 | b.show_options(igbase, false, window_position); | ||
95 | 192 | } | ||
96 | 186 | } | 193 | } |
97 | 187 | } | 194 | } |
98 | 188 | 195 | ||
99 | 189 | 196 | ||
100 | === modified file 'src/logic/item_ware_descr.h' | |||
101 | --- src/logic/item_ware_descr.h 2013-02-10 19:36:24 +0000 | |||
102 | +++ src/logic/item_ware_descr.h 2013-07-21 14:41:26 +0000 | |||
103 | @@ -36,6 +36,8 @@ | |||
104 | 36 | 36 | ||
105 | 37 | #define WARE_MENU_PIC_WIDTH 24 //< Default width for ware's menu icons | 37 | #define WARE_MENU_PIC_WIDTH 24 //< Default width for ware's menu icons |
106 | 38 | #define WARE_MENU_PIC_HEIGHT 24 //< Default height for ware's menu icons | 38 | #define WARE_MENU_PIC_HEIGHT 24 //< Default height for ware's menu icons |
107 | 39 | #define WARE_MENU_PIC_PAD_X 3 //< Default padding between menu icons | ||
108 | 40 | #define WARE_MENU_PIC_PAD_Y 4 //< Default padding between menu icons | ||
109 | 39 | 41 | ||
110 | 40 | namespace Widelands { | 42 | namespace Widelands { |
111 | 41 | 43 | ||
112 | 42 | 44 | ||
113 | === modified file 'src/logic/productionsite.cc' | |||
114 | --- src/logic/productionsite.cc 2013-07-18 16:47:56 +0000 | |||
115 | +++ src/logic/productionsite.cc 2013-07-21 14:41:26 +0000 | |||
116 | @@ -18,6 +18,7 @@ | |||
117 | 18 | */ | 18 | */ |
118 | 19 | 19 | ||
119 | 20 | #include <libintl.h> | 20 | #include <libintl.h> |
120 | 21 | #include <boost/format.hpp> | ||
121 | 21 | 22 | ||
122 | 22 | #include "helper.h" | 23 | #include "helper.h" |
123 | 23 | #include "i18n.h" | 24 | #include "i18n.h" |
124 | @@ -242,21 +243,23 @@ | |||
125 | 242 | uint32_t nr_workers = 0; | 243 | uint32_t nr_workers = 0; |
126 | 243 | for (uint32_t i = nr_working_positions; i;) | 244 | for (uint32_t i = nr_working_positions; i;) |
127 | 244 | nr_workers += m_working_positions[--i].worker ? 1 : 0; | 245 | nr_workers += m_working_positions[--i].worker ? 1 : 0; |
136 | 245 | if (!nr_workers) | 246 | if (!nr_workers) { |
137 | 246 | return _("(not occupied)"); | 247 | return |
138 | 247 | else if (uint32_t const nr_requests = nr_working_positions - nr_workers) { | 248 | (boost::format("<font color=%s>%s</font>") % UI_FONT_CLR_BAD_HEX % _("(not occupied)")).str(); |
139 | 248 | char buffer[1000]; | 249 | } else if (uint32_t const nr_requests = nr_working_positions - nr_workers) { |
140 | 249 | snprintf | 250 | return |
141 | 250 | (buffer, sizeof(buffer), "%s", | 251 | (boost::format("<font color=%s>%s</font>") % UI_FONT_CLR_BAD_HEX % |
142 | 251 | ngettext("Worker missing", "Workers missing", nr_requests)); | 252 | ngettext(_("Worker missing"), _("Workers missing"), nr_requests)) |
143 | 252 | return buffer; | 253 | .str(); |
144 | 253 | } | 254 | } |
145 | 254 | 255 | ||
147 | 255 | if (m_statistics_changed) | 256 | if (m_statistics_changed) { |
148 | 256 | calc_statistics(); | 257 | calc_statistics(); |
149 | 258 | } | ||
150 | 257 | 259 | ||
153 | 258 | if (m_is_stopped) | 260 | if (m_is_stopped) { |
154 | 259 | return _("(stopped)"); | 261 | return (boost::format("<font color=%s>%s</font>") % UI_FONT_CLR_BRIGHT_HEX % _("(stopped)")).str(); |
155 | 262 | } | ||
156 | 260 | 263 | ||
157 | 261 | return m_statistics_buffer; | 264 | return m_statistics_buffer; |
158 | 262 | } | 265 | } |
159 | @@ -315,21 +318,43 @@ | |||
160 | 315 | ++lastOk; | 318 | ++lastOk; |
161 | 316 | } | 319 | } |
162 | 317 | } | 320 | } |
173 | 318 | uint8_t const percOk = (ok * 100) / STATISTICS_VECTOR_LENGTH; | 321 | // Somehow boost::format doesn't handle correctly uint8_t in this case |
174 | 319 | uint8_t const lastPercOk = (lastOk * 100) / (STATISTICS_VECTOR_LENGTH / 2); | 322 | unsigned int percOk = (ok * 100) / STATISTICS_VECTOR_LENGTH; |
175 | 320 | 323 | unsigned int lastPercOk = (lastOk * 100) / (STATISTICS_VECTOR_LENGTH / 2); | |
176 | 321 | const std::string trend = | 324 | |
177 | 322 | lastPercOk > percOk ? "+" : lastPercOk < percOk ? "-" : "="; | 325 | std::string color; |
178 | 323 | 326 | if (percOk < 33) | |
179 | 324 | if (0 < percOk and percOk < 100) | 327 | color = UI_FONT_CLR_BAD_HEX; |
180 | 325 | snprintf | 328 | else if (percOk < 66) |
181 | 326 | (m_statistics_buffer, sizeof(m_statistics_buffer), | 329 | color = UI_FONT_CLR_OK_HEX; |
172 | 327 | "%d%% %s", percOk, trend.c_str()); | ||
182 | 328 | else | 330 | else |
187 | 329 | snprintf | 331 | color = UI_FONT_CLR_GOOD_HEX; |
188 | 330 | (m_statistics_buffer, sizeof(m_statistics_buffer), | 332 | const std::string perc_str = |
189 | 331 | "%d%%", percOk); | 333 | (boost::format("<font color=%1$s>%2$i%%</font>") % color % percOk).str(); |
190 | 332 | 334 | ||
191 | 335 | std::string trend; | ||
192 | 336 | if (lastPercOk > percOk) { | ||
193 | 337 | color = UI_FONT_CLR_GOOD_HEX; | ||
194 | 338 | trend = "+"; | ||
195 | 339 | } else if (lastPercOk < percOk) { | ||
196 | 340 | color = UI_FONT_CLR_BAD_HEX; | ||
197 | 341 | trend = "-"; | ||
198 | 342 | } else { | ||
199 | 343 | color = UI_FONT_CLR_BRIGHT_HEX; | ||
200 | 344 | trend = "="; | ||
201 | 345 | } | ||
202 | 346 | const std::string trend_str = | ||
203 | 347 | (boost::format("<font color=%s>%s</font>") % color % trend).str(); | ||
204 | 348 | |||
205 | 349 | if (0 < percOk and percOk < 100) { | ||
206 | 350 | snprintf | ||
207 | 351 | (m_statistics_buffer, sizeof(m_statistics_buffer), | ||
208 | 352 | "%s %s", perc_str.c_str(), trend_str.c_str()); | ||
209 | 353 | } else { | ||
210 | 354 | snprintf | ||
211 | 355 | (m_statistics_buffer, sizeof(m_statistics_buffer), | ||
212 | 356 | "%s", perc_str.c_str()); | ||
213 | 357 | } | ||
214 | 333 | m_last_stat_percent = percOk; | 358 | m_last_stat_percent = percOk; |
215 | 334 | 359 | ||
216 | 335 | m_statistics_changed = false; | 360 | m_statistics_changed = false; |
217 | 336 | 361 | ||
218 | === modified file 'src/logic/productionsite.h' | |||
219 | --- src/logic/productionsite.h 2013-04-22 20:15:00 +0000 | |||
220 | +++ src/logic/productionsite.h 2013-07-21 14:41:26 +0000 | |||
221 | @@ -256,7 +256,7 @@ | |||
222 | 256 | Input_Queues m_input_queues; ///< input queues for all inputs | 256 | Input_Queues m_input_queues; ///< input queues for all inputs |
223 | 257 | std::vector<bool> m_statistics; | 257 | std::vector<bool> m_statistics; |
224 | 258 | bool m_statistics_changed; | 258 | bool m_statistics_changed; |
226 | 259 | char m_statistics_buffer[40]; | 259 | char m_statistics_buffer[128]; |
227 | 260 | char m_result_buffer [213]; | 260 | char m_result_buffer [213]; |
228 | 261 | uint8_t m_last_stat_percent; | 261 | uint8_t m_last_stat_percent; |
229 | 262 | bool m_is_stopped; | 262 | bool m_is_stopped; |
230 | 263 | 263 | ||
231 | === modified file 'src/ui_basic/table.cc' | |||
232 | --- src/ui_basic/table.cc 2013-07-21 08:25:22 +0000 | |||
233 | +++ src/ui_basic/table.cc 2013-07-21 14:41:26 +0000 | |||
234 | @@ -293,6 +293,10 @@ | |||
235 | 293 | point.x += picw; | 293 | point.x += picw; |
236 | 294 | } | 294 | } |
237 | 295 | 295 | ||
238 | 296 | if (entry_string.empty()) { | ||
239 | 297 | curx += curw; | ||
240 | 298 | continue; | ||
241 | 299 | } | ||
242 | 296 | const Image* entry_text_im = UI::g_fh1->render(as_uifont(entry_string, m_fontsize)); | 300 | const Image* entry_text_im = UI::g_fh1->render(as_uifont(entry_string, m_fontsize)); |
243 | 297 | uint16_t text_width = entry_text_im->width(); | 301 | uint16_t text_width = entry_text_im->width(); |
244 | 298 | if (alignment & Align_Right) { | 302 | if (alignment & Align_Right) { |
245 | 299 | 303 | ||
246 | === modified file 'src/wui/building_ui.cc' | |||
247 | --- src/wui/building_ui.cc 2013-07-21 08:25:22 +0000 | |||
248 | +++ src/wui/building_ui.cc 2013-07-21 14:41:26 +0000 | |||
249 | @@ -30,7 +30,7 @@ | |||
250 | 30 | * Create the building's options window if necessary and bring it to | 30 | * Create the building's options window if necessary and bring it to |
251 | 31 | * the top to be seen by the player. | 31 | * the top to be seen by the player. |
252 | 32 | */ | 32 | */ |
254 | 33 | void Building::show_options(Interactive_GameBase & igbase, bool avoid_fastclick) | 33 | void Building::show_options(Interactive_GameBase & igbase, bool avoid_fastclick, Point pos) |
255 | 34 | { | 34 | { |
256 | 35 | if (m_optionswindow) { | 35 | if (m_optionswindow) { |
257 | 36 | if (m_optionswindow->is_minimal()) | 36 | if (m_optionswindow->is_minimal()) |
258 | @@ -45,6 +45,9 @@ | |||
259 | 45 | // get properly initialized | 45 | // get properly initialized |
260 | 46 | m_optionswindow->think(); | 46 | m_optionswindow->think(); |
261 | 47 | } | 47 | } |
262 | 48 | if (pos.x >= 0 && pos.y >= 0) { | ||
263 | 49 | m_optionswindow->set_pos(pos); | ||
264 | 50 | } | ||
265 | 48 | } | 51 | } |
266 | 49 | 52 | ||
267 | 50 | /** | 53 | /** |
268 | 51 | 54 | ||
269 | === modified file 'src/wui/buildingwindow.cc' | |||
270 | --- src/wui/buildingwindow.cc 2013-07-21 08:25:22 +0000 | |||
271 | +++ src/wui/buildingwindow.cc 2013-07-21 14:41:26 +0000 | |||
272 | @@ -23,6 +23,7 @@ | |||
273 | 23 | #include "graphic/image.h" | 23 | #include "graphic/image.h" |
274 | 24 | #include "graphic/rendertarget.h" | 24 | #include "graphic/rendertarget.h" |
275 | 25 | #include "interactive_player.h" | 25 | #include "interactive_player.h" |
276 | 26 | #include "logic/constructionsite.h" | ||
277 | 26 | #include "logic/dismantlesite.h" | 27 | #include "logic/dismantlesite.h" |
278 | 27 | #include "logic/maphollowregion.h" | 28 | #include "logic/maphollowregion.h" |
279 | 28 | #include "logic/militarysite.h" | 29 | #include "logic/militarysite.h" |
280 | @@ -35,8 +36,9 @@ | |||
281 | 35 | #include "upcast.h" | 36 | #include "upcast.h" |
282 | 36 | #include "waresqueuedisplay.h" | 37 | #include "waresqueuedisplay.h" |
283 | 37 | 38 | ||
284 | 39 | #include <boost/format.hpp> | ||
285 | 40 | |||
286 | 38 | #include "buildingwindow.h" | 41 | #include "buildingwindow.h" |
287 | 39 | #include "logic/militarysite.h" | ||
288 | 40 | 42 | ||
289 | 41 | static const char * pic_bulldoze = "pics/menu_bld_bulldoze.png"; | 43 | static const char * pic_bulldoze = "pics/menu_bld_bulldoze.png"; |
290 | 42 | static const char * pic_dismantle = "pics/menu_bld_dismantle.png"; | 44 | static const char * pic_dismantle = "pics/menu_bld_dismantle.png"; |
291 | @@ -78,10 +80,16 @@ | |||
292 | 78 | 80 | ||
293 | 79 | set_center_panel(vbox); | 81 | set_center_panel(vbox); |
294 | 80 | set_think(true); | 82 | set_think(true); |
295 | 83 | set_fastclick_panel(this); | ||
296 | 81 | 84 | ||
297 | 82 | show_workarea(); | 85 | show_workarea(); |
298 | 83 | 86 | ||
300 | 84 | set_fastclick_panel(this); | 87 | // Title for construction site |
301 | 88 | if (upcast(Widelands::ConstructionSite, csite, &m_building)) { | ||
302 | 89 | // Show name in parenthesis as it may take all width already | ||
303 | 90 | const std::string title = (boost::format("(%s)") % csite->building().descname()).str(); | ||
304 | 91 | set_title(title); | ||
305 | 92 | } | ||
306 | 85 | } | 93 | } |
307 | 86 | 94 | ||
308 | 87 | 95 | ||
309 | 88 | 96 | ||
310 | === modified file 'src/wui/waresdisplay.cc' | |||
311 | --- src/wui/waresdisplay.cc 2013-03-01 23:12:08 +0000 | |||
312 | +++ src/wui/waresdisplay.cc 2013-07-21 14:41:26 +0000 | |||
313 | @@ -63,12 +63,16 @@ | |||
314 | 63 | m_hidden | 63 | m_hidden |
315 | 64 | (m_type == Widelands::wwWORKER ? m_tribe.get_nrworkers() | 64 | (m_type == Widelands::wwWORKER ? m_tribe.get_nrworkers() |
316 | 65 | : m_tribe.get_nrwares(), false), | 65 | : m_tribe.get_nrwares(), false), |
317 | 66 | m_in_selection | ||
318 | 67 | (m_type == Widelands::wwWORKER ? m_tribe.get_nrworkers() | ||
319 | 68 | : m_tribe.get_nrwares(), false), | ||
320 | 66 | m_selectable(selectable), | 69 | m_selectable(selectable), |
321 | 67 | m_horizontal(horizontal), | 70 | m_horizontal(horizontal), |
322 | 71 | m_selection_anchor(Widelands::Ware_Index::Null()), | ||
323 | 68 | m_callback_function(callback_function) | 72 | m_callback_function(callback_function) |
324 | 69 | { | 73 | { |
325 | 70 | //resize the configuration of our wares if they won't fit in the current window | 74 | //resize the configuration of our wares if they won't fit in the current window |
327 | 71 | int number = (g_gr->get_yres() - 160) / (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + 3); | 75 | int number = (g_gr->get_yres() - 160) / (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + WARE_MENU_PIC_PAD_Y); |
328 | 72 | const_cast<Widelands::Tribe_Descr &>(m_tribe).resize_ware_orders(number); | 76 | const_cast<Widelands::Tribe_Descr &>(m_tribe).resize_ware_orders(number); |
329 | 73 | 77 | ||
330 | 74 | // Find out geometry from icons_order | 78 | // Find out geometry from icons_order |
331 | @@ -85,13 +89,13 @@ | |||
332 | 85 | 89 | ||
333 | 86 | // 25 is height of m_curware text | 90 | // 25 is height of m_curware text |
334 | 87 | set_desired_size | 91 | set_desired_size |
337 | 88 | (columns * (WARE_MENU_PIC_WIDTH + 3) + 1, | 92 | (columns * (WARE_MENU_PIC_WIDTH + WARE_MENU_PIC_PAD_X) + 1, |
338 | 89 | rows * (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + 3) + 1 + 25); | 93 | rows * (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + WARE_MENU_PIC_PAD_Y) + 1 + 25); |
339 | 90 | } | 94 | } |
340 | 91 | 95 | ||
341 | 92 | 96 | ||
342 | 93 | bool AbstractWaresDisplay::handle_mousemove | 97 | bool AbstractWaresDisplay::handle_mousemove |
344 | 94 | (uint8_t, int32_t x, int32_t y, int32_t, int32_t) | 98 | (uint8_t state, int32_t x, int32_t y, int32_t, int32_t) |
345 | 95 | { | 99 | { |
346 | 96 | const Widelands::Ware_Index index = ware_at_point(x, y); | 100 | const Widelands::Ware_Index index = ware_at_point(x, y); |
347 | 97 | 101 | ||
348 | @@ -104,6 +108,17 @@ | |||
349 | 104 | .c_str() | 108 | .c_str() |
350 | 105 | : | 109 | : |
351 | 106 | ""); | 110 | ""); |
352 | 111 | if (m_selection_anchor) { | ||
353 | 112 | // Ensure mouse button is still pressed as some | ||
354 | 113 | // mouse release events do not reach us | ||
355 | 114 | if (state ^ SDL_BUTTON_LMASK) { | ||
356 | 115 | // FIXME: We should call another function that will not pass that events | ||
357 | 116 | // to our Panel superclass | ||
358 | 117 | handle_mouserelease(SDL_BUTTON_LEFT, x, y); | ||
359 | 118 | return true; | ||
360 | 119 | } | ||
361 | 120 | update_anchor_selection(x, y); | ||
362 | 121 | } | ||
363 | 107 | return true; | 122 | return true; |
364 | 108 | } | 123 | } |
365 | 109 | 124 | ||
366 | @@ -112,11 +127,19 @@ | |||
367 | 112 | { | 127 | { |
368 | 113 | if (btn == SDL_BUTTON_LEFT) { | 128 | if (btn == SDL_BUTTON_LEFT) { |
369 | 114 | Widelands::Ware_Index ware = ware_at_point(x, y); | 129 | Widelands::Ware_Index ware = ware_at_point(x, y); |
371 | 115 | if (!ware) | 130 | if (!ware) { |
372 | 116 | return false; | 131 | return false; |
376 | 117 | 132 | } | |
377 | 118 | if (m_selectable) { | 133 | if (!m_selectable) { |
378 | 119 | toggle_ware(ware); | 134 | return true; |
379 | 135 | } | ||
380 | 136 | if (!m_selection_anchor) { | ||
381 | 137 | // Create the selection anchor to be able to select | ||
382 | 138 | // multiple ware by dragging. | ||
383 | 139 | m_selection_anchor = ware; | ||
384 | 140 | m_in_selection[ware] = true; | ||
385 | 141 | } else { | ||
386 | 142 | // A mouse release has been missed | ||
387 | 120 | } | 143 | } |
388 | 121 | return true; | 144 | return true; |
389 | 122 | } | 145 | } |
390 | @@ -124,6 +147,35 @@ | |||
391 | 124 | return UI::Panel::handle_mousepress(btn, x, y); | 147 | return UI::Panel::handle_mousepress(btn, x, y); |
392 | 125 | } | 148 | } |
393 | 126 | 149 | ||
394 | 150 | bool AbstractWaresDisplay::handle_mouserelease(Uint8 btn, int32_t x, int32_t y) | ||
395 | 151 | { | ||
396 | 152 | if (btn != SDL_BUTTON_LEFT || !m_selection_anchor) { | ||
397 | 153 | return UI::Panel::handle_mouserelease(btn, x, y); | ||
398 | 154 | } | ||
399 | 155 | |||
400 | 156 | Widelands::Ware_Index const number = | ||
401 | 157 | m_type == Widelands::wwWORKER ? m_tribe.get_nrworkers() : m_tribe.get_nrwares(); | ||
402 | 158 | |||
403 | 159 | bool to_be_selected = !ware_selected(m_selection_anchor); | ||
404 | 160 | for (Widelands::Ware_Index i = Widelands::Ware_Index::First(); i < number; ++i) | ||
405 | 161 | { | ||
406 | 162 | if (!m_in_selection[i]) { | ||
407 | 163 | continue; | ||
408 | 164 | } | ||
409 | 165 | if (to_be_selected) { | ||
410 | 166 | select_ware(i); | ||
411 | 167 | } else { | ||
412 | 168 | unselect_ware(i); | ||
413 | 169 | } | ||
414 | 170 | } | ||
415 | 171 | |||
416 | 172 | // Release anchor, empty selection | ||
417 | 173 | m_selection_anchor = Widelands::Ware_Index::Null(); | ||
418 | 174 | std::fill(m_in_selection.begin(), m_in_selection.end(), false); | ||
419 | 175 | return true; | ||
420 | 176 | } | ||
421 | 177 | |||
422 | 178 | |||
423 | 127 | /** | 179 | /** |
424 | 128 | * Returns the index of the ware under the given coordinates, or | 180 | * Returns the index of the ware under the given coordinates, or |
425 | 129 | * WareIndex::Null() if the given point is outside the range. | 181 | * WareIndex::Null() if the given point is outside the range. |
426 | @@ -134,8 +186,8 @@ | |||
427 | 134 | return Widelands::Ware_Index::Null(); | 186 | return Widelands::Ware_Index::Null(); |
428 | 135 | 187 | ||
429 | 136 | 188 | ||
432 | 137 | unsigned int i = x / (WARE_MENU_PIC_WIDTH + 4); | 189 | unsigned int i = x / (WARE_MENU_PIC_WIDTH + WARE_MENU_PIC_PAD_X); |
433 | 138 | unsigned int j = y / (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + 3); | 190 | unsigned int j = y / (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + WARE_MENU_PIC_PAD_Y); |
434 | 139 | if (m_horizontal) { | 191 | if (m_horizontal) { |
435 | 140 | unsigned int s = i; | 192 | unsigned int s = i; |
436 | 141 | i = j; | 193 | i = j; |
437 | @@ -151,6 +203,68 @@ | |||
438 | 151 | return Widelands::Ware_Index::Null(); | 203 | return Widelands::Ware_Index::Null(); |
439 | 152 | } | 204 | } |
440 | 153 | 205 | ||
441 | 206 | // Update the anchored selection. An anchor has been created by mouse | ||
442 | 207 | // press. Mouse move call this function with the current mouse position. | ||
443 | 208 | // This function will temporary store all wares in the rectangle between anchor | ||
444 | 209 | // and current pos to allow their selection on mouse release | ||
445 | 210 | void AbstractWaresDisplay::update_anchor_selection(int32_t x, int32_t y) | ||
446 | 211 | { | ||
447 | 212 | if (!m_selection_anchor || x < 0 || y < 0) { | ||
448 | 213 | return; | ||
449 | 214 | } | ||
450 | 215 | |||
451 | 216 | std::fill(m_in_selection.begin(), m_in_selection.end(), false); | ||
452 | 217 | Point anchor_pos = ware_position(m_selection_anchor); | ||
453 | 218 | // Add an offset to make sure the anchor line and column will be | ||
454 | 219 | // selected when selecting in topleft direction | ||
455 | 220 | int32_t anchor_x = anchor_pos.x + WARE_MENU_PIC_WIDTH / 2; | ||
456 | 221 | int32_t anchor_y = anchor_pos.y + WARE_MENU_PIC_HEIGHT / 2; | ||
457 | 222 | |||
458 | 223 | unsigned int left_ware_idx = anchor_x / (WARE_MENU_PIC_WIDTH + WARE_MENU_PIC_PAD_X); | ||
459 | 224 | unsigned int top_ware_idx = anchor_y / (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + WARE_MENU_PIC_PAD_Y); | ||
460 | 225 | unsigned int right_ware_idx = x / (WARE_MENU_PIC_WIDTH + WARE_MENU_PIC_PAD_X); | ||
461 | 226 | unsigned int bottom_ware_idx = y / (WARE_MENU_PIC_HEIGHT + WARE_MENU_INFO_SIZE + WARE_MENU_PIC_PAD_Y); | ||
462 | 227 | unsigned int tmp; | ||
463 | 228 | |||
464 | 229 | // Reverse col/row and anchor/endpoint if needed | ||
465 | 230 | if (m_horizontal) { | ||
466 | 231 | tmp = left_ware_idx; | ||
467 | 232 | left_ware_idx = top_ware_idx; | ||
468 | 233 | top_ware_idx = tmp; | ||
469 | 234 | tmp = right_ware_idx; | ||
470 | 235 | right_ware_idx = bottom_ware_idx; | ||
471 | 236 | bottom_ware_idx = tmp; | ||
472 | 237 | } | ||
473 | 238 | if (left_ware_idx > right_ware_idx) { | ||
474 | 239 | tmp = left_ware_idx; | ||
475 | 240 | left_ware_idx = right_ware_idx; | ||
476 | 241 | right_ware_idx = tmp; | ||
477 | 242 | } | ||
478 | 243 | if (top_ware_idx > bottom_ware_idx) { | ||
479 | 244 | tmp = top_ware_idx; | ||
480 | 245 | top_ware_idx = bottom_ware_idx; | ||
481 | 246 | bottom_ware_idx = tmp; | ||
482 | 247 | } | ||
483 | 248 | |||
484 | 249 | for (unsigned int cur_ware_x = left_ware_idx; cur_ware_x <= right_ware_idx; cur_ware_x++) { | ||
485 | 250 | if (cur_ware_x >= icons_order().size()) { | ||
486 | 251 | continue; | ||
487 | 252 | } | ||
488 | 253 | for (unsigned cur_ware_y = top_ware_idx; cur_ware_y <= bottom_ware_idx; cur_ware_y++) { | ||
489 | 254 | if (cur_ware_y >= icons_order()[cur_ware_x].size()) { | ||
490 | 255 | continue; | ||
491 | 256 | } | ||
492 | 257 | Widelands::Ware_Index ware = icons_order()[cur_ware_x][cur_ware_y]; | ||
493 | 258 | if (m_hidden[ware]) { | ||
494 | 259 | continue; | ||
495 | 260 | } | ||
496 | 261 | m_in_selection[ware] = true; | ||
497 | 262 | } | ||
498 | 263 | } | ||
499 | 264 | update(); | ||
500 | 265 | } | ||
501 | 266 | |||
502 | 267 | |||
503 | 154 | 268 | ||
504 | 155 | void AbstractWaresDisplay::layout() | 269 | void AbstractWaresDisplay::layout() |
505 | 156 | { | 270 | { |
506 | @@ -219,11 +333,15 @@ | |||
507 | 219 | { | 333 | { |
508 | 220 | Point p(2, 2); | 334 | Point p(2, 2); |
509 | 221 | if (m_horizontal) { | 335 | if (m_horizontal) { |
512 | 222 | p.x += icons_order_coords()[id].second * (WARE_MENU_PIC_WIDTH + 3); | 336 | p.x += icons_order_coords()[id].second * |
513 | 223 | p.y += icons_order_coords()[id].first * (WARE_MENU_PIC_HEIGHT + 3 + WARE_MENU_INFO_SIZE); | 337 | (WARE_MENU_PIC_WIDTH + WARE_MENU_PIC_PAD_X); |
514 | 338 | p.y += icons_order_coords()[id].first * | ||
515 | 339 | (WARE_MENU_PIC_HEIGHT + WARE_MENU_PIC_PAD_Y + WARE_MENU_INFO_SIZE); | ||
516 | 224 | } else { | 340 | } else { |
519 | 225 | p.x += icons_order_coords()[id].first * (WARE_MENU_PIC_WIDTH + 3); | 341 | p.x += icons_order_coords()[id].first * |
520 | 226 | p.y += icons_order_coords()[id].second * (WARE_MENU_PIC_HEIGHT + 3 + WARE_MENU_INFO_SIZE); | 342 | (WARE_MENU_PIC_WIDTH + WARE_MENU_PIC_PAD_X); |
521 | 343 | p.y += icons_order_coords()[id].second * | ||
522 | 344 | (WARE_MENU_PIC_HEIGHT + WARE_MENU_PIC_PAD_Y + WARE_MENU_INFO_SIZE); | ||
523 | 227 | } | 345 | } |
524 | 228 | return p; | 346 | return p; |
525 | 229 | } | 347 | } |
526 | @@ -241,9 +359,21 @@ | |||
527 | 241 | { | 359 | { |
528 | 242 | Point p = ware_position(id); | 360 | Point p = ware_position(id); |
529 | 243 | 361 | ||
530 | 362 | bool draw_selected = m_selected[id]; | ||
531 | 363 | if (m_selection_anchor) { | ||
532 | 364 | // Draw the temporary selected wares as if they were | ||
533 | 365 | // selected. | ||
534 | 366 | // TODO: Use another pic for the temporary selection | ||
535 | 367 | if (!ware_selected(m_selection_anchor)) { | ||
536 | 368 | draw_selected |= m_in_selection[id]; | ||
537 | 369 | } else { | ||
538 | 370 | draw_selected &= !m_in_selection[id]; | ||
539 | 371 | } | ||
540 | 372 | } | ||
541 | 373 | |||
542 | 244 | // draw a background | 374 | // draw a background |
543 | 245 | const Image* bgpic = | 375 | const Image* bgpic = |
545 | 246 | g_gr->images().get(ware_selected(id) ? "pics/ware_list_bg_selected.png" : "pics/ware_list_bg.png"); | 376 | g_gr->images().get(draw_selected ? "pics/ware_list_bg_selected.png" : "pics/ware_list_bg.png"); |
546 | 247 | uint16_t w = bgpic->width(); | 377 | uint16_t w = bgpic->width(); |
547 | 248 | 378 | ||
548 | 249 | dst.blit(p, bgpic); | 379 | dst.blit(p, bgpic); |
549 | @@ -378,3 +508,4 @@ | |||
550 | 378 | } | 508 | } |
551 | 379 | return ret; | 509 | return ret; |
552 | 380 | } | 510 | } |
553 | 511 | |||
554 | 381 | 512 | ||
555 | === modified file 'src/wui/waresdisplay.h' | |||
556 | --- src/wui/waresdisplay.h 2013-07-21 08:25:22 +0000 | |||
557 | +++ src/wui/waresdisplay.h 2013-07-21 14:41:26 +0000 | |||
558 | @@ -56,9 +56,8 @@ | |||
559 | 56 | 56 | ||
560 | 57 | bool handle_mousemove | 57 | bool handle_mousemove |
561 | 58 | (uint8_t state, int32_t x, int32_t y, int32_t xdiff, int32_t ydiff); | 58 | (uint8_t state, int32_t x, int32_t y, int32_t xdiff, int32_t ydiff); |
562 | 59 | |||
563 | 60 | bool handle_mousepress(uint8_t btn, int32_t x, int32_t y); | 59 | bool handle_mousepress(uint8_t btn, int32_t x, int32_t y); |
565 | 61 | 60 | bool handle_mouserelease(Uint8 btn, int32_t x, int32_t y); | |
566 | 62 | 61 | ||
567 | 63 | // Wares may be selected (highlighted) | 62 | // Wares may be selected (highlighted) |
568 | 64 | void select_ware(Widelands::Ware_Index); | 63 | void select_ware(Widelands::Ware_Index); |
569 | @@ -100,13 +99,31 @@ | |||
570 | 100 | typedef std::vector<const Widelands::WareList *> vector_type; | 99 | typedef std::vector<const Widelands::WareList *> vector_type; |
571 | 101 | typedef std::vector<bool> selection_type; | 100 | typedef std::vector<bool> selection_type; |
572 | 102 | 101 | ||
573 | 102 | /** | ||
574 | 103 | * Update the anchored selection. When first mouse button is | ||
575 | 104 | * pressed on a ware, it is stored in @ref m_selection_anchor. | ||
576 | 105 | * Mouse moves trigger this function to select all wares items | ||
577 | 106 | * in the rectangle between the anchor and the mouse position. | ||
578 | 107 | * They are temporary stored in @ref m_in_selection. | ||
579 | 108 | * Releasing the mouse button will performs the selection. | ||
580 | 109 | * This allows selection of multiple wares by dragging. | ||
581 | 110 | */ | ||
582 | 111 | void update_anchor_selection(int32_t x, int32_t y); | ||
583 | 112 | |||
584 | 103 | const Widelands::Tribe_Descr & m_tribe; | 113 | const Widelands::Tribe_Descr & m_tribe; |
585 | 104 | Widelands::WareWorker m_type; | 114 | Widelands::WareWorker m_type; |
586 | 105 | UI::Textarea m_curware; | 115 | UI::Textarea m_curware; |
587 | 106 | selection_type m_selected; | 116 | selection_type m_selected; |
588 | 107 | selection_type m_hidden; | 117 | selection_type m_hidden; |
589 | 118 | selection_type m_in_selection; //Wares in temporary anchored selection | ||
590 | 108 | bool m_selectable; | 119 | bool m_selectable; |
591 | 109 | bool m_horizontal; | 120 | bool m_horizontal; |
592 | 121 | |||
593 | 122 | /** | ||
594 | 123 | * The ware on which the mouse press has been performed. | ||
595 | 124 | * It is not selected directly, but will be on mouse release. | ||
596 | 125 | */ | ||
597 | 126 | Widelands::Ware_Index m_selection_anchor; | ||
598 | 110 | boost::function<void(Widelands::Ware_Index, bool)> m_callback_function; | 127 | boost::function<void(Widelands::Ware_Index, bool)> m_callback_function; |
599 | 111 | }; | 128 | }; |
600 | 112 | 129 |
I'll try to have a look at this during this week - I will be a bit busy though, so no promises. If anybody else can review this, go ahead of course :).