autoreplace_gui.cpp

Go to the documentation of this file.
00001 /* $Id: autoreplace_gui.cpp 15723 2009-03-15 15:12:06Z rubidium $ */
00002 
00005 #include "stdafx.h"
00006 #include "command_func.h"
00007 #include "vehicle_gui.h"
00008 #include "newgrf_engine.h"
00009 #include "group.h"
00010 #include "rail.h"
00011 #include "strings_func.h"
00012 #include "window_func.h"
00013 #include "autoreplace_func.h"
00014 #include "gfx_func.h"
00015 #include "company_func.h"
00016 #include "widgets/dropdown_type.h"
00017 #include "engine_base.h"
00018 #include "window_gui.h"
00019 #include "engine_gui.h"
00020 
00021 #include "table/strings.h"
00022 
00023 void DrawEngineList(VehicleType type, int x, int r, int y, const GUIEngineList *eng_list, uint16 min, uint16 max, EngineID selected_id, int count_location, GroupID selected_group);
00024 
00025 enum ReplaceVehicleWindowWidgets {
00026   RVW_WIDGET_LEFT_MATRIX = 3,
00027   RVW_WIDGET_LEFT_SCROLLBAR,
00028   RVW_WIDGET_RIGHT_MATRIX,
00029   RVW_WIDGET_RIGHT_SCROLLBAR,
00030   RVW_WIDGET_LEFT_DETAILS,
00031   RVW_WIDGET_RIGHT_DETAILS,
00032 
00033   /* Button row */
00034   RVW_WIDGET_START_REPLACE,
00035   RVW_WIDGET_INFO_TAB,
00036   RVW_WIDGET_STOP_REPLACE,
00037   RVW_WIDGET_RESIZE,
00038 
00039   /* Train only widgets */
00040   RVW_WIDGET_TRAIN_ENGINEWAGON_TOGGLE,
00041   RVW_WIDGET_TRAIN_FLUFF_LEFT,
00042   RVW_WIDGET_TRAIN_RAILTYPE_DROPDOWN,
00043   RVW_WIDGET_TRAIN_FLUFF_RIGHT,
00044   RVW_WIDGET_TRAIN_WAGONREMOVE_TOGGLE,
00045 };
00046 
00047 static int CDECL EngineNumberSorter(const void *a, const void *b)
00048 {
00049   const EngineID va = *(const EngineID*)a;
00050   const EngineID vb = *(const EngineID*)b;
00051   int r = ListPositionOfEngine(va) - ListPositionOfEngine(vb);
00052 
00053   return r;
00054 }
00055 
00064 void InvalidateAutoreplaceWindow(EngineID e, GroupID id_g)
00065 {
00066   Company *c = GetCompany(_local_company);
00067   uint num_engines = GetGroupNumEngines(_local_company, id_g, e);
00068 
00069   if (num_engines == 0 || c->num_engines[e] == 0) {
00070     /* We don't have any of this engine type.
00071      * Either we just sold the last one, we build a new one or we stopped replacing it.
00072      * In all cases, we need to update the left list */
00073     InvalidateWindowData(WC_REPLACE_VEHICLE, GetEngine(e)->type, true);
00074   }
00075 }
00076 
00080 void AddRemoveEngineFromAutoreplaceAndBuildWindows(VehicleType type)
00081 {
00082   InvalidateWindowData(WC_REPLACE_VEHICLE, type, false); // Update the autoreplace window
00083   InvalidateWindowClassesData(WC_BUILD_VEHICLE); // The build windows needs updating as well
00084 }
00085 
00089 class ReplaceVehicleWindow : public Window {
00090   byte sel_index[2];
00091   EngineID sel_engine[2];
00092   uint16 count[2];
00093   bool wagon_btnstate; 
00094   GUIEngineList list[2];
00095   bool update_left;
00096   bool update_right;
00097   bool init_lists;
00098   GroupID sel_group;
00099   static RailType sel_railtype;
00100 
00107   bool GenerateReplaceRailList(EngineID e, bool draw_left, bool show_engines)
00108   {
00109     const RailVehicleInfo *rvi = RailVehInfo(e);
00110 
00111     /* Ensure that the wagon/engine selection fits the engine. */
00112     if ((rvi->railveh_type == RAILVEH_WAGON) == show_engines) return false;
00113 
00114     if (draw_left && show_engines) {
00115       /* Ensure that the railtype is specific to the selected one */
00116       if (rvi->railtype != this->sel_railtype) return false;
00117     }
00118     return true;
00119   }
00120 
00121 
00126   void GenerateReplaceVehList(Window *w, bool draw_left)
00127   {
00128     EngineID selected_engine = INVALID_ENGINE;
00129     VehicleType type = (VehicleType)this->window_number;
00130     byte i = draw_left ? 0 : 1;
00131 
00132     GUIEngineList *list = &this->list[i];
00133     list->Clear();
00134 
00135     const Engine *e;
00136     FOR_ALL_ENGINES_OF_TYPE(e, type) {
00137       EngineID eid = e->index;
00138       if (type == VEH_TRAIN && !GenerateReplaceRailList(eid, draw_left, this->wagon_btnstate)) continue; // special rules for trains
00139 
00140       if (draw_left) {
00141         const GroupID selected_group = this->sel_group;
00142         const uint num_engines = GetGroupNumEngines(_local_company, selected_group, eid);
00143 
00144         /* Skip drawing the engines we don't have any of and haven't set for replacement */
00145         if (num_engines == 0 && EngineReplacementForCompany(GetCompany(_local_company), eid, selected_group) == INVALID_ENGINE) continue;
00146       } else {
00147         if (!CheckAutoreplaceValidity(this->sel_engine[0], eid, _local_company)) continue;
00148       }
00149 
00150       *list->Append() = eid;
00151       if (eid == this->sel_engine[i]) selected_engine = eid; // The selected engine is still in the list
00152     }
00153     this->sel_engine[i] = selected_engine; // update which engine we selected (the same or none, if it's not in the list anymore)
00154     EngList_Sort(list, &EngineNumberSorter);
00155   }
00156 
00158   void GenerateLists()
00159   {
00160     EngineID e = this->sel_engine[0];
00161 
00162     if (this->update_left == true) {
00163       /* We need to rebuild the left list */
00164       GenerateReplaceVehList(this, true);
00165       SetVScrollCount(this, this->list[0].Length());
00166       if (this->init_lists && this->sel_engine[0] == INVALID_ENGINE && this->list[0].Length() != 0) {
00167         this->sel_engine[0] = this->list[0][0];
00168       }
00169     }
00170 
00171     if (this->update_right || e != this->sel_engine[0]) {
00172       /* Either we got a request to rebuild the right list or the left list selected a different engine */
00173       if (this->sel_engine[0] == INVALID_ENGINE) {
00174         /* Always empty the right list when nothing is selected in the left list */
00175         this->list[1].Clear();
00176         this->sel_engine[1] = INVALID_ENGINE;
00177       } else {
00178         GenerateReplaceVehList(this, false);
00179         SetVScroll2Count(this, this->list[1].Length());
00180         if (this->init_lists && this->sel_engine[1] == INVALID_ENGINE && this->list[1].Length() != 0) {
00181           this->sel_engine[1] = this->list[1][0];
00182         }
00183       }
00184     }
00185     /* Reset the flags about needed updates */
00186     this->update_left  = false;
00187     this->update_right = false;
00188     this->init_lists   = false;
00189   }
00190 
00191 public:
00192   ReplaceVehicleWindow(const WindowDesc *desc, VehicleType vehicletype, GroupID id_g) : Window(desc, vehicletype)
00193   {
00194     this->wagon_btnstate = true; // start with locomotives (all other vehicles will not read this bool)
00195     this->update_left   = true;
00196     this->update_right  = true;
00197     this->init_lists    = true;
00198     this->sel_engine[0] = INVALID_ENGINE;
00199     this->sel_engine[1] = INVALID_ENGINE;
00200 
00201     this->resize.step_height = GetVehicleListHeight(vehicletype);
00202     this->vscroll.cap = this->resize.step_height == 14 ? 8 : 4;
00203 
00204     Widget *widget = this->widget;
00205     widget[RVW_WIDGET_LEFT_MATRIX].data = widget[RVW_WIDGET_RIGHT_MATRIX].data = (this->vscroll.cap << 8) + 1;
00206 
00207     if (vehicletype == VEH_TRAIN) {
00208       this->wagon_btnstate = true;
00209       /* The train window is bigger so we will move some of the widgets to fit the new size.
00210        * We will start by moving the resize button to the lower right corner.                 */
00211       widget[RVW_WIDGET_RESIZE].top         = widget[RVW_WIDGET_TRAIN_ENGINEWAGON_TOGGLE].top;
00212       widget[RVW_WIDGET_RESIZE].bottom      = widget[RVW_WIDGET_TRAIN_ENGINEWAGON_TOGGLE].bottom;
00213       widget[RVW_WIDGET_STOP_REPLACE].right = widget[RVW_WIDGET_RESIZE].right;
00214 
00215       /* The detail panel is one line taller for trains so we will move some of the widgets one line (10 pixels) down. */
00216       widget[RVW_WIDGET_LEFT_DETAILS].bottom  += 10;
00217       widget[RVW_WIDGET_RIGHT_DETAILS].bottom += 10;
00218       for (int i = RVW_WIDGET_START_REPLACE; i < RVW_WIDGET_RESIZE; i++) {
00219         widget[i].top    += 10;
00220         widget[i].bottom += 10;
00221       }
00222     } else {
00223       /* Since it's not a train we will hide the train only widgets. */
00224       this->SetWidgetsHiddenState(true,
00225                   RVW_WIDGET_TRAIN_ENGINEWAGON_TOGGLE,
00226                   RVW_WIDGET_TRAIN_FLUFF_LEFT,
00227                   RVW_WIDGET_TRAIN_RAILTYPE_DROPDOWN,
00228                   RVW_WIDGET_TRAIN_FLUFF_RIGHT,
00229                   RVW_WIDGET_TRAIN_WAGONREMOVE_TOGGLE,
00230                   WIDGET_LIST_END);
00231     }
00232 
00233     ResizeWindow(this, 0, this->resize.step_height * this->vscroll.cap);
00234 
00235     /* Set the minimum window size to the current window size */
00236     this->resize.width  = this->width;
00237     this->resize.height = this->height;
00238 
00239     this->owner = _local_company;
00240     this->sel_group = id_g;
00241     this->vscroll2.cap = this->vscroll.cap;   // these two are always the same
00242 
00243     this->FindWindowPlacementAndResize(desc);
00244   }
00245 
00246   virtual void OnPaint()
00247   {
00248     if (this->update_left || this->update_right) this->GenerateLists();
00249 
00250     Company *c = GetCompany(_local_company);
00251     EngineID selected_id[2];
00252     const GroupID selected_group = this->sel_group;
00253 
00254     selected_id[0] = this->sel_engine[0];
00255     selected_id[1] = this->sel_engine[1];
00256 
00257     /* Disable the "Start Replacing" button if:
00258      *    Either list is empty
00259      * or The selected replacement engine has a replacement (to prevent loops)
00260      * or The right list (new replacement) has the existing replacement vehicle selected */
00261     this->SetWidgetDisabledState(RVW_WIDGET_START_REPLACE,
00262                     selected_id[0] == INVALID_ENGINE ||
00263                     selected_id[1] == INVALID_ENGINE ||
00264                     EngineReplacementForCompany(c, selected_id[1], selected_group) != INVALID_ENGINE ||
00265                     EngineReplacementForCompany(c, selected_id[0], selected_group) == selected_id[1]);
00266 
00267     /* Disable the "Stop Replacing" button if:
00268      *   The left list (existing vehicle) is empty
00269      *   or The selected vehicle has no replacement set up */
00270     this->SetWidgetDisabledState(RVW_WIDGET_STOP_REPLACE,
00271                     selected_id[0] == INVALID_ENGINE ||
00272                     !EngineHasReplacementForCompany(c, selected_id[0], selected_group));
00273 
00274     /* now the actual drawing of the window itself takes place */
00275     SetDParam(0, STR_019F_TRAIN + this->window_number);
00276 
00277     if (this->window_number == VEH_TRAIN) {
00278       /* set on/off for renew_keep_length */
00279       SetDParam(1, c->renew_keep_length ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
00280 
00281       /* set wagon/engine button */
00282       SetDParam(2, this->wagon_btnstate ? STR_ENGINES : STR_WAGONS);
00283 
00284       /* sets the colour of that art thing */
00285       this->widget[RVW_WIDGET_TRAIN_FLUFF_LEFT].colour  = _company_colours[_local_company];
00286       this->widget[RVW_WIDGET_TRAIN_FLUFF_RIGHT].colour = _company_colours[_local_company];
00287     }
00288 
00289     if (this->window_number == VEH_TRAIN) {
00290       /* Show the selected railtype in the pulldown menu */
00291       const RailtypeInfo *rti = GetRailTypeInfo(sel_railtype);
00292       this->widget[RVW_WIDGET_TRAIN_RAILTYPE_DROPDOWN].data = rti->strings.replace_text;
00293     }
00294 
00295     this->DrawWidgets();
00296 
00297     /* sets up the string for the vehicle that is being replaced to */
00298     if (selected_id[0] != INVALID_ENGINE) {
00299       if (!EngineHasReplacementForCompany(c, selected_id[0], selected_group)) {
00300         SetDParam(0, STR_NOT_REPLACING);
00301       } else {
00302         SetDParam(0, STR_ENGINE_NAME);
00303         SetDParam(1, EngineReplacementForCompany(c, selected_id[0], selected_group));
00304       }
00305     } else {
00306       SetDParam(0, STR_NOT_REPLACING_VEHICLE_SELECTED);
00307     }
00308 
00309     DrawStringTruncated(this->widget[RVW_WIDGET_INFO_TAB].left + 6, this->widget[RVW_WIDGET_INFO_TAB].top + 1, STR_02BD, TC_BLACK, this->GetWidgetWidth(RVW_WIDGET_INFO_TAB) - 12);
00310 
00311     /* Draw the lists */
00312     for (byte i = 0; i < 2; i++) {
00313       uint widget     = (i == 0) ? RVW_WIDGET_LEFT_MATRIX : RVW_WIDGET_RIGHT_MATRIX;
00314       GUIEngineList *list = &this->list[i]; // which list to draw
00315       EngineID start  = i == 0 ? this->vscroll.pos : this->vscroll2.pos; // what is the offset for the start (scrolling)
00316       EngineID end    = min((i == 0 ? this->vscroll.cap : this->vscroll2.cap) + start, list->Length());
00317 
00318       /* Do the actual drawing */
00319       DrawEngineList((VehicleType)this->window_number, this->widget[widget].left + 2, this->widget[widget].right, this->widget[widget].top + 1, list, start, end, this->sel_engine[i], i == 0 ? this->widget[RVW_WIDGET_LEFT_MATRIX].right - 2 : 0, selected_group);
00320 
00321       /* Also draw the details if an engine is selected */
00322       if (this->sel_engine[i] != INVALID_ENGINE) {
00323         const Widget *wi = &this->widget[i == 0 ? RVW_WIDGET_LEFT_DETAILS : RVW_WIDGET_RIGHT_DETAILS];
00324         int text_end = DrawVehiclePurchaseInfo(wi->left + 2, wi->top + 1, wi->right - wi->left - 2, this->sel_engine[i]);
00325 
00326         if (text_end > wi->bottom) {
00327           this->SetDirty();
00328           ResizeWindowForWidget(this, i == 0 ? RVW_WIDGET_LEFT_DETAILS : RVW_WIDGET_RIGHT_DETAILS, 0, text_end - wi->bottom);
00329           this->SetDirty();
00330         }
00331       }
00332     }
00333   }
00334 
00335   virtual void OnClick(Point pt, int widget)
00336   {
00337     switch (widget) {
00338       case RVW_WIDGET_TRAIN_ENGINEWAGON_TOGGLE:
00339         this->wagon_btnstate = !(this->wagon_btnstate);
00340         this->update_left = true;
00341         this->init_lists  = true;
00342         this->SetDirty();
00343         break;
00344 
00345       case RVW_WIDGET_TRAIN_RAILTYPE_DROPDOWN: { // Railtype selection dropdown menu
00346         const Company *c = GetCompany(_local_company);
00347         DropDownList *list = new DropDownList();
00348         for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
00349           const RailtypeInfo *rti = GetRailTypeInfo(rt);
00350           /* Skip rail type if it has no label */
00351           if (rti->label == 0) continue;
00352           list->push_back(new DropDownListStringItem(rti->strings.replace_text, rt, !HasBit(c->avail_railtypes, rt)));
00353         }
00354         ShowDropDownList(this, list, sel_railtype, RVW_WIDGET_TRAIN_RAILTYPE_DROPDOWN);
00355         break;
00356       }
00357 
00358       case RVW_WIDGET_TRAIN_WAGONREMOVE_TOGGLE: // toggle renew_keep_length
00359         DoCommandP(0, 5, GetCompany(_local_company)->renew_keep_length ? 0 : 1, CMD_SET_AUTOREPLACE);
00360         break;
00361 
00362       case RVW_WIDGET_START_REPLACE: { // Start replacing
00363         EngineID veh_from = this->sel_engine[0];
00364         EngineID veh_to = this->sel_engine[1];
00365         DoCommandP(0, 3 + (this->sel_group << 16) , veh_from + (veh_to << 16), CMD_SET_AUTOREPLACE);
00366         this->SetDirty();
00367       } break;
00368 
00369       case RVW_WIDGET_STOP_REPLACE: { // Stop replacing
00370         EngineID veh_from = this->sel_engine[0];
00371         DoCommandP(0, 3 + (this->sel_group << 16), veh_from + (INVALID_ENGINE << 16), CMD_SET_AUTOREPLACE);
00372         this->SetDirty();
00373       } break;
00374 
00375       case RVW_WIDGET_LEFT_MATRIX:
00376       case RVW_WIDGET_RIGHT_MATRIX: {
00377         uint i = (pt.y - 14) / this->resize.step_height;
00378         uint16 click_scroll_pos = widget == RVW_WIDGET_LEFT_MATRIX ? this->vscroll.pos : this->vscroll2.pos;
00379         uint16 click_scroll_cap = widget == RVW_WIDGET_LEFT_MATRIX ? this->vscroll.cap : this->vscroll2.cap;
00380         byte click_side         = widget == RVW_WIDGET_LEFT_MATRIX ? 0 : 1;
00381         size_t engine_count     = this->list[click_side].Length();
00382 
00383         if (i < click_scroll_cap) {
00384           i += click_scroll_pos;
00385           EngineID e = engine_count > i ? this->list[click_side][i] : INVALID_ENGINE;
00386           if (e == this->sel_engine[click_side]) break; // we clicked the one we already selected
00387           this->sel_engine[click_side] = e;
00388           if (click_side == 0) {
00389             this->update_right = true;
00390             this->init_lists   = true;
00391           }
00392           this->SetDirty();
00393           }
00394         break;
00395         }
00396     }
00397   }
00398 
00399   virtual void OnDropdownSelect(int widget, int index)
00400   {
00401     RailType temp = (RailType)index;
00402     if (temp == sel_railtype) return; // we didn't select a new one. No need to change anything
00403     sel_railtype = temp;
00404     /* Reset scrollbar positions */
00405     this->vscroll.pos  = 0;
00406     this->vscroll2.pos = 0;
00407     /* Rebuild the lists */
00408     this->update_left  = true;
00409     this->update_right = true;
00410     this->init_lists   = true;
00411     this->SetDirty();
00412   }
00413 
00414   virtual void OnResize(Point new_size, Point delta) {
00415     this->vscroll.cap  += delta.y / (int)this->resize.step_height;
00416     this->vscroll2.cap += delta.y / (int)this->resize.step_height;
00417 
00418     Widget *widget = this->widget;
00419 
00420     widget[RVW_WIDGET_LEFT_MATRIX].data = widget[RVW_WIDGET_RIGHT_MATRIX].data = (this->vscroll2.cap << 8) + 1;
00421 
00422     if (delta.x != 0) {
00423       /* We changed the width of the window so we have to resize the lists.
00424        * Because ResizeButtons() makes each widget the same size it can't be used on the lists
00425        * because then the lists would have the same size as the scrollbars.
00426        * Instead we use it on the detail panels.
00427        * Afterwards we use the new location of the detail panels (the middle of the window)
00428        * to place the lists.
00429        * This way the lists will have equal size while keeping the width of the scrollbars unchanged. */
00430       ResizeButtons(this, RVW_WIDGET_LEFT_DETAILS, RVW_WIDGET_RIGHT_DETAILS);
00431       widget[RVW_WIDGET_RIGHT_MATRIX].left    = widget[RVW_WIDGET_RIGHT_DETAILS].left;
00432       widget[RVW_WIDGET_LEFT_SCROLLBAR].right = widget[RVW_WIDGET_LEFT_DETAILS].right;
00433       widget[RVW_WIDGET_LEFT_SCROLLBAR].left  = widget[RVW_WIDGET_LEFT_SCROLLBAR].right - 11;
00434       widget[RVW_WIDGET_LEFT_MATRIX].right    = widget[RVW_WIDGET_LEFT_SCROLLBAR].left - 1;
00435     }
00436   }
00437 
00438   virtual void OnInvalidateData(int data)
00439   {
00440     if (data != 0) {
00441       this->update_left = true;
00442     } else {
00443       this->update_right = true;
00444     }
00445   }
00446 };
00447 
00448 static const Widget _replace_vehicle_widgets[] = {
00449 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,                        STR_018B_CLOSE_WINDOW},
00450 {    WWT_CAPTION,  RESIZE_RIGHT,  COLOUR_GREY,    11,   443,     0,    13, STR_REPLACE_VEHICLES_WHITE,      STR_018C_WINDOW_TITLE_DRAG_THIS},
00451 {  WWT_STICKYBOX,     RESIZE_LR,  COLOUR_GREY,   444,   455,     0,    13, STR_NULL,                        STR_STICKY_BUTTON},
00452 
00453 {     WWT_MATRIX, RESIZE_BOTTOM,  COLOUR_GREY,     0,   215,    14,    13, 0x1,                             STR_REPLACE_HELP_LEFT_ARRAY},
00454 {  WWT_SCROLLBAR, RESIZE_BOTTOM,  COLOUR_GREY,   216,   227,    14,    13, STR_NULL,                        STR_0190_SCROLL_BAR_SCROLLS_LIST},
00455 {     WWT_MATRIX,    RESIZE_LRB,  COLOUR_GREY,   228,   443,    14,    13, 0x1,                             STR_REPLACE_HELP_RIGHT_ARRAY},
00456 { WWT_SCROLL2BAR,    RESIZE_LRB,  COLOUR_GREY,   444,   455,    14,    13, STR_NULL,                        STR_0190_SCROLL_BAR_SCROLLS_LIST},
00457 {      WWT_PANEL,     RESIZE_TB,  COLOUR_GREY,     0,   227,    14,   105, 0x0,                             STR_NULL},
00458 {      WWT_PANEL,    RESIZE_RTB,  COLOUR_GREY,   228,   455,    14,   105, 0x0,                             STR_NULL},
00459 
00460 { WWT_PUSHTXTBTN,     RESIZE_TB,  COLOUR_GREY,     0,   138,   106,   117, STR_REPLACE_VEHICLES_START,      STR_REPLACE_HELP_START_BUTTON},
00461 {      WWT_PANEL,    RESIZE_RTB,  COLOUR_GREY,   139,   305,   106,   117, 0x0,                             STR_REPLACE_HELP_REPLACE_INFO_TAB},
00462 { WWT_PUSHTXTBTN,   RESIZE_LRTB,  COLOUR_GREY,   306,   443,   106,   117, STR_REPLACE_VEHICLES_STOP,       STR_REPLACE_HELP_STOP_BUTTON},
00463 {  WWT_RESIZEBOX,   RESIZE_LRTB,  COLOUR_GREY,   444,   455,   106,   117, STR_NULL,                        STR_RESIZE_BUTTON},
00464 
00465 { WWT_PUSHTXTBTN,     RESIZE_TB,  COLOUR_GREY,     0,   138,   128,   139, STR_REPLACE_ENGINE_WAGON_SELECT, STR_REPLACE_ENGINE_WAGON_SELECT_HELP},
00466 {      WWT_PANEL,     RESIZE_TB,  COLOUR_GREY,   139,   153,   128,   139, 0x0,                             STR_NULL},
00467 {   WWT_DROPDOWN,    RESIZE_RTB,  COLOUR_GREY,   154,   289,   128,   139, 0x0,                             STR_REPLACE_HELP_RAILTYPE},
00468 {      WWT_PANEL,   RESIZE_LRTB,  COLOUR_GREY,   290,   305,   128,   139, 0x0,                             STR_NULL},
00469 { WWT_PUSHTXTBTN,   RESIZE_LRTB,  COLOUR_GREY,   306,   443,   128,   139, STR_REPLACE_REMOVE_WAGON,        STR_REPLACE_REMOVE_WAGON_HELP},
00470 {   WIDGETS_END},
00471 };
00472 
00473 static const WindowDesc _replace_rail_vehicle_desc(
00474   WDP_AUTO, WDP_AUTO, 456, 140, 456, 140,
00475   WC_REPLACE_VEHICLE, WC_NONE,
00476   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE | WDF_CONSTRUCTION,
00477   _replace_vehicle_widgets
00478 );
00479 
00480 static const WindowDesc _replace_vehicle_desc(
00481   WDP_AUTO, WDP_AUTO, 456, 118, 456, 118,
00482   WC_REPLACE_VEHICLE, WC_NONE,
00483   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE | WDF_CONSTRUCTION,
00484   _replace_vehicle_widgets
00485 );
00486 
00487 RailType ReplaceVehicleWindow::sel_railtype = RAILTYPE_RAIL;
00488 
00489 void ShowReplaceGroupVehicleWindow(GroupID id_g, VehicleType vehicletype)
00490 {
00491   DeleteWindowById(WC_REPLACE_VEHICLE, vehicletype);
00492   new ReplaceVehicleWindow(vehicletype == VEH_TRAIN ? &_replace_rail_vehicle_desc : &_replace_vehicle_desc, vehicletype, id_g);
00493 }

Generated on Mon May 11 15:48:02 2009 for OpenTTD by  doxygen 1.5.6