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