src/toolbar_gui.cpp
branchNewGRF_ports
changeset 10184 fcf5fb2548eb
child 9845 c359062b4db0
child 10242 52b4a9006029
equal deleted inserted replaced
10179:eec5a7dcbf61 10184:fcf5fb2548eb
       
     1 /* $Id$ */
       
     2 
       
     3 /** @file toolbar_gui.cpp Code related to the (main) toolbar. */
       
     4 
       
     5 #include "stdafx.h"
       
     6 #include "openttd.h"
       
     7 #include "gui.h"
       
     8 #include "window_gui.h"
       
     9 #include "window_func.h"
       
    10 #include "viewport_func.h"
       
    11 #include "command_func.h"
       
    12 #include "variables.h"
       
    13 #include "train.h"
       
    14 #include "roadveh.h"
       
    15 #include "vehicle_gui.h"
       
    16 #include "rail_gui.h"
       
    17 #include "road_gui.h"
       
    18 #include "date_func.h"
       
    19 #include "vehicle_func.h"
       
    20 #include "sound_func.h"
       
    21 #include "terraform_gui.h"
       
    22 #include "transparency.h"
       
    23 #include "strings_func.h"
       
    24 #include "player_base.h"
       
    25 #include "player_func.h"
       
    26 #include "player_gui.h"
       
    27 #include "settings_type.h"
       
    28 #include "toolbar_gui.h"
       
    29 #include "vehicle_base.h"
       
    30 #include "gfx_func.h"
       
    31 
       
    32 #include "network/network.h"
       
    33 
       
    34 #include "table/strings.h"
       
    35 #include "table/sprites.h"
       
    36 
       
    37 extern void SelectSignTool();
       
    38 extern RailType _last_built_railtype;
       
    39 extern RoadType _last_built_roadtype;
       
    40 
       
    41 /* Returns the position where the toolbar wants the menu to appear.
       
    42  * Make sure the dropdown is fully visible within the window.
       
    43  * x + w->left because x is supposed to be the offset of the toolbar-button
       
    44  * we clicked on and w->left the toolbar window itself. So meaning that
       
    45  * the default position is aligned with the left side of the clicked button */
       
    46 Point GetToolbarDropdownPos(uint16 parent_button, int width, int height)
       
    47 {
       
    48 	const Window *w = FindWindowById(WC_MAIN_TOOLBAR,0);
       
    49 	Point pos;
       
    50 	pos.x = w->widget[GB(parent_button, 0, 8)].left;
       
    51 	pos.x = w->left + Clamp(pos.x, 0, w->width - width);
       
    52 	pos.y = w->height;
       
    53 
       
    54 	return pos;
       
    55 }
       
    56 
       
    57 
       
    58 static void ToolbarPauseClick(Window *w)
       
    59 {
       
    60 	if (_networking && !_network_server) return; // only server can pause the game
       
    61 
       
    62 	if (DoCommandP(0, _pause_game ? 0 : 1, 0, NULL, CMD_PAUSE)) SndPlayFx(SND_15_BEEP);
       
    63 }
       
    64 
       
    65 static void ToolbarFastForwardClick(Window *w)
       
    66 {
       
    67 	_fast_forward ^= true;
       
    68 	SndPlayFx(SND_15_BEEP);
       
    69 }
       
    70 
       
    71 static void ToolbarSaveClick(Window *w)
       
    72 {
       
    73 	PopupMainToolbMenu(w, 3, STR_015C_SAVE_GAME, 4, 0);
       
    74 }
       
    75 
       
    76 static void ToolbarMapClick(Window *w)
       
    77 {
       
    78 	PopupMainToolbMenu(w, 4, STR_02DE_MAP_OF_WORLD, 3, 0);
       
    79 }
       
    80 
       
    81 static void ToolbarTownClick(Window *w)
       
    82 {
       
    83 	PopupMainToolbMenu(w, 5, STR_02BB_TOWN_DIRECTORY, 1, 0);
       
    84 }
       
    85 
       
    86 static void ToolbarSubsidiesClick(Window *w)
       
    87 {
       
    88 	PopupMainToolbMenu(w, 6, STR_02DD_SUBSIDIES, 1, 0);
       
    89 }
       
    90 
       
    91 static void ToolbarStationsClick(Window *w)
       
    92 {
       
    93 	PopupMainPlayerToolbMenu(w, 7, 0);
       
    94 }
       
    95 
       
    96 static void ToolbarMoneyClick(Window *w)
       
    97 {
       
    98 	PopupMainPlayerToolbMenu(w, 8, 0);
       
    99 }
       
   100 
       
   101 static void ToolbarPlayersClick(Window *w)
       
   102 {
       
   103 	PopupMainPlayerToolbMenu(w, 9, 0);
       
   104 }
       
   105 
       
   106 static void ToolbarGraphsClick(Window *w)
       
   107 {
       
   108 	PopupMainToolbMenu(w, 10, STR_0154_OPERATING_PROFIT_GRAPH, 6, 0);
       
   109 }
       
   110 
       
   111 static void ToolbarLeagueClick(Window *w)
       
   112 {
       
   113 	PopupMainToolbMenu(w, 11, STR_015A_COMPANY_LEAGUE_TABLE, 2, 0);
       
   114 }
       
   115 
       
   116 static void ToolbarIndustryClick(Window *w)
       
   117 {
       
   118 	/* Disable build-industry menu if we are a spectator */
       
   119 	PopupMainToolbMenu(w, 12, STR_INDUSTRY_DIR, 2, (_current_player == PLAYER_SPECTATOR) ? (1 << 1) : 0);
       
   120 }
       
   121 
       
   122 static void ToolbarTrainClick(Window *w)
       
   123 {
       
   124 	const Vehicle *v;
       
   125 	int dis = -1;
       
   126 
       
   127 	FOR_ALL_VEHICLES(v) {
       
   128 		if (v->type == VEH_TRAIN && IsFrontEngine(v)) ClrBit(dis, v->owner);
       
   129 	}
       
   130 	PopupMainPlayerToolbMenu(w, 13, dis);
       
   131 }
       
   132 
       
   133 static void ToolbarRoadClick(Window *w)
       
   134 {
       
   135 	const Vehicle *v;
       
   136 	int dis = -1;
       
   137 
       
   138 	FOR_ALL_VEHICLES(v) {
       
   139 		if (v->type == VEH_ROAD && IsRoadVehFront(v)) ClrBit(dis, v->owner);
       
   140 	}
       
   141 	PopupMainPlayerToolbMenu(w, 14, dis);
       
   142 }
       
   143 
       
   144 static void ToolbarShipClick(Window *w)
       
   145 {
       
   146 	const Vehicle *v;
       
   147 	int dis = -1;
       
   148 
       
   149 	FOR_ALL_VEHICLES(v) {
       
   150 		if (v->type == VEH_SHIP) ClrBit(dis, v->owner);
       
   151 	}
       
   152 	PopupMainPlayerToolbMenu(w, 15, dis);
       
   153 }
       
   154 
       
   155 static void ToolbarAirClick(Window *w)
       
   156 {
       
   157 	const Vehicle *v;
       
   158 	int dis = -1;
       
   159 
       
   160 	FOR_ALL_VEHICLES(v) {
       
   161 		if (v->type == VEH_AIRCRAFT) ClrBit(dis, v->owner);
       
   162 	}
       
   163 	PopupMainPlayerToolbMenu(w, 16, dis);
       
   164 }
       
   165 
       
   166 
       
   167 static void ToolbarZoomInClick(Window *w)
       
   168 {
       
   169 	if (DoZoomInOutWindow(ZOOM_IN, FindWindowById(WC_MAIN_WINDOW, 0))) {
       
   170 		w->HandleButtonClick(17);
       
   171 		SndPlayFx(SND_15_BEEP);
       
   172 	}
       
   173 }
       
   174 
       
   175 static void ToolbarZoomOutClick(Window *w)
       
   176 {
       
   177 	if (DoZoomInOutWindow(ZOOM_OUT,FindWindowById(WC_MAIN_WINDOW, 0))) {
       
   178 		w->HandleButtonClick(18);
       
   179 		SndPlayFx(SND_15_BEEP);
       
   180 	}
       
   181 }
       
   182 
       
   183 static void ToolbarBuildRailClick(Window *w)
       
   184 {
       
   185 	const Player *p = GetPlayer(_local_player);
       
   186 	Window *w2 = PopupMainToolbMenu(w, 19, STR_1015_RAILROAD_CONSTRUCTION, RAILTYPE_END, ~p->avail_railtypes);
       
   187 	WP(w2, menu_d).sel_index = _last_built_railtype;
       
   188 }
       
   189 
       
   190 static void ToolbarBuildRoadClick(Window *w)
       
   191 {
       
   192 	const Player *p = GetPlayer(_local_player);
       
   193 	/* The standard road button is *always* available */
       
   194 	Window *w2 = PopupMainToolbMenu(w, 20, STR_180A_ROAD_CONSTRUCTION, 2, ~(p->avail_roadtypes | ROADTYPES_ROAD));
       
   195 	WP(w2, menu_d).sel_index = _last_built_roadtype;
       
   196 }
       
   197 
       
   198 static void ToolbarBuildWaterClick(Window *w)
       
   199 {
       
   200 	PopupMainToolbMenu(w, 21, STR_9800_DOCK_CONSTRUCTION, 1, 0);
       
   201 }
       
   202 
       
   203 static void ToolbarBuildAirClick(Window *w)
       
   204 {
       
   205 	PopupMainToolbMenu(w, 22, STR_A01D_AIRPORT_CONSTRUCTION, 1, 0);
       
   206 }
       
   207 
       
   208 static void ToolbarForestClick(Window *w)
       
   209 {
       
   210 	PopupMainToolbMenu(w, 23, STR_LANDSCAPING, 3, 0);
       
   211 }
       
   212 
       
   213 static void ToolbarMusicClick(Window *w)
       
   214 {
       
   215 	PopupMainToolbMenu(w, 24, STR_01D3_SOUND_MUSIC, 1, 0);
       
   216 }
       
   217 
       
   218 static void ToolbarNewspaperClick(Window *w)
       
   219 {
       
   220 	PopupMainToolbMenu(w, 25, STR_0200_LAST_MESSAGE_NEWS_REPORT, 3, 0);
       
   221 }
       
   222 
       
   223 static void ToolbarHelpClick(Window *w)
       
   224 {
       
   225 	PopupMainToolbMenu(w, 26, STR_02D5_LAND_BLOCK_INFO, 6, 0);
       
   226 }
       
   227 
       
   228 static void ToolbarOptionsClick(Window *w)
       
   229 {
       
   230 	uint16 x = 0;
       
   231 
       
   232 	w = PopupMainToolbMenu(w, 2, STR_02C4_GAME_OPTIONS, 14, 0);
       
   233 
       
   234 	if (HasBit(_display_opt, DO_SHOW_TOWN_NAMES))    SetBit(x,  6);
       
   235 	if (HasBit(_display_opt, DO_SHOW_STATION_NAMES)) SetBit(x,  7);
       
   236 	if (HasBit(_display_opt, DO_SHOW_SIGNS))         SetBit(x,  8);
       
   237 	if (HasBit(_display_opt, DO_WAYPOINTS))          SetBit(x,  9);
       
   238 	if (HasBit(_display_opt, DO_FULL_ANIMATION))     SetBit(x, 10);
       
   239 	if (HasBit(_display_opt, DO_FULL_DETAIL))        SetBit(x, 11);
       
   240 	if (IsTransparencySet(TO_HOUSES))                SetBit(x, 12);
       
   241 	if (IsTransparencySet(TO_SIGNS))                 SetBit(x, 13);
       
   242 	WP(w, menu_d).checked_items = x;
       
   243 }
       
   244 
       
   245 
       
   246 static void ToolbarScenSaveOrLoad(Window *w)
       
   247 {
       
   248 	PopupMainToolbMenu(w, 3, STR_0292_SAVE_SCENARIO, 6, 0);
       
   249 }
       
   250 
       
   251 static void ToolbarScenDateBackward(Window *w)
       
   252 {
       
   253 	/* don't allow too fast scrolling */
       
   254 	if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
       
   255 		w->HandleButtonClick(6);
       
   256 		SetWindowDirty(w);
       
   257 
       
   258 		_patches_newgame.starting_year = Clamp(_patches_newgame.starting_year - 1, MIN_YEAR, MAX_YEAR);
       
   259 		SetDate(ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
       
   260 	}
       
   261 	_left_button_clicked = false;
       
   262 }
       
   263 
       
   264 static void ToolbarScenDateForward(Window *w)
       
   265 {
       
   266 	/* don't allow too fast scrolling */
       
   267 	if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
       
   268 		w->HandleButtonClick(7);
       
   269 		SetWindowDirty(w);
       
   270 
       
   271 		_patches_newgame.starting_year = Clamp(_patches_newgame.starting_year + 1, MIN_YEAR, MAX_YEAR);
       
   272 		SetDate(ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
       
   273 	}
       
   274 	_left_button_clicked = false;
       
   275 }
       
   276 
       
   277 static void ToolbarScenMapTownDir(Window *w)
       
   278 {
       
   279 	/* Scenario editor button, *hack*hack* use different button to activate */
       
   280 	PopupMainToolbMenu(w, 8 | (17 << 8), STR_02DE_MAP_OF_WORLD, 4, 0);
       
   281 }
       
   282 
       
   283 static void ToolbarScenZoomIn(Window *w)
       
   284 {
       
   285 	if (DoZoomInOutWindow(ZOOM_IN, FindWindowById(WC_MAIN_WINDOW, 0))) {
       
   286 		w->HandleButtonClick(9);
       
   287 		SndPlayFx(SND_15_BEEP);
       
   288 	}
       
   289 }
       
   290 
       
   291 static void ToolbarScenZoomOut(Window *w)
       
   292 {
       
   293 	if (DoZoomInOutWindow(ZOOM_OUT, FindWindowById(WC_MAIN_WINDOW, 0))) {
       
   294 		w->HandleButtonClick(10);
       
   295 		SndPlayFx(SND_15_BEEP);
       
   296 	}
       
   297 }
       
   298 
       
   299 static void ToolbarScenGenLand(Window *w)
       
   300 {
       
   301 	w->HandleButtonClick(11);
       
   302 	SndPlayFx(SND_15_BEEP);
       
   303 
       
   304 	ShowEditorTerraformToolbar();
       
   305 }
       
   306 
       
   307 
       
   308 static void ToolbarScenGenTown(Window *w)
       
   309 {
       
   310 	w->HandleButtonClick(12);
       
   311 	SndPlayFx(SND_15_BEEP);
       
   312 	ShowBuildTownWindow();
       
   313 }
       
   314 
       
   315 static void ToolbarScenGenIndustry(Window *w)
       
   316 {
       
   317 	w->HandleButtonClick(13);
       
   318 	SndPlayFx(SND_15_BEEP);
       
   319 	ShowBuildIndustryWindow();
       
   320 }
       
   321 
       
   322 static void ToolbarScenBuildRoad(Window *w)
       
   323 {
       
   324 	w->HandleButtonClick(14);
       
   325 	SndPlayFx(SND_15_BEEP);
       
   326 	ShowBuildRoadScenToolbar();
       
   327 }
       
   328 
       
   329 static void ToolbarScenPlantTrees(Window *w)
       
   330 {
       
   331 	w->HandleButtonClick(15);
       
   332 	SndPlayFx(SND_15_BEEP);
       
   333 	ShowBuildTreesScenToolbar();
       
   334 }
       
   335 
       
   336 static void ToolbarScenPlaceSign(Window *w)
       
   337 {
       
   338 	w->HandleButtonClick(16);
       
   339 	SndPlayFx(SND_15_BEEP);
       
   340 	SelectSignTool();
       
   341 }
       
   342 
       
   343 static void ToolbarBtn_NULL(Window *w)
       
   344 {
       
   345 }
       
   346 
       
   347 
       
   348 typedef void ToolbarButtonProc(Window *w);
       
   349 
       
   350 static ToolbarButtonProc * const _toolbar_button_procs[] = {
       
   351 	ToolbarPauseClick,
       
   352 	ToolbarFastForwardClick,
       
   353 	ToolbarOptionsClick,
       
   354 	ToolbarSaveClick,
       
   355 	ToolbarMapClick,
       
   356 	ToolbarTownClick,
       
   357 	ToolbarSubsidiesClick,
       
   358 	ToolbarStationsClick,
       
   359 	ToolbarMoneyClick,
       
   360 	ToolbarPlayersClick,
       
   361 	ToolbarGraphsClick,
       
   362 	ToolbarLeagueClick,
       
   363 	ToolbarIndustryClick,
       
   364 	ToolbarTrainClick,
       
   365 	ToolbarRoadClick,
       
   366 	ToolbarShipClick,
       
   367 	ToolbarAirClick,
       
   368 	ToolbarZoomInClick,
       
   369 	ToolbarZoomOutClick,
       
   370 	ToolbarBuildRailClick,
       
   371 	ToolbarBuildRoadClick,
       
   372 	ToolbarBuildWaterClick,
       
   373 	ToolbarBuildAirClick,
       
   374 	ToolbarForestClick,
       
   375 	ToolbarMusicClick,
       
   376 	ToolbarNewspaperClick,
       
   377 	ToolbarHelpClick,
       
   378 };
       
   379 
       
   380 extern void MenuClickSmallScreenshot();
       
   381 extern void MenuClickWorldScreenshot();
       
   382 extern void MenuClickSaveLoad(int index);
       
   383 
       
   384 void MainToolbarWndProc(Window *w, WindowEvent *e)
       
   385 {
       
   386 	switch (e->event) {
       
   387 		case WE_PAINT:
       
   388 			/* Draw brown-red toolbar bg. */
       
   389 			GfxFillRect(0, 0, w->width-1, w->height-1, 0xB2);
       
   390 			GfxFillRect(0, 0, w->width-1, w->height-1, 0xB4 | (1 << PALETTE_MODIFIER_GREYOUT));
       
   391 
       
   392 			/* If spectator, disable all construction buttons
       
   393 			* ie : Build road, rail, ships, airports and landscaping
       
   394 			* Since enabled state is the default, just disable when needed */
       
   395 			w->SetWidgetsDisabledState(_current_player == PLAYER_SPECTATOR, 19, 20, 21, 22, 23, WIDGET_LIST_END);
       
   396 			/* disable company list drop downs, if there are no companies */
       
   397 			w->SetWidgetsDisabledState(ActivePlayerCount() == 0, 7, 8, 13, 14, 15, 16, WIDGET_LIST_END);
       
   398 
       
   399 			w->SetWidgetDisabledState(19, !CanBuildVehicleInfrastructure(VEH_TRAIN));
       
   400 			w->SetWidgetDisabledState(22, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT));
       
   401 
       
   402 			DrawWindowWidgets(w);
       
   403 			break;
       
   404 
       
   405 		case WE_CLICK:
       
   406 			if (_game_mode != GM_MENU && !w->IsWidgetDisabled(e->we.click.widget))
       
   407 				_toolbar_button_procs[e->we.click.widget](w);
       
   408 			break;
       
   409 
       
   410 		case WE_KEYPRESS:
       
   411 			switch (e->we.keypress.keycode) {
       
   412 				case WKC_F1: case WKC_PAUSE: ToolbarPauseClick(w); break;
       
   413 				case WKC_F2: ShowGameOptions(); break;
       
   414 				case WKC_F3: MenuClickSaveLoad(0); break;
       
   415 				case WKC_F4: ShowSmallMap(); break;
       
   416 				case WKC_F5: ShowTownDirectory(); break;
       
   417 				case WKC_F6: ShowSubsidiesList(); break;
       
   418 				case WKC_F7: ShowPlayerStations(_local_player); break;
       
   419 				case WKC_F8: ShowPlayerFinances(_local_player); break;
       
   420 				case WKC_F9: ShowPlayerCompany(_local_player); break;
       
   421 				case WKC_F10: ShowOperatingProfitGraph(); break;
       
   422 				case WKC_F11: ShowCompanyLeagueTable(); break;
       
   423 				case WKC_F12: ShowBuildIndustryWindow(); break;
       
   424 				case WKC_SHIFT | WKC_F1: ShowVehicleListWindow(_local_player, VEH_TRAIN); break;
       
   425 				case WKC_SHIFT | WKC_F2: ShowVehicleListWindow(_local_player, VEH_ROAD); break;
       
   426 				case WKC_SHIFT | WKC_F3: ShowVehicleListWindow(_local_player, VEH_SHIP); break;
       
   427 				case WKC_SHIFT | WKC_F4: ShowVehicleListWindow(_local_player, VEH_AIRCRAFT); break;
       
   428 				case WKC_NUM_PLUS: // Fall through
       
   429 				case WKC_EQUALS: // Fall through
       
   430 				case WKC_SHIFT | WKC_EQUALS: // Fall through
       
   431 				case WKC_SHIFT | WKC_F5: ToolbarZoomInClick(w); break;
       
   432 				case WKC_NUM_MINUS: // Fall through
       
   433 				case WKC_MINUS: // Fall through
       
   434 				case WKC_SHIFT | WKC_MINUS: // Fall through
       
   435 				case WKC_SHIFT | WKC_F6: ToolbarZoomOutClick(w); break;
       
   436 				case WKC_SHIFT | WKC_F7: if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype, -1); break;
       
   437 				case WKC_SHIFT | WKC_F8: ShowBuildRoadToolbar(_last_built_roadtype); break;
       
   438 				case WKC_SHIFT | WKC_F9: ShowBuildDocksToolbar(); break;
       
   439 				case WKC_SHIFT | WKC_F10: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT)) ShowBuildAirToolbar(); break;
       
   440 				case WKC_SHIFT | WKC_F11: ShowBuildTreesToolbar(); break;
       
   441 				case WKC_SHIFT | WKC_F12: ShowMusicWindow(); break;
       
   442 				case WKC_CTRL  | 'S': MenuClickSmallScreenshot(); break;
       
   443 				case WKC_CTRL  | 'G': MenuClickWorldScreenshot(); break;
       
   444 				case WKC_CTRL | WKC_ALT | 'C': if (!_networking) ShowCheatWindow(); break;
       
   445 				case 'A': if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype, 4); break; // Invoke Autorail
       
   446 				case 'L': ShowTerraformToolbar(); break;
       
   447 				case 'M': ShowSmallMap(); break;
       
   448 				case 'V': ShowExtraViewPortWindow(); break;
       
   449 				default: return;
       
   450 			}
       
   451 			e->we.keypress.cont = false;
       
   452 			break;
       
   453 
       
   454 		case WE_PLACE_OBJ:
       
   455 			_place_proc(e->we.place.tile);
       
   456 			break;
       
   457 
       
   458 		case WE_ABORT_PLACE_OBJ:
       
   459 			w->RaiseWidget(25);
       
   460 			SetWindowDirty(w);
       
   461 			break;
       
   462 
       
   463 		case WE_MOUSELOOP:
       
   464 			if (w->IsWidgetLowered(0) != !!_pause_game) {
       
   465 				w->ToggleWidgetLoweredState(0);
       
   466 				w->InvalidateWidget(0);
       
   467 			}
       
   468 
       
   469 			if (w->IsWidgetLowered(1) != !!_fast_forward) {
       
   470 				w->ToggleWidgetLoweredState(1);
       
   471 				w->InvalidateWidget(1);
       
   472 			}
       
   473 			break;
       
   474 
       
   475 		case WE_RESIZE: {
       
   476 			/* There are 27 buttons plus some spacings if the space allows it */
       
   477 			uint button_width;
       
   478 			uint spacing;
       
   479 			if (w->width >= 27 * 22) {
       
   480 				button_width = 22;
       
   481 				spacing = w->width - (27 * button_width);
       
   482 			} else {
       
   483 				button_width = w->width / 27;
       
   484 				spacing = 0;
       
   485 			}
       
   486 			uint extra_spacing_at[] = { 4, 8, 13, 17, 19, 24, 0 };
       
   487 
       
   488 			for (uint i = 0, x = 0, j = 0; i < 27; i++) {
       
   489 				if (extra_spacing_at[j] == i) {
       
   490 					j++;
       
   491 					uint add = spacing / (lengthof(extra_spacing_at) - j);
       
   492 					spacing -= add;
       
   493 					x += add;
       
   494 				}
       
   495 
       
   496 				w->widget[i].left = x;
       
   497 				x += (spacing != 0) ? button_width : (w->width - x) / (27 - i);
       
   498 				w->widget[i].right = x - 1;
       
   499 			}
       
   500 		} break;
       
   501 
       
   502 		case WE_TIMEOUT:
       
   503 			for (uint i = 2; i < w->widget_count; i++) {
       
   504 				if (w->IsWidgetLowered(i)) {
       
   505 					w->RaiseWidget(i);
       
   506 					w->InvalidateWidget(i);
       
   507 				}
       
   508 			}
       
   509 			break;
       
   510 
       
   511 		case WE_MESSAGE:
       
   512 			if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(w, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, 17, 18);
       
   513 			break;
       
   514 	}
       
   515 }
       
   516 
       
   517 static const Widget _toolb_normal_widgets[] = {
       
   518 {     WWT_IMGBTN,   RESIZE_LEFT,    14,     0,     0,     0,    21, SPR_IMG_PAUSE,           STR_0171_PAUSE_GAME},
       
   519 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_FASTFORWARD,     STR_FAST_FORWARD},
       
   520 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_SETTINGS,        STR_0187_OPTIONS},
       
   521 {   WWT_IMGBTN_2,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_SAVE,            STR_0172_SAVE_GAME_ABANDON_GAME},
       
   522 
       
   523 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_SMALLMAP,        STR_0174_DISPLAY_MAP},
       
   524 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_TOWN,            STR_0176_DISPLAY_TOWN_DIRECTORY},
       
   525 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_SUBSIDIES,       STR_02DC_DISPLAY_SUBSIDIES},
       
   526 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_COMPANY_LIST,    STR_0173_DISPLAY_LIST_OF_COMPANY},
       
   527 
       
   528 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_COMPANY_FINANCE, STR_0177_DISPLAY_COMPANY_FINANCES},
       
   529 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_COMPANY_GENERAL, STR_0178_DISPLAY_COMPANY_GENERAL},
       
   530 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_GRAPHS,          STR_0179_DISPLAY_GRAPHS},
       
   531 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_COMPANY_LEAGUE,  STR_017A_DISPLAY_COMPANY_LEAGUE},
       
   532 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_INDUSTRY,        STR_0312_FUND_CONSTRUCTION_OF_NEW},
       
   533 
       
   534 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_TRAINLIST,       STR_017B_DISPLAY_LIST_OF_COMPANY},
       
   535 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_TRUCKLIST,       STR_017C_DISPLAY_LIST_OF_COMPANY},
       
   536 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_SHIPLIST,        STR_017D_DISPLAY_LIST_OF_COMPANY},
       
   537 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_AIRPLANESLIST,   STR_017E_DISPLAY_LIST_OF_COMPANY},
       
   538 
       
   539 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_ZOOMIN,          STR_017F_ZOOM_THE_VIEW_IN},
       
   540 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_ZOOMOUT,         STR_0180_ZOOM_THE_VIEW_OUT},
       
   541 
       
   542 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_BUILDRAIL,       STR_0181_BUILD_RAILROAD_TRACK},
       
   543 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_BUILDROAD,       STR_0182_BUILD_ROADS},
       
   544 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_BUILDWATER,      STR_0183_BUILD_SHIP_DOCKS},
       
   545 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_BUILDAIR,        STR_0184_BUILD_AIRPORTS},
       
   546 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_LANDSCAPING,     STR_LANDSCAPING_TOOLBAR_TIP}, // tree icon is 0x2E6
       
   547 
       
   548 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_MUSIC,           STR_01D4_SHOW_SOUND_MUSIC_WINDOW},
       
   549 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_MESSAGES,        STR_0203_SHOW_LAST_MESSAGE_NEWS},
       
   550 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_QUERY,           STR_0186_LAND_BLOCK_INFORMATION},
       
   551 {   WIDGETS_END},
       
   552 };
       
   553 
       
   554 static const WindowDesc _toolb_normal_desc = {
       
   555 	0, 0, 0, 22, 640, 22,
       
   556 	WC_MAIN_TOOLBAR, WC_NONE,
       
   557 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET,
       
   558 	_toolb_normal_widgets,
       
   559 	MainToolbarWndProc
       
   560 };
       
   561 
       
   562 
       
   563 static ToolbarButtonProc * const _scen_toolbar_button_procs[] = {
       
   564 	ToolbarPauseClick,
       
   565 	ToolbarFastForwardClick,
       
   566 	ToolbarOptionsClick,
       
   567 	ToolbarScenSaveOrLoad,
       
   568 	ToolbarBtn_NULL,
       
   569 	ToolbarBtn_NULL,
       
   570 	ToolbarScenDateBackward,
       
   571 	ToolbarScenDateForward,
       
   572 	ToolbarScenMapTownDir,
       
   573 	ToolbarScenZoomIn,
       
   574 	ToolbarScenZoomOut,
       
   575 	ToolbarScenGenLand,
       
   576 	ToolbarScenGenTown,
       
   577 	ToolbarScenGenIndustry,
       
   578 	ToolbarScenBuildRoad,
       
   579 	ToolbarScenPlantTrees,
       
   580 	ToolbarScenPlaceSign,
       
   581 	NULL,
       
   582 	NULL,
       
   583 	NULL,
       
   584 	NULL,
       
   585 	NULL,
       
   586 	NULL,
       
   587 	NULL,
       
   588 	ToolbarMusicClick,
       
   589 	NULL,
       
   590 	ToolbarHelpClick,
       
   591 };
       
   592 
       
   593 void ScenEditToolbarWndProc(Window *w, WindowEvent *e)
       
   594 {
       
   595 	switch (e->event) {
       
   596 		case WE_PAINT:
       
   597 			w->SetWidgetDisabledState(6, _patches_newgame.starting_year <= MIN_YEAR);
       
   598 			w->SetWidgetDisabledState(7, _patches_newgame.starting_year >= MAX_YEAR);
       
   599 
       
   600 			/* Draw brown-red toolbar bg. */
       
   601 			GfxFillRect(0, 0, w->width-1, w->height-1, 0xB2);
       
   602 			GfxFillRect(0, 0, w->width-1, w->height-1, 0xB4 | (1 << PALETTE_MODIFIER_GREYOUT));
       
   603 
       
   604 			DrawWindowWidgets(w);
       
   605 
       
   606 			SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
       
   607 			DrawStringCenteredTruncated(w->widget[6].right, w->widget[7].left, 6, STR_00AF, TC_FROMSTRING);
       
   608 
       
   609 			/* We hide this panel when the toolbar space gets too small */
       
   610 			if (w->widget[4].left != w->widget[4].right) {
       
   611 				DrawStringCenteredTruncated(w->widget[4].left + 1, w->widget[4].right - 1,  1, STR_0221_OPENTTD, TC_FROMSTRING);
       
   612 				DrawStringCenteredTruncated(w->widget[4].left + 1, w->widget[4].right - 1, 11, STR_0222_SCENARIO_EDITOR, TC_FROMSTRING);
       
   613 			}
       
   614 
       
   615 			break;
       
   616 
       
   617 		case WE_CLICK:
       
   618 			if (_game_mode == GM_MENU) return;
       
   619 			_scen_toolbar_button_procs[e->we.click.widget](w);
       
   620 			break;
       
   621 
       
   622 		case WE_KEYPRESS:
       
   623 			switch (e->we.keypress.keycode) {
       
   624 				case WKC_F1: case WKC_PAUSE: ToolbarPauseClick(w); break;
       
   625 				case WKC_F2: ShowGameOptions(); break;
       
   626 				case WKC_F3: MenuClickSaveLoad(0); break;
       
   627 				case WKC_F4: ToolbarScenGenLand(w); break;
       
   628 				case WKC_F5: ToolbarScenGenTown(w); break;
       
   629 				case WKC_F6: ToolbarScenGenIndustry(w); break;
       
   630 				case WKC_F7: ToolbarScenBuildRoad(w); break;
       
   631 				case WKC_F8: ToolbarScenPlantTrees(w); break;
       
   632 				case WKC_F9: ToolbarScenPlaceSign(w); break;
       
   633 				case WKC_F10: ShowMusicWindow(); break;
       
   634 				case WKC_F11: PlaceLandBlockInfo(); break;
       
   635 				case WKC_CTRL | 'S': MenuClickSmallScreenshot(); break;
       
   636 				case WKC_CTRL | 'G': MenuClickWorldScreenshot(); break;
       
   637 
       
   638 				/* those following are all fall through */
       
   639 				case WKC_NUM_PLUS:
       
   640 				case WKC_EQUALS:
       
   641 				case WKC_SHIFT | WKC_EQUALS:
       
   642 				case WKC_SHIFT | WKC_F5: ToolbarZoomInClick(w); break;
       
   643 
       
   644 				/* those following are all fall through */
       
   645 				case WKC_NUM_MINUS:
       
   646 				case WKC_MINUS:
       
   647 				case WKC_SHIFT | WKC_MINUS:
       
   648 				case WKC_SHIFT | WKC_F6: ToolbarZoomOutClick(w); break;
       
   649 
       
   650 				case 'L': ShowEditorTerraformToolbar(); break;
       
   651 				case 'M': ShowSmallMap(); break;
       
   652 				case 'V': ShowExtraViewPortWindow(); break;
       
   653 				default: return;
       
   654 			}
       
   655 			e->we.keypress.cont = false;
       
   656 			break;
       
   657 
       
   658 		case WE_PLACE_OBJ:
       
   659 			_place_proc(e->we.place.tile);
       
   660 			break;
       
   661 
       
   662 		case WE_ABORT_PLACE_OBJ:
       
   663 			w->RaiseWidget(25);
       
   664 			SetWindowDirty(w);
       
   665 			break;
       
   666 
       
   667 		case WE_RESIZE: {
       
   668 			/* There are 15 buttons plus some spacings if the space allows it.
       
   669 			* Furthermore there are two panels of which one is non-essential
       
   670 			* and that one can be removed is the space is too small. */
       
   671 			uint buttons_width;
       
   672 			uint spacing;
       
   673 
       
   674 			static int normal_min_width = (15 * 22) + (2 * 130);
       
   675 			static int one_less_panel_min_width = (15 * 22) + 130;
       
   676 
       
   677 			if (w->width >= one_less_panel_min_width) {
       
   678 				buttons_width = 15 * 22;
       
   679 				spacing = w->width - ((w->width >= normal_min_width) ? normal_min_width : one_less_panel_min_width);
       
   680 			} else {
       
   681 				buttons_width = w->width - 130;
       
   682 				spacing = 0;
       
   683 			}
       
   684 			uint extra_spacing_at[] = { 3, 4, 7, 8, 10, 16, 0 };
       
   685 
       
   686 			/* Yes, it defines about 27 widgets for this toolbar */
       
   687 			for (uint i = 0, x = 0, j = 0, b = 0; i < 27; i++) {
       
   688 				switch (i) {
       
   689 					case 4:
       
   690 						w->widget[i].left = x;
       
   691 						if (w->width < normal_min_width) {
       
   692 							w->widget[i].right = x;
       
   693 							j++;
       
   694 							continue;
       
   695 						}
       
   696 
       
   697 						x += 130;
       
   698 						w->widget[i].right = x - 1;
       
   699 						break;
       
   700 
       
   701 					case 5: {
       
   702 						int offset = x - w->widget[i].left;
       
   703 						w->widget[i + 1].left  += offset;
       
   704 						w->widget[i + 1].right += offset;
       
   705 						w->widget[i + 2].left  += offset;
       
   706 						w->widget[i + 2].right += offset;
       
   707 						w->widget[i].left = x;
       
   708 						x += 130;
       
   709 						w->widget[i].right = x - 1;
       
   710 						i += 2;
       
   711 					} break;
       
   712 
       
   713 					default:
       
   714 						if (w->widget[i].bottom == 0) continue;
       
   715 
       
   716 						w->widget[i].left = x;
       
   717 						x += buttons_width / (15 - b);
       
   718 						w->widget[i].right = x - 1;
       
   719 						buttons_width -= buttons_width / (15 - b);
       
   720 						b++;
       
   721 						break;
       
   722 				}
       
   723 
       
   724 				if (extra_spacing_at[j] == i) {
       
   725 					j++;
       
   726 					uint add = spacing / (lengthof(extra_spacing_at) - j);
       
   727 					spacing -= add;
       
   728 					x += add;
       
   729 				}
       
   730 			}
       
   731 		} break;
       
   732 
       
   733 		case WE_MOUSELOOP:
       
   734 			if (w->IsWidgetLowered(0) != !!_pause_game) {
       
   735 				w->ToggleWidgetLoweredState(0);
       
   736 				SetWindowDirty(w);
       
   737 			}
       
   738 
       
   739 			if (w->IsWidgetLowered(1) != !!_fast_forward) {
       
   740 				w->ToggleWidgetLoweredState(1);
       
   741 				SetWindowDirty(w);
       
   742 			}
       
   743 			break;
       
   744 
       
   745 		case WE_MESSAGE:
       
   746 			HandleZoomMessage(w, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, 9, 10);
       
   747 			break;
       
   748 	}
       
   749 }
       
   750 
       
   751 static const Widget _toolb_scen_widgets[] = {
       
   752 {  WWT_IMGBTN, RESIZE_LEFT, 14,   0,   0,  0, 21, SPR_IMG_PAUSE,       STR_0171_PAUSE_GAME},
       
   753 {  WWT_IMGBTN, RESIZE_NONE, 14,   0,   0,  0, 21, SPR_IMG_FASTFORWARD, STR_FAST_FORWARD},
       
   754 {  WWT_IMGBTN, RESIZE_NONE, 14,   0,   0,  0, 21, SPR_IMG_SETTINGS,    STR_0187_OPTIONS},
       
   755 {WWT_IMGBTN_2, RESIZE_NONE, 14,   0,   0,  0, 21, SPR_IMG_SAVE,        STR_0297_SAVE_SCENARIO_LOAD_SCENARIO},
       
   756 
       
   757 {   WWT_PANEL, RESIZE_NONE, 14,   0,   0,  0, 21, 0x0,                 STR_NULL},
       
   758 
       
   759 {   WWT_PANEL, RESIZE_NONE, 14,   0, 129,  0, 21, 0x0,                 STR_NULL},
       
   760 {  WWT_IMGBTN, RESIZE_NONE, 14,   3,  14,  5, 16, SPR_ARROW_DOWN,      STR_029E_MOVE_THE_STARTING_DATE},
       
   761 {  WWT_IMGBTN, RESIZE_NONE, 14, 113, 125,  5, 16, SPR_ARROW_UP,        STR_029F_MOVE_THE_STARTING_DATE},
       
   762 
       
   763 {  WWT_IMGBTN, RESIZE_NONE, 14,   0,   0,  0, 21, SPR_IMG_SMALLMAP,    STR_0175_DISPLAY_MAP_TOWN_DIRECTORY},
       
   764 
       
   765 {  WWT_IMGBTN, RESIZE_NONE, 14,   0,   0,  0, 21, SPR_IMG_ZOOMIN,      STR_017F_ZOOM_THE_VIEW_IN},
       
   766 {  WWT_IMGBTN, RESIZE_NONE, 14,   0,   0,  0, 21, SPR_IMG_ZOOMOUT,     STR_0180_ZOOM_THE_VIEW_OUT},
       
   767 
       
   768 {  WWT_IMGBTN, RESIZE_NONE, 14,   0,   0,  0, 21, SPR_IMG_LANDSCAPING, STR_022E_LANDSCAPE_GENERATION},
       
   769 {  WWT_IMGBTN, RESIZE_NONE, 14,   0,   0,  0, 21, SPR_IMG_TOWN,        STR_022F_TOWN_GENERATION},
       
   770 {  WWT_IMGBTN, RESIZE_NONE, 14,   0,   0,  0, 21, SPR_IMG_INDUSTRY,    STR_0230_INDUSTRY_GENERATION},
       
   771 {  WWT_IMGBTN, RESIZE_NONE, 14,   0,   0,  0, 21, SPR_IMG_BUILDROAD,   STR_0231_ROAD_CONSTRUCTION},
       
   772 {  WWT_IMGBTN, RESIZE_NONE, 14,   0,   0,  0, 21, SPR_IMG_PLANTTREES,  STR_0288_PLANT_TREES},
       
   773 {  WWT_IMGBTN, RESIZE_NONE, 14,   0,   0,  0, 21, SPR_IMG_SIGN,        STR_0289_PLACE_SIGN},
       
   774 
       
   775 {   WWT_EMPTY, RESIZE_NONE,  0,   0,   0,  0,  0, 0x0,                 STR_NULL},
       
   776 {   WWT_EMPTY, RESIZE_NONE,  0,   0,   0,  0,  0, 0x0,                 STR_NULL},
       
   777 {   WWT_EMPTY, RESIZE_NONE,  0,   0,   0,  0,  0, 0x0,                 STR_NULL},
       
   778 {   WWT_EMPTY, RESIZE_NONE,  0,   0,   0,  0,  0, 0x0,                 STR_NULL},
       
   779 {   WWT_EMPTY, RESIZE_NONE,  0,   0,   0,  0,  0, 0x0,                 STR_NULL},
       
   780 {   WWT_EMPTY, RESIZE_NONE,  0,   0,   0,  0,  0, 0x0,                 STR_NULL},
       
   781 {   WWT_EMPTY, RESIZE_NONE,  0,   0,   0,  0,  0, 0x0,                 STR_NULL},
       
   782 {  WWT_IMGBTN, RESIZE_NONE, 14,   0,   0,  0, 21, SPR_IMG_MUSIC,       STR_01D4_SHOW_SOUND_MUSIC_WINDOW},
       
   783 {   WWT_EMPTY, RESIZE_NONE,  0,   0,   0,  0,  0, 0x0,                 STR_NULL},
       
   784 {  WWT_IMGBTN, RESIZE_NONE, 14,   0,   0,  0, 21, SPR_IMG_QUERY,       STR_0186_LAND_BLOCK_INFORMATION},
       
   785 {WIDGETS_END},
       
   786 };
       
   787 
       
   788 static const WindowDesc _toolb_scen_desc = {
       
   789 	0, 0, 130, 22, 640, 22,
       
   790 	WC_MAIN_TOOLBAR, WC_NONE,
       
   791 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
       
   792 	_toolb_scen_widgets,
       
   793 	ScenEditToolbarWndProc
       
   794 };
       
   795 
       
   796 Window *AllocateToolbar()
       
   797 {
       
   798 	return AllocateWindowDesc((_game_mode != GM_EDITOR) ? &_toolb_normal_desc : &_toolb_scen_desc);
       
   799 }