Merge lp:~nomeata/widelands/plot-improvements into lp:widelands

Proposed by Joachim Breitner
Status: Merged
Merged at revision: 6064
Proposed branch: lp:~nomeata/widelands/plot-improvements
Merge into: lp:widelands
Diff against target: 499 lines (+202/-81)
6 files modified
src/ui_basic/button.h (+1/-0)
src/ui_basic/slider.cc (+13/-11)
src/wui/general_statistics_menu.cc (+20/-15)
src/wui/general_statistics_menu.h (+3/-3)
src/wui/plot_area.cc (+139/-46)
src/wui/plot_area.h (+26/-6)
To merge this branch: bzr merge lp:~nomeata/widelands/plot-improvements
Reviewer Review Type Date Requested Status
Widelands Developers Pending
Review via email: mp+81360@code.launchpad.net

Description of the change

Plot time slider offers only sensible times, automatically find a good choice of units and xticks, make units translatable and use buttons for the player selection.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/ui_basic/button.h'
2--- src/ui_basic/button.h 2011-11-04 18:22:20 +0000
3+++ src/ui_basic/button.h 2011-11-05 14:59:26 +0000
4@@ -79,6 +79,7 @@
5
6 // Set the permanently pressed state of the button
7 void set_perm_pressed(bool state);
8+ bool get_perm_pressed() const { return m_permpressed;}
9
10 // Set button to flat / not flat
11 void set_flat(bool flat);
12
13=== modified file 'src/ui_basic/slider.cc'
14--- src/ui_basic/slider.cc 2011-11-04 21:42:45 +0000
15+++ src/ui_basic/slider.cc 2011-11-05 14:59:26 +0000
16@@ -380,18 +380,20 @@
17 {
18 RGBAColor black(0, 0, 0, 255);
19
20- dst.brighten_rect // bottom edge
21- (Rect(Point(get_x_gap(), get_h() / 2), get_bar_size(), 2),
22- BUTTON_EDGE_BRIGHT_FACTOR);
23- dst.brighten_rect // right edge
24- (Rect(Point(get_x_gap() + get_bar_size() - 2, get_y_gap()), 2, 2),
25- BUTTON_EDGE_BRIGHT_FACTOR);
26+ if (get_bar_size() > 0) {
27+ dst.brighten_rect // bottom edge
28+ (Rect(Point(get_x_gap(), get_h() / 2), get_bar_size(), 2),
29+ BUTTON_EDGE_BRIGHT_FACTOR);
30+ dst.brighten_rect // right edge
31+ (Rect(Point(get_x_gap() + get_bar_size() - 2, get_y_gap()), 2, 2),
32+ BUTTON_EDGE_BRIGHT_FACTOR);
33
34- // top edge
35- dst.fill_rect
36- (Rect(Point(get_x_gap(), get_y_gap()), get_bar_size() - 1, 1), black);
37- dst.fill_rect
38- (Rect(Point(get_x_gap(), get_y_gap() + 1), get_bar_size() - 2, 1), black);
39+ // top edge
40+ dst.fill_rect
41+ (Rect(Point(get_x_gap(), get_y_gap()), get_bar_size() - 1, 1), black);
42+ dst.fill_rect
43+ (Rect(Point(get_x_gap(), get_y_gap() + 1), get_bar_size() - 2, 1), black);
44+ }
45
46 // left edge
47 dst.fill_rect(Rect(Point(get_x_gap(), get_y_gap()), 1, 4), black);
48
49=== modified file 'src/wui/general_statistics_menu.cc'
50--- src/wui/general_statistics_menu.cc 2011-11-04 22:07:49 +0000
51+++ src/wui/general_statistics_menu.cc 2011-11-05 14:59:26 +0000
52@@ -129,28 +129,30 @@
53 iterate_players_existing_const(p, nr_players, game, player) ++plr_in_game;
54
55 pos.x = spacing;
56- int32_t button_size =
57- (get_inner_w() - (spacing * (plr_in_game + 1))) / plr_in_game;
58 iterate_players_existing_const(p, nr_players, game, player) {
59 char buffer[36];
60 snprintf(buffer, sizeof(buffer), "pics/genstats_enable_plr_%02u.png", p);
61- UI::Checkbox & cb =
62- *new UI::Checkbox
63- (this, pos, g_gr->get_picture(PicMod_Game, buffer));
64- cb.set_size(button_size, 25);
65- cb.set_id(p);
66- cb.set_state(1);
67- cb.set_tooltip(player->get_name().c_str());
68- cb.changedtoid.set(this, &General_Statistics_Menu::cb_changed_to);
69+ UI::Callback_Button & cb =
70+ *new UI::Callback_Button
71+ (this, "playerbutton",
72+ pos.x, pos.y, 25, 25,
73+ g_gr->get_picture(PicMod_UI, "pics/but4.png"),
74+ g_gr->get_picture(PicMod_Game, buffer),
75+ boost::bind
76+ (&General_Statistics_Menu::cb_changed_to,
77+ boost::ref(*this),
78+ p),
79+ player->get_name().c_str());
80+ cb.set_perm_pressed(true);
81 m_cbs[p - 1] = &cb;
82- pos.x += button_size + spacing;
83+ pos.x += 25 + spacing;
84 } else // player nr p does not exist
85 m_cbs[p - 1] = 0;
86
87 pos.x = spacing;
88 pos.y += 25 + spacing + spacing;
89
90- button_size =
91+ int32_t button_size =
92 (get_inner_w() - spacing * (m_ndatasets + 1))
93 /
94 m_ndatasets;
95@@ -257,11 +259,14 @@
96 /*
97 * Cb has been changed to this state
98 */
99-void General_Statistics_Menu::cb_changed_to(int32_t const id, bool const what)
100+void General_Statistics_Menu::cb_changed_to(int32_t const id)
101 {
102 // This represents our player number
103+ m_cbs[id - 1]->set_perm_pressed(not m_cbs[id - 1]->get_perm_pressed());
104+
105 m_plot.show_plot
106- ((id - 1) * m_ndatasets + m_selected_information, what);
107+ ((id - 1) * m_ndatasets + m_selected_information,
108+ m_cbs[id - 1]->get_perm_pressed());
109 }
110
111 /*
112@@ -274,7 +279,7 @@
113 for (uint32_t i = 0; i < statistics_size; ++i)
114 if (m_cbs[i]) {
115 m_plot.show_plot
116- (i * m_ndatasets + id, m_cbs[i]->get_state());
117+ (i * m_ndatasets + id, m_cbs[i]->get_perm_pressed());
118 m_plot.show_plot
119 (i * m_ndatasets + m_selected_information, false);
120 }
121
122=== modified file 'src/wui/general_statistics_menu.h'
123--- src/wui/general_statistics_menu.h 2010-09-04 13:50:09 +0000
124+++ src/wui/general_statistics_menu.h 2011-11-05 14:59:26 +0000
125@@ -25,11 +25,11 @@
126 #include "plot_area.h"
127
128 #include "ui_basic/radiobutton.h"
129+#include "ui_basic/button.h"
130 #include "ui_basic/unique_window.h"
131
132 struct Interactive_GameBase;
133 namespace UI {
134-struct Checkbox;
135 struct Radiogroup;
136 }
137
138@@ -41,11 +41,11 @@
139 WUIPlot_Area m_plot;
140 UI::Radiogroup m_radiogroup;
141 int32_t m_selected_information;
142- UI::Checkbox * m_cbs[MAX_PLAYERS];
143+ UI::Callback_Button * m_cbs[MAX_PLAYERS];
144 uint32_t m_ndatasets;
145
146 void clicked_help();
147- void cb_changed_to(int32_t, bool);
148+ void cb_changed_to(int32_t);
149 void radiogroup_changed(int32_t);
150 };
151
152
153=== modified file 'src/wui/plot_area.cc'
154--- src/wui/plot_area.cc 2011-11-04 22:07:49 +0000
155+++ src/wui/plot_area.cc 2011-11-05 14:59:26 +0000
156@@ -19,48 +19,31 @@
157
158 #include "plot_area.h"
159
160+#include "i18n.h"
161 #include "constants.h"
162 #include "graphic/font.h"
163 #include "graphic/font_handler.h"
164 #include "graphic/graphic.h"
165 #include "graphic/rendertarget.h"
166
167+
168 #include "ui_basic/panel.h"
169
170 #include <cstdio>
171-
172-
173-/*
174- * Where to draw tics
175- */
176-static const int32_t how_many_ticks[] = {
177- 5, // 15 Mins
178- 3, // 30 Mins
179- 6, // 1 H
180- 4, // 2 H
181- 4, // 4 H
182- 4, // 8 H
183- 4, // 16 H
184-};
185-
186-static const int32_t max_x[] = {
187- 15,
188- 30,
189- 60,
190- 120,
191- 4,
192- 8,
193- 16
194-};
195+#include <boost/lexical_cast.hpp>
196+
197+static const uint32_t minutes = 60 * 1000;
198+static const uint32_t hours = 60 * 60 * 1000;
199+static const uint32_t days = 24 * 60 * 60 * 1000;
200
201 static const uint32_t time_in_ms[] = {
202- 15 * 60 * 1000,
203- 30 * 60 * 1000,
204- 1 * 60 * 60 * 1000,
205- 2 * 60 * 60 * 1000,
206- 4 * 60 * 60 * 1000,
207- 8 * 60 * 60 * 1000,
208- 16 * 60 * 60 * 1000,
209+ 15 * minutes,
210+ 30 * minutes,
211+ 1 * hours,
212+ 2 * hours,
213+ 5 * hours,
214+ 10 * hours,
215+ 30 * hours
216 };
217
218 #define NR_SAMPLES 30 // How many samples per diagramm when relative plotting
219@@ -74,16 +57,128 @@
220 int32_t const x, int32_t const y, int32_t const w, int32_t const h)
221 :
222 UI::Panel (parent, x, y, w, h),
223-m_time (TIME_ONE_HOUR),
224+m_time (TIME_GAME),
225 m_plotmode(PLOTMODE_ABSOLUTE)
226 {}
227
228
229+uint32_t WUIPlot_Area::get_game_time() {
230+ uint32_t game_time = 0;
231+
232+ // Find running time of the game, based on the plot data
233+ for (uint32_t plot = 0; plot < m_plotdata.size(); ++plot)
234+ if (game_time < m_plotdata[plot].dataset->size() * m_sample_rate)
235+ game_time = m_plotdata[plot].dataset->size() * m_sample_rate;
236+ return game_time;
237+}
238+
239+uint32_t WUIPlot_Area::get_plot_time() {
240+ if (m_time == TIME_GAME) {
241+ // Start with the game time
242+ uint32_t time_in_ms_ = get_game_time();
243+
244+ // Round up to a nice nearest multiple.
245+ // Either a multiple of 4 min
246+ // Either a multiple of 20 min
247+ // or a multiple of 2h
248+ // or a multiple of 20h
249+ // or a multiple of 4 days
250+ if (time_in_ms_ > 8 * days) {
251+ time_in_ms_ += - (time_in_ms_ % (4 * days)) + 4 * days;
252+ } else if (time_in_ms_ > 40 * hours) {
253+ time_in_ms_ += - (time_in_ms_ % (20 * hours)) + 20 * hours;
254+ } else if (time_in_ms_ > 4 * hours) {
255+ time_in_ms_ += - (time_in_ms_ % (2 * hours)) + 2 * hours;
256+ } else if (time_in_ms_ > 40 * minutes) {
257+ time_in_ms_ += - (time_in_ms_ % (20 * minutes)) + 20 * minutes;
258+ } else {
259+ time_in_ms_ += - (time_in_ms_ % (4 * minutes)) + 5 * minutes;
260+ }
261+ return time_in_ms_;
262+ } else {
263+ return time_in_ms[m_time];
264+ }
265+}
266+
267+WUIPlot_Area::UNIT WUIPlot_Area::get_suggested_unit(uint32_t game_time) {
268+ // Find a nice unit for max_x
269+ if (game_time > 4 * days) {
270+ return UNIT_DAY;
271+ } else if (game_time > 4 * hours) {
272+ return UNIT_HOUR;
273+ } else {
274+ return UNIT_MIN;
275+ }
276+}
277+
278+std::string WUIPlot_Area::get_unit_name(UNIT unit) {
279+ switch (unit) {
280+ case UNIT_DAY: return _("d");
281+ case UNIT_HOUR: return _("h");
282+ case UNIT_MIN: return _("min");
283+ }
284+}
285+
286+uint32_t WUIPlot_Area::ms_to_unit(UNIT unit, uint32_t ms) {
287+ switch (unit) {
288+ case UNIT_DAY: return ms / days;
289+ case UNIT_HOUR: return ms / hours;
290+ case UNIT_MIN: return ms / minutes;
291+ }
292+}
293+
294+std::vector<std::string> WUIPlot_Area::get_labels() {
295+ std::vector<std::string> labels;
296+ uint32_t game_time = get_game_time();
297+ uint32_t i = 0;
298+
299+ for (i = 0; i < 7; i++) {
300+ if (time_in_ms[i] < game_time) {
301+ UNIT unit = get_suggested_unit(time_in_ms[i]);
302+ uint32_t val = ms_to_unit(unit, time_in_ms[i]);
303+ labels.push_back(boost::lexical_cast<std::string>(val) + get_unit_name(unit));
304+ }
305+ }
306+ labels.push_back(_("game"));
307+ m_game_label = i;
308+ return labels;
309+}
310+
311+
312 /*
313 * Draw this. This is the main function
314 */
315 void WUIPlot_Area::draw(RenderTarget & dst) {
316
317+ uint32_t time_in_ms_, how_many_ticks, max_x;
318+
319+ time_in_ms_ = get_plot_time();
320+ UNIT unit = get_suggested_unit(time_in_ms_);
321+ max_x = ms_to_unit(unit, time_in_ms_);
322+
323+ // Find a nice division of max_x
324+ if (max_x % 5 == 0) {
325+ if (max_x <= 10) {
326+ how_many_ticks = 5;
327+ } else {
328+ how_many_ticks = max_x / 5;
329+ while (how_many_ticks > 7 && how_many_ticks % 2 == 0) {
330+ how_many_ticks /= 2;
331+ }
332+ while (how_many_ticks > 7 && how_many_ticks % 3 == 0) {
333+ how_many_ticks /= 3;
334+ }
335+ while (how_many_ticks > 7 && how_many_ticks % 5 == 0) {
336+ how_many_ticks /= 5;
337+ }
338+ while (how_many_ticks > 7 && how_many_ticks % 7 == 0) {
339+ how_many_ticks /= 7;
340+ }
341+ }
342+ } else {
343+ how_many_ticks = 4;
344+ }
345+
346 // first, tile the background
347 dst.tile
348 (Rect(Point(0, 0), get_inner_w(), get_inner_h()),
349@@ -123,10 +218,10 @@
350 UI::TextStyle xtickstyle(UI::TextStyle::ui_small());
351 xtickstyle.fg = RGBColor(255, 0, 0);
352
353- float sub = xline_length / how_many_ticks[m_time];
354+ float sub = xline_length / how_many_ticks;
355 float posx = get_inner_w() - space_at_right;
356 char buffer[200];
357- for (int32_t i = 0; i <= how_many_ticks[m_time]; ++i) {
358+ for (uint32_t i = 0; i <= how_many_ticks; ++i) {
359 dst.draw_line
360 (static_cast<int32_t>(posx), get_inner_h() - space_at_bottom,
361 static_cast<int32_t>(posx), get_inner_h() - space_at_bottom + 3,
362@@ -134,7 +229,7 @@
363
364 snprintf
365 (buffer, sizeof(buffer),
366- "%u", max_x[m_time] / how_many_ticks[m_time] * i);
367+ "%u", max_x / how_many_ticks * i);
368
369 UI::g_fh->draw_text
370 (dst, xtickstyle,
371@@ -176,7 +271,7 @@
372 // How many do we take together
373 int32_t const how_many =
374 static_cast<int32_t>
375- ((static_cast<float>(time_in_ms[m_time])
376+ ((static_cast<float>(time_in_ms_)
377 /
378 static_cast<float>(NR_SAMPLES))
379 /
380@@ -205,11 +300,17 @@
381 Point(get_inner_w() - space_at_right - 2, spacing + 2),
382 buffer, UI::Align_CenterRight);
383
384+ // print the used unit
385+ UI::g_fh->draw_text
386+ (dst, xtickstyle,
387+ Point(2, spacing + 2),
388+ get_unit_name(unit), UI::Align_CenterLeft);
389+
390 // plot the pixels
391 sub =
392 xline_length
393 /
394- (static_cast<float>(time_in_ms[m_time])
395+ (static_cast<float>(time_in_ms_)
396 /
397 static_cast<float>(m_sample_rate));
398 for (uint32_t plot = 0; plot < m_plotdata.size(); ++plot)
399@@ -222,7 +323,7 @@
400 if (m_plotmode == PLOTMODE_RELATIVE) {
401 // How many do we take together.
402 const int32_t how_many = static_cast<int32_t>
403- ((static_cast<float>(time_in_ms[m_time])
404+ ((static_cast<float>(time_in_ms_)
405 /
406 static_cast<float>(NR_SAMPLES))
407 /
408@@ -292,17 +393,9 @@
409 };
410
411 /*
412- * set time
413- */
414-void WUIPlot_Area::set_time(TIME const id) {m_time = id;}
415-
416-/*
417 * Set sample rate the data uses
418 */
419 void WUIPlot_Area::set_sample_rate(uint32_t const id) {
420 m_sample_rate = id;
421 }
422
423-std::string WUIPlot_Area::time_labels[WUIPlot_Area::TIME_LAST] =
424- {"15m", "30m", "1h", "2h", "4h", "8h", "16h"};
425-
426
427=== modified file 'src/wui/plot_area.h'
428--- src/wui/plot_area.h 2011-11-04 22:07:49 +0000
429+++ src/wui/plot_area.h 2011-11-05 14:59:26 +0000
430@@ -41,9 +41,14 @@
431 TIME_FOUR_HOURS,
432 TIME_EIGHT_HOURS,
433 TIME_16_HOURS,
434+ TIME_GAME,
435 TIME_LAST,
436 };
437- static std::string time_labels[TIME_LAST];
438+ enum UNIT {
439+ UNIT_MIN,
440+ UNIT_HOUR,
441+ UNIT_DAY,
442+ };
443 enum PLOTMODE {
444 // Always take the samples of some times together, so that the graph is
445 // not completely zigg-zagged.
446@@ -57,8 +62,16 @@
447
448 virtual void draw(RenderTarget &);
449
450- void set_time(TIME);
451- void set_time_int(int32_t time) {set_time(static_cast<TIME>(time)); };
452+ void set_time(TIME id) {
453+ m_time = id;
454+ }
455+
456+ void set_time_int(int32_t time) {
457+ if (time == m_game_label)
458+ set_time(TIME_GAME);
459+ else
460+ set_time(static_cast<TIME>(time));
461+ };
462 TIME get_time() {return static_cast<TIME>(m_time); };
463 void set_sample_rate(uint32_t id); // in milliseconds
464
465@@ -68,7 +81,15 @@
466
467 void set_plotmode(int32_t id) {m_plotmode = id;}
468
469+ std::vector<std::string> get_labels();
470+
471 private:
472+ uint32_t get_game_time();
473+ uint32_t get_plot_time();
474+ UNIT get_suggested_unit(uint32_t game_time);
475+ std::string get_unit_name(UNIT unit);
476+ uint32_t ms_to_unit(UNIT unit, uint32_t ms);
477+
478 struct __plotdata {
479 const std::vector<uint32_t> * dataset;
480 bool showplot;
481@@ -78,6 +99,7 @@
482 int32_t m_time; // How much do you want to list
483 int32_t m_sample_rate;
484 int32_t m_plotmode;
485+ int32_t m_game_label; // what label is used for TIME_GAME
486 };
487
488 /**
489@@ -96,9 +118,7 @@
490 : DiscreteSlider
491 (parent,
492 x, y, w, h,
493- std::vector<std::string>
494- (WUIPlot_Area::time_labels,
495- WUIPlot_Area::time_labels + WUIPlot_Area::TIME_LAST),
496+ plot_area.get_labels(),
497 plot_area.get_time(),
498 background_picture_id,
499 tooltip_text,

Subscribers

People subscribed via source and target branches

to status/vote changes: