1 /*
2 * Copyright (c) 1997 - 2001 Hansj�rg Malthaner
3 *
4 * This file is part of the Simutrans project under the artistic licence.
5 * (see licence.txt)
6 */
7
8 /*
9 * [Mathew Hounsell] Min Size Button On Map Window 20030313
10 */
11
12 #include <string>
13 #include <stdio.h>
14 #include <cmath>
15
16 #include "minimap.h"
17 #include "map_frame.h"
18
19 #include "simwin.h"
20 #include "../simsys.h"
21
22 #include "../simworld.h"
23 #include "../display/simgraph.h"
24 #include "../display/viewport.h"
25 #include "../simcolor.h"
26 #include "../bauer/fabrikbauer.h"
27 #include "../bauer/goods_manager.h"
28 #include "../dataobj/environment.h"
29 #include "../dataobj/translator.h"
30 #include "../dataobj/koord.h"
31 #include "../dataobj/loadsave.h"
32 #include "../descriptor/factory_desc.h"
33 #include "../simfab.h"
34 #include "../player/finance.h"
35
36 static koord old_ij=koord::invalid;
37
38 karte_ptr_t map_frame_t::welt;
39
40 scr_size map_frame_t::window_size;
41 bool map_frame_t::legend_visible=false;
42 bool map_frame_t::scale_visible=false;
43 bool map_frame_t::directory_visible=false;
44 bool map_frame_t::is_cursor_hidden=false;
45 bool map_frame_t::filter_factory_list=true;
46
47 // Hajo: we track our position onscreen
48 scr_coord map_frame_t::screenpos;
49
50 /**
51 * Scroll-container of map. Hack: size calculations of minimap_t are intertwined with map_frame_t.
52 */
53 class gui_scrollpane_map_t : public gui_scrollpane_t
54 {
55 public:
gui_scrollpane_map_t(gui_component_t * comp)56 gui_scrollpane_map_t(gui_component_t *comp) : gui_scrollpane_t(comp) {}
57
get_max_size() const58 scr_size get_max_size() const OVERRIDE { return scr_size::inf;}
59 };
60
61 /**
62 * Entries in factory legend: show color indicator + name
63 */
64 class legend_entry_t : public gui_component_t
65 {
66 gui_label_t label;
67 PIXVAL color;
68 public:
legend_entry_t(const char * text,PIXVAL c)69 legend_entry_t(const char* text, PIXVAL c) : label(text), color(c) {}
70
get_min_size() const71 scr_size get_min_size() const OVERRIDE
72 {
73 return label.get_min_size() + scr_size(D_INDICATOR_BOX_WIDTH + D_H_SPACE, 0);
74 }
75
get_max_size() const76 scr_size get_max_size() const OVERRIDE
77 {
78 return scr_size( scr_size::inf.w, label.get_max_size().h );
79 }
80
draw(scr_coord offset)81 void draw(scr_coord offset) OVERRIDE
82 {
83 scr_coord pos = get_pos() + offset;
84 display_fillbox_wh_clip_rgb(pos.x, pos.y + D_GET_CENTER_ALIGN_OFFSET(D_INDICATOR_BOX_HEIGHT,LINESPACE), D_INDICATOR_BOX_WIDTH, D_INDICATOR_BOX_HEIGHT, color, false);
85 label.draw(pos + scr_size(D_INDICATOR_BOX_WIDTH + D_H_SPACE, 0));
86 }
87 };
88
89 /**
90 * Show scale of severity-MAX_SEVERITY_COLORS
91 */
92 class gui_scale_t : public gui_component_t
93 {
94 public:
draw(scr_coord offset)95 void draw(scr_coord offset) OVERRIDE
96 {
97 scr_coord pos = get_pos() + offset;
98 double bar_width = (double)get_size().w/(double)MAX_SEVERITY_COLORS;
99 // color bar
100 for( int i=0; i<MAX_SEVERITY_COLORS; i++ ) {
101 display_fillbox_wh_clip_rgb(pos.x + (i*bar_width), pos.y+2, bar_width+1, 7, minimap_t::calc_severity_color(i, MAX_SEVERITY_COLORS-1), false);
102 }
103 }
get_min_size() const104 scr_size get_min_size() const OVERRIDE
105 {
106 return scr_size(0, 9);
107 }
get_max_size() const108 scr_size get_max_size() const OVERRIDE
109 {
110 return scr_size( scr_size::inf.w, 9);
111 }
112 };
113
114 typedef struct {
115 PIXVAL color;
116 PIXVAL select_color;
117 const char *button_text;
118 const char *tooltip_text;
119 minimap_t::MAP_DISPLAY_MODE mode;
120 } map_button_t;
121
122
123 map_button_t button_init[MAP_MAX_BUTTONS] = {
124 { COL_LIGHT_GREEN, COL_DARK_GREEN, "Towns", "Overlay town names", minimap_t::MAP_TOWN },
125 { COL_LIGHT_GREEN, COL_DARK_GREEN, "CityLimit", "Overlay city limits", minimap_t::MAP_CITYLIMIT },
126 { COL_WHITE, COL_GREY5, "Buildings", "Show level of city buildings", minimap_t::MAP_LEVEL },
127 { COL_LIGHT_GREEN, COL_DARK_GREEN, "PaxDest", "Overlay passenger destinations when a town window is open", minimap_t::MAP_PAX_DEST },
128 { COL_LIGHT_GREEN, COL_DARK_GREEN, "Tourists", "Highlite tourist attraction", minimap_t::MAP_TOURIST },
129 { COL_LIGHT_GREEN, COL_DARK_GREEN, "Factories", "Highlite factories", minimap_t::MAP_FACTORIES },
130 { COL_LIGHT_YELLOW, COL_DARK_YELLOW, "Passagiere", "Show passenger coverage/passenger network", minimap_t::MAP_PASSENGER },
131 { COL_LIGHT_YELLOW, COL_DARK_YELLOW, "Post", "Show mail service coverage/mail network", minimap_t::MAP_MAIL },
132 { COL_LIGHT_YELLOW, COL_DARK_YELLOW, "Fracht", "Show transported freight/freight network", minimap_t::MAP_FREIGHT },
133 { COL_LIGHT_PURPLE, COL_DARK_PURPLE, "Status", "Show capacity and if halt is overcrowded", minimap_t::MAP_STATUS },
134 { COL_LIGHT_PURPLE, COL_DARK_PURPLE, "hl_btn_sort_waiting", "Show how many people/much is waiting at halts", minimap_t::MAP_WAITING },
135 { COL_LIGHT_PURPLE, COL_DARK_PURPLE, "Queueing", "Show the change of waiting at halts", minimap_t::MAP_WAITCHANGE },
136 { COL_LIGHT_PURPLE, COL_DARK_PURPLE, "Service", "Show how many convoi reach a station", minimap_t::MAP_SERVICE },
137 { COL_LIGHT_PURPLE, COL_DARK_PURPLE, "Transfers", "Sum of departure/arrivals at halts", minimap_t::MAP_TRANSFER },
138 { COL_LIGHT_PURPLE, COL_DARK_PURPLE, "Origin", "Show initial passenger departure", minimap_t::MAP_ORIGIN },
139 { COL_WHITE, COL_GREY5, "Traffic", "Show usage of network", minimap_t::MAP_TRAFFIC },
140 { COL_WHITE, COL_GREY5, "Speedlimit", "Show speedlimit of ways", minimap_t::MAX_SPEEDLIMIT },
141 { COL_WHITE, COL_GREY5, "Tracks", "Highlight railroad tracks", minimap_t::MAP_TRACKS },
142 { COL_LIGHT_GREEN, COL_DARK_GREEN, "Depots", "Highlite depots", minimap_t::MAP_DEPOT },
143 { COL_WHITE, COL_GREY5, "Powerlines", "Highlite electrical transmission lines", minimap_t::MAP_POWERLINES },
144 { COL_WHITE, COL_GREY5, "Forest", "Highlite forests", minimap_t::MAP_FOREST },
145 { COL_WHITE, COL_GREY5, "Ownership", "Show the owenership of infrastructure", minimap_t::MAP_OWNER }
146 };
147
148 #define scrolly (*p_scrolly)
149
map_frame_t()150 map_frame_t::map_frame_t() :
151 gui_frame_t( translator::translate("Reliefkarte") )
152 {
153 // init statics
154 old_ij = koord::invalid;
155 is_dragging = false;
156 zoomed = false;
157
158 // init map
159 minimap_t *karte = minimap_t::get_instance();
160 karte->init();
161 karte->set_display_mode( ( minimap_t::MAP_DISPLAY_MODE)env_t::default_mapmode );
162 // show all players by default
163 karte->player_showed_on_map = -1;
164
165 p_scrolly = new gui_scrollpane_map_t( minimap_t::get_instance());
166 // initialize scrollbar positions -- LATER
167 const scr_size size = karte->get_size();
168 const scr_size s_size=scrolly.get_size();
169 const koord ij = welt->get_viewport()->get_world_position();
170 const scr_size win_size = size-s_size; // this is the visible area
171
172 scrolly.set_scroll_position( max(0,min(ij.x-win_size.w/2,size.w)), max(0, min(ij.y-win_size.h/2,size.h)) );
173 scrolly.set_focusable( true );
174 scrolly.set_scrollbar_mode(scrollbar_t::show_always);
175
176
177 set_table_layout(1,0);
178
179 // first row of controls
180 add_table(3,1);
181 {
182 // first row of controls
183 // selections button
184 b_show_legend.init(button_t::roundbox_state, "Show legend");
185 b_show_legend.set_tooltip("Shows buttons on special topics.");
186 b_show_legend.add_listener(this);
187 add_component(&b_show_legend);
188
189 // industry list button
190 b_show_directory.init(button_t::roundbox_state, "Show industry");
191 b_show_directory.set_tooltip("Shows a listing with all industries on the map.");
192 b_show_directory.add_listener(this);
193 add_component(&b_show_directory);
194
195 // scale button
196 b_show_scale.init(button_t::roundbox_state, "Show map scale");
197 b_show_scale.set_tooltip("Shows the color code for several selections.");
198 b_show_scale.add_listener(this);
199 add_component(&b_show_scale);
200 }
201 end_table();
202
203
204 // second row of controls
205 zoom_row = add_table(6,0);
206 {
207 // zoom levels label
208 new_component<gui_label_t>("map zoom");
209
210 // zoom levels arrow left
211 zoom_buttons[0].init(button_t::repeatarrowleft, NULL);
212 zoom_buttons[0].add_listener( this );
213 add_component( zoom_buttons+0 );
214
215 // zoom level value label
216 zoom_value_label.buf().append("1:1");
217 zoom_value_label.update();
218 add_component( &zoom_value_label );
219
220 // zoom levels arrow right
221 zoom_buttons[1].init(button_t::repeatarrowright, NULL);
222 zoom_buttons[1].add_listener( this );
223 add_component( zoom_buttons+1 );
224
225 // rotate map 45� (isometric view)
226 b_rotate45.init( button_t::square_state, "isometric map");
227 b_rotate45.set_tooltip("Similar view as the main window");
228 b_rotate45.add_listener(this);
229 b_rotate45.pressed = karte->is_isometric();
230 add_component(&b_rotate45);
231
232 new_component<gui_fill_t>();
233 }
234 end_table();
235
236 // filter container
237 filter_container.set_visible(false);
238 add_component(&filter_container);
239 filter_container.set_table_layout(1,0);
240
241 filter_container.add_table(5,0);
242 // insert selections: show networks, in filter container
243 b_overlay_networks.init(button_t::square_state, "Networks");
244 b_overlay_networks.set_tooltip("Overlay schedules/network");
245 b_overlay_networks.add_listener(this);
246 b_overlay_networks.pressed = (env_t::default_mapmode & minimap_t::MAP_LINES)!=0;
247 filter_container.add_component( &b_overlay_networks );
248
249 // player combo for network overlay
250 viewed_player_c.new_component<gui_scrolled_list_t::const_text_scrollitem_t>(translator::translate("All"), SYSCOL_TEXT);
251 viewable_players[ 0 ] = -1;
252 for( int np = 0, count = 1; np < MAX_PLAYER_COUNT; np++ ) {
253 if( welt->get_player( np ) && welt->get_player( np )->get_finance()->has_convoi()) {
254 viewed_player_c.new_component<gui_scrolled_list_t::const_text_scrollitem_t>(welt->get_player( np )->get_name(), color_idx_to_rgb(welt->get_player( np )->get_player_color1()+4));
255 viewable_players[ count++ ] = np;
256 }
257 }
258 viewed_player_c.set_selection(0);
259 viewed_player_c.set_focusable( true );
260 viewed_player_c.add_listener( this );
261 filter_container.add_component(&viewed_player_c);
262
263 // freight combo for network overlay
264 freight_type_c.set_pos( scr_coord(2*D_BUTTON_WIDTH+3*D_H_SPACE, 0) );
265 freight_type_c.set_size( scr_size(D_BUTTON_WIDTH,D_BUTTON_HEIGHT) );
266 freight_type_c.set_max_size( scr_size( 116, 5 * D_BUTTON_HEIGHT) );
267 {
268 viewable_freight_types.append(NULL);
269 freight_type_c.new_component<gui_scrolled_list_t::const_text_scrollitem_t>( translator::translate("All"), SYSCOL_TEXT) ;
270 viewable_freight_types.append(goods_manager_t::passengers);
271 freight_type_c.new_component<gui_scrolled_list_t::const_text_scrollitem_t>( translator::translate("Passagiere"), SYSCOL_TEXT) ;
272 viewable_freight_types.append(goods_manager_t::mail);
273 freight_type_c.new_component<gui_scrolled_list_t::const_text_scrollitem_t>( translator::translate("Post"), SYSCOL_TEXT) ;
274 viewable_freight_types.append(goods_manager_t::none); // for all freight ...
275 freight_type_c.new_component<gui_scrolled_list_t::const_text_scrollitem_t>( translator::translate("Fracht"), SYSCOL_TEXT) ;
276 for( int i = 0; i < goods_manager_t::get_max_catg_index(); i++ ) {
277 const goods_desc_t *freight_type = goods_manager_t::get_info_catg(i);
278 const int index = freight_type->get_catg_index();
279 if( index == goods_manager_t::INDEX_NONE || freight_type->get_catg()==0 ) {
280 continue;
281 }
282 freight_type_c.new_component<gui_scrolled_list_t::const_text_scrollitem_t>(translator::translate(freight_type->get_catg_name()), SYSCOL_TEXT);
283 viewable_freight_types.append(freight_type);
284 }
285 for( int i=0; i < goods_manager_t::get_count(); i++ ) {
286 const goods_desc_t *ware = goods_manager_t::get_info(i);
287 if( ware->get_catg() == 0 && ware->get_index() > 2 ) {
288 // Special freight: Each good is special
289 viewable_freight_types.append(ware);
290 freight_type_c.new_component<gui_scrolled_list_t::const_text_scrollitem_t>( translator::translate(ware->get_name()), SYSCOL_TEXT) ;
291 }
292 }
293 }
294 freight_type_c.set_selection(0);
295 minimap_t::get_instance()->freight_type_group_index_showed_on_map = NULL;
296 freight_type_c.set_focusable( true );
297 freight_type_c.add_listener( this );
298 filter_container.add_component(&freight_type_c);
299
300 // mode of transport combo for network overlay
301 for (int i = 0; i < simline_t::MAX_LINE_TYPE; i++) {
302 transport_type_c.new_component<gui_scrolled_list_t::const_text_scrollitem_t>(simline_t::get_linetype_name((simline_t::linetype)i), SYSCOL_TEXT);
303 }
304 transport_type_c.set_selection(0);
305 minimap_t::get_instance()->transport_type_showed_on_map = simline_t::line;
306 transport_type_c.set_focusable( true );
307 transport_type_c.add_listener( this );
308 filter_container.add_component(&transport_type_c);
309
310 b_overlay_networks_load_factor.init(button_t::square_state, "Free Capacity");
311 b_overlay_networks_load_factor.set_tooltip("Color according to transport capacity left");
312 b_overlay_networks_load_factor.add_listener(this);
313 b_overlay_networks_load_factor.pressed = 0;
314 minimap_t::get_instance()->show_network_load_factor = 0;
315 filter_container.add_component( &b_overlay_networks_load_factor );
316 filter_container.end_table();
317
318 filter_container.add_table(5,0)->set_force_equal_columns(true);
319 // insert filter buttons in legend container
320 for (int index=0; index<MAP_MAX_BUTTONS; index++) {
321 filter_buttons[index].init( button_t::box_state | button_t::flexible, button_init[index].button_text);
322 filter_buttons[index].text_color = SYSCOL_TEXT;
323 filter_buttons[index].set_tooltip( button_init[index].tooltip_text );
324 filter_buttons[index].add_listener(this);
325 filter_container.add_component(filter_buttons + index);
326 }
327 filter_container.end_table();
328 update_buttons();
329
330 // directory container
331 directory_container.set_table_layout(4,0);
332 directory_container.set_visible(false);
333 add_component(&directory_container);
334
335 // factory list: show used button
336 b_filter_factory_list.init(button_t::square_state, "Show only used");
337 b_filter_factory_list.set_tooltip("In the industry legend show only currently existing factories");
338 b_filter_factory_list.add_listener(this);
339 directory_container.add_component( &b_filter_factory_list, 4 );
340 update_factory_legend();
341
342 // scale container
343 scale_container.set_table_layout(3,0);
344 scale_container.set_visible(false);
345 add_component(&scale_container);
346 scale_container.new_component<gui_label_t>("min");
347 scale_container.new_component<gui_scale_t>();
348 scale_container.new_component<gui_label_t>("max");
349
350 // map scrolly
351 scrolly.set_show_scroll_x(true);
352 scrolly.set_scroll_discrete_y(false);
353 take_component(p_scrolly);
354
355 // restore window size and options
356 show_hide_legend( legend_visible );
357 show_hide_scale( scale_visible );
358 show_hide_directory( directory_visible );
359
360 reset_min_windowsize();
361 set_windowsize( window_size );
362 set_resizemode(diagonal_resize);
363 }
364
365
update_buttons()366 void map_frame_t::update_buttons()
367 {
368 for( int i=0; i<MAP_MAX_BUTTONS; i++ ) {
369 filter_buttons[i].pressed = (button_init[i].mode&env_t::default_mapmode)!=0;
370 filter_buttons[i].background_color = color_idx_to_rgb(filter_buttons[i].pressed ? button_init[i].select_color : button_init[i].color);
371 }
372 }
373
374
update_factory_legend()375 void map_frame_t::update_factory_legend()
376 {
377 directory_container.remove_all();
378 directory_container.add_component( &b_filter_factory_list, 4 );
379
380 if( directory_visible ) {
381 vector_tpl<const factory_desc_t*> factory_types;
382 // generate list of factory types
383 if( filter_factory_list ) {
384 FOR(slist_tpl<fabrik_t*>, const f, welt->get_fab_list()) {
385 if( f->get_desc()->get_distribution_weight() > 0 ) {
386 factory_types.append_unique(f->get_desc());
387 }
388 }
389 }
390 else {
391 FOR(stringhashtable_tpl<factory_desc_t const*>, i, factory_builder_t::get_factory_table()) {
392 factory_desc_t const* const d = i.value;
393 if (d->get_distribution_weight() > 0) {
394 factory_types.append_unique(d);
395 }
396 }
397 }
398 // add corresponding legend entries
399 FOR(vector_tpl<const factory_desc_t*>, f, factory_types) {
400 directory_container.new_component<legend_entry_t>(f->get_name(), f->get_color());
401 }
402 }
403 }
404
405
show_hide_legend(const bool show)406 void map_frame_t::show_hide_legend(const bool show)
407 {
408 filter_container.set_visible(show);
409 b_show_legend.pressed = show;
410 legend_visible = show;
411 reset_min_windowsize();
412 }
413
414
show_hide_scale(const bool show)415 void map_frame_t::show_hide_scale(const bool show)
416 {
417 scale_container.set_visible(show);
418 b_show_scale.pressed = show;
419 scale_visible = show;
420 reset_min_windowsize();
421 }
422
423
show_hide_directory(const bool show)424 void map_frame_t::show_hide_directory(const bool show)
425 {
426 directory_container.set_visible(show);
427 b_show_directory.pressed = show;
428 b_filter_factory_list.pressed = filter_factory_list;
429 directory_visible = show;
430 update_factory_legend();
431 reset_min_windowsize();
432 }
433
434
action_triggered(gui_action_creator_t * comp,value_t)435 bool map_frame_t::action_triggered( gui_action_creator_t *comp, value_t)
436 {
437 if( comp == &b_show_legend ) {
438 show_hide_legend( !b_show_legend.pressed );
439 }
440 else if( comp == &b_show_scale ) {
441 show_hide_scale( !b_show_scale.pressed );
442 }
443 else if( comp == &b_show_directory ) {
444 show_hide_directory( !b_show_directory.pressed );
445 }
446 else if ( comp == &b_filter_factory_list ) {
447 filter_factory_list = !filter_factory_list;
448 show_hide_directory( b_show_directory.pressed );
449 }
450 else if( comp == zoom_buttons+1 ) {
451 // zoom out
452 zoom(true);
453 }
454 else if( comp == zoom_buttons+0 ) {
455 // zoom in
456 zoom(false);
457 }
458 else if( comp == &b_rotate45 ) {
459 // rotated/straight map
460 minimap_t::get_instance()->toggle_isometric();
461 minimap_t::get_instance()->calc_map_size();
462 b_rotate45.pressed = minimap_t::get_instance()->is_isometric();
463 scrolly.set_size( scrolly.get_size() );
464 }
465 else if( comp == &b_overlay_networks ) {
466 b_overlay_networks.pressed ^= 1;
467 if( b_overlay_networks.pressed ) {
468 env_t::default_mapmode |= minimap_t::MAP_LINES;
469 }
470 else {
471 env_t::default_mapmode &= ~minimap_t::MAP_LINES;
472 }
473 minimap_t::get_instance()->set_display_mode( ( minimap_t::MAP_DISPLAY_MODE)env_t::default_mapmode );
474 }
475 else if ( comp == &viewed_player_c ) {
476 minimap_t::get_instance()->player_showed_on_map = viewable_players[viewed_player_c.get_selection()];
477 minimap_t::get_instance()->invalidate_map_lines_cache();
478 }
479 else if ( comp == &transport_type_c ) {
480 minimap_t::get_instance()->transport_type_showed_on_map = transport_type_c.get_selection();
481 minimap_t::get_instance()->invalidate_map_lines_cache();
482 }
483 else if ( comp == &freight_type_c ) {
484 minimap_t::get_instance()->freight_type_group_index_showed_on_map = viewable_freight_types[freight_type_c.get_selection()];
485 minimap_t::get_instance()->invalidate_map_lines_cache();
486 }
487 else if ( comp == &b_overlay_networks_load_factor ) {
488 minimap_t::get_instance()->show_network_load_factor = !minimap_t::get_instance()->show_network_load_factor;
489 b_overlay_networks_load_factor.pressed = !b_overlay_networks_load_factor.pressed;
490 minimap_t::get_instance()->invalidate_map_lines_cache();
491 }
492 else {
493 for( int i=0; i<MAP_MAX_BUTTONS; i++ ) {
494 if( comp == filter_buttons+i ) {
495 if( filter_buttons[i].pressed ) {
496 env_t::default_mapmode &= ~button_init[i].mode;
497 }
498 else {
499 if( (button_init[i].mode & minimap_t::MAP_MODE_FLAGS) == 0 ) {
500 // clear all persistent states
501 env_t::default_mapmode &= minimap_t::MAP_MODE_FLAGS;
502 }
503 else if( button_init[i].mode & minimap_t::MAP_MODE_HALT_FLAGS ) {
504 // clear all other halt states
505 env_t::default_mapmode &= ~minimap_t::MAP_MODE_HALT_FLAGS;
506 }
507 env_t::default_mapmode |= button_init[i].mode;
508 }
509 filter_buttons[i].pressed ^= 1;
510 break;
511 }
512 }
513 minimap_t::get_instance()->set_display_mode( ( minimap_t::MAP_DISPLAY_MODE)env_t::default_mapmode );
514 update_buttons();
515 }
516 return true;
517 }
518
519
zoom(bool magnify)520 void map_frame_t::zoom(bool magnify)
521 {
522 if ( minimap_t::get_instance()->change_zoom_factor(magnify)) {
523 zoomed = true;
524
525 // update zoom factors and zoom label
526 sint16 zoom_in, zoom_out;
527 minimap_t::get_instance()->get_zoom_factors(zoom_out, zoom_in);
528 zoom_value_label.buf().printf("%i:%i", zoom_in, zoom_out );
529 zoom_value_label.update();
530 zoom_row->set_size( zoom_row->get_size());
531 }
532 }
533
534
535 /**
536 * Events werden hiermit an die GUI-components
537 * gemeldet
538 * @author Hj. Malthaner
539 */
infowin_event(const event_t * ev)540 bool map_frame_t::infowin_event(const event_t *ev)
541 {
542 event_t ev2 = *ev;
543 translate_event(&ev2, -scrolly.get_pos().x, -scrolly.get_pos().y-D_TITLEBAR_HEIGHT);
544
545 if(ev->ev_class == INFOWIN) {
546 if(ev->ev_code == WIN_OPEN) {
547 minimap_t::get_instance()->set_xy_offset_size( scr_coord(0,0), scr_size(0,0) );
548 }
549 else if(ev->ev_code == WIN_CLOSE) {
550 minimap_t::get_instance()->is_visible = false;
551 }
552 }
553
554 if( minimap_t::get_instance()->getroffen(ev2.mx,ev2.my) ) {
555 set_focus( minimap_t::get_instance() );
556 }
557
558 if( (IS_WHEELUP(ev) || IS_WHEELDOWN(ev)) && minimap_t::get_instance()->getroffen(ev2.mx,ev2.my) ) {
559 // otherwise these would go to the vertical scroll bar
560 zoom(IS_WHEELUP(ev));
561 return true;
562 }
563
564 // Hajo: hack: minimap can resize upon right click
565 // we track this here, and adjust size.
566 if( IS_RIGHTCLICK(ev) ) {
567 is_dragging = false;
568 display_show_pointer(false);
569 is_cursor_hidden = true;
570 return true;
571 }
572 else if( IS_RIGHTRELEASE(ev) ) {
573 is_dragging = false;
574 display_show_pointer(true);
575 is_cursor_hidden = false;
576 return true;
577 }
578 else if( IS_RIGHTDRAG(ev) && ( minimap_t::get_instance()->getroffen(ev2.mx,ev2.my) || minimap_t::get_instance()->getroffen(ev2.cx,ev2.cy)) ) {
579 int x = scrolly.get_scroll_x();
580 int y = scrolly.get_scroll_y();
581 const int scroll_direction = ( env_t::scroll_multi>0 ? 1 : -1 );
582
583 x += (ev->mx - ev->cx)*scroll_direction*2;
584 y += (ev->my - ev->cy)*scroll_direction*2;
585
586 is_dragging = true;
587
588 scrolly.set_scroll_position( max(0, x), max(0, y) );
589
590 // Move the mouse pointer back to starting location
591 // To prevent a infinite mouse event loop, we just do it when needed.
592 if ((ev->mx - ev->cx)!=0 || (ev->my-ev->cy)!=0) {
593 move_pointer(screenpos.x + ev->cx, screenpos.y+ev->cy);
594 }
595
596 return true;
597 }
598 else if( IS_LEFTDBLCLK(ev) && minimap_t::get_instance()->getroffen(ev2.mx,ev2.my) ) {
599 // re-center cursor by scrolling
600 koord ij = welt->get_viewport()->get_world_position();
601 scr_coord center = minimap_t::get_instance()->map_to_screen_coord(ij);
602 const scr_size s_size = scrolly.get_size();
603
604 scrolly.set_scroll_position(max(0,center.x-(s_size.w/2)), max(0,center.y-(s_size.h/2)));
605 zoomed = false;
606
607 // remember world position, we do not want to have surprises when scrolling later on
608 old_ij = ij;
609 return true;
610 }
611 else if( IS_RIGHTDBLCLK(ev) ) {
612 // zoom to fit window
613 do { // first, zoom all the way in
614 zoomed = false;
615 zoom(true);
616 } while( zoomed );
617
618 // then zoom back out to fit
619 const scr_size s_size = scrolly.get_size() - D_SCROLLBAR_SIZE;
620 scr_size size = minimap_t::get_instance()->get_size();
621 zoomed = true;
622 while( zoomed && max(size.w/s_size.w, size.h/s_size.h) ) {
623 zoom(false);
624 size = minimap_t::get_instance()->get_size();
625 }
626 return true;
627 }
628 else if( is_cursor_hidden ) {
629 display_show_pointer(true);
630 is_cursor_hidden = false;
631 }
632
633 return gui_frame_t::infowin_event(ev);
634 }
635
636
637 /**
638 * size window in response and save it in static size
639 * @author (Mathew Hounsell)
640 * @date 11-Mar-2003
641 */
set_windowsize(scr_size size)642 void map_frame_t::set_windowsize(scr_size size)
643 {
644 gui_frame_t::set_windowsize( size );
645 window_size = get_windowsize();
646 }
647
648
649 /**
650 * Draw new component. The values to be passed refer to the window
651 * i.e. It's the screen coordinates of the window where the
652 * component is displayed.
653 * @author Hj. Malthaner
654 */
draw(scr_coord pos,scr_size size)655 void map_frame_t::draw(scr_coord pos, scr_size size)
656 {
657 // update our stored screen position
658 screenpos = pos;
659 minimap_t::get_instance()->set_xy_offset_size( scr_coord(scrolly.get_scroll_x(), scrolly.get_scroll_y()), scrolly.get_client().get_size() );
660
661 // first: check if cursor within map screen size
662 koord ij = welt->get_viewport()->get_world_position();
663 if(welt->is_within_limits(ij)) {
664 scr_coord center = minimap_t::get_instance()->map_to_screen_coord(ij);
665 // only re-center if zoomed or world position has changed and its outside visible area
666 const scr_size size = scrolly.get_size();
667 if(zoomed || ( old_ij != ij &&
668 ( scrolly.get_scroll_x()>center.x || scrolly.get_scroll_x()+size.w<=center.x ||
669 scrolly.get_scroll_y()>center.y || scrolly.get_scroll_y()+size.h<=center.y ) ) ) {
670 // re-center cursor by scrolling
671 scrolly.set_scroll_position( max(0,center.x-(size.w/2)), max(0,center.y-(size.h/2)) );
672 zoomed = false;
673 }
674 // remember world position, we do not want to have surprises when scrolling later on
675 old_ij = ij;
676 }
677
678 // draw all child controls
679 gui_frame_t::draw(pos, size);
680
681 // may add compass
682 if( skinverwaltung_t::compass_map && env_t::compass_map_position!=0 ) {
683 const uint16 isometric_img_offset = minimap_t::get_instance()->is_isometric() ? 4 : 0;
684 display_img_aligned( skinverwaltung_t::compass_map->get_image_id( isometric_img_offset+welt->get_settings().get_rotation() ),
685 scrolly.get_client()+pos+scr_coord(4,4+D_TITLEBAR_HEIGHT)-scr_size(8,8), env_t::compass_map_position, false );
686 }
687 }
688
689
rdwr(loadsave_t * file)690 void map_frame_t::rdwr( loadsave_t *file )
691 {
692 file->rdwr_bool( legend_visible );
693 file->rdwr_bool( scale_visible );
694 file->rdwr_bool( directory_visible );
695 file->rdwr_long( env_t::default_mapmode );
696
697 file->rdwr_bool( b_overlay_networks_load_factor.pressed );
698
699 minimap_t::get_instance()->rdwr(file);
700
701 window_size.rdwr(file);
702 scrolly.rdwr(file);
703
704 viewed_player_c.rdwr(file);
705 transport_type_c.rdwr(file);
706 freight_type_c.rdwr(file);
707
708 if( file->is_loading() ) {
709 set_windowsize( window_size );
710 // notify minimap of new settings
711 minimap_t::get_instance()->calc_map_size();
712 scrolly.set_size( scrolly.get_size() );
713
714 minimap_t::get_instance()->set_display_mode(( minimap_t::MAP_DISPLAY_MODE)env_t::default_mapmode);
715 update_buttons();
716
717 show_hide_directory(directory_visible);
718 show_hide_legend(legend_visible);
719 show_hide_scale(scale_visible);
720
721 b_overlay_networks.pressed = (env_t::default_mapmode & minimap_t::MAP_LINES)!=0;
722
723 minimap_t::get_instance()->player_showed_on_map = viewable_players[viewed_player_c.get_selection()];
724 minimap_t::get_instance()->transport_type_showed_on_map = transport_type_c.get_selection();
725 minimap_t::get_instance()->freight_type_group_index_showed_on_map = viewable_freight_types[freight_type_c.get_selection()];
726 minimap_t::get_instance()->show_network_load_factor = b_overlay_networks_load_factor.pressed;
727 minimap_t::get_instance()->invalidate_map_lines_cache();
728 }
729 }
730