# airport_gui.cpp

Go to the documentation of this file.

    00001 /* $Id$ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00012 #include "stdafx.h"
    00013 #include "window_gui.h"
    00014 #include "station_gui.h"
    00015 #include "terraform_gui.h"
    00016 #include "sound_func.h"
    00017 #include "window_func.h"
    00018 #include "strings_func.h"
    00019 #include "viewport_func.h"
    00020 #include "company_func.h"
    00021 #include "tilehighlight_func.h"
    00022 #include "company_base.h"
    00023 #include "station_type.h"
    00024 #include "newgrf_airport.h"
    00025 #include "newgrf_callbacks.h"
    00026 #include "widgets/dropdown_type.h"
    00027 #include "core/geometry_func.hpp"
    00028 #include "hotkeys.h"
    00029 #include "sprite.h"
    00030
    00031 #include "table/strings.h"
    00032
    00033 static AirportClassID _selected_airport_class;
    00034 static int _selected_airport_index;
    00035 static byte _selected_airport_layout;
    00036
    00037 static void ShowBuildAirportPicker(Window *parent);
    00038
    00039 SpriteID GetCustomAirportSprite(const AirportSpec *as, byte layout);
    00040
    00041 void CcBuildAirport(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
    00042 {
    00043   if (result.Failed()) return;
    00044
    00045   SndPlayTileFx(SND_1F_SPLAT, tile);
    00046   if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
    00047 }
    00048
    00053 static void PlaceAirport(TileIndex tile)
    00054 {
    00055   if (_selected_airport_index == -1) return;
    00056   uint32 p2 = _ctrl_pressed;
    00057   SB(p2, 16, 16, INVALID_STATION); // no station to join
    00058
    00059   uint32 p1 = AirportClass::Get(_selected_airport_class, _selected_airport_index)->GetIndex();
    00060   p1 |= _selected_airport_layout << 8;
    00061   CommandContainer cmdcont = { tile, p1, p2, CMD_BUILD_AIRPORT | CMD_MSG(STR_ERROR_CAN_T_BUILD_AIRPORT_HERE), CcBuildAirport, "" };
    00062   ShowSelectStationIfNeeded(cmdcont, TileArea(tile, _thd.size.x / TILE_SIZE, _thd.size.y / TILE_SIZE));
    00063 }
    00064
    00066 enum AirportToolbarWidgets {
    00067   ATW_AIRPORT,
    00068   ATW_DEMOLISH,
    00069 };
    00070
    00071
    00073 struct BuildAirToolbarWindow : Window {
    00074   int last_user_action; // Last started user action.
    00075
    00076   BuildAirToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
    00077   {
    00078     this->InitNested(desc, window_number);
    00079     if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this);
    00080     this->last_user_action = WIDGET_LIST_END;
    00081   }
    00082
    00083   ~BuildAirToolbarWindow()
    00084   {
    00085     if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false);
    00086   }
    00087
    00088   virtual void OnClick(Point pt, int widget, int click_count)
    00089   {
    00090     switch (widget) {
    00091       case ATW_AIRPORT:
    00092         if (HandlePlacePushButton(this, ATW_AIRPORT, SPR_CURSOR_AIRPORT, HT_RECT)) {
    00093           ShowBuildAirportPicker(this);
    00094           this->last_user_action = widget;
    00095         }
    00096         break;
    00097
    00098       case ATW_DEMOLISH:
    00099         HandlePlacePushButton(this, ATW_DEMOLISH, ANIMCURSOR_DEMOLISH, HT_RECT | HT_DIAGONAL);
    00100         this->last_user_action = widget;
    00101         break;
    00102
    00103       default: break;
    00104     }
    00105   }
    00106
    00107
    00108   virtual EventState OnKeyPress(uint16 key, uint16 keycode)
    00109   {
    00110     int num = CheckHotkeyMatch(airtoolbar_hotkeys, keycode, this);
    00111     if (num == -1) return ES_NOT_HANDLED;
    00112     this->OnClick(Point(), num, 1);
    00113     return ES_HANDLED;
    00114   }
    00115
    00116   virtual void OnPlaceObject(Point pt, TileIndex tile)
    00117   {
    00118     switch (this->last_user_action) {
    00119       case ATW_AIRPORT:
    00120         PlaceAirport(tile);
    00121         break;
    00122
    00123       case ATW_DEMOLISH:
    00124         PlaceProc_DemolishArea(tile);
    00125         break;
    00126
    00127       default: NOT_REACHED();
    00128     }
    00129   }
    00130
    00131   virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
    00132   {
    00133     VpSelectTilesWithMethod(pt.x, pt.y, select_method);
    00134   }
    00135
    00136   virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
    00137   {
    00138     if (pt.x != -1 && select_proc == DDSP_DEMOLISH_AREA) {
    00139       GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
    00140     }
    00141   }
    00142
    00143   virtual void OnPlaceObjectAbort()
    00144   {
    00145     this->RaiseButtons();
    00146
    00147     DeleteWindowById(WC_BUILD_STATION, TRANSPORT_AIR);
    00148     DeleteWindowById(WC_SELECT_STATION, 0);
    00149   }
    00150
    00151   static Hotkey<BuildAirToolbarWindow> airtoolbar_hotkeys[];
    00152 };
    00153
    00154 Hotkey<BuildAirToolbarWindow> BuildAirToolbarWindow::airtoolbar_hotkeys[] = {
    00155   Hotkey<BuildAirToolbarWindow>('1', "airport", ATW_AIRPORT),
    00156   Hotkey<BuildAirToolbarWindow>('2', "demolish", ATW_DEMOLISH),
    00157   HOTKEY_LIST_END(BuildAirToolbarWindow)
    00158 };
    00159 Hotkey<BuildAirToolbarWindow> *_airtoolbar_hotkeys = BuildAirToolbarWindow::airtoolbar_hotkeys;
    00160
    00161 static const NWidgetPart _nested_air_toolbar_widgets[] = {
    00162   NWidget(NWID_HORIZONTAL),
    00163     NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
    00164     NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_TOOLBAR_AIRCRAFT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
    00165     NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
    00166   EndContainer(),
    00167   NWidget(NWID_HORIZONTAL),
    00168     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, ATW_AIRPORT), SetFill(0, 1), SetMinimalSize(42, 22), SetDataTip(SPR_IMG_AIRPORT, STR_TOOLBAR_AIRCRAFT_BUILD_AIRPORT_TOOLTIP),
    00169     NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetMinimalSize(4, 22), SetFill(1, 1), EndContainer(),
    00170     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, ATW_DEMOLISH), SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
    00171   EndContainer(),
    00172 };
    00173
    00174 static const WindowDesc _air_toolbar_desc(
    00175   WDP_ALIGN_TOOLBAR, 0, 0,
    00176   WC_BUILD_TOOLBAR, WC_NONE,
    00177   WDF_CONSTRUCTION,
    00178   _nested_air_toolbar_widgets, lengthof(_nested_air_toolbar_widgets)
    00179 );
    00180
    00188 Window *ShowBuildAirToolbar()
    00189 {
    00190   if (!Company::IsValidID(_local_company)) return NULL;
    00191
    00192   DeleteWindowByClass(WC_BUILD_TOOLBAR);
    00193   return AllocateWindowDescFront<BuildAirToolbarWindow>(&_air_toolbar_desc, TRANSPORT_AIR);
    00194 }
    00195
    00196 EventState AirportToolbarGlobalHotkeys(uint16 key, uint16 keycode)
    00197 {
    00198   int num = CheckHotkeyMatch<BuildAirToolbarWindow>(_airtoolbar_hotkeys, keycode, NULL, true);
    00199   if (num == -1) return ES_NOT_HANDLED;
    00200   Window *w = ShowBuildAirToolbar();
    00201   if (w == NULL) return ES_NOT_HANDLED;
    00202   return w->OnKeyPress(key, keycode);
    00203 }
    00204
    00206 enum AirportPickerWidgets {
    00207   BAIRW_CLASS_DROPDOWN,
    00208   BAIRW_AIRPORT_LIST,
    00209   BAIRW_SCROLLBAR,
    00210   BAIRW_LAYOUT_NUM,
    00211   BAIRW_LAYOUT_DECREASE,
    00212   BAIRW_LAYOUT_INCREASE,
    00213   BAIRW_AIRPORT_SPRITE,
    00214   BAIRW_EXTRA_TEXT,
    00215   BAIRW_BOTTOMPANEL,
    00216   BAIRW_COVERAGE_LABEL,
    00217   BAIRW_BTN_DONTHILIGHT,
    00218   BAIRW_BTN_DOHILIGHT,
    00219 };
    00220
    00221 class BuildAirportWindow : public PickerWindowBase {
    00222   SpriteID preview_sprite;
    00223   int line_height;
    00224   Scrollbar *vscroll;
    00225
    00227   static DropDownList *BuildAirportClassDropDown()
    00228   {
    00229     DropDownList *list = new DropDownList();
    00230
    00231     for (uint i = 0; i < AirportClass::GetCount(); i++) {
    00232       list->push_back(new DropDownListStringItem(AirportClass::GetName((AirportClassID)i), i, false));
    00233     }
    00234
    00235     return list;
    00236   }
    00237
    00238 public:
    00239   BuildAirportWindow(const WindowDesc *desc, Window *parent) : PickerWindowBase(parent)
    00240   {
    00241     this->CreateNestedTree(desc);
    00242
    00243     this->vscroll = this->GetScrollbar(BAIRW_SCROLLBAR);
    00244     this->vscroll->SetCapacity(5);
    00245     this->vscroll->SetPosition(0);
    00246
    00247     this->FinishInitNested(desc, TRANSPORT_AIR);
    00248
    00249     this->SetWidgetLoweredState(BAIRW_BTN_DONTHILIGHT, !_settings_client.gui.station_show_coverage);
    00250     this->SetWidgetLoweredState(BAIRW_BTN_DOHILIGHT, _settings_client.gui.station_show_coverage);
    00251     this->OnInvalidateData();
    00252
    00253     this->vscroll->SetCount(AirportClass::GetCount(_selected_airport_class));
    00254     this->SelectFirstAvailableAirport(true);
    00255   }
    00256
    00257   virtual ~BuildAirportWindow()
    00258   {
    00259     DeleteWindowById(WC_SELECT_STATION, 0);
    00260   }
    00261
    00262   virtual void SetStringParameters(int widget) const
    00263   {
    00264     switch (widget) {
    00265       case BAIRW_CLASS_DROPDOWN:
    00266         SetDParam(0, AirportClass::GetName(_selected_airport_class));
    00267         break;
    00268
    00269       case BAIRW_LAYOUT_NUM:
    00270         SetDParam(0, STR_EMPTY);
    00271         if (_selected_airport_index != -1) {
    00272           const AirportSpec *as = AirportClass::Get(_selected_airport_class, _selected_airport_index);
    00273           StringID string = GetAirportTextCallback(as, _selected_airport_layout, CBID_AIRPORT_LAYOUT_NAME);
    00274           if (string != STR_UNDEFINED) {
    00275             SetDParam(0, string);
    00276           } else if (as->num_table > 1) {
    00277             SetDParam(0, STR_STATION_BUILD_AIRPORT_LAYOUT_NAME);
    00278             SetDParam(1, _selected_airport_layout + 1);
    00279           }
    00280         }
    00281         break;
    00282
    00283       default: break;
    00284     }
    00285   }
    00286
    00287   virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
    00288   {
    00289     switch (widget) {
    00290       case BAIRW_CLASS_DROPDOWN: {
    00291         Dimension d = {0, 0};
    00292         for (uint i = 0; i < AirportClass::GetCount(); i++) {
    00293           SetDParam(0, AirportClass::GetName((AirportClassID)i));
    00294           d = maxdim(d, GetStringBoundingBox(STR_BLACK_STRING));
    00295         }
    00296         d.width += padding.width;
    00297         d.height += padding.height;
    00298         *size = maxdim(*size, d);
    00299         break;
    00300       }
    00301
    00302       case BAIRW_AIRPORT_LIST: {
    00303         for (int i = 0; i < NUM_AIRPORTS; i++) {
    00304           const AirportSpec *as = AirportSpec::Get(i);
    00305           if (!as->enabled) continue;
    00306
    00307           size->width = max(size->width, GetStringBoundingBox(as->name).width);
    00308         }
    00309
    00310         this->line_height = FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
    00311         size->height = this->vscroll->GetCapacity() * this->line_height;
    00312         break;
    00313       }
    00314
    00315       case BAIRW_AIRPORT_SPRITE:
    00316         for (int i = 0; i < NUM_AIRPORTS; i++) {
    00317           const AirportSpec *as = AirportSpec::Get(i);
    00318           if (!as->enabled) continue;
    00319           for (byte layout = 0; layout < as->num_table; layout++) {
    00320             SpriteID sprite = GetCustomAirportSprite(as, layout);
    00321             if (sprite != 0) {
    00322               Dimension d = GetSpriteSize(sprite);
    00323               d.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
    00324               d.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
    00325               *size = maxdim(d, *size);
    00326             }
    00327           }
    00328         }
    00329         break;
    00330
    00331       case BAIRW_EXTRA_TEXT:
    00332         for (int i = NEW_AIRPORT_OFFSET; i < NUM_AIRPORTS; i++) {
    00333           const AirportSpec *as = AirportSpec::Get(i);
    00334           if (!as->enabled) continue;
    00335           for (byte layout = 0; layout < as->num_table; layout++) {
    00336             StringID string = GetAirportTextCallback(as, layout, CBID_AIRPORT_ADDITIONAL_TEXT);
    00337             if (string == STR_UNDEFINED) continue;
    00338
    00339             /* STR_BLACK_STRING is used to start the string with {BLACK} */
    00340             SetDParam(0, string);
    00341             Dimension d = GetStringMultiLineBoundingBox(STR_BLACK_STRING, *size);
    00342             *size = maxdim(d, *size);
    00343           }
    00344         }
    00345         break;
    00346
    00347       default: break;
    00348     }
    00349   }
    00350
    00351   virtual void DrawWidget(const Rect &r, int widget) const
    00352   {
    00353     switch (widget) {
    00354       case BAIRW_AIRPORT_LIST: {
    00355         int y = r.top;
    00356         for (uint i = this->vscroll->GetPosition(); this->vscroll->IsVisible(i) && i < AirportClass::GetCount(_selected_airport_class); i++) {
    00357           const AirportSpec *as = AirportClass::Get(_selected_airport_class, i);
    00358           if (!as->IsAvailable()) {
    00359             GfxFillRect(r.left + 1, y + 1, r.right - 1, y + this->line_height - 2, 0, FILLRECT_CHECKER);
    00360           }
    00361           DrawString(r.left + WD_MATRIX_LEFT, r.right + WD_MATRIX_RIGHT, y + WD_MATRIX_TOP, as->name, ((int)i == _selected_airport_index) ? TC_WHITE : TC_BLACK);
    00362           y += this->line_height;
    00363         }
    00364         break;
    00365       }
    00366
    00367       case BAIRW_AIRPORT_SPRITE:
    00368         if (this->preview_sprite != 0) {
    00369           Dimension d = GetSpriteSize(this->preview_sprite);
    00370           DrawSprite(this->preview_sprite, COMPANY_SPRITE_COLOUR(_local_company), (r.left + r.right - d.width) / 2, (r.top + r.bottom - d.height) / 2);
    00371         }
    00372         break;
    00373
    00374       case BAIRW_EXTRA_TEXT:
    00375         if (_selected_airport_index != -1) {
    00376           const AirportSpec *as = AirportClass::Get(_selected_airport_class, _selected_airport_index);
    00377           StringID string = GetAirportTextCallback(as, _selected_airport_layout, CBID_AIRPORT_ADDITIONAL_TEXT);
    00378           if (string != STR_UNDEFINED) {
    00379             SetDParam(0, string);
    00380             DrawStringMultiLine(r.left, r.right, r.top, r.bottom, STR_BLACK_STRING);
    00381           }
    00382         }
    00383         break;
    00384     }
    00385   }
    00386
    00387   virtual void OnPaint()
    00388   {
    00389     this->DrawWidgets();
    00390
    00391     uint16 top = this->GetWidget<NWidgetBase>(BAIRW_BTN_DOHILIGHT)->pos_y + this->GetWidget<NWidgetBase>(BAIRW_BTN_DOHILIGHT)->current_y + WD_PAR_VSEP_NORMAL;
    00392     NWidgetBase *panel_nwi = this->GetWidget<NWidgetBase>(BAIRW_BOTTOMPANEL);
    00393
    00394     int right = panel_nwi->pos_x +  panel_nwi->current_x;
    00395     int bottom = panel_nwi->pos_y +  panel_nwi->current_y;
    00396
    00397     if (_selected_airport_index != -1) {
    00398       const AirportSpec *as = AirportClass::Get(_selected_airport_class, _selected_airport_index);
    00399       int rad = _settings_game.station.modified_catchment ? as->catchment : (uint)CA_UNMODIFIED;
    00400
    00401       /* only show the station (airport) noise, if the noise option is activated */
    00402       if (_settings_game.economy.station_noise_level) {
    00403         /* show the noise of the selected airport */
    00404         SetDParam(0, as->noise_level);
    00405         DrawString(panel_nwi->pos_x + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, STR_STATION_BUILD_NOISE);
    00406         top += FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL;
    00407       }
    00408
    00409       /* strings such as 'Size' and 'Coverage Area' */
    00410       top = DrawStationCoverageAreaText(panel_nwi->pos_x + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, SCT_ALL, rad, false) + WD_PAR_VSEP_NORMAL;
    00411       top = DrawStationCoverageAreaText(panel_nwi->pos_x + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, SCT_ALL, rad, true) + WD_PAR_VSEP_NORMAL;
    00412     }
    00413
    00414     /* Resize background if the text is not equally long as the window. */
    00415     if (top > bottom || (top < bottom && panel_nwi->current_y > panel_nwi->smallest_y)) {
    00416       ResizeWindow(this, 0, top - bottom);
    00417     }
    00418   }
    00419
    00420   void SelectOtherAirport(int airport_index)
    00421   {
    00422     _selected_airport_index = airport_index;
    00423     _selected_airport_layout = 0;
    00424
    00425     if (_selected_airport_index != -1) {
    00426       const AirportSpec *as = AirportClass::Get(_selected_airport_class, _selected_airport_index);
    00427       this->preview_sprite = GetCustomAirportSprite(as, _selected_airport_layout);
    00428     }
    00429
    00430     this->UpdateSelectSize();
    00431     this->SetDirty();
    00432   }
    00433
    00434   void UpdateSelectSize()
    00435   {
    00436     if (_selected_airport_index == -1) {
    00437       SetTileSelectSize(1, 1);
    00438       this->DisableWidget(BAIRW_LAYOUT_DECREASE);
    00439       this->DisableWidget(BAIRW_LAYOUT_INCREASE);
    00440     } else {
    00441       const AirportSpec *as = AirportClass::Get(_selected_airport_class, _selected_airport_index);
    00442       int w = as->size_x;
    00443       int h = as->size_y;
    00444       Direction rotation = as->rotation[_selected_airport_layout];
    00445       if (rotation == DIR_E || rotation == DIR_W) Swap(w, h);
    00446       SetTileSelectSize(w, h);
    00447
    00448       this->SetWidgetDisabledState(BAIRW_LAYOUT_DECREASE, _selected_airport_layout == 0);
    00449       this->SetWidgetDisabledState(BAIRW_LAYOUT_INCREASE, _selected_airport_layout + 1 >= as->num_table);
    00450
    00451       int rad = _settings_game.station.modified_catchment ? as->catchment : (uint)CA_UNMODIFIED;
    00452       if (_settings_client.gui.station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
    00453     }
    00454   }
    00455
    00456   virtual void OnClick(Point pt, int widget, int click_count)
    00457   {
    00458     switch (widget) {
    00459       case BAIRW_CLASS_DROPDOWN:
    00460         ShowDropDownList(this, BuildAirportClassDropDown(), _selected_airport_class, BAIRW_CLASS_DROPDOWN);
    00461         break;
    00462
    00463       case BAIRW_AIRPORT_LIST: {
    00464         int num_clicked = this->vscroll->GetPosition() + (pt.y - this->nested_array[widget]->pos_y) / this->line_height;
    00465         if (num_clicked >= this->vscroll->GetCount()) break;
    00466         const AirportSpec *as = AirportClass::Get(_selected_airport_class, num_clicked);
    00467         if (as->IsAvailable()) this->SelectOtherAirport(num_clicked);
    00468         break;
    00469       }
    00470
    00471       case BAIRW_BTN_DONTHILIGHT: case BAIRW_BTN_DOHILIGHT:
    00472         _settings_client.gui.station_show_coverage = (widget != BAIRW_BTN_DONTHILIGHT);
    00473         this->SetWidgetLoweredState(BAIRW_BTN_DONTHILIGHT, !_settings_client.gui.station_show_coverage);
    00474         this->SetWidgetLoweredState(BAIRW_BTN_DOHILIGHT, _settings_client.gui.station_show_coverage);
    00475         this->SetDirty();
    00476         SndPlayFx(SND_15_BEEP);
    00477         this->UpdateSelectSize();
    00478         break;
    00479
    00480       case BAIRW_LAYOUT_DECREASE:
    00481         _selected_airport_layout--;
    00482         this->UpdateSelectSize();
    00483         this->SetDirty();
    00484         break;
    00485
    00486       case BAIRW_LAYOUT_INCREASE:
    00487         _selected_airport_layout++;
    00488         this->UpdateSelectSize();
    00489         this->SetDirty();
    00490         break;
    00491     }
    00492   }
    00493
    00499   void SelectFirstAvailableAirport(bool change_class)
    00500   {
    00501     /* First try to select an airport in the selected class. */
    00502     for (uint i = 0; i < AirportClass::GetCount(_selected_airport_class); i++) {
    00503       const AirportSpec *as = AirportClass::Get(_selected_airport_class, i);
    00504       if (as->IsAvailable()) {
    00505         this->SelectOtherAirport(i);
    00506         return;
    00507       }
    00508     }
    00509     if (change_class) {
    00510       /* If that fails, select the first available airport
    00511        * from a random class. */
    00512       for (AirportClassID j = APC_BEGIN; j < APC_MAX; j++) {
    00513         for (uint i = 0; i < AirportClass::GetCount(j); i++) {
    00514           const AirportSpec *as = AirportClass::Get(j, i);
    00515           if (as->IsAvailable()) {
    00516             _selected_airport_class = j;
    00517             this->SelectOtherAirport(i);
    00518             return;
    00519           }
    00520         }
    00521       }
    00522     }
    00523     /* If all airports are unavailable, select nothing. */
    00524     this->SelectOtherAirport(-1);
    00525   }
    00526
    00527   virtual void OnDropdownSelect(int widget, int index)
    00528   {
    00529     assert(widget == BAIRW_CLASS_DROPDOWN);
    00530     _selected_airport_class = (AirportClassID)index;
    00531     this->vscroll->SetCount(AirportClass::GetCount(_selected_airport_class));
    00532     this->SelectFirstAvailableAirport(false);
    00533   }
    00534
    00535   virtual void OnTick()
    00536   {
    00537     CheckRedrawStationCoverage(this);
    00538   }
    00539 };
    00540
    00541 static const NWidgetPart _nested_build_airport_widgets[] = {
    00542   NWidget(NWID_HORIZONTAL),
    00543     NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
    00544     NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_STATION_BUILD_AIRPORT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
    00545   EndContainer(),
    00546   NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetFill(1, 0), SetPIP(2, 0, 2),
    00547     NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetDataTip(STR_STATION_BUILD_AIRPORT_CLASS_LABEL, STR_NULL), SetFill(1, 0),
    00548     NWidget(WWT_DROPDOWN, COLOUR_GREY, BAIRW_CLASS_DROPDOWN), SetFill(1, 0), SetDataTip(STR_BLACK_STRING, STR_NULL),
    00549     NWidget(NWID_HORIZONTAL),
    00550       NWidget(WWT_MATRIX, COLOUR_GREY, BAIRW_AIRPORT_LIST), SetFill(1, 0), SetDataTip(0x501, STR_NULL), SetScrollbar(BAIRW_SCROLLBAR),
    00551       NWidget(NWID_VSCROLLBAR, COLOUR_GREY, BAIRW_SCROLLBAR),
    00552     EndContainer(),
    00553     NWidget(NWID_HORIZONTAL),
    00554       NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, BAIRW_LAYOUT_DECREASE), SetMinimalSize(12, 0), SetDataTip(AWV_DECREASE, STR_NULL),
    00555       NWidget(WWT_LABEL, COLOUR_GREY, BAIRW_LAYOUT_NUM), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_BLACK_STRING, STR_NULL),
    00556       NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, BAIRW_LAYOUT_INCREASE), SetMinimalSize(12, 0), SetDataTip(AWV_INCREASE, STR_NULL),
    00557     EndContainer(),
    00558     NWidget(WWT_EMPTY, COLOUR_DARK_GREEN, BAIRW_AIRPORT_SPRITE), SetFill(1, 0),
    00559     NWidget(WWT_EMPTY, COLOUR_DARK_GREEN, BAIRW_EXTRA_TEXT), SetFill(1, 0), SetMinimalSize(150, 0),
    00560   EndContainer(),
    00561   /* Bottom panel. */
    00562   NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BAIRW_BOTTOMPANEL), SetPIP(2, 2, 2),
    00563     NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetDataTip(STR_STATION_BUILD_COVERAGE_AREA_TITLE, STR_NULL), SetFill(1, 0),
    00564     NWidget(NWID_HORIZONTAL),
    00565       NWidget(NWID_SPACER), SetMinimalSize(14, 0), SetFill(1, 0),
    00566       NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
    00567         NWidget(WWT_TEXTBTN, COLOUR_GREY, BAIRW_BTN_DONTHILIGHT), SetMinimalSize(60, 12), SetFill(1, 0),
    00568                       SetDataTip(STR_STATION_BUILD_COVERAGE_OFF, STR_STATION_BUILD_COVERAGE_AREA_OFF_TOOLTIP),
    00569         NWidget(WWT_TEXTBTN, COLOUR_GREY, BAIRW_BTN_DOHILIGHT), SetMinimalSize(60, 12), SetFill(1, 0),
    00570                       SetDataTip(STR_STATION_BUILD_COVERAGE_ON, STR_STATION_BUILD_COVERAGE_AREA_ON_TOOLTIP),
    00571       EndContainer(),
    00572       NWidget(NWID_SPACER), SetMinimalSize(14, 0), SetFill(1, 0),
    00573     EndContainer(),
    00574     NWidget(NWID_SPACER), SetMinimalSize(0, 10), SetResize(0, 1), SetFill(1, 0),
    00575   EndContainer(),
    00576 };
    00577
    00578 static const WindowDesc _build_airport_desc(
    00579   WDP_AUTO, 0, 0,
    00580   WC_BUILD_STATION, WC_BUILD_TOOLBAR,
    00581   WDF_CONSTRUCTION,
    00582   _nested_build_airport_widgets, lengthof(_nested_build_airport_widgets)
    00583 );
    00584
    00585 static void ShowBuildAirportPicker(Window *parent)
    00586 {
    00587   new BuildAirportWindow(&_build_airport_desc, parent);
    00588 }
    00589
    00590 void InitializeAirportGui()
    00591 {
    00592   _selected_airport_class = APC_BEGIN;
    00593 }