|
1 /* $Id$ */ |
|
2 |
|
3 #include "stdafx.h" |
|
4 #include "openttd.h" |
|
5 #include "table/strings.h" |
|
6 #include "table/sprites.h" |
|
7 #include "functions.h" |
|
8 #include "window.h" |
|
9 #include "gui.h" |
|
10 #include "gfx.h" |
|
11 #include "player.h" |
|
12 #include "economy.h" |
|
13 #include "signs.h" |
|
14 #include "strings.h" |
|
15 #include "debug.h" |
|
16 #include "variables.h" |
|
17 #include "date.h" |
|
18 |
|
19 const byte _cargo_colours[NUM_CARGO] = {152, 32, 15, 174, 208, 194, 191, 84, 184, 10, 202, 48}; |
|
20 |
|
21 static uint _legend_excludebits; |
|
22 static uint _legend_cargobits; |
|
23 |
|
24 /************************/ |
|
25 /* GENERIC GRAPH DRAWER */ |
|
26 /************************/ |
|
27 |
|
28 enum {GRAPH_NUM = 16}; |
|
29 |
|
30 typedef struct GraphDrawer { |
|
31 uint sel; // bitmask of the players *excluded* (e.g. 11111111 means that no players are shown) |
|
32 byte num_dataset; |
|
33 byte num_on_x_axis; |
|
34 byte month; |
|
35 Year year; |
|
36 bool include_neg; |
|
37 byte num_vert_lines; |
|
38 uint16 unk61A; |
|
39 uint16 unk61C; |
|
40 int left, top; |
|
41 uint height; |
|
42 StringID format_str_y_axis; |
|
43 byte color_3, color_2, bg_line_color; |
|
44 byte colors[GRAPH_NUM]; |
|
45 uint64 cost[GRAPH_NUM][24]; // last 2 years |
|
46 } GraphDrawer; |
|
47 |
|
48 #define INVALID_VALUE 0x80000000 |
|
49 |
|
50 static void DrawGraph(const GraphDrawer *gw) |
|
51 { |
|
52 |
|
53 int i,j,k; |
|
54 uint x,y,old_x,old_y; |
|
55 int color; |
|
56 int right, bottom; |
|
57 int num_x, num_dataset; |
|
58 const uint64 *row_ptr, *col_ptr; |
|
59 int64 mx; |
|
60 int adj_height; |
|
61 uint64 y_scaling, tmp; |
|
62 int64 value; |
|
63 int64 cur_val; |
|
64 uint sel; |
|
65 |
|
66 /* the colors and cost array of GraphDrawer must accomodate |
|
67 * both values for cargo and players. So if any are higher, quit */ |
|
68 assert(GRAPH_NUM >= NUM_CARGO && GRAPH_NUM >= MAX_PLAYERS); |
|
69 |
|
70 color = _colour_gradient[gw->bg_line_color][4]; |
|
71 |
|
72 /* draw the vertical lines */ |
|
73 i = gw->num_vert_lines; assert(i > 0); |
|
74 x = gw->left + 66; |
|
75 bottom = gw->top + gw->height - 1; |
|
76 do { |
|
77 GfxFillRect(x, gw->top, x, bottom, color); |
|
78 x += 22; |
|
79 } while (--i); |
|
80 |
|
81 /* draw the horizontal lines */ |
|
82 i = 9; |
|
83 x = gw->left + 44; |
|
84 y = gw->height + gw->top; |
|
85 right = gw->left + 44 + gw->num_vert_lines*22-1; |
|
86 |
|
87 do { |
|
88 GfxFillRect(x, y, right, y, color); |
|
89 y -= gw->height >> 3; |
|
90 } while (--i); |
|
91 |
|
92 /* draw vertical edge line */ |
|
93 GfxFillRect(x, gw->top, x, bottom, gw->color_2); |
|
94 |
|
95 adj_height = gw->height; |
|
96 if (gw->include_neg) adj_height >>= 1; |
|
97 |
|
98 /* draw horiz edge line */ |
|
99 y = adj_height + gw->top; |
|
100 GfxFillRect(x, y, right, y, gw->color_2); |
|
101 |
|
102 /* find the max element */ |
|
103 if (gw->num_on_x_axis == 0) |
|
104 return; |
|
105 |
|
106 num_dataset = gw->num_dataset; |
|
107 assert(num_dataset > 0); |
|
108 |
|
109 row_ptr = gw->cost[0]; |
|
110 mx = 0; |
|
111 /* bit selection for the showing of various players, base max element |
|
112 * on to-be shown player-information. This way the graph can scale */ |
|
113 sel = gw->sel; |
|
114 do { |
|
115 if (!(sel&1)) { |
|
116 num_x = gw->num_on_x_axis; |
|
117 assert(num_x > 0); |
|
118 col_ptr = row_ptr; |
|
119 do { |
|
120 if (*col_ptr != INVALID_VALUE) { |
|
121 mx = max64(mx, myabs64(*col_ptr)); |
|
122 } |
|
123 } while (col_ptr++, --num_x); |
|
124 } |
|
125 } while (sel>>=1, row_ptr+=24, --num_dataset); |
|
126 |
|
127 /* setup scaling */ |
|
128 y_scaling = INVALID_VALUE; |
|
129 value = adj_height * 2; |
|
130 |
|
131 if (mx > value) { |
|
132 mx = (mx + 7) & ~7; |
|
133 y_scaling = (((uint64) (value>>1) << 32) / mx); |
|
134 value = mx; |
|
135 } |
|
136 |
|
137 /* draw text strings on the y axis */ |
|
138 tmp = value; |
|
139 if (gw->include_neg) tmp >>= 1; |
|
140 x = gw->left + 45; |
|
141 y = gw->top - 3; |
|
142 i = 9; |
|
143 do { |
|
144 SetDParam(0, gw->format_str_y_axis); |
|
145 SetDParam64(1, (int64)tmp); |
|
146 tmp -= (value >> 3); |
|
147 DrawStringRightAligned(x, y, STR_0170, gw->color_3); |
|
148 y += gw->height >> 3; |
|
149 } while (--i); |
|
150 |
|
151 /* draw strings on the x axis */ |
|
152 if (gw->month != 0xFF) { |
|
153 x = gw->left + 44; |
|
154 y = gw->top + gw->height + 1; |
|
155 j = gw->month; |
|
156 k = gw->year; |
|
157 i = gw->num_on_x_axis;assert(i>0); |
|
158 do { |
|
159 SetDParam(2, k); |
|
160 SetDParam(0, j + STR_0162_JAN); |
|
161 SetDParam(1, j + STR_0162_JAN + 2); |
|
162 DrawString(x, y, j == 0 ? STR_016F : STR_016E, gw->color_3); |
|
163 |
|
164 j += 3; |
|
165 if (j >= 12) { |
|
166 j = 0; |
|
167 k++; |
|
168 } |
|
169 x += 22; |
|
170 } while (--i); |
|
171 } else { |
|
172 x = gw->left + 52; |
|
173 y = gw->top + gw->height + 1; |
|
174 j = gw->unk61A; |
|
175 i = gw->num_on_x_axis;assert(i>0); |
|
176 do { |
|
177 SetDParam(0, j); |
|
178 DrawString(x, y, STR_01CB, gw->color_3); |
|
179 j += gw->unk61C; |
|
180 x += 22; |
|
181 } while (--i); |
|
182 } |
|
183 |
|
184 /* draw lines and dots */ |
|
185 i = 0; |
|
186 row_ptr = gw->cost[0]; |
|
187 sel = gw->sel; // show only selected lines. GraphDrawer qw->sel set in Graph-Legend (_legend_excludebits) |
|
188 do { |
|
189 if (!(sel & 1)) { |
|
190 x = gw->left + 55; |
|
191 j = gw->num_on_x_axis;assert(j>0); |
|
192 col_ptr = row_ptr; |
|
193 color = gw->colors[i]; |
|
194 old_y = old_x = INVALID_VALUE; |
|
195 do { |
|
196 cur_val = *col_ptr++; |
|
197 if (cur_val != INVALID_VALUE) { |
|
198 y = adj_height - BIGMULSS64(cur_val, y_scaling >> 1, 31) + gw->top; |
|
199 |
|
200 GfxFillRect(x-1, y-1, x+1, y+1, color); |
|
201 if (old_x != INVALID_VALUE) |
|
202 GfxDrawLine(old_x, old_y, x, y, color); |
|
203 |
|
204 old_x = x; |
|
205 old_y = y; |
|
206 } else { |
|
207 old_x = INVALID_VALUE; |
|
208 } |
|
209 } while (x+=22,--j); |
|
210 } |
|
211 } while (sel>>=1,row_ptr+=24, ++i < gw->num_dataset); |
|
212 } |
|
213 |
|
214 /****************/ |
|
215 /* GRAPH LEGEND */ |
|
216 /****************/ |
|
217 |
|
218 void DrawPlayerIcon(PlayerID p, int x, int y) |
|
219 { |
|
220 DrawSprite(SPRITE_PALETTE(PLAYER_SPRITE_COLOR(p) + 0x2EB), x, y); |
|
221 } |
|
222 |
|
223 static void GraphLegendWndProc(Window *w, WindowEvent *e) |
|
224 { |
|
225 const Player* p; |
|
226 |
|
227 switch (e->event) { |
|
228 case WE_CREATE: { |
|
229 uint i; |
|
230 for (i = 3; i < w->widget_count; i++) { |
|
231 if (!HASBIT(_legend_excludebits, i - 3)) LowerWindowWidget(w, i); |
|
232 } |
|
233 break; |
|
234 } |
|
235 |
|
236 case WE_PAINT: |
|
237 FOR_ALL_PLAYERS(p) { |
|
238 if (!p->is_active) { |
|
239 SETBIT(_legend_excludebits, p->index); |
|
240 RaiseWindowWidget(w, p->index + 3); |
|
241 } |
|
242 } |
|
243 DrawWindowWidgets(w); |
|
244 |
|
245 FOR_ALL_PLAYERS(p) { |
|
246 if (!p->is_active) continue; |
|
247 |
|
248 DrawPlayerIcon(p->index, 4, 18+p->index*12); |
|
249 |
|
250 SetDParam(0, p->name_1); |
|
251 SetDParam(1, p->name_2); |
|
252 SetDParam(2, GetPlayerNameString(p->index, 3)); |
|
253 DrawString(21,17+p->index*12,STR_7021,HASBIT(_legend_excludebits, p->index) ? 0x10 : 0xC); |
|
254 } |
|
255 break; |
|
256 |
|
257 case WE_CLICK: |
|
258 if (IS_INT_INSIDE(e->we.click.widget, 3, 11)) { |
|
259 _legend_excludebits ^= (1 << (e->we.click.widget - 3)); |
|
260 ToggleWidgetLoweredState(w, e->we.click.widget); |
|
261 SetWindowDirty(w); |
|
262 InvalidateWindow(WC_INCOME_GRAPH, 0); |
|
263 InvalidateWindow(WC_OPERATING_PROFIT, 0); |
|
264 InvalidateWindow(WC_DELIVERED_CARGO, 0); |
|
265 InvalidateWindow(WC_PERFORMANCE_HISTORY, 0); |
|
266 InvalidateWindow(WC_COMPANY_VALUE, 0); |
|
267 } |
|
268 break; |
|
269 } |
|
270 } |
|
271 |
|
272 static const Widget _graph_legend_widgets[] = { |
|
273 { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, |
|
274 { WWT_CAPTION, RESIZE_NONE, 14, 11, 249, 0, 13, STR_704E_KEY_TO_COMPANY_GRAPHS, STR_018C_WINDOW_TITLE_DRAG_THIS}, |
|
275 { WWT_PANEL, RESIZE_NONE, 14, 0, 249, 14, 113, 0x0, STR_NULL}, |
|
276 { WWT_PANEL, RESIZE_NONE, 14, 2, 247, 16, 27, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, |
|
277 { WWT_PANEL, RESIZE_NONE, 14, 2, 247, 28, 39, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, |
|
278 { WWT_PANEL, RESIZE_NONE, 14, 2, 247, 40, 51, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, |
|
279 { WWT_PANEL, RESIZE_NONE, 14, 2, 247, 52, 63, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, |
|
280 { WWT_PANEL, RESIZE_NONE, 14, 2, 247, 64, 75, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, |
|
281 { WWT_PANEL, RESIZE_NONE, 14, 2, 247, 76, 87, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, |
|
282 { WWT_PANEL, RESIZE_NONE, 14, 2, 247, 88, 99, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, |
|
283 { WWT_PANEL, RESIZE_NONE, 14, 2, 247, 100, 111, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, |
|
284 { WIDGETS_END}, |
|
285 }; |
|
286 |
|
287 static const WindowDesc _graph_legend_desc = { |
|
288 WDP_AUTO, WDP_AUTO, 250, 114, |
|
289 WC_GRAPH_LEGEND,0, |
|
290 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, |
|
291 _graph_legend_widgets, |
|
292 GraphLegendWndProc |
|
293 }; |
|
294 |
|
295 static void ShowGraphLegend(void) |
|
296 { |
|
297 AllocateWindowDescFront(&_graph_legend_desc, 0); |
|
298 } |
|
299 |
|
300 /********************/ |
|
301 /* OPERATING PROFIT */ |
|
302 /********************/ |
|
303 |
|
304 static void SetupGraphDrawerForPlayers(GraphDrawer *gd) |
|
305 { |
|
306 const Player* p; |
|
307 uint excludebits = _legend_excludebits; |
|
308 int nums; |
|
309 int mo,yr; |
|
310 |
|
311 // Exclude the players which aren't valid |
|
312 FOR_ALL_PLAYERS(p) { |
|
313 if (!p->is_active) SETBIT(excludebits,p->index); |
|
314 } |
|
315 gd->sel = excludebits; |
|
316 gd->num_vert_lines = 24; |
|
317 |
|
318 nums = 0; |
|
319 FOR_ALL_PLAYERS(p) { |
|
320 if (p->is_active) nums = max(nums,p->num_valid_stat_ent); |
|
321 } |
|
322 gd->num_on_x_axis = min(nums,24); |
|
323 |
|
324 mo = (_cur_month/3-nums)*3; |
|
325 yr = _cur_year; |
|
326 while (mo < 0) { |
|
327 yr--; |
|
328 mo += 12; |
|
329 } |
|
330 |
|
331 gd->year = yr; |
|
332 gd->month = mo; |
|
333 } |
|
334 |
|
335 static void OperatingProfitWndProc(Window *w, WindowEvent *e) |
|
336 { |
|
337 switch (e->event) { |
|
338 case WE_PAINT: { |
|
339 GraphDrawer gd; |
|
340 const Player* p; |
|
341 int i,j; |
|
342 int numd; |
|
343 |
|
344 DrawWindowWidgets(w); |
|
345 |
|
346 gd.left = 2; |
|
347 gd.top = 18; |
|
348 gd.height = 136; |
|
349 gd.include_neg = true; |
|
350 gd.format_str_y_axis = STR_CURRCOMPACT; |
|
351 gd.color_3 = 0x10; |
|
352 gd.color_2 = 0xD7; |
|
353 gd.bg_line_color = 0xE; |
|
354 |
|
355 SetupGraphDrawerForPlayers(&gd); |
|
356 |
|
357 numd = 0; |
|
358 FOR_ALL_PLAYERS(p) { |
|
359 if (p->is_active) { |
|
360 gd.colors[numd] = _colour_gradient[p->player_color][6]; |
|
361 for (j = gd.num_on_x_axis, i = 0; --j >= 0;) { |
|
362 gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? INVALID_VALUE : (uint64)(p->old_economy[j].income + p->old_economy[j].expenses); |
|
363 i++; |
|
364 } |
|
365 } |
|
366 numd++; |
|
367 } |
|
368 |
|
369 gd.num_dataset = numd; |
|
370 |
|
371 DrawGraph(&gd); |
|
372 } break; |
|
373 case WE_CLICK: |
|
374 if (e->we.click.widget == 2) /* Clicked on Legend */ |
|
375 ShowGraphLegend(); |
|
376 break; |
|
377 } |
|
378 } |
|
379 |
|
380 static const Widget _operating_profit_widgets[] = { |
|
381 { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, |
|
382 { WWT_CAPTION, RESIZE_NONE, 14, 11, 525, 0, 13, STR_7025_OPERATING_PROFIT_GRAPH, STR_018C_WINDOW_TITLE_DRAG_THIS}, |
|
383 { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 526, 575, 0, 13, STR_704C_KEY, STR_704D_SHOW_KEY_TO_GRAPHS}, |
|
384 { WWT_PANEL, RESIZE_NONE, 14, 0, 575, 14, 173, 0x0, STR_NULL}, |
|
385 { WIDGETS_END}, |
|
386 }; |
|
387 |
|
388 static const WindowDesc _operating_profit_desc = { |
|
389 WDP_AUTO, WDP_AUTO, 576, 174, |
|
390 WC_OPERATING_PROFIT,0, |
|
391 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, |
|
392 _operating_profit_widgets, |
|
393 OperatingProfitWndProc |
|
394 }; |
|
395 |
|
396 |
|
397 void ShowOperatingProfitGraph(void) |
|
398 { |
|
399 if (AllocateWindowDescFront(&_operating_profit_desc, 0)) { |
|
400 InvalidateWindow(WC_GRAPH_LEGEND, 0); |
|
401 } |
|
402 } |
|
403 |
|
404 |
|
405 /****************/ |
|
406 /* INCOME GRAPH */ |
|
407 /****************/ |
|
408 |
|
409 static void IncomeGraphWndProc(Window *w, WindowEvent *e) |
|
410 { |
|
411 switch (e->event) { |
|
412 case WE_PAINT: { |
|
413 GraphDrawer gd; |
|
414 const Player* p; |
|
415 int i,j; |
|
416 int numd; |
|
417 |
|
418 DrawWindowWidgets(w); |
|
419 |
|
420 gd.left = 2; |
|
421 gd.top = 18; |
|
422 gd.height = 104; |
|
423 gd.include_neg = false; |
|
424 gd.format_str_y_axis = STR_CURRCOMPACT; |
|
425 gd.color_3 = 0x10; |
|
426 gd.color_2 = 0xD7; |
|
427 gd.bg_line_color = 0xE; |
|
428 SetupGraphDrawerForPlayers(&gd); |
|
429 |
|
430 numd = 0; |
|
431 FOR_ALL_PLAYERS(p) { |
|
432 if (p->is_active) { |
|
433 gd.colors[numd] = _colour_gradient[p->player_color][6]; |
|
434 for (j = gd.num_on_x_axis, i = 0; --j >= 0;) { |
|
435 gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? INVALID_VALUE : (uint64)p->old_economy[j].income; |
|
436 i++; |
|
437 } |
|
438 } |
|
439 numd++; |
|
440 } |
|
441 |
|
442 gd.num_dataset = numd; |
|
443 |
|
444 DrawGraph(&gd); |
|
445 break; |
|
446 } |
|
447 |
|
448 case WE_CLICK: |
|
449 if (e->we.click.widget == 2) |
|
450 ShowGraphLegend(); |
|
451 break; |
|
452 } |
|
453 } |
|
454 |
|
455 static const Widget _income_graph_widgets[] = { |
|
456 { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, |
|
457 { WWT_CAPTION, RESIZE_NONE, 14, 11, 525, 0, 13, STR_7022_INCOME_GRAPH, STR_018C_WINDOW_TITLE_DRAG_THIS}, |
|
458 { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 526, 575, 0, 13, STR_704C_KEY, STR_704D_SHOW_KEY_TO_GRAPHS}, |
|
459 { WWT_PANEL, RESIZE_NONE, 14, 0, 575, 14, 141, 0x0, STR_NULL}, |
|
460 { WIDGETS_END}, |
|
461 }; |
|
462 |
|
463 static const WindowDesc _income_graph_desc = { |
|
464 WDP_AUTO, WDP_AUTO, 576, 142, |
|
465 WC_INCOME_GRAPH,0, |
|
466 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, |
|
467 _income_graph_widgets, |
|
468 IncomeGraphWndProc |
|
469 }; |
|
470 |
|
471 void ShowIncomeGraph(void) |
|
472 { |
|
473 if (AllocateWindowDescFront(&_income_graph_desc, 0)) { |
|
474 InvalidateWindow(WC_GRAPH_LEGEND, 0); |
|
475 } |
|
476 } |
|
477 |
|
478 /*******************/ |
|
479 /* DELIVERED CARGO */ |
|
480 /*******************/ |
|
481 |
|
482 static void DeliveredCargoGraphWndProc(Window *w, WindowEvent *e) |
|
483 { |
|
484 switch (e->event) { |
|
485 case WE_PAINT: { |
|
486 GraphDrawer gd; |
|
487 const Player* p; |
|
488 int i,j; |
|
489 int numd; |
|
490 |
|
491 DrawWindowWidgets(w); |
|
492 |
|
493 gd.left = 2; |
|
494 gd.top = 18; |
|
495 gd.height = 104; |
|
496 gd.include_neg = false; |
|
497 gd.format_str_y_axis = STR_7024; |
|
498 gd.color_3 = 0x10; |
|
499 gd.color_2 = 0xD7; |
|
500 gd.bg_line_color = 0xE; |
|
501 SetupGraphDrawerForPlayers(&gd); |
|
502 |
|
503 numd = 0; |
|
504 FOR_ALL_PLAYERS(p) { |
|
505 if (p->is_active) { |
|
506 gd.colors[numd] = _colour_gradient[p->player_color][6]; |
|
507 for (j = gd.num_on_x_axis, i = 0; --j >= 0;) { |
|
508 gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? INVALID_VALUE : (uint64)p->old_economy[j].delivered_cargo; |
|
509 i++; |
|
510 } |
|
511 } |
|
512 numd++; |
|
513 } |
|
514 |
|
515 gd.num_dataset = numd; |
|
516 |
|
517 DrawGraph(&gd); |
|
518 break; |
|
519 } |
|
520 |
|
521 case WE_CLICK: |
|
522 if (e->we.click.widget == 2) |
|
523 ShowGraphLegend(); |
|
524 break; |
|
525 } |
|
526 } |
|
527 |
|
528 static const Widget _delivered_cargo_graph_widgets[] = { |
|
529 { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, |
|
530 { WWT_CAPTION, RESIZE_NONE, 14, 11, 525, 0, 13, STR_7050_UNITS_OF_CARGO_DELIVERED, STR_018C_WINDOW_TITLE_DRAG_THIS}, |
|
531 { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 526, 575, 0, 13, STR_704C_KEY, STR_704D_SHOW_KEY_TO_GRAPHS}, |
|
532 { WWT_PANEL, RESIZE_NONE, 14, 0, 575, 14, 141, 0x0, STR_NULL}, |
|
533 { WIDGETS_END}, |
|
534 }; |
|
535 |
|
536 static const WindowDesc _delivered_cargo_graph_desc = { |
|
537 WDP_AUTO, WDP_AUTO, 576, 142, |
|
538 WC_DELIVERED_CARGO,0, |
|
539 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, |
|
540 _delivered_cargo_graph_widgets, |
|
541 DeliveredCargoGraphWndProc |
|
542 }; |
|
543 |
|
544 void ShowDeliveredCargoGraph(void) |
|
545 { |
|
546 if (AllocateWindowDescFront(&_delivered_cargo_graph_desc, 0)) { |
|
547 InvalidateWindow(WC_GRAPH_LEGEND, 0); |
|
548 } |
|
549 } |
|
550 |
|
551 /***********************/ |
|
552 /* PERFORMANCE HISTORY */ |
|
553 /***********************/ |
|
554 |
|
555 static void PerformanceHistoryWndProc(Window *w, WindowEvent *e) |
|
556 { |
|
557 switch (e->event) { |
|
558 case WE_PAINT: { |
|
559 GraphDrawer gd; |
|
560 const Player* p; |
|
561 int i,j; |
|
562 int numd; |
|
563 |
|
564 DrawWindowWidgets(w); |
|
565 |
|
566 gd.left = 2; |
|
567 gd.top = 18; |
|
568 gd.height = 200; |
|
569 gd.include_neg = false; |
|
570 gd.format_str_y_axis = STR_7024; |
|
571 gd.color_3 = 0x10; |
|
572 gd.color_2 = 0xD7; |
|
573 gd.bg_line_color = 0xE; |
|
574 SetupGraphDrawerForPlayers(&gd); |
|
575 |
|
576 numd = 0; |
|
577 FOR_ALL_PLAYERS(p) { |
|
578 if (p->is_active) { |
|
579 gd.colors[numd] = _colour_gradient[p->player_color][6]; |
|
580 for (j = gd.num_on_x_axis, i = 0; --j >= 0;) { |
|
581 gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? INVALID_VALUE : (uint64)p->old_economy[j].performance_history; |
|
582 i++; |
|
583 } |
|
584 } |
|
585 numd++; |
|
586 } |
|
587 |
|
588 gd.num_dataset = numd; |
|
589 |
|
590 DrawGraph(&gd); |
|
591 break; |
|
592 } |
|
593 |
|
594 case WE_CLICK: |
|
595 if (e->we.click.widget == 2) |
|
596 ShowGraphLegend(); |
|
597 if (e->we.click.widget == 3) |
|
598 ShowPerformanceRatingDetail(); |
|
599 break; |
|
600 } |
|
601 } |
|
602 |
|
603 static const Widget _performance_history_widgets[] = { |
|
604 { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, |
|
605 { WWT_CAPTION, RESIZE_NONE, 14, 11, 475, 0, 13, STR_7051_COMPANY_PERFORMANCE_RATINGS, STR_018C_WINDOW_TITLE_DRAG_THIS}, |
|
606 { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 526, 575, 0, 13, STR_704C_KEY, STR_704D_SHOW_KEY_TO_GRAPHS}, |
|
607 { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 476, 525, 0, 13, STR_PERFORMANCE_DETAIL_KEY, STR_704D_SHOW_KEY_TO_GRAPHS}, |
|
608 { WWT_PANEL, RESIZE_NONE, 14, 0, 575, 14, 237, 0x0, STR_NULL}, |
|
609 { WIDGETS_END}, |
|
610 }; |
|
611 |
|
612 static const WindowDesc _performance_history_desc = { |
|
613 WDP_AUTO, WDP_AUTO, 576, 238, |
|
614 WC_PERFORMANCE_HISTORY,0, |
|
615 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, |
|
616 _performance_history_widgets, |
|
617 PerformanceHistoryWndProc |
|
618 }; |
|
619 |
|
620 void ShowPerformanceHistoryGraph(void) |
|
621 { |
|
622 if (AllocateWindowDescFront(&_performance_history_desc, 0)) { |
|
623 InvalidateWindow(WC_GRAPH_LEGEND, 0); |
|
624 } |
|
625 } |
|
626 |
|
627 /*****************/ |
|
628 /* COMPANY VALUE */ |
|
629 /*****************/ |
|
630 |
|
631 static void CompanyValueGraphWndProc(Window *w, WindowEvent *e) |
|
632 { |
|
633 switch (e->event) { |
|
634 case WE_PAINT: { |
|
635 GraphDrawer gd; |
|
636 const Player* p; |
|
637 int i,j; |
|
638 int numd; |
|
639 |
|
640 DrawWindowWidgets(w); |
|
641 |
|
642 gd.left = 2; |
|
643 gd.top = 18; |
|
644 gd.height = 200; |
|
645 gd.include_neg = false; |
|
646 gd.format_str_y_axis = STR_CURRCOMPACT; |
|
647 gd.color_3 = 0x10; |
|
648 gd.color_2 = 0xD7; |
|
649 gd.bg_line_color = 0xE; |
|
650 SetupGraphDrawerForPlayers(&gd); |
|
651 |
|
652 numd = 0; |
|
653 FOR_ALL_PLAYERS(p) { |
|
654 if (p->is_active) { |
|
655 gd.colors[numd] = _colour_gradient[p->player_color][6]; |
|
656 for (j = gd.num_on_x_axis, i = 0; --j >= 0;) { |
|
657 gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? INVALID_VALUE : (uint64)p->old_economy[j].company_value; |
|
658 i++; |
|
659 } |
|
660 } |
|
661 numd++; |
|
662 } |
|
663 |
|
664 gd.num_dataset = numd; |
|
665 |
|
666 DrawGraph(&gd); |
|
667 break; |
|
668 } |
|
669 |
|
670 case WE_CLICK: |
|
671 if (e->we.click.widget == 2) |
|
672 ShowGraphLegend(); |
|
673 break; |
|
674 } |
|
675 } |
|
676 |
|
677 static const Widget _company_value_graph_widgets[] = { |
|
678 { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, |
|
679 { WWT_CAPTION, RESIZE_NONE, 14, 11, 525, 0, 13, STR_7052_COMPANY_VALUES, STR_018C_WINDOW_TITLE_DRAG_THIS}, |
|
680 { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 526, 575, 0, 13, STR_704C_KEY, STR_704D_SHOW_KEY_TO_GRAPHS}, |
|
681 { WWT_PANEL, RESIZE_NONE, 14, 0, 575, 14, 237, 0x0, STR_NULL}, |
|
682 { WIDGETS_END}, |
|
683 }; |
|
684 |
|
685 static const WindowDesc _company_value_graph_desc = { |
|
686 WDP_AUTO, WDP_AUTO, 576, 238, |
|
687 WC_COMPANY_VALUE,0, |
|
688 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, |
|
689 _company_value_graph_widgets, |
|
690 CompanyValueGraphWndProc |
|
691 }; |
|
692 |
|
693 void ShowCompanyValueGraph(void) |
|
694 { |
|
695 if (AllocateWindowDescFront(&_company_value_graph_desc, 0)) { |
|
696 InvalidateWindow(WC_GRAPH_LEGEND, 0); |
|
697 } |
|
698 } |
|
699 |
|
700 /*****************/ |
|
701 /* PAYMENT RATES */ |
|
702 /*****************/ |
|
703 |
|
704 static void CargoPaymentRatesWndProc(Window *w, WindowEvent *e) |
|
705 { |
|
706 switch (e->event) { |
|
707 case WE_CREATE: { |
|
708 uint i; |
|
709 for (i = 3; i < w->widget_count; i++) { |
|
710 if (!HASBIT(_legend_cargobits, i - 3)) LowerWindowWidget(w, i); |
|
711 } |
|
712 break; |
|
713 } |
|
714 |
|
715 case WE_PAINT: { |
|
716 int j, x, y; |
|
717 CargoID i; |
|
718 GraphDrawer gd; |
|
719 |
|
720 DrawWindowWidgets(w); |
|
721 |
|
722 x = 495; |
|
723 y = 24; |
|
724 |
|
725 gd.sel = _legend_cargobits; |
|
726 gd.left = 2; |
|
727 gd.top = 24; |
|
728 gd.height = 104; |
|
729 gd.include_neg = false; |
|
730 gd.format_str_y_axis = STR_CURRCOMPACT; |
|
731 gd.color_3 = 16; |
|
732 gd.color_2 = 215; |
|
733 gd.bg_line_color = 14; |
|
734 gd.num_dataset = NUM_CARGO; |
|
735 gd.num_on_x_axis = 20; |
|
736 gd.num_vert_lines = 20; |
|
737 gd.month = 0xFF; |
|
738 gd.unk61A = 10; |
|
739 gd.unk61C = 10; |
|
740 |
|
741 for (i = 0; i != NUM_CARGO; i++) { |
|
742 /* Since the buttons have no text, no images, |
|
743 * both the text and the colored box have to be manually painted. |
|
744 * clk_dif will move one pixel down and one pixel to the right |
|
745 * when the button is clicked */ |
|
746 byte clk_dif = IsWindowWidgetLowered(w, i + 3) ? 1 : 0; |
|
747 |
|
748 GfxFillRect(x + clk_dif, y + clk_dif, x + 8 + clk_dif, y + 5 + clk_dif, 0); |
|
749 GfxFillRect(x + 1 + clk_dif, y + 1 + clk_dif, x + 7 + clk_dif, y + 4 + clk_dif, _cargo_colours[i]); |
|
750 SetDParam(0, _cargoc.names_s[i]); |
|
751 DrawString(x + 14 + clk_dif, y + clk_dif, STR_7065, 0); |
|
752 y += 8; |
|
753 gd.colors[i] = _cargo_colours[i]; |
|
754 for (j = 0; j != 20; j++) { |
|
755 gd.cost[i][j] = (uint64)GetTransportedGoodsIncome(10, 20, j * 6 + 6, i); |
|
756 } |
|
757 } |
|
758 |
|
759 DrawGraph(&gd); |
|
760 |
|
761 DrawString(2 + 46, 24 + gd.height + 7, STR_7062_DAYS_IN_TRANSIT, 0); |
|
762 DrawString(2 + 84, 24 - 9, STR_7063_PAYMENT_FOR_DELIVERING, 0); |
|
763 } break; |
|
764 |
|
765 case WE_CLICK: { |
|
766 switch (e->we.click.widget) { |
|
767 case 3: case 4: case 5: case 6: |
|
768 case 7: case 8: case 9: case 10: |
|
769 case 11: case 12: case 13: case 14: |
|
770 TOGGLEBIT(_legend_cargobits, e->we.click.widget - 3); |
|
771 ToggleWidgetLoweredState(w, e->we.click.widget); |
|
772 SetWindowDirty(w); |
|
773 break; |
|
774 } |
|
775 } break; |
|
776 } |
|
777 } |
|
778 |
|
779 static const Widget _cargo_payment_rates_widgets[] = { |
|
780 { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, |
|
781 { WWT_CAPTION, RESIZE_NONE, 14, 11, 567, 0, 13, STR_7061_CARGO_PAYMENT_RATES, STR_018C_WINDOW_TITLE_DRAG_THIS}, |
|
782 { WWT_PANEL, RESIZE_NONE, 14, 0, 567, 14, 141, 0x0, STR_NULL}, |
|
783 { WWT_PANEL, RESIZE_NONE, 12, 493, 562, 24, 31, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, |
|
784 { WWT_PANEL, RESIZE_NONE, 12, 493, 562, 32, 39, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, |
|
785 { WWT_PANEL, RESIZE_NONE, 12, 493, 562, 40, 47, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, |
|
786 { WWT_PANEL, RESIZE_NONE, 12, 493, 562, 48, 55, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, |
|
787 { WWT_PANEL, RESIZE_NONE, 12, 493, 562, 56, 63, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, |
|
788 { WWT_PANEL, RESIZE_NONE, 12, 493, 562, 64, 71, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, |
|
789 { WWT_PANEL, RESIZE_NONE, 12, 493, 562, 72, 79, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, |
|
790 { WWT_PANEL, RESIZE_NONE, 12, 493, 562, 80, 87, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, |
|
791 { WWT_PANEL, RESIZE_NONE, 12, 493, 562, 88, 95, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, |
|
792 { WWT_PANEL, RESIZE_NONE, 12, 493, 562, 96, 103, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, |
|
793 { WWT_PANEL, RESIZE_NONE, 12, 493, 562, 104, 111, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, |
|
794 { WWT_PANEL, RESIZE_NONE, 12, 493, 562, 112, 119, 0x0, STR_7064_TOGGLE_GRAPH_FOR_CARGO}, |
|
795 { WIDGETS_END}, |
|
796 }; |
|
797 |
|
798 static const WindowDesc _cargo_payment_rates_desc = { |
|
799 WDP_AUTO, WDP_AUTO, 568, 142, |
|
800 WC_PAYMENT_RATES,0, |
|
801 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, |
|
802 _cargo_payment_rates_widgets, |
|
803 CargoPaymentRatesWndProc |
|
804 }; |
|
805 |
|
806 |
|
807 void ShowCargoPaymentRates(void) |
|
808 { |
|
809 AllocateWindowDescFront(&_cargo_payment_rates_desc, 0); |
|
810 } |
|
811 |
|
812 /************************/ |
|
813 /* COMPANY LEAGUE TABLE */ |
|
814 /************************/ |
|
815 |
|
816 static const StringID _performance_titles[] = { |
|
817 STR_7066_ENGINEER, |
|
818 STR_7066_ENGINEER, |
|
819 STR_7067_TRAFFIC_MANAGER, |
|
820 STR_7067_TRAFFIC_MANAGER, |
|
821 STR_7068_TRANSPORT_COORDINATOR, |
|
822 STR_7068_TRANSPORT_COORDINATOR, |
|
823 STR_7069_ROUTE_SUPERVISOR, |
|
824 STR_7069_ROUTE_SUPERVISOR, |
|
825 STR_706A_DIRECTOR, |
|
826 STR_706A_DIRECTOR, |
|
827 STR_706B_CHIEF_EXECUTIVE, |
|
828 STR_706B_CHIEF_EXECUTIVE, |
|
829 STR_706C_CHAIRMAN, |
|
830 STR_706C_CHAIRMAN, |
|
831 STR_706D_PRESIDENT, |
|
832 STR_706E_TYCOON, |
|
833 }; |
|
834 |
|
835 static inline StringID GetPerformanceTitleFromValue(uint value) |
|
836 { |
|
837 return _performance_titles[minu(value, 1000) >> 6]; |
|
838 } |
|
839 |
|
840 static int CDECL PerfHistComp(const void* elem1, const void* elem2) |
|
841 { |
|
842 const Player* p1 = *(const Player* const*)elem1; |
|
843 const Player* p2 = *(const Player* const*)elem2; |
|
844 |
|
845 return p2->old_economy[1].performance_history - p1->old_economy[1].performance_history; |
|
846 } |
|
847 |
|
848 static void CompanyLeagueWndProc(Window *w, WindowEvent *e) |
|
849 { |
|
850 switch (e->event) { |
|
851 case WE_PAINT: { |
|
852 const Player* plist[MAX_PLAYERS]; |
|
853 const Player* p; |
|
854 uint pl_num; |
|
855 uint i; |
|
856 |
|
857 DrawWindowWidgets(w); |
|
858 |
|
859 pl_num = 0; |
|
860 FOR_ALL_PLAYERS(p) if (p->is_active) plist[pl_num++] = p; |
|
861 |
|
862 qsort((void*)plist, pl_num, sizeof(*plist), PerfHistComp); |
|
863 |
|
864 for (i = 0; i != pl_num; i++) { |
|
865 p = plist[i]; |
|
866 SetDParam(0, i + STR_01AC_1ST); |
|
867 SetDParam(1, p->name_1); |
|
868 SetDParam(2, p->name_2); |
|
869 SetDParam(3, GetPlayerNameString(p->index, 4)); |
|
870 SetDParam(5, GetPerformanceTitleFromValue(p->old_economy[1].performance_history)); |
|
871 |
|
872 DrawString(2, 15 + i * 10, i == 0 ? STR_7054 : STR_7055, 0); |
|
873 DrawPlayerIcon(p->index, 27, 16 + i * 10); |
|
874 } |
|
875 |
|
876 break; |
|
877 } |
|
878 } |
|
879 } |
|
880 |
|
881 |
|
882 static const Widget _company_league_widgets[] = { |
|
883 { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, |
|
884 { WWT_CAPTION, RESIZE_NONE, 14, 11, 387, 0, 13, STR_7053_COMPANY_LEAGUE_TABLE, STR_018C_WINDOW_TITLE_DRAG_THIS}, |
|
885 { WWT_STICKYBOX, RESIZE_NONE, 14, 388, 399, 0, 13, STR_NULL, STR_STICKY_BUTTON}, |
|
886 { WWT_PANEL, RESIZE_NONE, 14, 0, 399, 14, 96, 0x0, STR_NULL}, |
|
887 { WIDGETS_END}, |
|
888 }; |
|
889 |
|
890 static const WindowDesc _company_league_desc = { |
|
891 WDP_AUTO, WDP_AUTO, 400, 97, |
|
892 WC_COMPANY_LEAGUE,0, |
|
893 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON, |
|
894 _company_league_widgets, |
|
895 CompanyLeagueWndProc |
|
896 }; |
|
897 |
|
898 void ShowCompanyLeagueTable(void) |
|
899 { |
|
900 AllocateWindowDescFront(&_company_league_desc,0); |
|
901 } |
|
902 |
|
903 /*****************************/ |
|
904 /* PERFORMANCE RATING DETAIL */ |
|
905 /*****************************/ |
|
906 |
|
907 static void PerformanceRatingDetailWndProc(Window *w, WindowEvent *e) |
|
908 { |
|
909 static PlayerID _performance_rating_detail_player = 0; |
|
910 |
|
911 switch (e->event) { |
|
912 case WE_PAINT: { |
|
913 int i; |
|
914 byte x; |
|
915 uint16 y = 14; |
|
916 int total_score = 0; |
|
917 int color_done, color_notdone; |
|
918 |
|
919 // Draw standard stuff |
|
920 DrawWindowWidgets(w); |
|
921 |
|
922 // Paint the player icons |
|
923 for (i = 0; i < MAX_PLAYERS; i++) { |
|
924 if (!GetPlayer(i)->is_active) { |
|
925 // Check if we have the player as an active player |
|
926 if (!IsWindowWidgetDisabled(w, i + 13)) { |
|
927 // Bah, player gone :( |
|
928 DisableWindowWidget(w, i + 13); |
|
929 // Is this player selected? If so, select first player (always save? :s) |
|
930 if (IsWindowWidgetLowered(w, i + 13)) { |
|
931 RaiseWindowWidget(w, i + 13); |
|
932 LowerWindowWidget(w, 13); |
|
933 _performance_rating_detail_player = 0; |
|
934 } |
|
935 // We need a repaint |
|
936 SetWindowDirty(w); |
|
937 } |
|
938 continue; |
|
939 } |
|
940 |
|
941 // Check if we have the player marked as inactive |
|
942 if (IsWindowWidgetDisabled(w, i + 13)) { |
|
943 // New player! Yippie :p |
|
944 EnableWindowWidget(w, i + 13); |
|
945 // We need a repaint |
|
946 SetWindowDirty(w); |
|
947 } |
|
948 |
|
949 x = (i == _performance_rating_detail_player) ? 1 : 0; |
|
950 DrawPlayerIcon(i, i * 37 + 13 + x, 16 + x); |
|
951 } |
|
952 |
|
953 // The colors used to show how the progress is going |
|
954 color_done = _colour_gradient[COLOUR_GREEN][4]; |
|
955 color_notdone = _colour_gradient[COLOUR_RED][4]; |
|
956 |
|
957 // Draw all the score parts |
|
958 for (i = 0; i < NUM_SCORE; i++) { |
|
959 int val = _score_part[_performance_rating_detail_player][i]; |
|
960 int needed = _score_info[i].needed; |
|
961 int score = _score_info[i].score; |
|
962 |
|
963 y += 20; |
|
964 // SCORE_TOTAL has his own rulez ;) |
|
965 if (i == SCORE_TOTAL) { |
|
966 needed = total_score; |
|
967 score = SCORE_MAX; |
|
968 } else { |
|
969 total_score += score; |
|
970 } |
|
971 |
|
972 DrawString(7, y, STR_PERFORMANCE_DETAIL_VEHICLES + i, 0); |
|
973 |
|
974 // Draw the score |
|
975 SetDParam(0, score); |
|
976 DrawStringRightAligned(107, y, SET_PERFORMANCE_DETAIL_INT, 0); |
|
977 |
|
978 // Calculate the %-bar |
|
979 if (val > needed) { |
|
980 x = 50; |
|
981 } else if (val == 0) { |
|
982 x = 0; |
|
983 } else { |
|
984 x = val * 50 / needed; |
|
985 } |
|
986 |
|
987 // SCORE_LOAN is inversed |
|
988 if (val < 0 && i == SCORE_LOAN) x = 0; |
|
989 |
|
990 // Draw the bar |
|
991 if (x != 0) GfxFillRect(112, y - 2, 112 + x, y + 10, color_done); |
|
992 if (x != 50) GfxFillRect(112 + x, y - 2, 112 + 50, y + 10, color_notdone); |
|
993 |
|
994 // Calculate the % |
|
995 x = (val <= needed) ? val * 100 / needed : 100; |
|
996 |
|
997 // SCORE_LOAN is inversed |
|
998 if (val < 0 && i == SCORE_LOAN) x = 0; |
|
999 |
|
1000 // Draw it |
|
1001 SetDParam(0, x); |
|
1002 DrawStringCentered(137, y, STR_PERFORMANCE_DETAIL_PERCENT, 0); |
|
1003 |
|
1004 // SCORE_LOAN is inversed |
|
1005 if (i == SCORE_LOAN) val = needed - val; |
|
1006 |
|
1007 // Draw the amount we have against what is needed |
|
1008 // For some of them it is in currency format |
|
1009 SetDParam(0, val); |
|
1010 SetDParam(1, needed); |
|
1011 switch (i) { |
|
1012 case SCORE_MIN_PROFIT: |
|
1013 case SCORE_MIN_INCOME: |
|
1014 case SCORE_MAX_INCOME: |
|
1015 case SCORE_MONEY: |
|
1016 case SCORE_LOAN: |
|
1017 DrawString(167, y, STR_PERFORMANCE_DETAIL_AMOUNT_CURRENCY, 0); |
|
1018 break; |
|
1019 default: |
|
1020 DrawString(167, y, STR_PERFORMANCE_DETAIL_AMOUNT_INT, 0); |
|
1021 } |
|
1022 } |
|
1023 |
|
1024 break; |
|
1025 } |
|
1026 |
|
1027 case WE_CLICK: |
|
1028 // Check which button is clicked |
|
1029 if (IS_INT_INSIDE(e->we.click.widget, 13, 21)) { |
|
1030 // Is it no on disable? |
|
1031 if (!IsWindowWidgetDisabled(w, e->we.click.widget)) { |
|
1032 RaiseWindowWidget(w, _performance_rating_detail_player + 13); |
|
1033 _performance_rating_detail_player = e->we.click.widget - 13; |
|
1034 LowerWindowWidget(w, _performance_rating_detail_player + 13); |
|
1035 SetWindowDirty(w); |
|
1036 } |
|
1037 } |
|
1038 break; |
|
1039 |
|
1040 case WE_CREATE: { |
|
1041 int i; |
|
1042 Player *p2; |
|
1043 |
|
1044 /* Disable the players who are not active */ |
|
1045 for (i = 0; i < MAX_PLAYERS; i++) { |
|
1046 SetWindowWidgetDisabledState(w, i + 13, !GetPlayer(i)->is_active); |
|
1047 } |
|
1048 /* Update all player stats with the current data |
|
1049 * (this is because _score_info is not saved to a savegame) */ |
|
1050 FOR_ALL_PLAYERS(p2) { |
|
1051 if (p2->is_active) UpdateCompanyRatingAndValue(p2, false); |
|
1052 } |
|
1053 |
|
1054 w->custom[0] = DAY_TICKS; |
|
1055 w->custom[1] = 5; |
|
1056 |
|
1057 _performance_rating_detail_player = 0; |
|
1058 LowerWindowWidget(w, _performance_rating_detail_player + 13); |
|
1059 SetWindowDirty(w); |
|
1060 |
|
1061 break; |
|
1062 } |
|
1063 |
|
1064 case WE_TICK: { |
|
1065 // Update the player score every 5 days |
|
1066 if (--w->custom[0] == 0) { |
|
1067 w->custom[0] = DAY_TICKS; |
|
1068 if (--w->custom[1] == 0) { |
|
1069 Player *p2; |
|
1070 |
|
1071 w->custom[1] = 5; |
|
1072 FOR_ALL_PLAYERS(p2) { |
|
1073 // Skip if player is not active |
|
1074 if (p2->is_active) UpdateCompanyRatingAndValue(p2, false); |
|
1075 } |
|
1076 SetWindowDirty(w); |
|
1077 } |
|
1078 } |
|
1079 |
|
1080 break; |
|
1081 } |
|
1082 } |
|
1083 } |
|
1084 |
|
1085 static const Widget _performance_rating_detail_widgets[] = { |
|
1086 { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, |
|
1087 { WWT_CAPTION, RESIZE_NONE, 14, 11, 298, 0, 13, STR_PERFORMANCE_DETAIL, STR_018C_WINDOW_TITLE_DRAG_THIS}, |
|
1088 { WWT_PANEL, RESIZE_NONE, 14, 0, 298, 14, 27, 0x0, STR_NULL}, |
|
1089 |
|
1090 { WWT_PANEL, RESIZE_NONE, 14, 0, 298, 28, 47, 0x0, STR_PERFORMANCE_DETAIL_VEHICLES_TIP}, |
|
1091 { WWT_PANEL, RESIZE_NONE, 14, 0, 298, 48, 67, 0x0, STR_PERFORMANCE_DETAIL_STATIONS_TIP}, |
|
1092 { WWT_PANEL, RESIZE_NONE, 14, 0, 298, 68, 87, 0x0, STR_PERFORMANCE_DETAIL_MIN_PROFIT_TIP}, |
|
1093 { WWT_PANEL, RESIZE_NONE, 14, 0, 298, 88, 107, 0x0, STR_PERFORMANCE_DETAIL_MIN_INCOME_TIP}, |
|
1094 { WWT_PANEL, RESIZE_NONE, 14, 0, 298, 108, 127, 0x0, STR_PERFORMANCE_DETAIL_MAX_INCOME_TIP}, |
|
1095 { WWT_PANEL, RESIZE_NONE, 14, 0, 298, 128, 147, 0x0, STR_PERFORMANCE_DETAIL_DELIVERED_TIP}, |
|
1096 { WWT_PANEL, RESIZE_NONE, 14, 0, 298, 148, 167, 0x0, STR_PERFORMANCE_DETAIL_CARGO_TIP}, |
|
1097 { WWT_PANEL, RESIZE_NONE, 14, 0, 298, 168, 187, 0x0, STR_PERFORMANCE_DETAIL_MONEY_TIP}, |
|
1098 { WWT_PANEL, RESIZE_NONE, 14, 0, 298, 188, 207, 0x0, STR_PERFORMANCE_DETAIL_LOAN_TIP}, |
|
1099 { WWT_PANEL, RESIZE_NONE, 14, 0, 298, 208, 227, 0x0, STR_PERFORMANCE_DETAIL_TOTAL_TIP}, |
|
1100 |
|
1101 { WWT_PANEL, RESIZE_NONE, 14, 2, 38, 14, 26, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, |
|
1102 { WWT_PANEL, RESIZE_NONE, 14, 39, 75, 14, 26, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, |
|
1103 { WWT_PANEL, RESIZE_NONE, 14, 76, 112, 14, 26, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, |
|
1104 { WWT_PANEL, RESIZE_NONE, 14, 113, 149, 14, 26, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, |
|
1105 { WWT_PANEL, RESIZE_NONE, 14, 150, 186, 14, 26, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, |
|
1106 { WWT_PANEL, RESIZE_NONE, 14, 187, 223, 14, 26, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, |
|
1107 { WWT_PANEL, RESIZE_NONE, 14, 224, 260, 14, 26, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, |
|
1108 { WWT_PANEL, RESIZE_NONE, 14, 261, 297, 14, 26, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, |
|
1109 { WIDGETS_END}, |
|
1110 }; |
|
1111 |
|
1112 static const WindowDesc _performance_rating_detail_desc = { |
|
1113 WDP_AUTO, WDP_AUTO, 299, 228, |
|
1114 WC_PERFORMANCE_DETAIL,0, |
|
1115 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, |
|
1116 _performance_rating_detail_widgets, |
|
1117 PerformanceRatingDetailWndProc |
|
1118 }; |
|
1119 |
|
1120 void ShowPerformanceRatingDetail(void) |
|
1121 { |
|
1122 AllocateWindowDescFront(&_performance_rating_detail_desc, 0); |
|
1123 } |
|
1124 |
|
1125 |
|
1126 static const Sign **_sign_sort; |
|
1127 static uint _num_sign_sort; |
|
1128 |
|
1129 static char _bufcache[64]; |
|
1130 static const Sign *_last_sign; |
|
1131 |
|
1132 static int CDECL SignNameSorter(const void *a, const void *b) |
|
1133 { |
|
1134 const Sign *sign0 = *(const Sign**)a; |
|
1135 const Sign *sign1 = *(const Sign**)b; |
|
1136 char buf1[64]; |
|
1137 |
|
1138 GetString(buf1, sign0->str, lastof(buf1)); |
|
1139 |
|
1140 if (sign1 != _last_sign) { |
|
1141 _last_sign = sign1; |
|
1142 GetString(_bufcache, sign1->str, lastof(_bufcache)); |
|
1143 } |
|
1144 |
|
1145 return strcmp(buf1, _bufcache); // sort by name |
|
1146 } |
|
1147 |
|
1148 static void GlobalSortSignList(void) |
|
1149 { |
|
1150 const Sign *si; |
|
1151 uint n = 0; |
|
1152 |
|
1153 /* Create array for sorting */ |
|
1154 _sign_sort = realloc((void *)_sign_sort, (GetMaxSignIndex() + 1)* sizeof(_sign_sort[0])); |
|
1155 if (_sign_sort == NULL) error("Could not allocate memory for the sign-sorting-list"); |
|
1156 |
|
1157 FOR_ALL_SIGNS(si) _sign_sort[n++] = si; |
|
1158 _num_sign_sort = n; |
|
1159 |
|
1160 qsort((void*)_sign_sort, n, sizeof(_sign_sort[0]), SignNameSorter); |
|
1161 |
|
1162 _sign_sort_dirty = false; |
|
1163 |
|
1164 DEBUG(misc, 3, "Resorting global signs list"); |
|
1165 } |
|
1166 |
|
1167 static void SignListWndProc(Window *w, WindowEvent *e) |
|
1168 { |
|
1169 switch (e->event) { |
|
1170 case WE_PAINT: { |
|
1171 int y = 16; // offset from top of widget |
|
1172 |
|
1173 if (_sign_sort_dirty) |
|
1174 GlobalSortSignList(); |
|
1175 |
|
1176 SetVScrollCount(w, _num_sign_sort); |
|
1177 |
|
1178 SetDParam(0, w->vscroll.count); |
|
1179 DrawWindowWidgets(w); |
|
1180 |
|
1181 /* No signs? */ |
|
1182 if (w->vscroll.count == 0) { |
|
1183 DrawString(2, y, STR_304A_NONE, 0); |
|
1184 return; |
|
1185 } |
|
1186 |
|
1187 { |
|
1188 uint16 i; |
|
1189 |
|
1190 /* Start drawing the signs */ |
|
1191 for (i = w->vscroll.pos; i < w->vscroll.cap + w->vscroll.pos && i < w->vscroll.count; i++) { |
|
1192 const Sign *si = _sign_sort[i]; |
|
1193 |
|
1194 if (si->owner != OWNER_NONE) |
|
1195 DrawPlayerIcon(si->owner, 4, y + 1); |
|
1196 |
|
1197 DrawString(22, y, si->str, 8); |
|
1198 y += 10; |
|
1199 } |
|
1200 } |
|
1201 } break; |
|
1202 |
|
1203 case WE_CLICK: { |
|
1204 switch (e->we.click.widget) { |
|
1205 case 3: { |
|
1206 uint32 id_v = (e->we.click.pt.y - 15) / 10; |
|
1207 const Sign *si; |
|
1208 |
|
1209 if (id_v >= w->vscroll.cap) |
|
1210 return; |
|
1211 |
|
1212 id_v += w->vscroll.pos; |
|
1213 |
|
1214 if (id_v >= w->vscroll.count) |
|
1215 return; |
|
1216 |
|
1217 si = _sign_sort[id_v]; |
|
1218 ScrollMainWindowToTile(TileVirtXY(si->x, si->y)); |
|
1219 } break; |
|
1220 } |
|
1221 } break; |
|
1222 |
|
1223 case WE_RESIZE: |
|
1224 w->vscroll.cap += e->we.sizing.diff.y / 10; |
|
1225 break; |
|
1226 } |
|
1227 } |
|
1228 |
|
1229 static const Widget _sign_list_widget[] = { |
|
1230 { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, |
|
1231 { WWT_CAPTION, RESIZE_RIGHT, 14, 11, 345, 0, 13, STR_SIGN_LIST_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, |
|
1232 { WWT_STICKYBOX, RESIZE_LR, 14, 346, 357, 0, 13, 0x0, STR_STICKY_BUTTON}, |
|
1233 { WWT_PANEL, RESIZE_RB, 14, 0, 345, 14, 137, 0x0, STR_NULL}, |
|
1234 { WWT_SCROLLBAR, RESIZE_LRB, 14, 346, 357, 14, 125, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, |
|
1235 { WWT_RESIZEBOX, RESIZE_LRTB, 14, 346, 357, 126, 137, 0x0, STR_RESIZE_BUTTON}, |
|
1236 { WIDGETS_END}, |
|
1237 }; |
|
1238 |
|
1239 static const WindowDesc _sign_list_desc = { |
|
1240 WDP_AUTO, WDP_AUTO, 358, 138, |
|
1241 WC_SIGN_LIST,0, |
|
1242 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON | WDF_RESIZABLE, |
|
1243 _sign_list_widget, |
|
1244 SignListWndProc |
|
1245 }; |
|
1246 |
|
1247 |
|
1248 void ShowSignList(void) |
|
1249 { |
|
1250 Window *w; |
|
1251 |
|
1252 w = AllocateWindowDescFront(&_sign_list_desc, 0); |
|
1253 if (w != NULL) { |
|
1254 w->vscroll.cap = 12; |
|
1255 w->resize.step_height = 10; |
|
1256 w->resize.height = w->height - 10 * 7; // minimum if 5 in the list |
|
1257 } |
|
1258 } |