00001
00002
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "train.h"
00008 #include "roadveh.h"
00009 #include "ship.h"
00010 #include "aircraft.h"
00011 #include "debug.h"
00012 #include "gui.h"
00013 #include "articulated_vehicles.h"
00014 #include "textbuf_gui.h"
00015 #include "station.h"
00016 #include "command_func.h"
00017 #include "engine.h"
00018 #include "player_func.h"
00019 #include "depot.h"
00020 #include "airport.h"
00021 #include "vehicle_gui.h"
00022 #include "newgrf_engine.h"
00023 #include "cargotype.h"
00024 #include "group.h"
00025 #include "road_map.h"
00026 #include "strings_func.h"
00027 #include "window_func.h"
00028 #include "date_func.h"
00029 #include "vehicle_func.h"
00030 #include "settings_type.h"
00031 #include "gfx_func.h"
00032 #include "widgets/dropdown_func.h"
00033
00034 #include "table/sprites.h"
00035 #include "table/strings.h"
00036
00037 struct buildvehicle_d {
00038 VehicleType vehicle_type;
00039 union {
00040 RailTypeByte railtype;
00041 AirportFTAClass::Flags flags;
00042 RoadTypes roadtypes;
00043 } filter;
00044 byte sel_index;
00045 bool descending_sort_order;
00046 byte sort_criteria;
00047 bool regenerate_list;
00048 EngineID sel_engine;
00049 EngineID rename_engine;
00050 EngineList eng_list;
00051 };
00052 assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(buildvehicle_d));
00053
00054 enum BuildVehicleWidgets {
00055 BUILD_VEHICLE_WIDGET_CLOSEBOX = 0,
00056 BUILD_VEHICLE_WIDGET_CAPTION,
00057 BUILD_VEHICLE_WIDGET_SORT_ASSENDING_DESCENDING,
00058 BUILD_VEHICLE_WIDGET_SORT_DROPDOWN,
00059 BUILD_VEHICLE_WIDGET_LIST,
00060 BUILD_VEHICLE_WIDGET_SCROLLBAR,
00061 BUILD_VEHICLE_WIDGET_PANEL,
00062 BUILD_VEHICLE_WIDGET_BUILD,
00063 BUILD_VEHICLE_WIDGET_RENAME,
00064 BUILD_VEHICLE_WIDGET_RESIZE,
00065 BUILD_VEHICLE_WIDGET_END
00066 };
00067
00068 static const Widget _build_vehicle_widgets[] = {
00069 { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
00070 { WWT_CAPTION, RESIZE_RIGHT, 14, 11, 239, 0, 13, 0x0, STR_018C_WINDOW_TITLE_DRAG_THIS },
00071 { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 0, 80, 14, 25, STR_SORT_BY, STR_SORT_ORDER_TIP},
00072 { WWT_DROPDOWN, RESIZE_RIGHT, 14, 81, 239, 14, 25, 0x0, STR_SORT_CRITERIA_TIP},
00073 { WWT_MATRIX, RESIZE_RB, 14, 0, 227, 26, 39, 0x101, STR_NULL },
00074 { WWT_SCROLLBAR, RESIZE_LRB, 14, 228, 239, 26, 39, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST },
00075 { WWT_PANEL, RESIZE_RTB, 14, 0, 239, 40, 161, 0x0, STR_NULL },
00076
00077 { WWT_PUSHTXTBTN, RESIZE_TB, 14, 0, 114, 162, 173, 0x0, STR_NULL },
00078 { WWT_PUSHTXTBTN, RESIZE_RTB, 14, 115, 227, 162, 173, 0x0, STR_NULL },
00079 { WWT_RESIZEBOX, RESIZE_LRTB, 14, 228, 239, 162, 173, 0x0, STR_RESIZE_BUTTON },
00080 { WIDGETS_END},
00081 };
00082
00083
00084 static void SetupWindowStrings(Window *w, VehicleType type)
00085 {
00086 switch (type) {
00087 default: NOT_REACHED();
00088
00089 case VEH_TRAIN:
00090 w->widget[BUILD_VEHICLE_WIDGET_CAPTION].data = STR_JUST_STRING;
00091 w->widget[BUILD_VEHICLE_WIDGET_LIST].tooltips = STR_8843_TRAIN_VEHICLE_SELECTION;
00092 w->widget[BUILD_VEHICLE_WIDGET_BUILD].data = STR_881F_BUILD_VEHICLE;
00093 w->widget[BUILD_VEHICLE_WIDGET_BUILD].tooltips = STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN;
00094 w->widget[BUILD_VEHICLE_WIDGET_RENAME].data = STR_8820_RENAME;
00095 w->widget[BUILD_VEHICLE_WIDGET_RENAME].tooltips = STR_8845_RENAME_TRAIN_VEHICLE_TYPE;
00096 break;
00097
00098 case VEH_ROAD:
00099 w->widget[BUILD_VEHICLE_WIDGET_CAPTION].data = STR_9006_NEW_ROAD_VEHICLES;
00100 w->widget[BUILD_VEHICLE_WIDGET_LIST].tooltips = STR_9026_ROAD_VEHICLE_SELECTION;
00101 w->widget[BUILD_VEHICLE_WIDGET_BUILD].data = STR_9007_BUILD_VEHICLE;
00102 w->widget[BUILD_VEHICLE_WIDGET_BUILD].tooltips = STR_9027_BUILD_THE_HIGHLIGHTED_ROAD;
00103 w->widget[BUILD_VEHICLE_WIDGET_RENAME].data = STR_9034_RENAME;
00104 w->widget[BUILD_VEHICLE_WIDGET_RENAME].tooltips = STR_9035_RENAME_ROAD_VEHICLE_TYPE;
00105 break;
00106
00107 case VEH_SHIP:
00108 w->widget[BUILD_VEHICLE_WIDGET_CAPTION].data = STR_9808_NEW_SHIPS;
00109 w->widget[BUILD_VEHICLE_WIDGET_LIST].tooltips = STR_9825_SHIP_SELECTION_LIST_CLICK;
00110 w->widget[BUILD_VEHICLE_WIDGET_BUILD].data = STR_9809_BUILD_SHIP;
00111 w->widget[BUILD_VEHICLE_WIDGET_BUILD].tooltips = STR_9826_BUILD_THE_HIGHLIGHTED_SHIP;
00112 w->widget[BUILD_VEHICLE_WIDGET_RENAME].data = STR_9836_RENAME;
00113 w->widget[BUILD_VEHICLE_WIDGET_RENAME].tooltips = STR_9837_RENAME_SHIP_TYPE;
00114 break;
00115
00116 case VEH_AIRCRAFT:
00117 w->widget[BUILD_VEHICLE_WIDGET_CAPTION].data = STR_A005_NEW_AIRCRAFT;
00118 w->widget[BUILD_VEHICLE_WIDGET_LIST].tooltips = STR_A025_AIRCRAFT_SELECTION_LIST;
00119 w->widget[BUILD_VEHICLE_WIDGET_BUILD].data = STR_A006_BUILD_AIRCRAFT;
00120 w->widget[BUILD_VEHICLE_WIDGET_BUILD].tooltips = STR_A026_BUILD_THE_HIGHLIGHTED_AIRCRAFT;
00121 w->widget[BUILD_VEHICLE_WIDGET_RENAME].data = STR_A037_RENAME;
00122 w->widget[BUILD_VEHICLE_WIDGET_RENAME].tooltips = STR_A038_RENAME_AIRCRAFT_TYPE;
00123 break;
00124 }
00125 }
00126
00127 static bool _internal_sort_order;
00128
00129 static byte _last_sort_criteria[] = {0, 0, 0, 0};
00130 static bool _last_sort_order[] = {false, false, false, false};
00131
00132 static int CDECL EngineNumberSorter(const void *a, const void *b)
00133 {
00134 const EngineID va = *(const EngineID*)a;
00135 const EngineID vb = *(const EngineID*)b;
00136 int r = va - vb;
00137
00138 return _internal_sort_order ? -r : r;
00139 }
00140
00141 static int CDECL EngineIntroDateSorter(const void *a, const void *b)
00142 {
00143 const int va = GetEngine(*(const EngineID*)a)->intro_date;
00144 const int vb = GetEngine(*(const EngineID*)b)->intro_date;
00145 const int r = va - vb;
00146
00147 if (r == 0) {
00148
00149 return EngineNumberSorter(a, b);
00150 }
00151 return _internal_sort_order ? -r : r;
00152 }
00153
00154 static int CDECL EngineNameSorter(const void *a, const void *b)
00155 {
00156 static EngineID last_engine[2] = { INVALID_ENGINE, INVALID_ENGINE };
00157 static char last_name[2][64] = { "\0", "\0" };
00158
00159 const EngineID va = *(const EngineID*)a;
00160 const EngineID vb = *(const EngineID*)b;
00161 int r;
00162
00163 if (va != last_engine[0]) {
00164 last_engine[0] = va;
00165 SetDParam(0, va);
00166 GetString(last_name[0], STR_ENGINE_NAME, lastof(last_name[0]));
00167 }
00168
00169 if (vb != last_engine[1]) {
00170 last_engine[1] = vb;
00171 SetDParam(0, vb);
00172 GetString(last_name[1], STR_ENGINE_NAME, lastof(last_name[1]));
00173 }
00174
00175 r = strcmp(last_name[0], last_name[1]);
00176
00177 if (r == 0) {
00178
00179 return EngineNumberSorter(a, b);
00180 }
00181 return _internal_sort_order ? -r : r;
00182 }
00183
00184 static int CDECL EngineReliabilitySorter(const void *a, const void *b)
00185 {
00186 const int va = GetEngine(*(const EngineID*)a)->reliability;
00187 const int vb = GetEngine(*(const EngineID*)b)->reliability;
00188 const int r = va - vb;
00189
00190 if (r == 0) {
00191
00192 return EngineNumberSorter(a, b);
00193 }
00194 return _internal_sort_order ? -r : r;
00195 }
00196
00197
00198 static int CDECL TrainEngineCostSorter(const void *a, const void *b)
00199 {
00200 int va = RailVehInfo(*(const EngineID*)a)->base_cost;
00201 int vb = RailVehInfo(*(const EngineID*)b)->base_cost;
00202 int r = va - vb;
00203
00204 return _internal_sort_order ? -r : r;
00205 }
00206
00207 static int CDECL TrainEngineSpeedSorter(const void *a, const void *b)
00208 {
00209 int va = RailVehInfo(*(const EngineID*)a)->max_speed;
00210 int vb = RailVehInfo(*(const EngineID*)b)->max_speed;
00211 int r = va - vb;
00212
00213 return _internal_sort_order ? -r : r;
00214 }
00215
00216 static int CDECL TrainEnginePowerSorter(const void *a, const void *b)
00217 {
00218 const RailVehicleInfo *rvi_a = RailVehInfo(*(const EngineID*)a);
00219 const RailVehicleInfo *rvi_b = RailVehInfo(*(const EngineID*)b);
00220
00221 int va = rvi_a->power;
00222 int vb = rvi_b->power;
00223 int r = va - vb;
00224
00225 return _internal_sort_order ? -r : r;
00226 }
00227
00228 static int CDECL TrainEngineRunningCostSorter(const void *a, const void *b)
00229 {
00230 const RailVehicleInfo *rvi_a = RailVehInfo(*(const EngineID*)a);
00231 const RailVehicleInfo *rvi_b = RailVehInfo(*(const EngineID*)b);
00232
00233 Money va = rvi_a->running_cost * GetPriceByIndex(rvi_a->running_cost_class);
00234 Money vb = rvi_b->running_cost * GetPriceByIndex(rvi_b->running_cost_class);
00235 int r = ClampToI32(va - vb);
00236
00237 return _internal_sort_order ? -r : r;
00238 }
00239
00240 static int CDECL TrainEnginePowerVsRunningCostSorter(const void *a, const void *b)
00241 {
00242 const RailVehicleInfo *rvi_a = RailVehInfo(*(const EngineID*)a);
00243 const RailVehicleInfo *rvi_b = RailVehInfo(*(const EngineID*)b);
00244
00245
00246
00247
00248
00249
00250
00251 Money va = (rvi_a->running_cost * GetPriceByIndex(rvi_a->running_cost_class)) / max(1U, (uint)rvi_a->power);
00252 Money vb = (rvi_b->running_cost * GetPriceByIndex(rvi_b->running_cost_class)) / max(1U, (uint)rvi_b->power);
00253 int r = ClampToI32(vb - va);
00254
00255 return _internal_sort_order ? -r : r;
00256 }
00257
00258 static int CDECL TrainEngineNumberSorter(const void *a, const void *b)
00259 {
00260 const EngineID va = *(const EngineID*)a;
00261 const EngineID vb = *(const EngineID*)b;
00262 int r = ListPositionOfEngine(va) - ListPositionOfEngine(vb);
00263
00264 return _internal_sort_order ? -r : r;
00265 }
00266
00267 static int CDECL TrainEngineCapacitySorter(const void *a, const void *b)
00268 {
00269 const RailVehicleInfo *rvi_a = RailVehInfo(*(const EngineID*)a);
00270 const RailVehicleInfo *rvi_b = RailVehInfo(*(const EngineID*)b);
00271
00272 int va = rvi_a->capacity * (rvi_a->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1);
00273 int vb = rvi_b->capacity * (rvi_b->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1);
00274 int r = va - vb;
00275
00276 if (r == 0) {
00277
00278 return EngineNumberSorter(a, b);
00279 }
00280 return _internal_sort_order ? -r : r;
00281 }
00282
00283 static int CDECL TrainEnginesThenWagonsSorter(const void *a, const void *b)
00284 {
00285 EngineID va = *(const EngineID*)a;
00286 EngineID vb = *(const EngineID*)b;
00287 int val_a = (RailVehInfo(va)->railveh_type == RAILVEH_WAGON ? 1 : 0);
00288 int val_b = (RailVehInfo(vb)->railveh_type == RAILVEH_WAGON ? 1 : 0);
00289 int r = val_a - val_b;
00290
00291
00292 if (r == 0) return EngineNumberSorter(a, b);
00293
00294 return _internal_sort_order ? -r : r;
00295 }
00296
00297
00298 static int CDECL RoadVehEngineCostSorter(const void *a, const void *b)
00299 {
00300 int va = RoadVehInfo(*(const EngineID*)a)->base_cost;
00301 int vb = RoadVehInfo(*(const EngineID*)b)->base_cost;
00302 int r = va - vb;
00303
00304 return _internal_sort_order ? -r : r;
00305 }
00306
00307 static int CDECL RoadVehEngineSpeedSorter(const void *a, const void *b)
00308 {
00309 int va = RoadVehInfo(*(const EngineID*)a)->max_speed;
00310 int vb = RoadVehInfo(*(const EngineID*)b)->max_speed;
00311 int r = va - vb;
00312
00313 return _internal_sort_order ? -r : r;
00314 }
00315
00316 static int CDECL RoadVehEngineRunningCostSorter(const void *a, const void *b)
00317 {
00318 const RoadVehicleInfo *rvi_a = RoadVehInfo(*(const EngineID*)a);
00319 const RoadVehicleInfo *rvi_b = RoadVehInfo(*(const EngineID*)b);
00320
00321 Money va = rvi_a->running_cost * GetPriceByIndex(rvi_a->running_cost_class);
00322 Money vb = rvi_b->running_cost * GetPriceByIndex(rvi_b->running_cost_class);
00323 int r = ClampToI32(va - vb);
00324
00325 if (r == 0) {
00326
00327 return EngineNumberSorter(a, b);
00328 }
00329 return _internal_sort_order ? -r : r;
00330 }
00331
00332 static int CDECL RoadVehEngineCapacitySorter(const void *a, const void *b)
00333 {
00334 int va = RoadVehInfo(*(const EngineID*)a)->capacity;
00335 int vb = RoadVehInfo(*(const EngineID*)b)->capacity;
00336 int r = va - vb;
00337
00338 if (r == 0) {
00339
00340 return EngineNumberSorter(a, b);
00341 }
00342 return _internal_sort_order ? -r : r;
00343 }
00344
00345
00346 static int CDECL ShipEngineCostSorter(const void *a, const void *b)
00347 {
00348 int va = ShipVehInfo(*(const EngineID*)a)->base_cost;
00349 int vb = ShipVehInfo(*(const EngineID*)b)->base_cost;
00350 int r = va - vb;
00351
00352 return _internal_sort_order ? -r : r;
00353 }
00354
00355 static int CDECL ShipEngineSpeedSorter(const void *a, const void *b)
00356 {
00357 int va = ShipVehInfo(*(const EngineID*)a)->max_speed;
00358 int vb = ShipVehInfo(*(const EngineID*)b)->max_speed;
00359 int r = va - vb;
00360
00361 return _internal_sort_order ? -r : r;
00362 }
00363
00364 static int CDECL ShipEngineRunningCostSorter(const void *a, const void *b)
00365 {
00366 const int va = ShipVehInfo(*(const EngineID*)a)->running_cost;
00367 const int vb = ShipVehInfo(*(const EngineID*)b)->running_cost;
00368 const int r = va - vb;
00369
00370 if (r == 0) {
00371
00372 return EngineNumberSorter(a, b);
00373 }
00374 return _internal_sort_order ? -r : r;
00375 }
00376
00377 static int CDECL ShipEngineCapacitySorter(const void *a, const void *b)
00378 {
00379 int va = ShipVehInfo(*(const EngineID*)a)->capacity;
00380 int vb = ShipVehInfo(*(const EngineID*)b)->capacity;
00381 int r = va - vb;
00382
00383 if (r == 0) {
00384
00385 return EngineNumberSorter(a, b);
00386 }
00387 return _internal_sort_order ? -r : r;
00388 }
00389
00390
00391
00392 static int CDECL AircraftEngineCostSorter(const void *a, const void *b)
00393 {
00394 const int va = AircraftVehInfo(*(const EngineID*)a)->base_cost;
00395 const int vb = AircraftVehInfo(*(const EngineID*)b)->base_cost;
00396 int r = va - vb;
00397
00398 return _internal_sort_order ? -r : r;
00399 }
00400
00401 static int CDECL AircraftEngineSpeedSorter(const void *a, const void *b)
00402 {
00403 const int va = AircraftVehInfo(*(const EngineID*)a)->max_speed;
00404 const int vb = AircraftVehInfo(*(const EngineID*)b)->max_speed;
00405 const int r = va - vb;
00406
00407 if (r == 0) {
00408
00409 return EngineNumberSorter(a, b);
00410 }
00411 return _internal_sort_order ? -r : r;
00412 }
00413
00414 static int CDECL AircraftEngineRunningCostSorter(const void *a, const void *b)
00415 {
00416 const int va = AircraftVehInfo(*(const EngineID*)a)->running_cost;
00417 const int vb = AircraftVehInfo(*(const EngineID*)b)->running_cost;
00418 const int r = va - vb;
00419
00420 if (r == 0) {
00421
00422 return EngineNumberSorter(a, b);
00423 }
00424 return _internal_sort_order ? -r : r;
00425 }
00426
00427 static int CDECL AircraftEngineCargoSorter(const void *a, const void *b)
00428 {
00429 int va = AircraftVehInfo(*(const EngineID*)a)->passenger_capacity;
00430 int vb = AircraftVehInfo(*(const EngineID*)b)->passenger_capacity;
00431 int r = va - vb;
00432
00433 if (r == 0) {
00434
00435 va = AircraftVehInfo(*(const EngineID*)a)->mail_capacity;
00436 vb = AircraftVehInfo(*(const EngineID*)b)->mail_capacity;
00437 r = va - vb;
00438
00439 if (r == 0) {
00440
00441 return EngineNumberSorter(a, b);
00442 }
00443 }
00444 return _internal_sort_order ? -r : r;
00445 }
00446
00447 static EngList_SortTypeFunction * const _sorter[][10] = {{
00448
00449 &TrainEngineNumberSorter,
00450 &TrainEngineCostSorter,
00451 &TrainEngineSpeedSorter,
00452 &TrainEnginePowerSorter,
00453 &EngineIntroDateSorter,
00454 &EngineNameSorter,
00455 &TrainEngineRunningCostSorter,
00456 &TrainEnginePowerVsRunningCostSorter,
00457 &EngineReliabilitySorter,
00458 &TrainEngineCapacitySorter,
00459 }, {
00460
00461 &EngineNumberSorter,
00462 &RoadVehEngineCostSorter,
00463 &RoadVehEngineSpeedSorter,
00464 &EngineIntroDateSorter,
00465 &EngineNameSorter,
00466 &RoadVehEngineRunningCostSorter,
00467 &EngineReliabilitySorter,
00468 &RoadVehEngineCapacitySorter,
00469 }, {
00470
00471 &EngineNumberSorter,
00472 &ShipEngineCostSorter,
00473 &ShipEngineSpeedSorter,
00474 &EngineIntroDateSorter,
00475 &EngineNameSorter,
00476 &ShipEngineRunningCostSorter,
00477 &EngineReliabilitySorter,
00478 &ShipEngineCapacitySorter,
00479 }, {
00480
00481 &EngineNumberSorter,
00482 &AircraftEngineCostSorter,
00483 &AircraftEngineSpeedSorter,
00484 &EngineIntroDateSorter,
00485 &EngineNameSorter,
00486 &AircraftEngineRunningCostSorter,
00487 &EngineReliabilitySorter,
00488 &AircraftEngineCargoSorter,
00489 }};
00490
00491 static const StringID _sort_listing[][11] = {{
00492
00493 STR_ENGINE_SORT_ENGINE_ID,
00494 STR_ENGINE_SORT_COST,
00495 STR_SORT_BY_MAX_SPEED,
00496 STR_ENGINE_SORT_POWER,
00497 STR_ENGINE_SORT_INTRO_DATE,
00498 STR_SORT_BY_DROPDOWN_NAME,
00499 STR_ENGINE_SORT_RUNNING_COST,
00500 STR_ENGINE_SORT_POWER_VS_RUNNING_COST,
00501 STR_SORT_BY_RELIABILITY,
00502 STR_ENGINE_SORT_CARGO_CAPACITY,
00503 INVALID_STRING_ID
00504 }, {
00505
00506 STR_ENGINE_SORT_ENGINE_ID,
00507 STR_ENGINE_SORT_COST,
00508 STR_SORT_BY_MAX_SPEED,
00509 STR_ENGINE_SORT_INTRO_DATE,
00510 STR_SORT_BY_DROPDOWN_NAME,
00511 STR_ENGINE_SORT_RUNNING_COST,
00512 STR_SORT_BY_RELIABILITY,
00513 STR_ENGINE_SORT_CARGO_CAPACITY,
00514 INVALID_STRING_ID
00515 }, {
00516
00517 STR_ENGINE_SORT_ENGINE_ID,
00518 STR_ENGINE_SORT_COST,
00519 STR_SORT_BY_MAX_SPEED,
00520 STR_ENGINE_SORT_INTRO_DATE,
00521 STR_SORT_BY_DROPDOWN_NAME,
00522 STR_ENGINE_SORT_RUNNING_COST,
00523 STR_SORT_BY_RELIABILITY,
00524 STR_ENGINE_SORT_CARGO_CAPACITY,
00525 INVALID_STRING_ID
00526 }, {
00527
00528 STR_ENGINE_SORT_ENGINE_ID,
00529 STR_ENGINE_SORT_COST,
00530 STR_SORT_BY_MAX_SPEED,
00531 STR_ENGINE_SORT_INTRO_DATE,
00532 STR_SORT_BY_DROPDOWN_NAME,
00533 STR_ENGINE_SORT_RUNNING_COST,
00534 STR_SORT_BY_RELIABILITY,
00535 STR_ENGINE_SORT_CARGO_CAPACITY,
00536 INVALID_STRING_ID
00537 }};
00538
00539 static int DrawCargoCapacityInfo(int x, int y, EngineID engine, VehicleType type, bool refittable)
00540 {
00541 uint16 *cap = GetCapacityOfArticulatedParts(engine, type);
00542
00543 for (uint c = 0; c < NUM_CARGO; c++) {
00544 if (cap[c] == 0) continue;
00545
00546 SetDParam(0, c);
00547 SetDParam(1, cap[c]);
00548 SetDParam(2, refittable ? STR_9842_REFITTABLE : STR_EMPTY);
00549 DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, TC_FROMSTRING);
00550 y += 10;
00551
00552
00553 refittable = false;
00554 }
00555
00556 return y;
00557 }
00558
00559
00560 static int DrawRailWagonPurchaseInfo(int x, int y, EngineID engine_number, const RailVehicleInfo *rvi)
00561 {
00562
00563 SetDParam(0, (GetEngineProperty(engine_number, 0x17, rvi->base_cost) * _price.build_railwagon) >> 8);
00564 DrawString(x, y, STR_PURCHASE_INFO_COST, TC_FROMSTRING);
00565 y += 10;
00566
00567
00568 uint weight = GetEngineProperty(engine_number, 0x16, rvi->weight);
00569 SetDParam(0, weight);
00570 SetDParam(1, (GetCargo(rvi->cargo_type)->weight * GetEngineProperty(engine_number, 0x14, rvi->capacity) >> 4) + weight);
00571 DrawString(x, y, STR_PURCHASE_INFO_WEIGHT_CWEIGHT, TC_FROMSTRING);
00572 y += 10;
00573
00574
00575 if (_patches.wagon_speed_limits) {
00576 uint max_speed = GetEngineProperty(engine_number, 0x09, rvi->max_speed);
00577 if (max_speed > 0) {
00578 SetDParam(0, max_speed * 10 / 16);
00579 DrawString(x, y, STR_PURCHASE_INFO_SPEED, TC_FROMSTRING);
00580 y += 10;
00581 }
00582 }
00583
00584
00585 if (rvi->running_cost_class != 0xFF) {
00586 SetDParam(0, GetEngineProperty(engine_number, 0x0D, rvi->running_cost) * GetPriceByIndex(rvi->running_cost_class) >> 8);
00587 DrawString(x, y, STR_PURCHASE_INFO_RUNNINGCOST, TC_FROMSTRING);
00588 y += 10;
00589 }
00590
00591 return y;
00592 }
00593
00594
00595 static int DrawRailEnginePurchaseInfo(int x, int y, EngineID engine_number, const RailVehicleInfo *rvi)
00596 {
00597 int multihead = (rvi->railveh_type == RAILVEH_MULTIHEAD ? 1 : 0);
00598 uint weight = GetEngineProperty(engine_number, 0x16, rvi->weight);
00599
00600
00601 SetDParam(0, GetEngineProperty(engine_number, 0x17, rvi->base_cost) * (_price.build_railvehicle >> 3) >> 5);
00602 SetDParam(1, weight << multihead);
00603 DrawString(x, y, STR_PURCHASE_INFO_COST_WEIGHT, TC_FROMSTRING);
00604 y += 10;
00605
00606
00607 SetDParam(0, GetEngineProperty(engine_number, 0x09, rvi->max_speed) * 10 / 16);
00608 SetDParam(1, GetEngineProperty(engine_number, 0x0B, rvi->power));
00609 DrawString(x, y, STR_PURCHASE_INFO_SPEED_POWER, TC_FROMSTRING);
00610 y += 10;
00611
00612
00613 if (_patches.realistic_acceleration && rvi->railtype != RAILTYPE_MAGLEV) {
00614 SetDParam(0, ((weight << multihead) * 10 * GetEngineProperty(engine_number, 0x1F, rvi->tractive_effort)) / 256);
00615 DrawString(x, y, STR_PURCHASE_INFO_MAX_TE, TC_FROMSTRING);
00616 y += 10;
00617 }
00618
00619
00620 if (rvi->running_cost_class != 0xFF) {
00621 SetDParam(0, GetEngineProperty(engine_number, 0x0D, rvi->running_cost) * GetPriceByIndex(rvi->running_cost_class) >> 8);
00622 DrawString(x, y, STR_PURCHASE_INFO_RUNNINGCOST, TC_FROMSTRING);
00623 y += 10;
00624 }
00625
00626
00627 if (rvi->pow_wag_power != 0) {
00628 SetDParam(0, rvi->pow_wag_power);
00629 SetDParam(1, rvi->pow_wag_weight);
00630 DrawString(x, y, STR_PURCHASE_INFO_PWAGPOWER_PWAGWEIGHT, TC_FROMSTRING);
00631 y += 10;
00632 };
00633
00634 return y;
00635 }
00636
00637
00638 static int DrawRoadVehPurchaseInfo(int x, int y, EngineID engine_number, const RoadVehicleInfo *rvi)
00639 {
00640 bool refittable = (EngInfo(engine_number)->refit_mask != 0);
00641
00642
00643 SetDParam(0, GetEngineProperty(engine_number, 0x11, rvi->base_cost) * (_price.roadveh_base >> 3) >> 5);
00644 SetDParam(1, rvi->max_speed * 10 / 32);
00645 DrawString(x, y, STR_PURCHASE_INFO_COST_SPEED, TC_FROMSTRING);
00646 y += 10;
00647
00648
00649 SetDParam(0, rvi->running_cost * GetPriceByIndex(rvi->running_cost_class) >> 8);
00650 DrawString(x, y, STR_PURCHASE_INFO_RUNNINGCOST, TC_FROMSTRING);
00651 y += 10;
00652
00653
00654 return DrawCargoCapacityInfo(x, y, engine_number, VEH_ROAD, refittable);
00655 }
00656
00657
00658 static int DrawShipPurchaseInfo(int x, int y, EngineID engine_number, const ShipVehicleInfo *svi)
00659 {
00660
00661 SetDParam(0, GetEngineProperty(engine_number, 0x0A, svi->base_cost) * (_price.ship_base >> 3) >> 5);
00662 SetDParam(1, GetEngineProperty(engine_number, 0x0B, svi->max_speed) * 10 / 32);
00663 DrawString(x, y, STR_PURCHASE_INFO_COST_SPEED, TC_FROMSTRING);
00664 y += 10;
00665
00666
00667 SetDParam(0, svi->cargo_type);
00668 SetDParam(1, GetEngineProperty(engine_number, 0x0D, svi->capacity));
00669 SetDParam(2, svi->refittable ? STR_9842_REFITTABLE : STR_EMPTY);
00670 DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, TC_FROMSTRING);
00671 y += 10;
00672
00673
00674 SetDParam(0, GetEngineProperty(engine_number, 0x0F, svi->running_cost) * _price.ship_running >> 8);
00675 DrawString(x, y, STR_PURCHASE_INFO_RUNNINGCOST, TC_FROMSTRING);
00676 y += 10;
00677
00678 return y;
00679 }
00680
00681
00682 static int DrawAircraftPurchaseInfo(int x, int y, EngineID engine_number, const AircraftVehicleInfo *avi)
00683 {
00684 CargoID cargo;
00685
00686
00687 SetDParam(0, GetEngineProperty(engine_number, 0x0B, avi->base_cost) * (_price.aircraft_base >> 3) >> 5);
00688 SetDParam(1, avi->max_speed * 10 / 16);
00689 DrawString(x, y, STR_PURCHASE_INFO_COST_SPEED, TC_FROMSTRING);
00690 y += 10;
00691
00692
00693 cargo = FindFirstRefittableCargo(engine_number);
00694 if (cargo == CT_INVALID || cargo == CT_PASSENGERS) {
00695 SetDParam(0, avi->passenger_capacity);
00696 SetDParam(1, avi->mail_capacity);
00697 DrawString(x, y, STR_PURCHASE_INFO_AIRCRAFT_CAPACITY, TC_FROMSTRING);
00698 } else {
00699
00700
00701 SetDParam(0, cargo);
00702 SetDParam(1, AircraftDefaultCargoCapacity(cargo, avi));
00703 SetDParam(2, STR_9842_REFITTABLE);
00704 DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, TC_FROMSTRING);
00705 }
00706 y += 10;
00707
00708
00709 SetDParam(0, GetEngineProperty(engine_number, 0x0E, avi->running_cost) * _price.aircraft_running >> 8);
00710 DrawString(x, y, STR_PURCHASE_INFO_RUNNINGCOST, TC_FROMSTRING);
00711 y += 10;
00712
00713 return y;
00714 }
00715
00723 int DrawVehiclePurchaseInfo(int x, int y, uint w, EngineID engine_number)
00724 {
00725 const Engine *e = GetEngine(engine_number);
00726 YearMonthDay ymd;
00727 ConvertDateToYMD(e->intro_date, &ymd);
00728 bool refitable = false;
00729
00730 switch (e->type) {
00731 default: NOT_REACHED();
00732 case VEH_TRAIN: {
00733 const RailVehicleInfo *rvi = RailVehInfo(engine_number);
00734 uint capacity = GetEngineProperty(engine_number, 0x14, rvi->capacity);
00735
00736 refitable = (EngInfo(engine_number)->refit_mask != 0) && (capacity > 0);
00737
00738 if (rvi->railveh_type == RAILVEH_WAGON) {
00739 y = DrawRailWagonPurchaseInfo(x, y, engine_number, rvi);
00740 } else {
00741 y = DrawRailEnginePurchaseInfo(x, y, engine_number, rvi);
00742 }
00743
00744
00745 int new_y = DrawCargoCapacityInfo(x, y, engine_number, VEH_TRAIN, refitable);
00746
00747 if (new_y == y) {
00748 SetDParam(0, CT_INVALID);
00749 SetDParam(2, STR_EMPTY);
00750 DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, TC_FROMSTRING);
00751 y += 10;
00752 } else {
00753 y = new_y;
00754 }
00755 break;
00756 }
00757 case VEH_ROAD:
00758 y = DrawRoadVehPurchaseInfo(x, y, engine_number, RoadVehInfo(engine_number));
00759 refitable = true;
00760 break;
00761 case VEH_SHIP: {
00762 const ShipVehicleInfo *svi = ShipVehInfo(engine_number);
00763 y = DrawShipPurchaseInfo(x, y, engine_number, svi);
00764 refitable = svi->refittable;
00765 } break;
00766 case VEH_AIRCRAFT:
00767 y = DrawAircraftPurchaseInfo(x, y, engine_number, AircraftVehInfo(engine_number));
00768 refitable = true;
00769 break;
00770 }
00771
00772
00773 if (e->type != VEH_TRAIN || RailVehInfo(engine_number)->railveh_type != RAILVEH_WAGON) {
00774
00775 SetDParam(0, ymd.year);
00776 SetDParam(1, e->lifelength);
00777 DrawString(x, y, STR_PURCHASE_INFO_DESIGNED_LIFE, TC_FROMSTRING);
00778 y += 10;
00779
00780
00781 SetDParam(0, e->reliability * 100 >> 16);
00782 DrawString(x, y, STR_PURCHASE_INFO_RELIABILITY, TC_FROMSTRING);
00783 y += 10;
00784 }
00785
00786
00787 y += ShowAdditionalText(x, y, w, engine_number);
00788 if (refitable) y += ShowRefitOptionsList(x, y, w, engine_number);
00789
00790 return y;
00791 }
00792
00793
00794 static void GenerateBuildTrainList(Window *w)
00795 {
00796 EngineID sel_id = INVALID_ENGINE;
00797 int num_engines = 0;
00798 int num_wagons = 0;
00799 buildvehicle_d *bv = &WP(w, buildvehicle_d);
00800
00801 bv->filter.railtype = (w->window_number <= VEH_END) ? RAILTYPE_END : GetRailType(w->window_number);
00802
00803 EngList_RemoveAll(&bv->eng_list);
00804
00805
00806
00807
00808
00809 EngineID eid;
00810 FOR_ALL_ENGINEIDS_OF_TYPE(eid, VEH_TRAIN) {
00811 const RailVehicleInfo *rvi = RailVehInfo(eid);
00812
00813 if (bv->filter.railtype != RAILTYPE_END && !HasPowerOnRail(rvi->railtype, bv->filter.railtype)) continue;
00814 if (!IsEngineBuildable(eid, VEH_TRAIN, _local_player)) continue;
00815
00816 EngList_Add(&bv->eng_list, eid);
00817 if (rvi->railveh_type != RAILVEH_WAGON) {
00818 num_engines++;
00819 } else {
00820 num_wagons++;
00821 }
00822
00823 if (eid == bv->sel_engine) sel_id = eid;
00824 }
00825
00826 bv->sel_engine = sel_id;
00827
00828
00829 _internal_sort_order = false;
00830 EngList_Sort(&bv->eng_list, TrainEnginesThenWagonsSorter);
00831
00832
00833 _internal_sort_order = bv->descending_sort_order;
00834 EngList_SortPartial(&bv->eng_list, _sorter[0][bv->sort_criteria], 0, num_engines);
00835
00836
00837 EngList_SortPartial(&bv->eng_list, _sorter[0][bv->sort_criteria], num_engines, num_wagons);
00838 }
00839
00840
00841 static void GenerateBuildRoadVehList(Window *w)
00842 {
00843 EngineID sel_id = INVALID_ENGINE;
00844 buildvehicle_d *bv = &WP(w, buildvehicle_d);
00845
00846 EngList_RemoveAll(&bv->eng_list);
00847
00848 EngineID eid;
00849 FOR_ALL_ENGINEIDS_OF_TYPE(eid, VEH_ROAD) {
00850 if (!IsEngineBuildable(eid, VEH_ROAD, _local_player)) continue;
00851 if (!HasBit(bv->filter.roadtypes, HasBit(EngInfo(eid)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD)) continue;
00852 EngList_Add(&bv->eng_list, eid);
00853
00854 if (eid == bv->sel_engine) sel_id = eid;
00855 }
00856 bv->sel_engine = sel_id;
00857 }
00858
00859
00860 static void GenerateBuildShipList(Window *w)
00861 {
00862 EngineID sel_id = INVALID_ENGINE;
00863 buildvehicle_d *bv = &WP(w, buildvehicle_d);
00864
00865 EngList_RemoveAll(&bv->eng_list);
00866
00867 EngineID eid;
00868 FOR_ALL_ENGINEIDS_OF_TYPE(eid, VEH_SHIP) {
00869 if (!IsEngineBuildable(eid, VEH_SHIP, _local_player)) continue;
00870 EngList_Add(&bv->eng_list, eid);
00871
00872 if (eid == bv->sel_engine) sel_id = eid;
00873 }
00874 bv->sel_engine = sel_id;
00875 }
00876
00877
00878 static void GenerateBuildAircraftList(Window *w)
00879 {
00880 EngineID sel_id = INVALID_ENGINE;
00881 buildvehicle_d *bv = &WP(w, buildvehicle_d);
00882
00883 EngList_RemoveAll(&bv->eng_list);
00884
00885
00886
00887
00888
00889 EngineID eid;
00890 FOR_ALL_ENGINEIDS_OF_TYPE(eid, VEH_AIRCRAFT) {
00891 if (!IsEngineBuildable(eid, VEH_AIRCRAFT, _local_player)) continue;
00892
00893 if (w->window_number > VEH_END && !CanAircraftUseStation(eid, w->window_number)) continue;
00894
00895 EngList_Add(&bv->eng_list, eid);
00896 if (eid == bv->sel_engine) sel_id = eid;
00897 }
00898
00899 bv->sel_engine = sel_id;
00900 }
00901
00902
00903 static void GenerateBuildList(Window *w)
00904 {
00905 buildvehicle_d *bv = &WP(w, buildvehicle_d);
00906
00907 switch (bv->vehicle_type) {
00908 default: NOT_REACHED();
00909 case VEH_TRAIN:
00910 GenerateBuildTrainList(w);
00911 return;
00912 case VEH_ROAD:
00913 GenerateBuildRoadVehList(w);
00914 break;
00915 case VEH_SHIP:
00916 GenerateBuildShipList(w);
00917 break;
00918 case VEH_AIRCRAFT:
00919 GenerateBuildAircraftList(w);
00920 break;
00921 }
00922 _internal_sort_order = bv->descending_sort_order;
00923 EngList_Sort(&bv->eng_list, _sorter[bv->vehicle_type][bv->sort_criteria]);
00924 }
00925
00926 static void DrawVehicleEngine(VehicleType type, int x, int y, EngineID engine, SpriteID pal)
00927 {
00928 switch (type) {
00929 case VEH_TRAIN: DrawTrainEngine( x, y, engine, pal); break;
00930 case VEH_ROAD: DrawRoadVehEngine( x, y, engine, pal); break;
00931 case VEH_SHIP: DrawShipEngine( x, y, engine, pal); break;
00932 case VEH_AIRCRAFT: DrawAircraftEngine(x, y, engine, pal); break;
00933 default: NOT_REACHED();
00934 }
00935 }
00936
00946 void DrawEngineList(VehicleType type, int x, int y, const EngineList eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group)
00947 {
00948 byte step_size = GetVehicleListHeight(type);
00949 byte x_offset = 0;
00950 byte y_offset = 0;
00951
00952 assert(max <= EngList_Count(&eng_list));
00953
00954 switch (type) {
00955 case VEH_TRAIN:
00956 x++;
00957
00958 case VEH_ROAD:
00959 x += 26;
00960 x_offset = 30;
00961 y += 2;
00962 y_offset = 4;
00963 break;
00964 case VEH_SHIP:
00965 x += 35;
00966 x_offset = 40;
00967 y += 7;
00968 y_offset = 3;
00969 break;
00970 case VEH_AIRCRAFT:
00971 x += 27;
00972 x_offset = 33;
00973 y += 7;
00974 y_offset = 3;
00975 break;
00976 default: NOT_REACHED();
00977 }
00978
00979 for (; min < max; min++, y += step_size) {
00980 const EngineID engine = eng_list[min];
00981
00982 const uint num_engines = GetGroupNumEngines(_local_player, selected_group, engine);
00983
00984 SetDParam(0, engine);
00985 DrawString(x + x_offset, y, STR_ENGINE_NAME, engine == selected_id ? TC_WHITE : TC_BLACK);
00986 DrawVehicleEngine(type, x, y + y_offset, engine, (show_count && num_engines == 0) ? PALETTE_CRASH : GetEnginePalette(engine, _local_player));
00987 if (show_count) {
00988 SetDParam(0, num_engines);
00989 DrawStringRightAligned(213, y + (GetVehicleListHeight(type) == 14 ? 3 : 8), STR_TINY_BLACK, TC_FROMSTRING);
00990 }
00991 }
00992 }
00993
00994 static void DrawBuildVehicleWindow(Window *w)
00995 {
00996 const buildvehicle_d *bv = &WP(w, buildvehicle_d);
00997 uint max = min(w->vscroll.pos + w->vscroll.cap, EngList_Count(&bv->eng_list));
00998
00999 w->SetWidgetDisabledState(BUILD_VEHICLE_WIDGET_BUILD, w->window_number <= VEH_END);
01000
01001 SetVScrollCount(w, EngList_Count(&bv->eng_list));
01002 SetDParam(0, bv->filter.railtype + STR_881C_NEW_RAIL_VEHICLES);
01003
01004
01005 w->widget[BUILD_VEHICLE_WIDGET_SORT_DROPDOWN].data = _sort_listing[bv->vehicle_type][bv->sort_criteria];
01006
01007 DrawWindowWidgets(w);
01008
01009 DrawEngineList(bv->vehicle_type, w->widget[BUILD_VEHICLE_WIDGET_LIST].left + 2, w->widget[BUILD_VEHICLE_WIDGET_LIST].top + 1, bv->eng_list, w->vscroll.pos, max, bv->sel_engine, false, DEFAULT_GROUP);
01010
01011 if (bv->sel_engine != INVALID_ENGINE) {
01012 const Widget *wi = &w->widget[BUILD_VEHICLE_WIDGET_PANEL];
01013 int text_end = DrawVehiclePurchaseInfo(2, wi->top + 1, wi->right - wi->left - 2, bv->sel_engine);
01014
01015 if (text_end > wi->bottom) {
01016 SetWindowDirty(w);
01017 ResizeWindowForWidget(w, BUILD_VEHICLE_WIDGET_PANEL, 0, text_end - wi->bottom);
01018 SetWindowDirty(w);
01019 }
01020 }
01021
01022 DrawSortButtonState(w, BUILD_VEHICLE_WIDGET_SORT_ASSENDING_DESCENDING, bv->descending_sort_order ? SBS_DOWN : SBS_UP);
01023 }
01024
01025 static void BuildVehicleClickEvent(Window *w, WindowEvent *e)
01026 {
01027 buildvehicle_d *bv = &WP(w, buildvehicle_d);
01028
01029 switch (e->we.click.widget) {
01030 case BUILD_VEHICLE_WIDGET_SORT_ASSENDING_DESCENDING:
01031 bv->descending_sort_order ^= true;
01032 _last_sort_order[bv->vehicle_type] = bv->descending_sort_order;
01033 bv->regenerate_list = true;
01034 SetWindowDirty(w);
01035 break;
01036
01037 case BUILD_VEHICLE_WIDGET_LIST: {
01038 uint i = (e->we.click.pt.y - w->widget[BUILD_VEHICLE_WIDGET_LIST].top) / GetVehicleListHeight(bv->vehicle_type) + w->vscroll.pos;
01039 uint num_items = EngList_Count(&bv->eng_list);
01040 bv->sel_engine = (i < num_items) ? bv->eng_list[i] : INVALID_ENGINE;
01041 SetWindowDirty(w);
01042 break;
01043 }
01044
01045 case BUILD_VEHICLE_WIDGET_SORT_DROPDOWN:
01046 ShowDropDownMenu(w, _sort_listing[bv->vehicle_type], bv->sort_criteria, BUILD_VEHICLE_WIDGET_SORT_DROPDOWN, 0, 0);
01047 break;
01048
01049 case BUILD_VEHICLE_WIDGET_BUILD: {
01050 EngineID sel_eng = bv->sel_engine;
01051 if (sel_eng != INVALID_ENGINE) {
01052 switch (bv->vehicle_type) {
01053 default: NOT_REACHED();
01054 case VEH_TRAIN:
01055 DoCommandP(w->window_number, sel_eng, 0, (RailVehInfo(sel_eng)->railveh_type == RAILVEH_WAGON) ? CcBuildWagon : CcBuildLoco,
01056 CMD_BUILD_RAIL_VEHICLE | CMD_MSG(STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE));
01057 break;
01058 case VEH_ROAD:
01059 DoCommandP(w->window_number, sel_eng, 0, CcBuildRoadVeh, CMD_BUILD_ROAD_VEH | CMD_MSG(STR_9009_CAN_T_BUILD_ROAD_VEHICLE));
01060 break;
01061 case VEH_SHIP:
01062 DoCommandP(w->window_number, sel_eng, 0, CcBuildShip, CMD_BUILD_SHIP | CMD_MSG(STR_980D_CAN_T_BUILD_SHIP));
01063 break;
01064 case VEH_AIRCRAFT:
01065 DoCommandP(w->window_number, sel_eng, 0, CcBuildAircraft, CMD_BUILD_AIRCRAFT | CMD_MSG(STR_A008_CAN_T_BUILD_AIRCRAFT));
01066 break;
01067 }
01068 }
01069 break;
01070 }
01071
01072 case BUILD_VEHICLE_WIDGET_RENAME: {
01073 EngineID sel_eng = bv->sel_engine;
01074 if (sel_eng != INVALID_ENGINE) {
01075 StringID str = STR_NULL;
01076
01077 bv->rename_engine = sel_eng;
01078 switch (bv->vehicle_type) {
01079 default: NOT_REACHED();
01080 case VEH_TRAIN: str = STR_886A_RENAME_TRAIN_VEHICLE_TYPE; break;
01081 case VEH_ROAD: str = STR_9036_RENAME_ROAD_VEHICLE_TYPE; break;
01082 case VEH_SHIP: str = STR_9838_RENAME_SHIP_TYPE; break;
01083 case VEH_AIRCRAFT: str = STR_A039_RENAME_AIRCRAFT_TYPE; break;
01084 }
01085 SetDParam(0, sel_eng);
01086 ShowQueryString(STR_ENGINE_NAME, str, 31, 160, w, CS_ALPHANUMERAL);
01087 }
01088 break;
01089 }
01090 }
01091 }
01092
01093 static void NewVehicleWndProc(Window *w, WindowEvent *e)
01094 {
01095 buildvehicle_d *bv = &WP(w, buildvehicle_d);
01096
01097 switch (e->event) {
01098 case WE_CREATE: {
01099 bv->vehicle_type = *(VehicleType*)e->we.create.data;
01100 int vlh = GetVehicleListHeight(bv->vehicle_type);
01101
01102 ResizeWindow(w, 0, vlh - 14);
01103 w->resize.step_height = vlh;
01104 w->vscroll.cap = 1;
01105 w->widget[BUILD_VEHICLE_WIDGET_LIST].data = 0x101;
01106
01107 w->resize.width = w->width;
01108 w->resize.height = w->height;
01109 } break;
01110
01111 case WE_INVALIDATE_DATA:
01112 bv->regenerate_list = true;
01113 SetWindowDirty(w);
01114 break;
01115
01116 case WE_DESTROY:
01117 EngList_Destroy(&bv->eng_list);
01118 break;
01119
01120 case WE_PAINT:
01121 if (bv->regenerate_list) {
01122 bv->regenerate_list = false;
01123 GenerateBuildList(w);
01124 }
01125 DrawBuildVehicleWindow(w);
01126 break;
01127
01128 case WE_CLICK:
01129 BuildVehicleClickEvent(w, e);
01130 break;
01131
01132 case WE_DOUBLE_CLICK:
01133 if (e->we.click.widget == BUILD_VEHICLE_WIDGET_LIST) {
01134
01135 e->we.click.widget = BUILD_VEHICLE_WIDGET_BUILD;
01136 BuildVehicleClickEvent(w, e);
01137 }
01138 break;
01139
01140 case WE_ON_EDIT_TEXT: {
01141 if (e->we.edittext.str[0] != '\0') {
01142 StringID str = STR_NULL;
01143 _cmd_text = e->we.edittext.str;
01144 switch (bv->vehicle_type) {
01145 default: NOT_REACHED();
01146 case VEH_TRAIN: str = STR_886B_CAN_T_RENAME_TRAIN_VEHICLE; break;
01147 case VEH_ROAD: str = STR_9037_CAN_T_RENAME_ROAD_VEHICLE; break;
01148 case VEH_SHIP: str = STR_9839_CAN_T_RENAME_SHIP_TYPE; break;
01149 case VEH_AIRCRAFT: str = STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE; break;
01150 }
01151 DoCommandP(0, bv->rename_engine, 0, NULL, CMD_RENAME_ENGINE | CMD_MSG(str));
01152 }
01153 break;
01154 }
01155
01156 case WE_DROPDOWN_SELECT:
01157 if (bv->sort_criteria != e->we.dropdown.index) {
01158 bv->sort_criteria = e->we.dropdown.index;
01159 _last_sort_criteria[bv->vehicle_type] = bv->sort_criteria;
01160 bv->regenerate_list = true;
01161 }
01162 SetWindowDirty(w);
01163 break;
01164
01165 case WE_RESIZE:
01166 if (e->we.sizing.diff.x != 0) ResizeButtons(w, BUILD_VEHICLE_WIDGET_BUILD, BUILD_VEHICLE_WIDGET_RENAME);
01167 if (e->we.sizing.diff.y == 0) break;
01168
01169 w->vscroll.cap += e->we.sizing.diff.y / (int)GetVehicleListHeight(bv->vehicle_type);
01170 w->widget[BUILD_VEHICLE_WIDGET_LIST].data = (w->vscroll.cap << 8) + 1;
01171 break;
01172 }
01173 }
01174
01175 static const WindowDesc _build_vehicle_desc = {
01176 WDP_AUTO, WDP_AUTO, 240, 174, 240, 256,
01177 WC_BUILD_VEHICLE, WC_NONE,
01178 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
01179 _build_vehicle_widgets,
01180 NewVehicleWndProc
01181 };
01182
01183 void ShowBuildVehicleWindow(TileIndex tile, VehicleType type)
01184 {
01185 buildvehicle_d *bv;
01186 Window *w;
01187
01188
01189
01190
01191 uint num = (tile == 0) ? (int)type : tile;
01192
01193 assert(IsPlayerBuildableVehicleType(type));
01194
01195 DeleteWindowById(WC_BUILD_VEHICLE, num);
01196
01197 w = AllocateWindowDescFront(&_build_vehicle_desc, num, &type);
01198
01199 if (w == NULL) return;
01200
01201 w->caption_color = (tile != 0) ? GetTileOwner(tile) : _local_player;
01202
01203 bv = &WP(w, buildvehicle_d);
01204 EngList_Create(&bv->eng_list);
01205 bv->sel_engine = INVALID_ENGINE;
01206
01207 bv->regenerate_list = false;
01208
01209 bv->sort_criteria = _last_sort_criteria[type];
01210 bv->descending_sort_order = _last_sort_order[type];
01211
01212 switch (type) {
01213 default: NOT_REACHED();
01214 case VEH_TRAIN:
01215 WP(w, buildvehicle_d).filter.railtype = (tile == 0) ? RAILTYPE_END : GetRailType(tile);
01216 break;
01217 case VEH_ROAD:
01218 WP(w, buildvehicle_d).filter.roadtypes = (tile == 0) ? ROADTYPES_ALL : GetRoadTypes(tile);
01219 case VEH_SHIP:
01220 break;
01221 case VEH_AIRCRAFT:
01222 bv->filter.flags =
01223 tile == 0 ? AirportFTAClass::ALL : GetStationByTile(tile)->Airport()->flags;
01224 break;
01225 }
01226 SetupWindowStrings(w, type);
01227 ResizeButtons(w, BUILD_VEHICLE_WIDGET_BUILD, BUILD_VEHICLE_WIDGET_RENAME);
01228
01229 GenerateBuildList(w);
01230
01231 if (EngList_Count(&bv->eng_list) > 0) bv->sel_engine = bv->eng_list[0];
01232 }