1 /*
2 * Copyright (c) 1997 - 2001 Hj. Malthaner
3 *
4 * This file is part of the Simutrans project under the artistic licence.
5 * (see licence.txt)
6 */
7
8 /*
9 * The depot window, where to buy convois
10 */
11
12 #include <algorithm>
13 #include <stdio.h>
14 #include <string.h>
15
16 #include "../simunits.h"
17 #include "../simworld.h"
18 #include "../vehicle/simvehicle.h"
19 #include "../simconvoi.h"
20 #include "../simdepot.h"
21 #include "simwin.h"
22 #include "../simcolor.h"
23 #include "../simdebug.h"
24 #include "../display/simgraph.h"
25 #include "../display/viewport.h"
26 #include "../simline.h"
27 #include "../simlinemgmt.h"
28 #include "../simmenu.h"
29 #include "../simskin.h"
30
31 #include "../tpl/slist_tpl.h"
32
33 #include "schedule_gui.h"
34 #include "line_management_gui.h"
35 #include "line_item.h"
36 #include "convoy_item.h"
37 #include "components/gui_image_list.h"
38 #include "messagebox.h"
39 #include "depot_frame.h"
40 #include "schedule_list.h"
41
42 #include "../descriptor/goods_desc.h"
43 #include "../descriptor/intro_dates.h"
44 #include "../bauer/vehikelbauer.h"
45 #include "../dataobj/schedule.h"
46 #include "../dataobj/translator.h"
47 #include "../dataobj/environment.h"
48
49 #include "../player/simplay.h"
50
51 #include "../utils/simstring.h"
52 #include "../utils/cbuffer_t.h"
53 #include "../utils/simrandom.h"
54
55 #include "../bauer/goods_manager.h"
56
57 #include "../boden/wege/weg.h"
58
59
60 char depot_frame_t::name_filter_value[64] = "";
61
62 static const char* engine_type_names[9] =
63 {
64 "unknown",
65 "steam",
66 "diesel",
67 "electric",
68 "bio",
69 "sail",
70 "fuel_cell",
71 "hydrogene",
72 "battery"
73 };
74
75 static int sort_by_action;
76
77 bool depot_frame_t::show_retired_vehicles = false;
78 bool depot_frame_t::show_all = true;
79
depot_frame_t(depot_t * depot)80 depot_frame_t::depot_frame_t(depot_t* depot) :
81 gui_frame_t("", NULL),
82 depot(depot),
83 icnv(-1),
84 lb_convoi_line("Serves Line:", SYSCOL_TEXT, gui_label_t::left),
85 lb_sort_by("Sort by:", SYSCOL_TEXT, gui_label_t::right),
86 lb_name_filter_input("Search:", SYSCOL_TEXT, gui_label_t::right),
87 lb_veh_action("Fahrzeuge:", SYSCOL_TEXT, gui_label_t::right),
88 convoi(&convoi_pics),
89 scrolly_convoi(&cont_convoi),
90 pas(&pas_vec),
91 electrics(&electrics_vec),
92 loks(&loks_vec),
93 waggons(&waggons_vec),
94 scrolly_pas(&pas),
95 scrolly_electrics(&electrics),
96 scrolly_loks(&loks),
97 scrolly_waggons(&waggons),
98 line_selector(line_scrollitem_t::compare),
99 lb_vehicle_filter("Filter:", SYSCOL_TEXT, gui_label_t::right)
100 {
101 if (depot) {
102 init(depot);
103 }
104 }
105
init(depot_t * dep)106 void depot_frame_t::init(depot_t *dep)
107 {
108 depot = dep;
109 set_name(translator::translate(depot->get_name()));
110 set_owner(depot->get_owner());
111 icnv = depot->convoi_count()-1;
112
113 scr_size size = scr_size(0,0);
114
115 DBG_DEBUG("depot_frame_t::depot_frame_t()","get_max_convoi_length()=%i",depot->get_max_convoi_length());
116 last_selected_line = depot->get_last_selected_line();
117 no_schedule_text = translator::translate("<no schedule set>");
118 clear_schedule_text = translator::translate("<clear schedule>");
119 unique_schedule_text = translator::translate("<individual schedule>");
120 new_line_text = translator::translate("<create new line>");
121 line_seperator = translator::translate("--------------------------------");
122 new_convoy_text = translator::translate("new convoi");
123 promote_to_line_text = translator::translate("<promote to line>");
124
125 /*
126 * [SELECT]:
127 */
128 add_component(&lb_convois);
129
130 convoy_selector.add_listener(this);
131 add_component(&convoy_selector);
132
133 /*
134 * [SELECT ROUTE]:
135 */
136 line_selector.add_listener(this);
137 line_selector.set_wrapping(false);
138 add_component(&line_selector);
139
140 // goto line button
141 line_button.set_typ(button_t::posbutton);
142 line_button.set_targetpos(koord(0,0));
143 line_button.add_listener(this);
144 add_component(&line_button);
145
146 /*
147 * [CONVOI]
148 */
149 convoi.set_player_nr(depot->get_player_nr());
150 convoi.add_listener(this);
151
152 cont_convoi.add_component(&lb_convoi_number);
153 cont_convoi.add_component(&convoi);
154
155 // add_component(&convoi);
156
157 add_component(&lb_convoi_count);
158 add_component(&lb_convoi_speed);
159 add_component(&lb_convoi_cost);
160 add_component(&lb_convoi_value);
161 add_component(&lb_convoi_line);
162 add_component(&lb_convoi_power);
163 add_component(&lb_convoi_weight);
164 add_component(&cont_convoi_capacity);
165
166 sb_convoi_length.set_base( depot->get_max_convoi_length() * CARUNITS_PER_TILE / 2 - 1);
167 sb_convoi_length.set_vertical(false);
168 convoi_length_ok_sb = 0;
169 convoi_length_slower_sb = 0;
170 convoi_length_too_slow_sb = 0;
171 convoi_tile_length_sb = 0;
172 new_vehicle_length_sb = 0;
173 if( depot->get_max_convoi_length() > 1 ) { // no convoy length bar for ships or aircraft
174 sb_convoi_length.add_color_value(&convoi_tile_length_sb, color_idx_to_rgb(COL_BROWN));
175 sb_convoi_length.add_color_value(&new_vehicle_length_sb, color_idx_to_rgb(COL_DARK_GREEN));
176 sb_convoi_length.add_color_value(&convoi_length_ok_sb, color_idx_to_rgb(COL_GREEN));
177 sb_convoi_length.add_color_value(&convoi_length_slower_sb, color_idx_to_rgb(COL_ORANGE));
178 sb_convoi_length.add_color_value(&convoi_length_too_slow_sb, color_idx_to_rgb(COL_RED));
179 cont_convoi.add_component(&sb_convoi_length);
180 }
181
182 scrolly_convoi.set_scrollbar_mode(scrollbar_t::show_disabled);
183 scrolly_convoi.set_size_corner(false);
184 add_component(&scrolly_convoi);
185
186 /*
187 * [ACTIONS]
188 */
189 bt_start.set_typ(button_t::roundbox);
190 bt_start.add_listener(this);
191 bt_start.set_tooltip("Start the selected vehicle(s)");
192 add_component(&bt_start);
193
194 bt_schedule.set_typ(button_t::roundbox);
195 bt_schedule.add_listener(this);
196 bt_schedule.set_tooltip("Give the selected vehicle(s) an individual schedule"); // translated to "Edit the selected vehicle(s) individual schedule or assigned line"
197 add_component(&bt_schedule);
198
199 bt_copy_convoi.set_typ(button_t::roundbox);
200 bt_copy_convoi.add_listener(this);
201 bt_copy_convoi.set_tooltip("Copy the selected convoi and its schedule or line");
202 add_component(&bt_copy_convoi);
203
204 bt_sell.set_typ(button_t::roundbox);
205 bt_sell.add_listener(this);
206 bt_sell.set_tooltip("Sell the selected vehicle(s)");
207 add_component(&bt_sell);
208
209 /*
210 * [PANEL]
211 */
212 pas.set_player_nr(depot->get_player_nr());
213 pas.add_listener(this);
214
215 electrics.set_player_nr(depot->get_player_nr());
216 electrics.add_listener(this);
217
218 loks.set_player_nr(depot->get_player_nr());
219 loks.add_listener(this);
220
221 waggons.set_player_nr(depot->get_player_nr());
222 waggons.add_listener(this);
223
224 add_component(&tabs);
225 add_component(&div_tabbottom);
226 add_component(&lb_veh_action);
227 add_component(&lb_sort_by);
228 add_component(&lb_name_filter_input);
229 add_component(&lb_vehicle_filter);
230 add_component(&div_action_bottom);
231
232 veh_action = va_append;
233 bt_veh_action.set_typ(button_t::roundbox);
234 bt_veh_action.add_listener(this);
235 bt_veh_action.set_tooltip("Choose operation executed on clicking stored/new vehicles");
236 add_component(&bt_veh_action);
237
238 bt_show_all.set_typ(button_t::square_state);
239 bt_show_all.set_text("Show all");
240 bt_show_all.add_listener(this);
241 bt_show_all.set_tooltip("Show also vehicles that do not match for current action.");
242 bt_show_all.pressed = show_all;
243 add_component(&bt_show_all);
244
245 bt_obsolete.set_typ(button_t::square_state);
246 bt_obsolete.set_text("Show obsolete");
247 bt_obsolete.pressed = show_retired_vehicles;
248 if( welt->get_settings().get_allow_buying_obsolete_vehicles() ) {
249 bt_obsolete.add_listener(this);
250 bt_obsolete.set_tooltip("Show also vehicles no longer in production.");
251 add_component(&bt_obsolete);
252 }
253
254 sort_by.add_listener(this);
255 add_component(&sort_by);
256
257 vehicle_filter.add_listener(this);
258 add_component(&vehicle_filter);
259
260 name_filter_input.set_text(name_filter_value, 60);
261 add_component(&name_filter_input);
262 name_filter_input.add_listener(this);
263
264 build_vehicle_lists();
265
266 // text will be translated by ourselves (after update data)!
267 lb_convois.set_text_pointer( txt_convois );
268 lb_convoi_number.set_text_pointer( txt_convoi_number );
269 lb_convoi_count.set_text_pointer( txt_convoi_count );
270 lb_convoi_speed.set_text_pointer( txt_convoi_speed );
271 lb_convoi_cost.set_text_pointer( txt_convoi_cost );
272 lb_convoi_value.set_text_pointer( txt_convoi_value );
273 lb_convoi_power.set_text_pointer( txt_convoi_power );
274 lb_convoi_weight.set_text_pointer( txt_convoi_weight );
275
276 // Bolt image for electrified depots:
277 add_component(&img_bolt);
278
279 scrolly_pas.set_scrollbar_mode ( scrollbar_t::show_disabled );
280 scrolly_pas.set_size_corner(false);
281 scrolly_electrics.set_scrollbar_mode ( scrollbar_t::show_disabled );
282 scrolly_electrics.set_size_corner(false);
283 scrolly_loks.set_scrollbar_mode ( scrollbar_t::show_disabled );
284 scrolly_loks.set_size_corner(false);
285 scrolly_waggons.set_scrollbar_mode ( scrollbar_t::show_disabled );
286 scrolly_waggons.set_size_corner(false);
287
288 layout(&size);
289 gui_frame_t::set_windowsize(size);
290 set_resizemode( diagonal_resize );
291
292 depot->clear_command_pending();
293 }
294
295
296 // free memory: all the image_data_t
~depot_frame_t()297 depot_frame_t::~depot_frame_t()
298 {
299 clear_ptr_vector(pas_vec);
300 clear_ptr_vector(electrics_vec);
301 clear_ptr_vector(loks_vec);
302 clear_ptr_vector(waggons_vec);
303 }
304
305
306 // returns position of depot on the map
get_weltpos(bool)307 koord3d depot_frame_t::get_weltpos(bool)
308 {
309 return depot->get_pos();
310 }
311
312
is_weltpos()313 bool depot_frame_t::is_weltpos()
314 {
315 return ( welt->get_viewport()->is_on_center( get_weltpos(false) ) );
316 }
317
318
layout(scr_size * size)319 void depot_frame_t::layout(scr_size *size)
320 {
321 scr_coord placement;
322 scr_coord grid;
323 scr_coord_val grid_dx;
324 scr_coord_val placement_dx;
325
326 /*
327 * These parameter are adjusted to resolution.
328 * - Some extra space looks nicer.
329 */
330 grid.x = depot->get_x_grid() * get_base_tile_raster_width() / 64 + 4;
331 grid.y = depot->get_y_grid() * get_base_tile_raster_width() / 64 + 6;
332 placement.x = depot->get_x_placement() * get_base_tile_raster_width() / 64 + 2;
333 placement.y = depot->get_y_placement() * get_base_tile_raster_width() / 64 + 2;
334 grid_dx = depot->get_x_grid() * get_base_tile_raster_width() / 64 / 2;
335 placement_dx = depot->get_x_grid() * get_base_tile_raster_width() / 64 / 4;
336
337 // calculate some useful default width first (since everything depends on width)
338 scr_size win_size = (size != NULL) ? *size : get_windowsize();
339 if (win_size.w <= 0) {
340 win_size.w = max(D_DEFAULT_WIDTH,(grid.x - grid_dx)*18);
341 win_size.h = 0;
342 }
343 if (size && size->w == 0) {
344 size->w = D_DEFAULT_WIDTH;
345 }
346
347 /*
348 * Dialog format:
349 *
350 * Main structure are these parts from top to bottom:
351 *
352 * [SELECT] convoi-selector
353 * [CONVOI] current convoi
354 * [ACTIONS] convoi action buttons
355 * [PANEL] vehicle panel
356 * [VINFO] vehicle infotext
357 *
358 *
359 * Structure of [SELECT] is:
360 *
361 * [Info]
362 * [PREV][LABEL][NEXT]
363 *
364 * PREV and NEXT are small buttons - Label is adjusted to total width.
365 */
366 const scr_coord_val SELECT_HEIGHT = D_BUTTON_HEIGHT;
367 const scr_coord_val selector_x = max(max(max(max(max(102, proportional_string_width(translator::translate("no convois")) + 4),
368 proportional_string_width(translator::translate("1 convoi")) + 4),
369 proportional_string_width(translator::translate("%d convois")) + 4),
370 proportional_string_width(translator::translate("convoi %d of %d")) + 4),
371 line_button.get_size().w + 2 + proportional_string_width(translator::translate(lb_convoi_line.get_text_pointer())) + 4
372 );
373
374 const scr_coord_val BUTTON_WIDTH_DEPOT = max(D_BUTTON_WIDTH,(win_size.w - D_MARGIN_LEFT - D_MARGIN_RIGHT - 4*D_H_SPACE) / 4);
375
376 /*
377 * Structure of [CONVOI] is a image_list and an infos:
378 *
379 * [List]
380 * [Info]
381 *
382 * The image list is horizontally "condensed".
383 */
384 const scr_coord_val CLIST_WIDTH = depot->get_max_convoi_length() * (grid.x - grid_dx) + 2 * gui_image_list_t::BORDER;
385 const scr_coord_val CLIST_HEIGHT = grid.y + 2 * gui_image_list_t::BORDER + 5;
386 const scr_coord_val CINFO_HEIGHT = LINESPACE * 3 + D_BUTTON_HEIGHT + 1;
387
388 /*
389 * Structure of [ACTIONS] is a row of buttons:
390 *
391 * [Start][Schedule][Destroy][Sell]
392 * [new Route][change Route][delete Route]
393 */
394 /*
395 * Structure of [VINFO] is one multiline text.
396 */
397 const scr_coord_val VINFO_HEIGHT = 7*LINESPACE + D_BUTTON_HEIGHT + D_EDIT_HEIGHT + 5*D_V_SPACE;
398
399 /*
400 * Now we can do the first vertical adjustment:
401 * Calculate position of each element to tabs.
402 */
403 const scr_coord_val SELECT_VSTART = D_MARGIN_TOP;
404 const scr_coord_val CONVOI_VSTART = SELECT_VSTART + SELECT_HEIGHT + LINESPACE + D_V_SPACE;
405 const scr_coord_val CINFO_VSTART = CONVOI_VSTART + CLIST_HEIGHT + D_SCROLLBAR_HEIGHT*(CLIST_WIDTH >= win_size.w-D_MARGIN_LEFT-D_MARGIN_RIGHT);
406 const scr_coord_val ACTIONS_VSTART = CINFO_VSTART + CINFO_HEIGHT;
407 const scr_coord_val PANEL_VSTART = ACTIONS_VSTART + D_BUTTON_HEIGHT;
408
409 /*
410 * Now we determine the row/col layout for the panel and the total panel
411 * size.
412 * build_vehicle_lists() fills loks_vec and waggon_vec.
413 * Total width will be expanded to match complete columns in panel.
414 */
415 const scr_coord_val TAB_HEADER_HEIGHT = tabs.get_required_size().h;
416 const scr_coord_val total_h = PANEL_VSTART + VINFO_HEIGHT + D_TITLEBAR_HEIGHT + TAB_HEADER_HEIGHT + 2 * gui_image_list_t::BORDER + D_MARGIN_BOTTOM + 1;
417 scr_coord_val PANEL_ROWS = max(1, ((win_size.h - total_h) / grid.y));
418 if (size && size->h == 0) {
419 PANEL_ROWS = 3;
420 }
421 const scr_coord_val PANEL_HEIGHT = PANEL_ROWS * grid.y + TAB_HEADER_HEIGHT + 2 * gui_image_list_t::BORDER;
422 const scr_coord_val MIN_PANEL_HEIGHT = grid.y + TAB_HEADER_HEIGHT + 2 * gui_image_list_t::BORDER;
423 const scr_coord_val INFO_VSTART = PANEL_VSTART + PANEL_HEIGHT + div_tabbottom.get_size().h;
424
425 /*
426 * Now we can do the complete vertical adjustment:
427 */
428 const scr_coord_val TOTAL_HEIGHT = PANEL_VSTART + PANEL_HEIGHT + D_V_SPACE + VINFO_HEIGHT + D_TITLEBAR_HEIGHT + 1 + D_MARGIN_BOTTOM;
429 const scr_coord_val MIN_TOTAL_HEIGHT = PANEL_VSTART + MIN_PANEL_HEIGHT + D_V_SPACE + VINFO_HEIGHT + D_TITLEBAR_HEIGHT + 1 + D_MARGIN_BOTTOM;
430
431 // now we know also the height, so we can set the size of the whole dialogue
432 if( win_size.h <= 0 ) {
433 // set default size on first call
434 win_size.h = TOTAL_HEIGHT;
435 }
436 win_size.h = max(win_size.h, MIN_TOTAL_HEIGHT);
437 if( size ) {
438 *size = win_size;
439 }
440 gui_frame_t::set_windowsize(win_size);
441 set_min_windowsize(scr_size(D_DEFAULT_WIDTH, MIN_TOTAL_HEIGHT));
442
443 /*
444 * DONE with layout planning - now build everything.
445 */
446
447 /*
448 * [SELECT]:
449 */
450 lb_convois.set_pos(scr_coord(D_MARGIN_LEFT, SELECT_VSTART + 3));
451 lb_convois.set_width(selector_x - D_H_SPACE);
452
453 convoy_selector.set_pos(scr_coord(D_MARGIN_LEFT + selector_x, SELECT_VSTART));
454 convoy_selector.set_size(scr_size(win_size.w - D_MARGIN_RIGHT - D_MARGIN_LEFT - selector_x, D_BUTTON_HEIGHT));
455 convoy_selector.set_max_size(scr_size(win_size.w - D_MARGIN_RIGHT - D_MARGIN_LEFT - selector_x, LINESPACE * 13 + 2 + 16));
456
457 /*
458 * [SELECT ROUTE]:
459 * @author hsiegeln
460 */
461 line_button.set_pos(scr_coord(D_MARGIN_LEFT, SELECT_VSTART + D_BUTTON_HEIGHT));
462 lb_convoi_line.set_pos(scr_coord(D_MARGIN_LEFT + line_button.get_size().w + 2, SELECT_VSTART + D_BUTTON_HEIGHT));
463 lb_convoi_line.set_width(selector_x - line_button.get_size().w - 2 - D_H_SPACE);
464
465 line_selector.set_pos(scr_coord(D_MARGIN_LEFT + selector_x, SELECT_VSTART + D_BUTTON_HEIGHT));
466 line_selector.set_size(scr_size(win_size.w - D_MARGIN_RIGHT - D_MARGIN_LEFT - selector_x, D_BUTTON_HEIGHT));
467 line_selector.set_max_size(scr_size(win_size.w - D_MARGIN_RIGHT - D_MARGIN_LEFT - selector_x, LINESPACE * 13 + 2 + 16));
468
469 line_button.align_to(&line_selector, ALIGN_CENTER_V);
470 lb_convoi_line.align_to(&line_selector, ALIGN_CENTER_V);
471
472 /*
473 * [CONVOI]
474 */
475 convoi.set_grid(scr_coord(grid.x - grid_dx, grid.y));
476 convoi.set_placement(scr_coord(placement.x - placement_dx, placement.y));
477 convoi.set_pos(scr_coord(0, 0));
478 convoi.set_size(scr_size(CLIST_WIDTH, CLIST_HEIGHT));
479
480 sb_convoi_length.set_pos(scr_coord(5, grid.y + 5));
481 sb_convoi_length.set_size(scr_size(CLIST_WIDTH - 10, 4));
482
483 cont_convoi.set_size(scr_size(CLIST_WIDTH, grid.y + 5 + 4));
484 scrolly_convoi.set_size(scr_size(win_size.w - D_MARGIN_LEFT - D_MARGIN_RIGHT, cont_convoi.get_size().h + (3+D_SCROLLBAR_HEIGHT)*(CLIST_WIDTH >= win_size.w-D_MARGIN_LEFT-D_MARGIN_RIGHT) ));
485 scrolly_convoi.set_show_scroll_x(true);
486 scrolly_convoi.set_show_scroll_y(false);
487 scrolly_convoi.set_scroll_discrete_x(false);
488 scrolly_convoi.set_size_corner(false);
489 scrolly_convoi.set_pos(scr_coord(D_MARGIN_LEFT,CONVOI_VSTART));
490
491 lb_convoi_number.set_width(30);
492 lb_convoi_number.set_color(COL_WHITE);
493
494 // place for description text
495 second_column_x = D_MARGIN_LEFT + (BUTTON_WIDTH_DEPOT+D_H_SPACE*2)*2;
496 second_column_w = (BUTTON_WIDTH_DEPOT+D_H_SPACE)*2;
497
498 lb_convoi_count.set_pos(scr_coord(D_MARGIN_LEFT, CINFO_VSTART));
499 lb_convoi_count.set_width(second_column_w);
500
501 cont_convoi_capacity.set_pos(scr_coord(second_column_x, CINFO_VSTART));
502 cont_convoi_capacity.set_width(second_column_w);
503
504 lb_convoi_cost.set_pos(scr_coord(D_MARGIN_LEFT, CINFO_VSTART + LINESPACE * 1));
505 lb_convoi_cost.set_width(second_column_w);
506 lb_convoi_value.set_pos(scr_coord(second_column_x, CINFO_VSTART + LINESPACE * 1));
507 lb_convoi_value.set_width(second_column_w);
508
509 lb_convoi_power.set_pos(scr_coord(D_MARGIN_LEFT, CINFO_VSTART + LINESPACE * 2));
510 lb_convoi_power.set_width(second_column_w);
511 lb_convoi_weight.set_pos(scr_coord(second_column_x, CINFO_VSTART + LINESPACE * 2));
512 lb_convoi_weight.set_width(second_column_w);
513
514 lb_convoi_speed.set_pos(scr_coord(D_MARGIN_LEFT, CINFO_VSTART + LINESPACE * 3));
515 lb_convoi_speed.set_width(win_size.w - D_MARGIN_RIGHT - D_MARGIN_LEFT);
516
517 /*
518 * [ACTIONS]
519 */
520 bt_start.set_pos(scr_coord(D_MARGIN_LEFT, ACTIONS_VSTART));
521 bt_start.set_size(scr_size(BUTTON_WIDTH_DEPOT, D_BUTTON_HEIGHT));
522 bt_start.set_text("Start");
523
524 bt_schedule.set_pos(scr_coord(D_MARGIN_LEFT + (BUTTON_WIDTH_DEPOT + D_H_SPACE), ACTIONS_VSTART));
525 bt_schedule.set_size(scr_size(BUTTON_WIDTH_DEPOT, D_BUTTON_HEIGHT));
526 bt_schedule.set_text("Fahrplan");
527
528 bt_copy_convoi.set_pos(scr_coord(D_MARGIN_LEFT + (BUTTON_WIDTH_DEPOT + D_H_SPACE)*2, ACTIONS_VSTART));
529 bt_copy_convoi.set_size(scr_size(BUTTON_WIDTH_DEPOT, D_BUTTON_HEIGHT));
530 bt_copy_convoi.set_text("Copy Convoi");
531
532 bt_sell.set_pos(scr_coord(D_MARGIN_LEFT + (BUTTON_WIDTH_DEPOT + D_H_SPACE)*3, ACTIONS_VSTART));
533 bt_sell.set_size(scr_size(BUTTON_WIDTH_DEPOT, D_BUTTON_HEIGHT));
534 bt_sell.set_text("verkaufen");
535
536 /*
537 * [PANEL]
538 */
539 tabs.set_pos(scr_coord(0, PANEL_VSTART));
540 tabs.set_size(scr_size(win_size.w, PANEL_HEIGHT));
541
542 pas.set_grid(grid);
543 pas.set_placement(placement);
544 pas.set_size(tabs.get_size() - scr_size(D_SCROLLBAR_WIDTH, 0));
545 pas.recalc_size();
546 pas.set_pos(scr_coord(0, 0));
547 scrolly_pas.set_size(scrolly_pas.get_size());
548 scrolly_pas.set_scroll_amount_y(grid.y);
549 scrolly_pas.set_scroll_discrete_y(false);
550 scrolly_pas.set_size_corner(false);
551
552 electrics.set_grid(grid);
553 electrics.set_placement(placement);
554 electrics.set_size(tabs.get_size() - scr_size(D_SCROLLBAR_WIDTH, 0));
555 electrics.recalc_size();
556 electrics.set_pos(scr_coord(0, 0));
557 scrolly_electrics.set_size(scrolly_electrics.get_size());
558 scrolly_electrics.set_scroll_amount_y(grid.y);
559 scrolly_electrics.set_scroll_discrete_y(false);
560 scrolly_electrics.set_size_corner(false);
561
562 loks.set_grid(grid);
563 loks.set_placement(placement);
564 loks.set_size(tabs.get_size() - scr_size(D_SCROLLBAR_WIDTH, 0));
565 loks.recalc_size();
566 loks.set_pos(scr_coord(0, 0));
567 scrolly_loks.set_size(scrolly_loks.get_size());
568 scrolly_loks.set_scroll_amount_y(grid.y);
569 scrolly_loks.set_scroll_discrete_y(false);
570 scrolly_loks.set_size_corner(false);
571
572 waggons.set_grid(grid);
573 waggons.set_placement(placement);
574 waggons.set_size(tabs.get_size() - scr_size(D_SCROLLBAR_WIDTH, 0));
575 waggons.recalc_size();
576 waggons.set_pos(scr_coord(0, 0));
577 scrolly_waggons.set_size(scrolly_waggons.get_size());
578 scrolly_waggons.set_scroll_amount_y(grid.y);
579 scrolly_waggons.set_scroll_discrete_y(false);
580 scrolly_waggons.set_size_corner(false);
581
582 div_tabbottom.set_pos(scr_coord(0, PANEL_VSTART + PANEL_HEIGHT));
583 div_tabbottom.set_width(win_size.w);
584
585 /*
586 * [BOTTOM]
587 */
588
589 // 1st line
590 bt_veh_action.set_pos(scr_coord(D_MARGIN_LEFT + (BUTTON_WIDTH_DEPOT+D_H_SPACE)*3, INFO_VSTART));
591 bt_veh_action.set_size(scr_size(BUTTON_WIDTH_DEPOT, D_BUTTON_HEIGHT));
592 lb_veh_action.align_to(&bt_veh_action, ALIGN_RIGHT | ALIGN_EXTERIOR_H | ALIGN_CENTER_V, scr_coord(D_H_SPACE, 0));
593
594 // 2nd line
595 vehicle_filter.set_pos(scr_coord(D_MARGIN_LEFT + (BUTTON_WIDTH_DEPOT+D_H_SPACE)*2 - proportional_string_width(translator::translate("Search:")), INFO_VSTART + D_BUTTON_HEIGHT + D_V_SPACE));
596 vehicle_filter.set_size(scr_size(BUTTON_WIDTH_DEPOT, D_BUTTON_HEIGHT));
597 vehicle_filter.set_max_size(scr_size(D_BUTTON_WIDTH, LINESPACE*7));
598 lb_vehicle_filter.align_to(&vehicle_filter, ALIGN_RIGHT | ALIGN_EXTERIOR_H | ALIGN_TOP, scr_coord(2,D_GET_CENTER_ALIGN_OFFSET(LINESPACE,D_BUTTON_HEIGHT)));
599
600 name_filter_input.set_pos( scr_coord(D_MARGIN_LEFT + (BUTTON_WIDTH_DEPOT+D_H_SPACE)*3, INFO_VSTART + D_BUTTON_HEIGHT + D_V_SPACE) );
601 name_filter_input.set_size( scr_size( BUTTON_WIDTH_DEPOT, D_EDIT_HEIGHT ) );
602 lb_name_filter_input.align_to(&name_filter_input, ALIGN_RIGHT | ALIGN_EXTERIOR_H | ALIGN_TOP, scr_coord(D_H_SPACE,D_GET_CENTER_ALIGN_OFFSET(LINESPACE,D_BUTTON_HEIGHT)));
603
604 bt_obsolete.set_pos(scr_coord(D_MARGIN_LEFT, INFO_VSTART + (D_BUTTON_HEIGHT + D_V_SPACE)*2));
605 bt_obsolete.align_to(&name_filter_input, ALIGN_CENTER_V);
606
607 //3rd line
608 sort_by.set_pos(scr_coord(D_MARGIN_LEFT + (BUTTON_WIDTH_DEPOT+D_H_SPACE)*3, INFO_VSTART + (D_BUTTON_HEIGHT + D_V_SPACE)*2));
609 sort_by.set_size(scr_size(BUTTON_WIDTH_DEPOT, D_BUTTON_HEIGHT));
610 sort_by.set_max_size(scr_size(D_BUTTON_WIDTH, LINESPACE * 7));
611 lb_sort_by.align_to(&sort_by, ALIGN_RIGHT | ALIGN_EXTERIOR_H | ALIGN_TOP, scr_coord(D_H_SPACE,D_GET_CENTER_ALIGN_OFFSET(LINESPACE,D_BUTTON_HEIGHT)));
612
613 bt_show_all.set_pos(scr_coord(D_MARGIN_LEFT, INFO_VSTART + (D_BUTTON_HEIGHT + D_V_SPACE)*2));
614 // bt_show_all.align_to(&sort_by, ALIGN_CENTER_TOP); Comboboxes change height when openen!!!
615
616 div_action_bottom.set_pos(scr_coord(0, INFO_VSTART + (D_BUTTON_HEIGHT + D_V_SPACE) * 3));
617 div_action_bottom.set_width(win_size.w);
618
619 const scr_coord_val margin = 4;
620 img_bolt.set_pos(scr_coord(get_windowsize().w - skinverwaltung_t::electricity->get_image(0)->get_pic()->w - margin, margin));
621
622 }
623
624
set_windowsize(scr_size size)625 void depot_frame_t::set_windowsize( scr_size size )
626 {
627 if (depot) {
628 update_data();
629 layout(&size);
630 }
631 gui_frame_t::set_windowsize(size);
632 }
633
634
activate_convoi(convoihandle_t c)635 void depot_frame_t::activate_convoi( convoihandle_t c )
636 {
637 icnv = -1; // deselect
638 for( uint i = 0; i < depot->convoi_count(); i++ ) {
639 if( c == depot->get_convoi(i) ) {
640 icnv = i;
641 break;
642 }
643 }
644 build_vehicle_lists();
645 }
646
647
648 // true if already stored here
is_in_vehicle_list(const vehicle_desc_t * info)649 bool depot_frame_t::is_in_vehicle_list(const vehicle_desc_t *info)
650 {
651 FOR(slist_tpl<vehicle_t*>, const v, depot->get_vehicle_list()) {
652 if( v->get_desc() == info ) {
653 return true;
654 }
655 }
656 return false;
657 }
658
659
660 // add a single vehicle (helper function)
add_to_vehicle_list(const vehicle_desc_t * info)661 void depot_frame_t::add_to_vehicle_list(const vehicle_desc_t *info)
662 {
663 // prissi: is it a non-electric track?
664 // Hajo: check for timeline
665 // prissi: and retirement date
666
667 // Check if vehicle should be filtered
668 const goods_desc_t *freight = info->get_freight_type();
669 // Only filter when required and never filter engines
670 if (depot->selected_filter > 0 && info->get_capacity() > 0) {
671 if (depot->selected_filter == VEHICLE_FILTER_RELEVANT) {
672 if(freight->get_catg_index() >= 3) {
673 bool found = false;
674 FOR(vector_tpl<goods_desc_t const*>, const i, welt->get_goods_list()) {
675 if (freight->get_catg_index() == i->get_catg_index()) {
676 found = true;
677 break;
678 }
679 }
680
681 // If no current goods can be transported by this vehicle, don't display it
682 if (!found) return;
683 }
684 }
685 else if (depot->selected_filter > VEHICLE_FILTER_RELEVANT) {
686 // Filter on specific selected good
687 uint32 goods_index = depot->selected_filter - VEHICLE_FILTER_GOODS_OFFSET;
688 if (goods_index < welt->get_goods_list().get_count()) {
689 const goods_desc_t *selected_good = welt->get_goods_list()[goods_index];
690 if (freight->get_catg_index() != selected_good->get_catg_index()) {
691 return; // This vehicle can't transport the selected good
692 }
693 }
694 }
695 }
696
697 gui_image_list_t::image_data_t* img_data = new gui_image_list_t::image_data_t(info->get_name(), info->get_base_image());
698
699 if( info->get_engine_type() == vehicle_desc_t::electric && (info->get_freight_type()==goods_manager_t::passengers || info->get_freight_type()==goods_manager_t::mail) ) {
700 electrics_vec.append(img_data);
701 }
702 // since they come "pre-sorted" for the vehikelbauer, we have to do nothing to keep them sorted
703 else if(info->get_freight_type() == goods_manager_t::passengers || info->get_freight_type() == goods_manager_t::mail) {
704 pas_vec.append(img_data);
705 }
706 else if(info->get_power() > 0 || info->get_capacity()==0) {
707 loks_vec.append(img_data);
708 }
709 else {
710 waggons_vec.append(img_data);
711 }
712 // add reference to map
713 vehicle_map.set(info, img_data);
714 }
715
716 // add all current vehicles
build_vehicle_lists()717 void depot_frame_t::build_vehicle_lists()
718 {
719 if (depot->get_vehicle_type().empty()) {
720 // there are tracks etc. but no vehicles => do nothing
721 // at least initialize some data
722 update_data();
723 update_tabs();
724 return;
725 }
726
727 const int month_now = welt->get_timeline_year_month();
728
729 // free vectors
730 clear_ptr_vector(pas_vec);
731 clear_ptr_vector(electrics_vec);
732 clear_ptr_vector(loks_vec);
733 clear_ptr_vector(waggons_vec);
734 // clear map
735 vehicle_map.clear();
736
737 // we do not allow to built electric vehicle in a depot without electrification
738 const waytype_t wt = depot->get_waytype();
739 const weg_t *w = welt->lookup(depot->get_pos())->get_weg(wt!=tram_wt ? wt : track_wt);
740 const bool weg_electrified = w ? w->is_electrified() : false;
741
742 img_bolt.set_image( weg_electrified ? skinverwaltung_t::electricity->get_image_id(0) : IMG_EMPTY );
743
744 sort_by_action = depot->selected_sort_by;
745
746 vector_tpl<const vehicle_desc_t*> typ_list;
747
748 if(!show_all && veh_action==va_sell) {
749 // show only sellable vehicles
750 FOR(slist_tpl<vehicle_t*>, const v, depot->get_vehicle_list()) {
751 vehicle_desc_t const* const d = v->get_desc();
752 typ_list.append(d);
753 }
754 }
755 else {
756 slist_tpl<const vehicle_desc_t*> const& tmp_list = depot->get_vehicle_type(sort_by_action);
757 for(slist_tpl<const vehicle_desc_t*>::const_iterator itr = tmp_list.begin(); itr != tmp_list.end(); ++itr) {
758 typ_list.append(*itr);
759 }
760 }
761
762 // use this to show only sellable vehicles
763 if(!show_all && veh_action==va_sell) {
764 // just list the one to sell
765 FOR(vector_tpl<vehicle_desc_t const*>, const info, typ_list) {
766 if (vehicle_map.get(info)) continue;
767 add_to_vehicle_list(info);
768 }
769 }
770 else {
771 // list only matching ones
772 FOR(vector_tpl<vehicle_desc_t const*>, const info, typ_list) {
773 const vehicle_desc_t *veh = NULL;
774 convoihandle_t cnv = depot->get_convoi(icnv);
775 if(cnv.is_bound() && cnv->get_vehicle_count()>0) {
776 veh = (veh_action == va_insert ? cnv->front() : cnv->back())->get_desc();
777 }
778
779 // current vehicle
780 if( is_in_vehicle_list(info) ||
781 ((weg_electrified || info->get_engine_type()!=vehicle_desc_t::electric) &&
782 ((!info->is_future(month_now)) && (show_retired_vehicles || (!info->is_retired(month_now)) ) ) )) {
783 // check, if allowed
784 bool append = true;
785 if(!show_all) {
786 if(veh_action == va_insert) {
787 append = info->can_lead(veh) && (veh==NULL || veh->can_follow(info));
788 } else if(veh_action == va_append) {
789 append = info->can_follow(veh) && (veh==NULL || veh->can_lead(info));
790 }
791 }
792 if(append) {
793 // name filter. Try to check both object name and translation name (case sensitive though!)
794 if( name_filter_value[0]==0 || (strstr(info->get_name(), name_filter_value) || strstr(translator::translate(info->get_name()), name_filter_value)) ) {
795 add_to_vehicle_list( info );
796 }
797 }
798 }
799 }
800 }
801 DBG_DEBUG("depot_frame_t::build_vehicle_lists()","finally %i passenger vehicle, %i engines, %i good wagons",pas_vec.get_count(),loks_vec.get_count(),waggons_vec.get_count());
802 update_data();
803 update_tabs();
804 }
805
806
get_line_list(const depot_t * depot,vector_tpl<linehandle_t> * lines)807 static void get_line_list(const depot_t* depot, vector_tpl<linehandle_t>* lines)
808 {
809 depot->get_owner()->simlinemgmt.get_lines(depot->get_line_type(), lines);
810 }
811
812
update_data()813 void depot_frame_t::update_data()
814 {
815 static const char *txt_veh_action[3] = { "anhaengen", "voranstellen", "verkaufen" };
816 static const char *txt_sort_by[sb_length] = { "Vehicle Name", "Capacity", "Price", "Cost", "Cost per unit", "Max. speed", "Vehicle Power", "Weight", "Intro. date", "Retire date" };
817
818 // change green into blue for retired vehicles
819 const int month_now = welt->get_timeline_year_month();
820
821 bt_veh_action.set_text(txt_veh_action[veh_action]);
822
823 txt_convois.clear();
824 switch( depot->convoi_count() ) {
825 case 0: {
826 txt_convois.append( translator::translate("no convois") );
827 break;
828 }
829 case 1: {
830 if( icnv == -1 ) {
831 txt_convois.append( translator::translate("1 convoi") );
832 }
833 else {
834 txt_convois.printf( translator::translate("convoi %d of %d"), icnv + 1, depot->convoi_count() );
835 }
836 break;
837 }
838 default: {
839 if( icnv == -1 ) {
840 txt_convois.printf( translator::translate("%d convois"), depot->convoi_count() );
841 }
842 else {
843 txt_convois.printf( translator::translate("convoi %d of %d"), icnv + 1, depot->convoi_count() );
844 }
845 break;
846 }
847 }
848
849 /*
850 * Reset counts and check for valid vehicles
851 */
852 convoihandle_t cnv = depot->get_convoi( icnv );
853
854 // update convoy selector
855 convoy_selector.clear_elements();
856 convoy_selector.new_component<gui_scrolled_list_t::const_text_scrollitem_t>( new_convoy_text, SYSCOL_TEXT ) ;
857 convoy_selector.set_selection(0);
858
859 // check all matching convoys
860 FOR(slist_tpl<convoihandle_t>, const c, depot->get_convoy_list()) {
861 convoy_selector.new_component<convoy_scrollitem_t>(c) ;
862 if( cnv.is_bound() && c == cnv ) {
863 convoy_selector.set_selection( convoy_selector.count_elements() - 1 );
864 }
865 }
866
867 const vehicle_desc_t *veh = NULL;
868
869 clear_ptr_vector( convoi_pics );
870 if( cnv.is_bound() && cnv->get_vehicle_count() > 0 ) {
871 for( unsigned i=0; i < cnv->get_vehicle_count(); i++ ) {
872 // just make sure, there is this vehicle also here!
873 const vehicle_desc_t *info=cnv->get_vehikel(i)->get_desc();
874 if( vehicle_map.get( info ) == NULL ) {
875 add_to_vehicle_list( info );
876 }
877
878 gui_image_list_t::image_data_t* img_data = new gui_image_list_t::image_data_t(info->get_name(), info->get_base_image());
879 convoi_pics.append(img_data);
880 }
881
882 /* color bars for current convoi: */
883 convoi_pics[0]->lcolor = color_idx_to_rgb(cnv->front()->get_desc()->can_follow(NULL) ? COL_GREEN : COL_YELLOW);
884 {
885 unsigned i;
886 for( i = 1; i < cnv->get_vehicle_count(); i++ ) {
887 convoi_pics[i - 1]->rcolor = color_idx_to_rgb(cnv->get_vehikel(i-1)->get_desc()->can_lead(cnv->get_vehikel(i)->get_desc()) ? COL_GREEN : COL_RED);
888 convoi_pics[i]->lcolor = color_idx_to_rgb(cnv->get_vehikel(i)->get_desc()->can_follow(cnv->get_vehikel(i-1)->get_desc()) ? COL_GREEN : COL_RED);
889 }
890 convoi_pics[i - 1]->rcolor = color_idx_to_rgb(cnv->get_vehikel(i-1)->get_desc()->can_lead(NULL) ? COL_GREEN : COL_YELLOW);
891 }
892
893 // change green into blue for vehicles that are not available
894 for( unsigned i = 0; i < cnv->get_vehicle_count(); i++ ) {
895 if( !cnv->get_vehikel(i)->get_desc()->is_available(month_now) ) {
896 if( convoi_pics[i]->lcolor == color_idx_to_rgb(COL_GREEN) ) {
897 convoi_pics[i]->lcolor = color_idx_to_rgb(COL_BLUE);
898 }
899 if( convoi_pics[i]->rcolor == color_idx_to_rgb(COL_GREEN) ) {
900 convoi_pics[i]->rcolor = color_idx_to_rgb(COL_BLUE);
901 }
902 }
903 }
904
905 veh = (veh_action == va_insert ? cnv->front() : cnv->back())->get_desc();
906 }
907
908 FOR(vehicle_image_map, const& i, vehicle_map) {
909 vehicle_desc_t const* const info = i.key;
910 gui_image_list_t::image_data_t& img = *i.value;
911 const PIXVAL ok_color = color_idx_to_rgb(info->is_available(month_now) ? COL_GREEN : COL_BLUE);
912
913 img.count = 0;
914 img.lcolor = ok_color;
915 img.rcolor = ok_color;
916
917 /*
918 * color bars for current convoi:
919 * green/green okay to append/insert
920 * red/red cannot be appended/inserted
921 * green/yellow append okay, cannot be end of train
922 * yellow/green insert okay, cannot be start of train
923 */
924
925 if(veh_action == va_insert) {
926 if(!info->can_lead(veh) || (veh && !veh->can_follow(info))) {
927 img.lcolor = color_idx_to_rgb(COL_RED);
928 img.rcolor = color_idx_to_rgb(COL_RED);
929 }
930 else if(!info->can_follow(NULL)) {
931 img.lcolor = color_idx_to_rgb(COL_YELLOW);
932 }
933 }
934 else if(veh_action == va_append) {
935 if(!info->can_follow(veh) || (veh && !veh->can_lead(info))) {
936 img.lcolor = color_idx_to_rgb(COL_RED);
937 img.rcolor = color_idx_to_rgb(COL_RED);
938 }
939 else if(!info->can_lead(NULL)) {
940 img.rcolor = color_idx_to_rgb(COL_YELLOW);
941 }
942 }
943 else if( veh_action == va_sell ) {
944 img.lcolor = color_idx_to_rgb(COL_RED);
945 img.rcolor = color_idx_to_rgb(COL_RED);
946 }
947 }
948
949 FOR(slist_tpl<vehicle_t*>, const v, depot->get_vehicle_list()) {
950 // can fail, if currently not visible
951 if (gui_image_list_t::image_data_t* const imgdat = vehicle_map.get(v->get_desc())) {
952 imgdat->count++;
953 if(veh_action == va_sell) {
954 imgdat->lcolor = color_idx_to_rgb(COL_GREEN);
955 imgdat->rcolor = color_idx_to_rgb(COL_GREEN);
956 }
957 }
958 }
959
960 // update the line selector
961 line_selector.clear_elements();
962
963 if( !last_selected_line.is_bound() ) {
964 // new line may have a valid line now
965 last_selected_line = selected_line;
966 // if still nothing, resort to line management dialoge
967 if( !last_selected_line.is_bound() ) {
968 // try last specific line
969 last_selected_line = schedule_list_gui_t::selected_line[ depot->get_owner()->get_player_nr() ][ depot->get_line_type() ];
970 }
971 if( !last_selected_line.is_bound() ) {
972 // try last general line
973 last_selected_line = schedule_list_gui_t::selected_line[ depot->get_owner()->get_player_nr() ][ 0 ];
974 if( last_selected_line.is_bound() && last_selected_line->get_linetype() != depot->get_line_type() ) {
975 last_selected_line = linehandle_t();
976 }
977 }
978 }
979 if( cnv.is_bound() && cnv->get_schedule() && !cnv->get_schedule()->empty() ) {
980 if( cnv->get_line().is_bound() ) {
981 line_selector.new_component<gui_scrolled_list_t::const_text_scrollitem_t>( clear_schedule_text, SYSCOL_TEXT ) ;
982 line_selector.new_component<gui_scrolled_list_t::const_text_scrollitem_t>( new_line_text, SYSCOL_TEXT ) ;
983 }
984 else {
985 line_selector.new_component<gui_scrolled_list_t::const_text_scrollitem_t>( unique_schedule_text, SYSCOL_TEXT ) ;
986 line_selector.new_component<gui_scrolled_list_t::const_text_scrollitem_t>( promote_to_line_text, SYSCOL_TEXT ) ;
987 }
988 }
989 else {
990 line_selector.new_component<gui_scrolled_list_t::const_text_scrollitem_t>( no_schedule_text, SYSCOL_TEXT ) ;
991 line_selector.new_component<gui_scrolled_list_t::const_text_scrollitem_t>( new_line_text, SYSCOL_TEXT ) ;
992 }
993 if( last_selected_line.is_bound() ) {
994 line_selector.new_component<line_scrollitem_t>( last_selected_line ) ;
995 }
996 if( !selected_line.is_bound() ) {
997 // select "create new schedule"
998 line_selector.set_selection( 0 );
999 }
1000 line_selector.new_component<gui_scrolled_list_t::const_text_scrollitem_t>( line_seperator, SYSCOL_TEXT ) ;
1001
1002 // check all matching lines
1003 if( cnv.is_bound() ) {
1004 selected_line = cnv->get_line();
1005 }
1006 vector_tpl<linehandle_t> lines;
1007 get_line_list(depot, &lines);
1008 line_selector.set_selection( 0 );
1009 FOR( vector_tpl<linehandle_t>, const line, lines ) {
1010 line_selector.new_component<line_scrollitem_t>(line) ;
1011 if( selected_line.is_bound() && selected_line == line ) {
1012 line_selector.set_selection( line_selector.count_elements() - 1 );
1013 }
1014 }
1015 if( line_selector.get_selection() == 0 ) {
1016 // no line selected
1017 selected_line = linehandle_t();
1018 }
1019 line_selector.sort( last_selected_line.is_bound()+3 );
1020
1021 // Update vehicle filter
1022 vehicle_filter.clear_elements();
1023 vehicle_filter.new_component<gui_scrolled_list_t::const_text_scrollitem_t>(translator::translate("All"), SYSCOL_TEXT);
1024 vehicle_filter.new_component<gui_scrolled_list_t::const_text_scrollitem_t>(translator::translate("Relevant"), SYSCOL_TEXT);
1025
1026 FOR(vector_tpl<goods_desc_t const*>, const i, welt->get_goods_list()) {
1027 vehicle_filter.new_component<gui_scrolled_list_t::const_text_scrollitem_t>(translator::translate(i->get_name()), SYSCOL_TEXT);
1028 }
1029
1030 if( depot->selected_filter > vehicle_filter.count_elements() ) {
1031 depot->selected_filter = VEHICLE_FILTER_RELEVANT;
1032 }
1033 vehicle_filter.set_selection(depot->selected_filter);
1034
1035 sort_by.clear_elements();
1036 for(int i = 0; i < sb_length; i++)
1037 {
1038 sort_by.new_component<gui_scrolled_list_t::const_text_scrollitem_t>(translator::translate(txt_sort_by[i]), SYSCOL_TEXT);
1039 }
1040 if( depot->selected_sort_by > sort_by.count_elements() ) {
1041 depot->selected_sort_by = sb_name;
1042 }
1043 sort_by.set_selection(depot->selected_sort_by);
1044
1045 // finally: update text
1046 uint32 total_pax = 0;
1047 uint32 total_mail = 0;
1048 uint32 total_goods = 0;
1049
1050 uint64 total_power = 0;
1051 uint32 total_empty_weight = 0;
1052 uint32 total_selected_weight = 0;
1053 uint32 total_max_weight = 0;
1054 uint32 total_min_weight = 0;
1055 bool use_sel_weight = true;
1056
1057 if( cnv.is_bound() ) {
1058 if( cnv->get_vehicle_count() > 0 ) {
1059 uint8 selected_good_index = 0;
1060 if( depot->selected_filter > VEHICLE_FILTER_RELEVANT ) {
1061 // Filter is set to specific good
1062 const uint32 goods_index = depot->selected_filter - VEHICLE_FILTER_GOODS_OFFSET;
1063 if( goods_index < welt->get_goods_list().get_count() ) {
1064 selected_good_index = welt->get_goods_list()[goods_index]->get_index();
1065 }
1066 }
1067
1068 for( unsigned i = 0; i < cnv->get_vehicle_count(); i++ ) {
1069 const vehicle_desc_t *desc = cnv->get_vehikel(i)->get_desc();
1070
1071 total_power += desc->get_power()*desc->get_gear();
1072
1073 uint32 sel_weight = 0; // actual weight using vehicle filter selected good to fill
1074 uint32 max_weight = 0;
1075 uint32 min_weight = 100000;
1076 bool sel_found = false;
1077 for( uint32 j=0; j<goods_manager_t::get_count(); j++ ) {
1078 const goods_desc_t *ware = goods_manager_t::get_info(j);
1079
1080 if( desc->get_freight_type()->get_catg_index() == ware->get_catg_index() ) {
1081 max_weight = max(max_weight, (uint32)ware->get_weight_per_unit());
1082 min_weight = min(min_weight, (uint32)ware->get_weight_per_unit());
1083
1084 // find number of goods in in this category. TODO: gotta be a better way...
1085 uint8 catg_count = 0;
1086 FOR(vector_tpl<goods_desc_t const*>, const i, welt->get_goods_list()) {
1087 if( ware->get_catg_index() == i->get_catg_index() ) {
1088 catg_count++;
1089 }
1090 }
1091
1092 if( ware->get_index() == selected_good_index || catg_count < 2 ) {
1093 sel_found = true;
1094 sel_weight = ware->get_weight_per_unit();
1095 }
1096 }
1097 }
1098 if( !sel_found ) {
1099 // vehicle carries more than one good, but not the selected one
1100 use_sel_weight = false;
1101 }
1102
1103 total_empty_weight += desc->get_weight();
1104 total_selected_weight += desc->get_weight() + sel_weight * desc->get_capacity();
1105 total_max_weight += desc->get_weight() + max_weight * desc->get_capacity();
1106 total_min_weight += desc->get_weight() + min_weight * desc->get_capacity();
1107
1108 const goods_desc_t* const ware = desc->get_freight_type();
1109 switch( ware->get_catg_index() ) {
1110 case goods_manager_t::INDEX_PAS: {
1111 total_pax += desc->get_capacity();
1112 break;
1113 }
1114 case goods_manager_t::INDEX_MAIL: {
1115 total_mail += desc->get_capacity();
1116 break;
1117 }
1118 default: {
1119 total_goods += desc->get_capacity();
1120 break;
1121 }
1122 }
1123 }
1124
1125 sint32 empty_kmh, sel_kmh, max_kmh, min_kmh;
1126 if( cnv->front()->get_waytype() == air_wt ) {
1127 // flying aircraft have 0 friction --> speed not limited by power, so just use top_speed
1128 empty_kmh = sel_kmh = max_kmh = min_kmh = speed_to_kmh( cnv->get_min_top_speed() );
1129 }
1130 else {
1131 empty_kmh = speed_to_kmh(convoi_t::calc_max_speed(total_power, total_empty_weight, cnv->get_min_top_speed()));
1132 sel_kmh = speed_to_kmh(convoi_t::calc_max_speed(total_power, total_selected_weight, cnv->get_min_top_speed()));
1133 max_kmh = speed_to_kmh(convoi_t::calc_max_speed(total_power, total_min_weight, cnv->get_min_top_speed()));
1134 min_kmh = speed_to_kmh(convoi_t::calc_max_speed(total_power, total_max_weight, cnv->get_min_top_speed()));
1135 }
1136
1137 const sint32 convoi_length = (cnv->get_vehicle_count()) * CARUNITS_PER_TILE / 2 - 1;
1138 convoi_tile_length_sb = convoi_length + (cnv->get_tile_length() * CARUNITS_PER_TILE - cnv->get_length());
1139
1140 txt_convoi_count.clear();
1141 if( cnv->get_vehicle_count()>1 ) {
1142 txt_convoi_count.printf( translator::translate("%i car(s),"), cnv->get_vehicle_count() );
1143 }
1144 txt_convoi_count.append( translator::translate("Station tiles:") );
1145 txt_convoi_count.append( (double)cnv->get_tile_length(), 0 );
1146
1147 txt_convoi_speed.clear();
1148 if( empty_kmh != (use_sel_weight ? sel_kmh : min_kmh) ) {
1149 convoi_length_ok_sb = 0;
1150 if( max_kmh != min_kmh && !use_sel_weight ) {
1151 txt_convoi_speed.printf("%s %d km/h, %d-%d km/h %s", translator::translate("Max. speed:"), empty_kmh, min_kmh, max_kmh, translator::translate("loaded") );
1152 if( max_kmh != empty_kmh ) {
1153 convoi_length_slower_sb = 0;
1154 convoi_length_too_slow_sb = convoi_length;
1155 }
1156 else {
1157 convoi_length_slower_sb = convoi_length;
1158 convoi_length_too_slow_sb = 0;
1159 }
1160 }
1161 else {
1162 txt_convoi_speed.printf("%s %d km/h, %d km/h %s", translator::translate("Max. speed:"), empty_kmh, use_sel_weight ? sel_kmh : min_kmh, translator::translate("loaded") );
1163 convoi_length_slower_sb = 0;
1164 convoi_length_too_slow_sb = convoi_length;
1165 }
1166 }
1167 else {
1168 txt_convoi_speed.printf("%s %d km/h", translator::translate("Max. speed:"), empty_kmh );
1169 convoi_length_ok_sb = convoi_length;
1170 convoi_length_slower_sb = 0;
1171 convoi_length_too_slow_sb = 0;
1172 }
1173
1174 {
1175 char buf[128];
1176 txt_convoi_value.clear();
1177 money_to_string( buf, cnv->calc_restwert() / 100.0, false );
1178 txt_convoi_value.printf("%s %8s", translator::translate("Restwert:"), buf );
1179
1180 txt_convoi_cost.clear();
1181 if( sint64 fix_cost = welt->scale_with_month_length((sint64)cnv->get_fix_cost()) ) {
1182 money_to_string( buf, (double)fix_cost / 100.0, false );
1183 txt_convoi_cost.printf( translator::translate("Cost: %8s (%.2f$/km %.2f$/m)\n"), buf, (double)cnv->get_running_cost()/100.0, (double)fix_cost/100.0 );
1184 }
1185 else {
1186 money_to_string( buf, cnv->get_purchase_cost() / 100.0, false );
1187 txt_convoi_cost.printf( translator::translate("Cost: %8s (%.2f$/km)\n"), buf, (double)cnv->get_running_cost() / 100.0 );
1188 }
1189 }
1190
1191 txt_convoi_power.clear();
1192 txt_convoi_power.printf( translator::translate("Power: %4d kW\n"), cnv->get_sum_power() );
1193
1194 txt_convoi_weight.clear();
1195 if( total_empty_weight != (use_sel_weight ? total_selected_weight : total_max_weight) ) {
1196 if( total_min_weight != total_max_weight && !use_sel_weight ) {
1197 txt_convoi_weight.printf("%s %.1ft, %.1f-%.1ft", translator::translate("Weight:"), total_empty_weight / 1000.0, total_min_weight / 1000.0, total_max_weight / 1000.0 );
1198 }
1199 else {
1200 txt_convoi_weight.printf("%s %.1ft, %.1ft", translator::translate("Weight:"), total_empty_weight / 1000.0, (use_sel_weight ? total_selected_weight : total_max_weight) / 1000.0 );
1201 }
1202 }
1203 else {
1204 txt_convoi_weight.printf("%s %.1ft", translator::translate("Weight:"), total_empty_weight / 1000.0 );
1205 }
1206 }
1207 else {
1208 txt_convoi_count.clear();
1209 txt_convoi_count.append(translator::translate("keine Fahrzeuge"));
1210 txt_convoi_value.clear();
1211 txt_convoi_cost.clear();
1212 txt_convoi_power.clear();
1213 txt_convoi_weight.clear();
1214 }
1215
1216 sb_convoi_length.set_visible(true);
1217 cont_convoi_capacity.set_totals( total_pax, total_mail, total_goods );
1218 cont_convoi_capacity.set_visible(true);
1219 }
1220 else {
1221 txt_convoi_count.clear();
1222 txt_convoi_speed.clear();
1223 txt_convoi_value.clear();
1224 txt_convoi_cost.clear();
1225 txt_convoi_power.clear();
1226 txt_convoi_weight.clear();
1227 sb_convoi_length.set_visible(false);
1228 cont_convoi_capacity.set_visible(false);
1229 }
1230 }
1231
1232
calc_restwert(const vehicle_desc_t * veh_type)1233 sint64 depot_frame_t::calc_restwert(const vehicle_desc_t *veh_type)
1234 {
1235 sint64 wert = 0;
1236 FOR(slist_tpl<vehicle_t*>, const v, depot->get_vehicle_list()) {
1237 if( v->get_desc() == veh_type ) {
1238 wert += v->calc_sale_value();
1239 }
1240 }
1241 return wert;
1242 }
1243
1244
image_from_storage_list(gui_image_list_t::image_data_t * image_data)1245 void depot_frame_t::image_from_storage_list(gui_image_list_t::image_data_t *image_data)
1246 {
1247 if( image_data->lcolor != color_idx_to_rgb(COL_RED) && image_data->rcolor != color_idx_to_rgb(COL_RED) ) {
1248 if( veh_action == va_sell ) {
1249 depot->call_depot_tool('s', convoihandle_t(), image_data->text );
1250 }
1251 else {
1252 convoihandle_t cnv = depot->get_convoi( icnv );
1253 if( !cnv.is_bound() && !depot->get_owner()->is_locked() ) {
1254 // adding new convoi, block depot actions until command executed
1255 // otherwise in multiplayer it's likely multiple convois get created
1256 // rather than one new convoi with multiple vehicles
1257 depot->set_command_pending();
1258 }
1259 depot->call_depot_tool( veh_action == va_insert ? 'i' : 'a', cnv, image_data->text );
1260 }
1261 }
1262 }
1263
1264
image_from_convoi_list(uint nr,bool to_end)1265 void depot_frame_t::image_from_convoi_list(uint nr, bool to_end)
1266 {
1267 const convoihandle_t cnv = depot->get_convoi( icnv );
1268 if( cnv.is_bound() && nr < cnv->get_vehicle_count() ) {
1269 // we remove all connected vehicles together!
1270 // find start
1271 unsigned start_nr = nr;
1272 while( start_nr > 0 ) {
1273 start_nr--;
1274 const vehicle_desc_t *info = cnv->get_vehikel(start_nr)->get_desc();
1275 if( info->get_trailer_count() != 1 ) {
1276 start_nr++;
1277 break;
1278 }
1279 }
1280
1281 cbuffer_t start;
1282 start.printf("%u", start_nr);
1283
1284 const char tool = to_end ? 'R' : 'r';
1285 depot->call_depot_tool( tool, cnv, start );
1286 }
1287 }
1288
1289
action_triggered(gui_action_creator_t * comp,value_t p)1290 bool depot_frame_t::action_triggered( gui_action_creator_t *comp, value_t p)
1291 {
1292 convoihandle_t cnv = depot->get_convoi( icnv );
1293
1294 if( depot->is_command_pending() ) {
1295 // block new commands until last command is executed
1296 return true;
1297 }
1298
1299 if( comp != NULL ) { // message from outside!
1300 if( comp == &bt_start ) {
1301 if( cnv.is_bound() ) {
1302 //first: close schedule (will update schedule on clients)
1303 destroy_win( (ptrdiff_t)cnv->get_schedule() );
1304 // only then call the tool to start
1305 char tool = event_get_last_control_shift() == 2 ? 'B' : 'b'; // start all with CTRL-click
1306 depot->call_depot_tool( tool, cnv, NULL);
1307 }
1308 }
1309 else if( comp == &bt_schedule ) {
1310 if( line_selector.get_selection() == 1 && !line_selector.is_dropped() ) { // create new line
1311 // promote existing individual schedule to line
1312 cbuffer_t buf;
1313 if( cnv.is_bound() && !selected_line.is_bound() ) {
1314 schedule_t* schedule = cnv->get_schedule();
1315 if( schedule ) {
1316 schedule->sprintf_schedule( buf );
1317 }
1318 }
1319 depot->call_depot_tool('l', convoihandle_t(), buf);
1320 return true;
1321 }
1322 else {
1323 open_schedule_editor();
1324 return true;
1325 }
1326 }
1327 else if( comp == &line_button ) {
1328 if( cnv.is_bound() ) {
1329 cnv->get_owner()->simlinemgmt.show_lineinfo( cnv->get_owner(), cnv->get_line() );
1330 welt->set_dirty();
1331 }
1332 }
1333 else if( comp == &bt_sell ) {
1334 depot->call_depot_tool('v', cnv, NULL);
1335 }
1336 // image list selection here ...
1337 else if( comp == &convoi ) {
1338 image_from_convoi_list( p.i, last_meta_event_get_class() == EVENT_DOUBLE_CLICK);
1339 }
1340 else if( comp == &pas && last_meta_event_get_class() != EVENT_DOUBLE_CLICK ) {
1341 image_from_storage_list(pas_vec[p.i]);
1342 }
1343 else if( comp == &electrics && last_meta_event_get_class() != EVENT_DOUBLE_CLICK ) {
1344 image_from_storage_list(electrics_vec[p.i]);
1345 }
1346 else if( comp == &loks && last_meta_event_get_class() != EVENT_DOUBLE_CLICK ) {
1347 image_from_storage_list(loks_vec[p.i]);
1348 }
1349 else if( comp == &waggons && last_meta_event_get_class() != EVENT_DOUBLE_CLICK ) {
1350 image_from_storage_list(waggons_vec[p.i]);
1351 }
1352 // convoi filters
1353 else if( comp == &bt_obsolete ) {
1354 show_retired_vehicles = (show_retired_vehicles == 0);
1355 bt_obsolete.pressed = show_retired_vehicles;
1356 depot_t::update_all_win();
1357 }
1358 else if( comp == &bt_show_all ) {
1359 show_all = (show_all == 0);
1360 bt_show_all.pressed = show_all;
1361 depot_t::update_all_win();
1362 }
1363 else if( comp == &name_filter_input ) {
1364 depot_t::update_all_win();
1365 }
1366 else if( comp == &bt_veh_action ) {
1367 if( veh_action == va_sell ) {
1368 veh_action = va_append;
1369 }
1370 else {
1371 veh_action++;
1372 }
1373 }
1374 else if( comp == &sort_by ) {
1375 depot->selected_sort_by = sort_by.get_selection();
1376 }
1377 else if( comp == &bt_copy_convoi ) {
1378 if( cnv.is_bound() ) {
1379 if( !welt->use_timeline() || welt->get_settings().get_allow_buying_obsolete_vehicles() || depot->check_obsolete_inventory( cnv ) ) {
1380 depot->call_depot_tool('c', cnv, NULL);
1381 }
1382 else {
1383 create_win( new news_img("Can't buy obsolete vehicles!"), w_time_delete, magic_none );
1384 }
1385 }
1386 return true;
1387 }
1388 else if( comp == &convoy_selector ) {
1389 icnv = p.i - 1;
1390 /* if( !depot->get_convoi(icnv).is_bound() ) {
1391 set_focus( NULL );
1392 }
1393 else {
1394 set_focus( (gui_component_t *)&convoy_selector );
1395 }*/
1396 }
1397 else if( comp == &line_selector ) {
1398 const int selection = p.i;
1399 if( selection == 0 ) { // unique
1400 if( selected_line.is_bound() ) {
1401 selected_line = linehandle_t();
1402 apply_line();
1403 }
1404 return true;
1405 }
1406 else if( selection == 1 ) { // create new line
1407 if( line_selector.is_dropped() ) { // but not from next/prev buttons
1408 // promote existing individual schedule to line
1409 cbuffer_t buf;
1410 if( cnv.is_bound() && !selected_line.is_bound() ) {
1411 schedule_t* schedule = cnv->get_schedule();
1412 if( schedule ) {
1413 schedule->sprintf_schedule( buf );
1414 }
1415 }
1416 last_selected_line = linehandle_t(); // clear last selected line so we can get a new one ...
1417 depot->call_depot_tool('l', convoihandle_t(), buf);
1418 }
1419 return true;
1420 }
1421 if( last_selected_line.is_bound() ) {
1422 if( selection == 2 ) { // last selected line
1423 selected_line = last_selected_line;
1424 apply_line();
1425 return true;
1426 }
1427 }
1428
1429 // access the selected element to get selected line
1430 line_scrollitem_t *item = dynamic_cast<line_scrollitem_t*>(line_selector.get_element(selection));
1431 if( item ) {
1432 selected_line = item->get_line();
1433 depot->set_last_selected_line( selected_line );
1434 last_selected_line = selected_line;
1435 apply_line();
1436 return true;
1437 }
1438 }
1439 else if( comp == &vehicle_filter ) {
1440 depot->selected_filter = vehicle_filter.get_selection();
1441 }
1442 else {
1443 return false;
1444 }
1445 build_vehicle_lists();
1446 }
1447 else {
1448 update_data();
1449 update_tabs();
1450 }
1451 layout(NULL);
1452 return true;
1453 }
1454
1455
infowin_event(const event_t * ev)1456 bool depot_frame_t::infowin_event(const event_t *ev)
1457 {
1458 // enable disable button actions
1459 if( ev->ev_class < INFOWIN && (depot == NULL || welt->get_active_player() != depot->get_owner()) ) {
1460 return false;
1461 }
1462
1463 const bool swallowed = gui_frame_t::infowin_event(ev);
1464
1465 if(IS_WINDOW_CHOOSE_NEXT(ev)) {
1466
1467 bool dir = (ev->ev_code==NEXT_WINDOW);
1468 depot_t *next_dep = depot_t::find_depot( depot->get_pos(), depot->get_typ(), depot->get_owner(), dir == NEXT_WINDOW );
1469 if(next_dep == NULL) {
1470 if(dir == NEXT_WINDOW) {
1471 // check the next from start of map
1472 next_dep = depot_t::find_depot( koord3d(-1,-1,0), depot->get_typ(), depot->get_owner(), true );
1473 }
1474 else {
1475 // respective end of map
1476 next_dep = depot_t::find_depot( koord3d(8192,8192,127), depot->get_typ(), depot->get_owner(), false );
1477 }
1478 }
1479
1480 if(next_dep && next_dep!=this->depot) {
1481 /**
1482 * Replace our depot_frame_t with a new at the same position.
1483 * Volker Meyer
1484 */
1485 scr_coord const pos = win_get_pos(this);
1486 destroy_win( this );
1487
1488 next_dep->show_info();
1489 win_set_pos(win_get_magic((ptrdiff_t)next_dep), pos.x, pos.y);
1490 welt->get_viewport()->change_world_position(next_dep->get_pos());
1491 }
1492 else {
1493 // recenter on current depot
1494 welt->get_viewport()->change_world_position(depot->get_pos());
1495 }
1496
1497 return true;
1498 }
1499
1500 if( swallowed && get_focus()==&name_filter_input && (ev->ev_class == EVENT_KEYBOARD || ev->ev_class == EVENT_STRING) ) {
1501 depot_t::update_all_win();
1502 }
1503
1504 return swallowed;
1505 }
1506
1507
draw(scr_coord pos,scr_size size)1508 void depot_frame_t::draw(scr_coord pos, scr_size size)
1509 {
1510 const bool action_allowed = welt->get_active_player() == depot->get_owner();
1511
1512 bt_new_line.enable( action_allowed );
1513 bt_change_line.enable( action_allowed );
1514 bt_copy_convoi.enable( action_allowed );
1515 bt_apply_line.enable( action_allowed );
1516 bt_start.enable( action_allowed );
1517 bt_schedule.enable( action_allowed );
1518 bt_destroy.enable( action_allowed );
1519 bt_sell.enable( action_allowed );
1520 bt_obsolete.enable( action_allowed );
1521 bt_show_all.enable( action_allowed );
1522 bt_veh_action.enable( action_allowed );
1523 line_button.enable( action_allowed );
1524
1525 convoihandle_t cnv = depot->get_convoi(icnv);
1526 // check for data inconsistencies (can happen with withdraw-all and vehicle in depot)
1527 if( !cnv.is_bound() && !convoi_pics.empty() ) {
1528 icnv=0;
1529 update_data();
1530 cnv = depot->get_convoi(icnv);
1531 }
1532
1533 gui_frame_t::draw(pos, size);
1534 draw_vehicle_info_text(pos);
1535 }
1536
1537
apply_line()1538 void depot_frame_t::apply_line()
1539 {
1540 if( icnv > -1 ) {
1541 convoihandle_t cnv = depot->get_convoi( icnv );
1542 // if no convoi is selected, do nothing
1543 if( !cnv.is_bound() ) {
1544 return;
1545 }
1546
1547 if( selected_line.is_bound() ) {
1548 // set new route only, a valid route is selected:
1549 char id[16];
1550 sprintf( id, "%i", selected_line.get_id() );
1551 cnv->call_convoi_tool('l', id );
1552 }
1553 else {
1554 // sometimes the user might wish to remove convoy from line
1555 // => we clear the schedule completely
1556 schedule_t *dummy = cnv->create_schedule()->copy();
1557 dummy->entries.clear();
1558
1559 cbuffer_t buf;
1560 dummy->sprintf_schedule(buf);
1561 cnv->call_convoi_tool('g', (const char*)buf );
1562
1563 delete dummy;
1564 }
1565 }
1566 }
1567
1568
open_schedule_editor()1569 void depot_frame_t::open_schedule_editor()
1570 {
1571 convoihandle_t cnv = depot->get_convoi( icnv );
1572
1573 if( cnv.is_bound() && cnv->get_vehicle_count() > 0 ) {
1574 if( selected_line.is_bound() && event_get_last_control_shift() == 2 ) { // update line with CTRL-click
1575 create_win( new line_management_gui_t( selected_line, depot->get_owner() ), w_info, (ptrdiff_t)selected_line.get_rep() );
1576 }
1577 else { // edit individual schedule
1578 // this can happen locally, since any update of the schedule is done during closing window
1579 schedule_t *schedule = cnv->create_schedule();
1580 assert(schedule!=NULL);
1581 gui_frame_t *schedulewin = win_get_magic( (ptrdiff_t)schedule );
1582 if( schedulewin == NULL ) {
1583 cnv->open_schedule_window( welt->get_active_player() == cnv->get_owner() );
1584 }
1585 else {
1586 top_win( schedulewin );
1587 }
1588 }
1589 }
1590 else {
1591 create_win( new news_img("Please choose vehicles first\n"), w_time_delete, magic_none );
1592 }
1593 }
1594
1595
draw_vehicle_info_text(scr_coord pos)1596 void depot_frame_t::draw_vehicle_info_text(scr_coord pos)
1597 {
1598 cbuffer_t buf;
1599 const scr_size size = get_windowsize();
1600 PUSH_CLIP(pos.x, pos.y, size.w-1, size.h-1);
1601
1602 gui_component_t const* const tab = tabs.get_aktives_tab();
1603 gui_image_list_t const* const lst =
1604 tab == &scrolly_pas ? &pas :
1605 tab == &scrolly_electrics ? &electrics :
1606 tab == &scrolly_loks ? &loks :
1607 &waggons;
1608 int x = get_mouse_x();
1609 int y = get_mouse_y();
1610 double resale_value = -1.0;
1611 const vehicle_desc_t *veh_type = NULL;
1612 bool new_vehicle_length_sb_force_zero = false;
1613 sint16 convoi_number = -1;
1614 scr_coord relpos = scr_coord(0, ((gui_scrollpane_t *)tabs.get_aktives_tab())->get_scroll_y());
1615 int sel_index = lst->index_at( pos + tabs.get_pos() - relpos, x, y - D_TITLEBAR_HEIGHT - tabs.get_required_size().h);
1616
1617 if( (sel_index != -1) && (tabs.getroffen(x - pos.x, y - pos.y - D_TITLEBAR_HEIGHT)) ) {
1618 // cursor over a vehicle in the selection list
1619 const vector_tpl<gui_image_list_t::image_data_t*>& vec = (lst == &electrics ? electrics_vec : (lst == &pas ? pas_vec : (lst == &loks ? loks_vec : waggons_vec)));
1620 veh_type = vehicle_builder_t::get_info( vec[sel_index]->text );
1621 if( vec[sel_index]->lcolor == color_idx_to_rgb(COL_RED) || veh_action == va_sell ) {
1622 // don't show new_vehicle_length_sb when can't actually add the highlighted vehicle, or selling from inventory
1623 new_vehicle_length_sb_force_zero = true;
1624 }
1625 if( vec[sel_index]->count > 0 ) {
1626 resale_value = (double)calc_restwert( veh_type );
1627 }
1628 }
1629 else {
1630 // cursor over a vehicle in the convoi
1631 relpos = scr_coord(scrolly_convoi.get_scroll_x(), 0);
1632
1633 convoi_number = sel_index = convoi.index_at(pos - relpos + scrolly_convoi.get_pos(), x, y - D_TITLEBAR_HEIGHT);
1634 if( sel_index != -1 ) {
1635 convoihandle_t cnv = depot->get_convoi( icnv );
1636 veh_type = cnv->get_vehikel( sel_index )->get_desc();
1637 resale_value = cnv->get_vehikel( sel_index )->calc_sale_value();
1638 new_vehicle_length_sb_force_zero = true;
1639 }
1640 }
1641
1642 {
1643 const char *c;
1644 switch( const uint32 count = depot->get_vehicle_list().get_count() ) {
1645 case 0: {
1646 c = translator::translate("Keine Einzelfahrzeuge im Depot");
1647 break;
1648 }
1649 case 1: {
1650 c = translator::translate("1 Einzelfahrzeug im Depot");
1651 break;
1652 }
1653 default: {
1654 buf.printf( translator::translate("%d Einzelfahrzeuge im Depot"), count );
1655 c = buf;
1656 break;
1657 }
1658 }
1659 display_proportional_rgb( pos.x + D_MARGIN_LEFT, pos.y + D_TITLEBAR_HEIGHT + div_tabbottom.get_pos().y + div_tabbottom.get_size().h + 1, c, ALIGN_LEFT, SYSCOL_TEXT, true );
1660 }
1661
1662 if( veh_type ) {
1663
1664 // column 1
1665 buf.clear();
1666 buf.printf( "%s", translator::translate( veh_type->get_name(), welt->get_settings().get_name_language_id() ) );
1667
1668 if( veh_type->get_power() > 0 ) { // LOCO
1669 buf.printf( " (%s)\n", translator::translate( engine_type_names[veh_type->get_engine_type()+1] ) );
1670 }
1671 else {
1672 buf.append( "\n" );
1673 }
1674
1675 if( sint64 fix_cost = welt->scale_with_month_length(veh_type->get_maintenance()) ) {
1676 char tmp[128];
1677 money_to_string( tmp, veh_type->get_price() / 100.0, false );
1678 buf.printf( translator::translate("Cost: %8s (%.2f$/km %.2f$/m)\n"), tmp, veh_type->get_running_cost()/100.0, fix_cost/100.0 );
1679 }
1680 else {
1681 char tmp[128];
1682 money_to_string( tmp, veh_type->get_price() / 100.0, false );
1683 buf.printf( translator::translate("Cost: %8s (%.2f$/km)\n"), tmp, veh_type->get_running_cost()/100.0 );
1684 }
1685
1686 if( veh_type->get_capacity() > 0 ) { // must translate as "Capacity: %3d%s %s\n"
1687 buf.printf( translator::translate("Capacity: %d%s %s\n"),
1688 veh_type->get_capacity(),
1689 translator::translate( veh_type->get_freight_type()->get_mass() ),
1690 veh_type->get_freight_type()->get_catg()==0 ? translator::translate( veh_type->get_freight_type()->get_name() ) : translator::translate( veh_type->get_freight_type()->get_catg_name() )
1691 );
1692 }
1693 else {
1694 buf.append( "\n" );
1695 }
1696
1697 buf.printf( "%s %3d km/h\n", translator::translate("Max. speed:"), veh_type->get_topspeed() );
1698
1699 if( veh_type->get_power() > 0 ) {
1700 if( veh_type->get_gear() != 64 ){
1701 buf.printf( "%s %4d kW (x%0.2f)\n", translator::translate("Power:"), veh_type->get_power(), veh_type->get_gear() / 64.0 );
1702 }
1703 else {
1704 buf.printf( translator::translate("Power: %4d kW\n"), veh_type->get_power() );
1705 }
1706 }
1707
1708 int yyy = pos.y + D_TITLEBAR_HEIGHT + div_action_bottom.get_pos().y + div_action_bottom.get_size().h + 2;
1709 display_multiline_text_rgb( pos.x + D_MARGIN_LEFT, yyy, buf, SYSCOL_TEXT);
1710
1711 // column 2
1712 buf.clear();
1713 buf.printf( "%s %4.1ft\n", translator::translate("Weight:"), veh_type->get_weight() / 1000.0 );
1714 buf.printf( "%s %s - ", translator::translate("Available:"), translator::get_short_date(veh_type->get_intro_year_month() / 12, veh_type->get_intro_year_month() % 12) );
1715
1716 if( veh_type->get_retire_year_month() != DEFAULT_RETIRE_DATE * 12 ) {
1717 buf.printf( "%s\n", translator::get_short_date(veh_type->get_retire_year_month() / 12, veh_type->get_retire_year_month() % 12) );
1718 }
1719 else {
1720 buf.append( "*\n" );
1721 }
1722
1723 if( char const* const copyright = veh_type->get_copyright() ) {
1724 buf.printf( translator::translate("Constructed by %s"), copyright );
1725 }
1726 buf.append( "\n" );
1727
1728 if( resale_value != -1.0 ) {
1729 char tmp[128];
1730 money_to_string( tmp, resale_value / 100.0, false );
1731 buf.printf( "%s %8s", translator::translate("Restwert:"), tmp );
1732 }
1733
1734 display_multiline_text_rgb( pos.x + second_column_x, yyy + LINESPACE, buf, SYSCOL_TEXT);
1735
1736 // update speedbar
1737 new_vehicle_length_sb = new_vehicle_length_sb_force_zero ? 0 : convoi_length_ok_sb + convoi_length_slower_sb + convoi_length_too_slow_sb + veh_type->get_length();
1738
1739 txt_convoi_number.clear();
1740 if (convoi_number>-1){
1741 txt_convoi_number.printf("%d", convoi_number + 1);
1742 lb_convoi_number.set_pos(scr_coord(((depot->get_x_grid() * get_base_tile_raster_width() / 64 + 4) - (depot->get_x_grid() * get_base_tile_raster_width() / 64 / 2))*convoi_number + 4, 4));
1743 }
1744 }
1745 else {
1746 txt_convoi_number.clear();
1747 new_vehicle_length_sb = 0;
1748 }
1749
1750 POP_CLIP();
1751 }
1752
1753
update_tabs()1754 void depot_frame_t::update_tabs()
1755 {
1756 gui_component_t *old_tab = tabs.get_aktives_tab();
1757 tabs.clear();
1758
1759 bool one = false;
1760
1761 // add only if there are any
1762 if( !pas_vec.empty() ) {
1763 tabs.add_tab(&scrolly_pas, translator::translate( depot->get_passenger_name() ) );
1764 one = true;
1765 }
1766
1767 // add only if there are any trolleybuses
1768 if( !electrics_vec.empty() ) {
1769 tabs.add_tab(&scrolly_electrics, translator::translate( depot->get_electrics_name() ) );
1770 one = true;
1771 }
1772
1773 // add, if wagons are there ...
1774 if( !loks_vec.empty() || !waggons_vec.empty() ) {
1775 tabs.add_tab(&scrolly_loks, translator::translate( depot->get_zieher_name() ) );
1776 one = true;
1777 }
1778
1779 // only add, if there are wagons
1780 if( !waggons_vec.empty() ) {
1781 tabs.add_tab(&scrolly_waggons, translator::translate( depot->get_haenger_name() ) );
1782 one = true;
1783 }
1784
1785 if( !one ) {
1786 // add passenger as default
1787 tabs.add_tab(&scrolly_pas, translator::translate( depot->get_passenger_name() ) );
1788 }
1789
1790 // Look, if there is our old tab present again (otherwise it will be 0 by tabs.clear()).
1791 for( uint8 i = 0; i < tabs.get_count(); i++ ) {
1792 if( old_tab == tabs.get_tab(i) ) {
1793 // Found it!
1794 tabs.set_active_tab_index(i);
1795 break;
1796 }
1797 }
1798 }
1799
1800
depot_convoi_capacity_t()1801 depot_convoi_capacity_t::depot_convoi_capacity_t()
1802 {
1803 total_pax = 0;
1804 total_mail = 0;
1805 total_goods = 0;
1806 }
1807
1808
set_totals(uint32 pax,uint32 mail,uint32 goods)1809 void depot_convoi_capacity_t::set_totals(uint32 pax, uint32 mail, uint32 goods)
1810 {
1811 total_pax = pax;
1812 total_mail = mail;
1813 total_goods = goods;
1814 }
1815
1816
draw(scr_coord off)1817 void depot_convoi_capacity_t::draw(scr_coord off)
1818 {
1819 cbuffer_t cbuf;
1820
1821 scr_coord_val w = 0;
1822 cbuf.clear();
1823 cbuf.printf("%s %d", translator::translate("Capacity:"), total_pax );
1824 w += display_proportional_clip_rgb( pos.x+off.x + w, pos.y+off.y , cbuf, ALIGN_LEFT, SYSCOL_TEXT, true);
1825 display_color_img( skinverwaltung_t::passengers->get_image_id(0), pos.x + off.x + w, pos.y + off.y, 0, false, false);
1826
1827 w += 16;
1828 cbuf.clear();
1829 cbuf.printf("%d", total_mail );
1830 w += display_proportional_clip_rgb( pos.x+off.x + w, pos.y+off.y, cbuf, ALIGN_LEFT, SYSCOL_TEXT, true);
1831 display_color_img( skinverwaltung_t::mail->get_image_id(0), pos.x + off.x + w, pos.y + off.y, 0, false, false);
1832
1833 w += 16;
1834 cbuf.clear();
1835 cbuf.printf("%d", total_goods );
1836 w += display_proportional_clip_rgb( pos.x+off.x + w, pos.y+off.y, cbuf, ALIGN_LEFT, SYSCOL_TEXT, true);
1837 display_color_img( skinverwaltung_t::goods->get_image_id(0), pos.x + off.x + w, pos.y + off.y, 0, false, false);
1838 }
1839
1840
get_rdwr_id()1841 uint32 depot_frame_t::get_rdwr_id()
1842 {
1843 return magic_depot;
1844 }
1845
rdwr(loadsave_t * file)1846 void depot_frame_t::rdwr( loadsave_t *file)
1847 {
1848 if (file->is_version_less(120, 9)) {
1849 destroy_win(this);
1850 return;
1851 }
1852
1853 // depot position
1854 koord3d pos;
1855 if( file->is_saving() ) {
1856 pos = depot->get_pos();
1857 }
1858 pos.rdwr( file );
1859 // window size
1860 scr_size size = get_windowsize();
1861 size.rdwr( file );
1862
1863 if( file->is_loading() ) {
1864 depot_t *dep = welt->lookup(pos)->get_depot();
1865 if (dep) {
1866 init(dep);
1867 }
1868 }
1869 tabs.rdwr(file);
1870 vehicle_filter.rdwr(file);
1871 file->rdwr_byte(veh_action);
1872 file->rdwr_long(icnv);
1873 sort_by.rdwr(file);
1874 simline_t::rdwr_linehandle_t(file, selected_line);
1875
1876 if( depot && file->is_loading() ) {
1877 update_data();
1878 update_tabs();
1879 reset_min_windowsize();
1880 set_windowsize(size);
1881
1882 win_set_magic(this, (ptrdiff_t)depot);
1883 }
1884
1885 if (depot == NULL) {
1886 destroy_win(this);
1887 }
1888 }
1889