# order_gui.cpp

Go to the documentation of this file.

    00001 /* $Id: order_gui.cpp 14367 2008-09-20 20:34:36Z peter1138 $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "openttd.h"
    00007 #include "road_map.h"
    00008 #include "station_map.h"
    00009 #include "gui.h"
    00010 #include "window_gui.h"
    00011 #include "station.h"
    00012 #include "town.h"
    00013 #include "command_func.h"
    00014 #include "viewport_func.h"
    00015 #include "gfx_func.h"
    00016 #include "depot.h"
    00017 #include "waypoint.h"
    00018 #include "train.h"
    00019 #include "water_map.h"
    00020 #include "vehicle_gui.h"
    00021 #include "timetable.h"
    00022 #include "cargotype.h"
    00023 #include "order.h"
    00024 #include "strings_func.h"
    00025 #include "window_func.h"
    00026 #include "vehicle_func.h"
    00027 #include "settings_type.h"
    00028 #include "player_func.h"
    00029
    00030 #include "table/sprites.h"
    00031 #include "table/strings.h"
    00032
    00033 enum OrderWindowWidgets {
    00034   ORDER_WIDGET_CLOSEBOX = 0,
    00035   ORDER_WIDGET_CAPTION,
    00036   ORDER_WIDGET_TIMETABLE_VIEW,
    00037   ORDER_WIDGET_ORDER_LIST,
    00038   ORDER_WIDGET_SCROLLBAR,
    00039   ORDER_WIDGET_SKIP,
    00040   ORDER_WIDGET_DELETE,
    00041   ORDER_WIDGET_NON_STOP,
    00042   ORDER_WIDGET_GOTO,
    00043   ORDER_WIDGET_FULL_LOAD,
    00044   ORDER_WIDGET_UNLOAD,
    00045   ORDER_WIDGET_REFIT,
    00046   ORDER_WIDGET_TRANSFER,
    00047   ORDER_WIDGET_SHARED_ORDER_LIST,
    00048   ORDER_WIDGET_RESIZE_BAR,
    00049   ORDER_WIDGET_RESIZE,
    00050 };
    00051
    00059 static int OrderGetSel(const Window *w)
    00060 {
    00061   const Vehicle *v = GetVehicle(w->window_number);
    00062   int num = WP(w, order_d).sel;
    00063
    00064   return (num >= 0 && num < v->num_orders) ? num : v->num_orders;
    00065 }
    00066
    00078 static int GetOrderFromOrderWndPt(Window *w, int y, const Vehicle *v)
    00079 {
    00080   /*
    00081    * Calculation description:
    00082    * 15 = 14 (w->widget[ORDER_WIDGET_ORDER_LIST].top) + 1 (frame-line)
    00083    * 10 = order text hight
    00084    */
    00085   int sel = (y - 15) / 10;
    00086
    00087   if ((uint)sel >= w->vscroll.cap) return INVALID_ORDER;
    00088
    00089   sel += w->vscroll.pos;
    00090
    00091   return (sel <= v->num_orders && sel >= 0) ? sel : INVALID_ORDER;
    00092 }
    00093
    00094 static StringID StationOrderStrings[] = {
    00095   STR_8806_GO_TO,
    00096   STR_GO_TO_TRANSFER,
    00097   STR_8807_GO_TO_UNLOAD,
    00098   STR_GO_TO_TRANSFER_UNLOAD,
    00099   STR_8808_GO_TO_LOAD,
    00100   STR_GO_TO_TRANSFER_LOAD,
    00101   STR_NULL,
    00102   STR_NULL,
    00103   STR_880A_GO_NON_STOP_TO,
    00104   STR_GO_TO_NON_STOP_TRANSFER,
    00105   STR_880B_GO_NON_STOP_TO_UNLOAD,
    00106   STR_GO_TO_NON_STOP_TRANSFER_UNLOAD,
    00107   STR_880C_GO_NON_STOP_TO_LOAD,
    00108   STR_GO_TO_NON_STOP_TRANSFER_LOAD,
    00109   STR_NULL
    00110 };
    00111
    00112 static void DrawOrdersWindow(Window *w)
    00113 {
    00114   const Vehicle *v;
    00115   const Order *order;
    00116   StringID str;
    00117   int sel;
    00118   int y, i;
    00119   bool shared_orders;
    00120
    00121   v = GetVehicle(w->window_number);
    00122
    00123   shared_orders = v->IsOrderListShared();
    00124
    00125   SetVScrollCount(w, v->num_orders + 1);
    00126
    00127   sel = OrderGetSel(w);
    00128   SetDParam(2, STR_8827_FULL_LOAD);
    00129
    00130   order = GetVehicleOrder(v, sel);
    00131
    00132   if (v->owner == _local_player) {
    00133     /* skip */
    00134     w->SetWidgetDisabledState(ORDER_WIDGET_SKIP, v->num_orders <= 1);
    00135
    00136     /* delete */
    00137     w->SetWidgetDisabledState(ORDER_WIDGET_DELETE,
    00138         (uint)v->num_orders + ((shared_orders || v->num_orders != 0) ? 1 : 0) <= (uint)WP(w, order_d).sel);
    00139
    00140     /* non-stop only for trains */
    00141     w->SetWidgetDisabledState(ORDER_WIDGET_NON_STOP,  v->type != VEH_TRAIN || order == NULL);
    00142     w->SetWidgetDisabledState(ORDER_WIDGET_FULL_LOAD, order == NULL); // full load
    00143     w->SetWidgetDisabledState(ORDER_WIDGET_UNLOAD,    order == NULL); // unload
    00144     w->SetWidgetDisabledState(ORDER_WIDGET_TRANSFER,  order == NULL); // transfer
    00145     /* Disable list of vehicles with the same shared orders if there is no list */
    00146     w->SetWidgetDisabledState(ORDER_WIDGET_SHARED_ORDER_LIST, !shared_orders || v->orders == NULL);
    00147     w->SetWidgetDisabledState(ORDER_WIDGET_REFIT,     order == NULL); // Refit
    00148     w->HideWidget(ORDER_WIDGET_REFIT); // Refit
    00149   } else {
    00150     w->DisableWidget(ORDER_WIDGET_RESIZE_BAR);
    00151   }
    00152
    00153   w->ShowWidget(ORDER_WIDGET_UNLOAD); // Unload
    00154
    00155   if (order != NULL) {
    00156     switch (order->type) {
    00157       case OT_GOTO_STATION:
    00158         if (!GetStation(order->dest)->IsBuoy()) break;
    00159         /* Fall-through */
    00160
    00161       case OT_GOTO_WAYPOINT:
    00162         w->DisableWidget(ORDER_WIDGET_FULL_LOAD);
    00163         w->DisableWidget(ORDER_WIDGET_UNLOAD);
    00164         w->DisableWidget(ORDER_WIDGET_TRANSFER);
    00165         break;
    00166
    00167       case OT_GOTO_DEPOT:
    00168         w->DisableWidget(ORDER_WIDGET_TRANSFER);
    00169
    00170         /* Remove unload and replace it with refit */
    00171         w->HideWidget(ORDER_WIDGET_UNLOAD);
    00172         w->ShowWidget(ORDER_WIDGET_REFIT);
    00173         SetDParam(2,STR_SERVICE);
    00174         break;
    00175
    00176       default: // every other orders
    00177         w->DisableWidget(ORDER_WIDGET_NON_STOP);
    00178         w->DisableWidget(ORDER_WIDGET_FULL_LOAD);
    00179         w->DisableWidget(ORDER_WIDGET_UNLOAD);
    00180     }
    00181   }
    00182
    00183   SetDParam(0, v->index);
    00184   DrawWindowWidgets(w);
    00185
    00186   y = 15;
    00187
    00188   i = w->vscroll.pos;
    00189   order = GetVehicleOrder(v, i);
    00190   while (order != NULL) {
    00191     str = (v->cur_order_index == i) ? STR_8805 : STR_8804;
    00192     SetDParam(3, STR_EMPTY);
    00193
    00194     if (i - w->vscroll.pos < w->vscroll.cap) {
    00195       SetDParam(1, 6);
    00196
    00197       switch (order->type) {
    00198         case OT_DUMMY:
    00199           SetDParam(1, STR_INVALID_ORDER);
    00200           SetDParam(2, order->dest);
    00201           break;
    00202
    00203         case OT_GOTO_STATION:
    00204           SetDParam(1, StationOrderStrings[order->flags]);
    00205           SetDParam(2, order->dest);
    00206           break;
    00207
    00208         case OT_GOTO_DEPOT: {
    00209           StringID s = STR_NULL;
    00210
    00211           if (v->type == VEH_AIRCRAFT) {
    00212             s = STR_GO_TO_AIRPORT_HANGAR;
    00213             SetDParam(2, order->dest);
    00214           } else {
    00215             SetDParam(2, GetDepot(order->dest)->town_index);
    00216
    00217             switch (v->type) {
    00218               case VEH_TRAIN: s = (order->flags & OFB_NON_STOP) ? STR_880F_GO_NON_STOP_TO_TRAIN_DEPOT : STR_GO_TO_TRAIN_DEPOT; break;
    00219               case VEH_ROAD:  s = STR_GO_TO_ROADVEH_DEPOT; break;
    00220               case VEH_SHIP:  s = STR_GO_TO_SHIP_DEPOT; break;
    00221               default: break;
    00222             }
    00223           }
    00224
    00225           if (order->flags & OFB_FULL_LOAD) s++; /* service at */
    00226
    00227           SetDParam(1, s);
    00228           if (order->refit_cargo < NUM_CARGO) {
    00229             SetDParam(3, STR_REFIT_ORDER);
    00230             SetDParam(4, GetCargo(order->refit_cargo)->name);
    00231           } else {
    00232             SetDParam(3, STR_EMPTY);
    00233           }
    00234           break;
    00235         }
    00236
    00237         case OT_GOTO_WAYPOINT:
    00238           SetDParam(1, (order->flags & OFB_NON_STOP) ? STR_GO_NON_STOP_TO_WAYPOINT : STR_GO_TO_WAYPOINT);
    00239           SetDParam(2, order->dest);
    00240           break;
    00241
    00242         default: break;
    00243       }
    00244
    00245       SetDParam(0, i + 1);
    00246       DrawString(2, y, str, (i == WP(w, order_d).sel) ? TC_WHITE : TC_BLACK);
    00247
    00248       y += 10;
    00249     }
    00250
    00251     i++;
    00252     order = order->next;
    00253   }
    00254
    00255   if (i - w->vscroll.pos < w->vscroll.cap) {
    00256     str = shared_orders ? STR_END_OF_SHARED_ORDERS : STR_882A_END_OF_ORDERS;
    00257     DrawString(2, y, str, (i == WP(w, order_d).sel) ? TC_WHITE : TC_BLACK);
    00258   }
    00259 }
    00260
    00261 static Order GetOrderCmdFromTile(const Vehicle *v, TileIndex tile)
    00262 {
    00263   Order order;
    00264   order.next  = NULL;
    00265   order.index = 0;
    00266   order.refit_cargo   = CT_INVALID;
    00267   order.refit_subtype = 0;
    00268
    00269   // check depot first
    00270   if (_patches.gotodepot) {
    00271     switch (GetTileType(tile)) {
    00272     case MP_RAILWAY:
    00273       if (v->type == VEH_TRAIN && IsTileOwner(tile, _local_player)) {
    00274         if (IsRailDepot(tile)) {
    00275           order.type = OT_GOTO_DEPOT;
    00276           order.flags = OFB_PART_OF_ORDERS;
    00277           order.dest = GetDepotByTile(tile)->index;
    00278           return order;
    00279         }
    00280       }
    00281       break;
    00282
    00283     case MP_ROAD:
    00284       if (IsRoadDepot(tile) && v->type == VEH_ROAD && IsTileOwner(tile, _local_player)) {
    00285         order.type = OT_GOTO_DEPOT;
    00286         order.flags = OFB_PART_OF_ORDERS;
    00287         order.dest = GetDepotByTile(tile)->index;
    00288         return order;
    00289       }
    00290       break;
    00291
    00292     case MP_STATION:
    00293       if (v->type != VEH_AIRCRAFT) break;
    00294       if (IsHangar(tile) && IsTileOwner(tile, _local_player)) {
    00295         order.type = OT_GOTO_DEPOT;
    00296         order.flags = OFB_PART_OF_ORDERS;
    00297         order.dest = GetStationIndex(tile);
    00298         return order;
    00299       }
    00300       break;
    00301
    00302     case MP_WATER:
    00303       if (v->type != VEH_SHIP) break;
    00304       if (IsTileDepotType(tile, TRANSPORT_WATER) &&
    00305           IsTileOwner(tile, _local_player)) {
    00306         TileIndex tile2 = GetOtherShipDepotTile(tile);
    00307
    00308         order.type = OT_GOTO_DEPOT;
    00309         order.flags = OFB_PART_OF_ORDERS;
    00310         order.dest = GetDepotByTile(tile < tile2 ? tile : tile2)->index;
    00311         return order;
    00312       }
    00313
    00314       default:
    00315         break;
    00316     }
    00317   }
    00318
    00319   // check waypoint
    00320   if (IsTileType(tile, MP_RAILWAY) &&
    00321       v->type == VEH_TRAIN &&
    00322       IsTileOwner(tile, _local_player) &&
    00323       IsRailWaypoint(tile)) {
    00324     order.type = OT_GOTO_WAYPOINT;
    00325     order.flags = 0;
    00326     order.dest = GetWaypointByTile(tile)->index;
    00327     return order;
    00328   }
    00329
    00330   if (IsTileType(tile, MP_STATION)) {
    00331     StationID st_index = GetStationIndex(tile);
    00332     const Station *st = GetStation(st_index);
    00333
    00334     if (st->owner == _current_player || st->owner == OWNER_NONE) {
    00335       byte facil;
    00336       (facil=FACIL_DOCK, v->type == VEH_SHIP) ||
    00337       (facil=FACIL_TRAIN, v->type == VEH_TRAIN) ||
    00338       (facil=FACIL_AIRPORT, v->type == VEH_AIRCRAFT) ||
    00339       (facil=FACIL_BUS_STOP, v->type == VEH_ROAD && IsCargoInClass(v->cargo_type, CC_PASSENGERS)) ||
    00340       (facil=FACIL_TRUCK_STOP, 1);
    00341       if (st->facilities & facil) {
    00342         order.type = OT_GOTO_STATION;
    00343         order.flags = 0;
    00344         order.dest = st_index;
    00345         return order;
    00346       }
    00347     }
    00348   }
    00349
    00350   // not found
    00351   order.Free();
    00352   order.dest = INVALID_STATION;
    00353   return order;
    00354 }
    00355
    00356 static bool HandleOrderVehClick(const Vehicle *v, const Vehicle *u, Window *w)
    00357 {
    00358   if (u->type != v->type) return false;
    00359
    00360   if (!u->IsPrimaryVehicle()) {
    00361     u = u->First();
    00362     if (!u->IsPrimaryVehicle()) return false;
    00363   }
    00364
    00365   // v is vehicle getting orders. Only copy/clone orders if vehicle doesn't have any orders yet
    00366   // obviously if you press CTRL on a non-empty orders vehicle you know what you are doing
    00367   if (v->num_orders != 0 && _ctrl_pressed == 0) return false;
    00368
    00369   if (DoCommandP(v->tile, v->index | (u->index << 16), _ctrl_pressed ? CO_SHARE : CO_COPY, NULL,
    00370     _ctrl_pressed ? CMD_CLONE_ORDER | CMD_MSG(STR_CANT_SHARE_ORDER_LIST) : CMD_CLONE_ORDER | CMD_MSG(STR_CANT_COPY_ORDER_LIST))) {
    00371     WP(w, order_d).sel = -1;
    00372     ResetObjectToPlace();
    00373   }
    00374
    00375   return true;
    00376 }
    00377
    00378 static void OrdersPlaceObj(const Vehicle *v, TileIndex tile, Window *w)
    00379 {
    00380   Order cmd;
    00381   const Vehicle *u;
    00382
    00383   // check if we're clicking on a vehicle first.. clone orders in that case.
    00384   u = CheckMouseOverVehicle();
    00385   if (u != NULL && HandleOrderVehClick(v, u, w)) return;
    00386
    00387   cmd = GetOrderCmdFromTile(v, tile);
    00388   if (!cmd.IsValid()) return;
    00389
    00390   if (DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), PackOrder(&cmd), NULL, CMD_INSERT_ORDER | CMD_MSG(STR_8833_CAN_T_INSERT_NEW_ORDER))) {
    00391     if (WP(w, order_d).sel != -1) WP(w,order_d).sel++;
    00392     ResetObjectToPlace();
    00393   }
    00394 }
    00395
    00402 static void OrderClick_Goto(Window *w, const Vehicle *v)
    00403 {
    00404   w->InvalidateWidget(ORDER_WIDGET_GOTO);
    00405   w->ToggleWidgetLoweredState(ORDER_WIDGET_GOTO);
    00406   if (w->IsWidgetLowered(ORDER_WIDGET_GOTO)) {
    00407     _place_clicked_vehicle = NULL;
    00408     SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, VHM_RECT, w);
    00409   } else {
    00410     ResetObjectToPlace();
    00411   }
    00412 }
    00413
    00420 static void OrderClick_FullLoad(Window *w, const Vehicle *v)
    00421 {
    00422   DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), OF_FULL_LOAD, NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
    00423 }
    00424
    00431 static void OrderClick_Unload(Window *w, const Vehicle *v)
    00432 {
    00433   DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), OF_UNLOAD,    NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
    00434 }
    00435
    00442 static void OrderClick_Nonstop(Window *w, const Vehicle *v)
    00443 {
    00444   DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), OF_NON_STOP,  NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
    00445 }
    00446
    00453 static void OrderClick_Transfer(Window* w, const Vehicle* v)
    00454 {
    00455   DoCommandP(v->tile, v->index + (OrderGetSel(w) <<  16), OF_TRANSFER, NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
    00456 }
    00457
    00466 static void OrderClick_Skip(Window *w, const Vehicle *v)
    00467 {
    00468   /* Don't skip when there's nothing to skip */
    00469   if (_ctrl_pressed && v->cur_order_index == OrderGetSel(w)) return;
    00470
    00471   DoCommandP(v->tile, v->index, _ctrl_pressed ? OrderGetSel(w) : ((v->cur_order_index + 1) % v->num_orders),
    00472       NULL, CMD_SKIP_TO_ORDER | CMD_MSG(_ctrl_pressed ? STR_CAN_T_SKIP_TO_ORDER : STR_CAN_T_SKIP_ORDER));
    00473 }
    00474
    00481 static void OrderClick_Delete(Window *w, const Vehicle *v)
    00482 {
    00483   DoCommandP(v->tile, v->index, OrderGetSel(w), NULL, CMD_DELETE_ORDER | CMD_MSG(STR_8834_CAN_T_DELETE_THIS_ORDER));
    00484 }
    00485
    00494 static void OrderClick_Refit(Window *w, const Vehicle *v)
    00495 {
    00496   if (_ctrl_pressed) {
    00497     /* Cancel refitting */
    00498     DoCommandP(v->tile, v->index, (WP(w, order_d).sel << 16) | (CT_NO_REFIT << 8) | CT_NO_REFIT, NULL, CMD_ORDER_REFIT);
    00499   } else {
    00500     ShowVehicleRefitWindow(v, WP(w, order_d).sel);
    00501   }
    00502 }
    00503
    00504 typedef void OnButtonVehClick(Window *w, const Vehicle *v);
    00505
    00512 static OnButtonVehClick* const _order_button_proc[] = {
    00513   OrderClick_Skip,
    00514   OrderClick_Delete,
    00515   OrderClick_Nonstop,
    00516   OrderClick_Goto,
    00517   OrderClick_FullLoad,
    00518   OrderClick_Unload,
    00519   OrderClick_Transfer
    00520 };
    00521
    00522 static const uint16 _order_keycodes[] = {
    00523   'D', //skip order
    00524   'F', //delete order
    00525   'G', //non-stop
    00526   'H', //goto order
    00527   'J', //full load
    00528   'K'  //unload
    00529 };
    00530
    00531 static void OrdersWndProc(Window *w, WindowEvent *e)
    00532 {
    00533   switch (e->event) {
    00534     case WE_CREATE:
    00535       /* Ensure that the refit and unload buttons always remain at the same location.
    00536        * Only one of them can be active at any one time and takes turns on being disabled.
    00537        * To ensure that they stay at the same location, we also verify that they behave the same
    00538        * when resizing. */
    00539       if (GetVehicle(w->window_number)->owner == _local_player) { // only the vehicle owner got these buttons
    00540         assert(w->widget[ORDER_WIDGET_REFIT].left          == w->widget[ORDER_WIDGET_UNLOAD].left);
    00541         assert(w->widget[ORDER_WIDGET_REFIT].right         == w->widget[ORDER_WIDGET_UNLOAD].right);
    00542         assert(w->widget[ORDER_WIDGET_REFIT].top           == w->widget[ORDER_WIDGET_UNLOAD].top);
    00543         assert(w->widget[ORDER_WIDGET_REFIT].bottom        == w->widget[ORDER_WIDGET_UNLOAD].bottom);
    00544         assert(w->widget[ORDER_WIDGET_REFIT].display_flags == w->widget[ORDER_WIDGET_UNLOAD].display_flags);
    00545       }
    00546     if (GetVehicle(w->window_number)->num_orders == 0) return;
    00547
    00548       if (_patches.timetabling) {
    00549         w->widget[ORDER_WIDGET_CAPTION].right -= 61;
    00550       } else {
    00551         w->HideWidget(ORDER_WIDGET_TIMETABLE_VIEW);
    00552       }
    00553
    00554       break;
    00555
    00556   case WE_PAINT:
    00557     DrawOrdersWindow(w);
    00558     break;
    00559
    00560   case WE_CLICK: {
    00561     const Vehicle *v = GetVehicle(w->window_number);
    00562     switch (e->we.click.widget) {
    00563     case ORDER_WIDGET_ORDER_LIST: {
    00564       ResetObjectToPlace();
    00565
    00566       int sel = GetOrderFromOrderWndPt(w, e->we.click.pt.y, v);
    00567
    00568       if (sel == INVALID_ORDER) {
    00569         /* This was a click on an empty part of the orders window, so
    00570          * deselect the currently selected order. */
    00571         WP(w, order_d).sel = -1;
    00572         SetWindowDirty(w);
    00573         return;
    00574       }
    00575
    00576       if (_ctrl_pressed && sel < v->num_orders) {
    00577         const Order *ord = GetVehicleOrder(v, sel);
    00578         TileIndex xy;
    00579
    00580         switch (ord->type) {
    00581           case OT_GOTO_STATION:  xy = GetStation(ord->dest)->xy ; break;
    00582           case OT_GOTO_DEPOT:    xy = (v->type == VEH_AIRCRAFT) ?  GetStation(ord->dest)->xy : GetDepot(ord->dest)->xy;    break;
    00583           case OT_GOTO_WAYPOINT: xy = GetWaypoint(ord->dest)->xy; break;
    00584           default:               xy = 0; break;
    00585         }
    00586
    00587         if (xy != 0) ScrollMainWindowToTile(xy);
    00588         return;
    00589       } else {
    00590         if (sel == WP(w, order_d).sel) {
    00591           /* Deselect clicked order */
    00592           WP(w, order_d).sel = -1;
    00593         } else {
    00594           /* Select clicked order */
    00595           WP(w, order_d).sel = sel;
    00596
    00597           if (v->owner == _local_player) {
    00598             /* Activate drag and drop */
    00599             SetObjectToPlaceWnd(SPR_CURSOR_MOUSE, PAL_NONE, VHM_DRAG, w);
    00600           }
    00601         }
    00602       }
    00603
    00604       SetWindowDirty(w);
    00605     } break;
    00606
    00607     case ORDER_WIDGET_SKIP:
    00608       OrderClick_Skip(w, v);
    00609       break;
    00610
    00611     case ORDER_WIDGET_DELETE:
    00612       OrderClick_Delete(w, v);
    00613       break;
    00614
    00615     case ORDER_WIDGET_NON_STOP:
    00616       OrderClick_Nonstop(w, v);
    00617       break;
    00618
    00619     case ORDER_WIDGET_GOTO:
    00620       OrderClick_Goto(w, v);
    00621       break;
    00622
    00623     case ORDER_WIDGET_FULL_LOAD:
    00624       OrderClick_FullLoad(w, v);
    00625       break;
    00626
    00627     case ORDER_WIDGET_UNLOAD:
    00628       OrderClick_Unload(w, v);
    00629       break;
    00630     case ORDER_WIDGET_REFIT:
    00631       OrderClick_Refit(w, v);
    00632       break;
    00633
    00634     case ORDER_WIDGET_TRANSFER:
    00635       OrderClick_Transfer(w, v);
    00636       break;
    00637
    00638     case ORDER_WIDGET_TIMETABLE_VIEW:
    00639       ShowTimetableWindow(v);
    00640       break;
    00641
    00642     case ORDER_WIDGET_SHARED_ORDER_LIST:
    00643       ShowVehicleListWindow(v);
    00644       break;
    00645     }
    00646   } break;
    00647
    00648   case WE_DRAGDROP: {
    00649     const Vehicle *v = GetVehicle(w->window_number);
    00650
    00651     switch (e->we.click.widget) {
    00652       case ORDER_WIDGET_ORDER_LIST: {
    00653         int from_order = OrderGetSel(w);
    00654         int to_order = GetOrderFromOrderWndPt(w, e->we.dragdrop.pt.y, v);
    00655
    00656         if (!(from_order == to_order || from_order == INVALID_ORDER || from_order > v->num_orders || to_order == INVALID_ORDER || to_order > v->num_orders) &&
    00657             DoCommandP(v->tile, v->index, from_order | (to_order << 16), NULL, CMD_MOVE_ORDER | CMD_MSG(STR_CAN_T_MOVE_THIS_ORDER))) {
    00658           WP(w, order_d).sel = -1;
    00659         }
    00660
    00661         break;
    00662       }
    00663
    00664       case ORDER_WIDGET_DELETE:
    00665         OrderClick_Delete(w, v);
    00666         break;
    00667     }
    00668
    00669     ResetObjectToPlace();
    00670     break;
    00671   }
    00672
    00673   case WE_KEYPRESS: {
    00674     Vehicle *v = GetVehicle(w->window_number);
    00675     uint i;
    00676
    00677     if (v->owner != _local_player) break;
    00678
    00679     for (i = 0; i < lengthof(_order_keycodes); i++) {
    00680       if (e->we.keypress.keycode == _order_keycodes[i]) {
    00681         e->we.keypress.cont = false;
    00682         //see if the button is disabled
    00683         if (!w->IsWidgetDisabled(i + ORDER_WIDGET_SKIP)) _order_button_proc[i](w, v);
    00684         break;
    00685       }
    00686     }
    00687     break;
    00688   }
    00689
    00690   case WE_RCLICK: {
    00691     const Vehicle *v = GetVehicle(w->window_number);
    00692     int s = OrderGetSel(w);
    00693
    00694     if (e->we.click.widget != ORDER_WIDGET_FULL_LOAD) break;
    00695     if (s == v->num_orders || GetVehicleOrder(v, s)->type != OT_GOTO_DEPOT) {
    00696       GuiShowTooltips(STR_8857_MAKE_THE_HIGHLIGHTED_ORDER);
    00697     } else {
    00698       GuiShowTooltips(STR_SERVICE_HINT);
    00699     }
    00700   } break;
    00701
    00702   case WE_PLACE_OBJ: {
    00703     OrdersPlaceObj(GetVehicle(w->window_number), e->we.place.tile, w);
    00704   } break;
    00705
    00706   case WE_ABORT_PLACE_OBJ: {
    00707     w->RaiseWidget(ORDER_WIDGET_GOTO);
    00708     w->InvalidateWidget(ORDER_WIDGET_GOTO);
    00709   } break;
    00710
    00711   // check if a vehicle in a depot was clicked..
    00712   case WE_MOUSELOOP: {
    00713     const Vehicle *v = _place_clicked_vehicle;
    00714     /*
    00715      * Check if we clicked on a vehicle
    00716      * and if the GOTO button of this window is pressed
    00717      * This is because of all open order windows WE_MOUSELOOP is called
    00718      * and if you have 3 windows open, and this check is not done
    00719      * the order is copied to the last open window instead of the
    00720      * one where GOTO is enabled
    00721      */
    00722     if (v != NULL && w->IsWidgetLowered(ORDER_WIDGET_GOTO)) {
    00723       _place_clicked_vehicle = NULL;
    00724       HandleOrderVehClick(GetVehicle(w->window_number), v, w);
    00725     }
    00726   } break;
    00727
    00728   case WE_RESIZE:
    00729     /* Update the scroll + matrix */
    00730     w->vscroll.cap = (w->widget[ORDER_WIDGET_ORDER_LIST].bottom - w->widget[ORDER_WIDGET_ORDER_LIST].top) / 10;
    00731     break;
    00732
    00733   case WE_TIMEOUT: { // handle button unclick ourselves...
    00734     // unclick all buttons except for the 'goto' button (ORDER_WIDGET_GOTO), which is 'persistent'
    00735     uint i;
    00736     for (i = 0; i < w->widget_count; i++) {
    00737       if (w->IsWidgetLowered(i) && i != ORDER_WIDGET_GOTO) {
    00738         w->RaiseWidget(i);
    00739         w->InvalidateWidget(i);
    00740       }
    00741     }
    00742   } break;
    00743   }
    00744 }
    00745
    00749 static const Widget _orders_train_widgets[] = {
    00750   {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,                STR_018B_CLOSE_WINDOW},               // ORDER_WIDGET_CLOSEBOX
    00751   {    WWT_CAPTION,   RESIZE_RIGHT,   14,    11,   398,     0,    13, STR_8829_ORDERS,         STR_018C_WINDOW_TITLE_DRAG_THIS},     // ORDER_WIDGET_CAPTION
    00752   { WWT_PUSHTXTBTN,   RESIZE_LR,      14,   338,   398,     0,    13, STR_TIMETABLE_VIEW,      STR_TIMETABLE_VIEW_TOOLTIP},          // ORDER_WIDGET_TIMETABLE_VIEW
    00753
    00754   {      WWT_PANEL,   RESIZE_RB,      14,     0,   386,    14,    75, 0x0,                     STR_8852_ORDERS_LIST_CLICK_ON_ORDER}, // ORDER_WIDGET_ORDER_LIST
    00755
    00756   {  WWT_SCROLLBAR,   RESIZE_LRB,     14,   387,   398,    14,    75, 0x0,                     STR_0190_SCROLL_BAR_SCROLLS_LIST},    // ORDER_WIDGET_SCROLLBAR
    00757
    00758   { WWT_PUSHTXTBTN,   RESIZE_TB,      14,     0,    52,    76,    87, STR_8823_SKIP,           STR_8853_SKIP_THE_CURRENT_ORDER},     // ORDER_WIDGET_SKIP
    00759   { WWT_PUSHTXTBTN,   RESIZE_TB,      14,    53,   105,    76,    87, STR_8824_DELETE,         STR_8854_DELETE_THE_HIGHLIGHTED},     // ORDER_WIDGET_DELETE
    00760   { WWT_PUSHTXTBTN,   RESIZE_TB,      14,   106,   158,    76,    87, STR_8825_NON_STOP,       STR_8855_MAKE_THE_HIGHLIGHTED_ORDER}, // ORDER_WIDGET_NON_STOP
    00761   {    WWT_TEXTBTN,   RESIZE_TB,      14,   159,   211,    76,    87, STR_8826_GO_TO,          STR_8856_INSERT_A_NEW_ORDER_BEFORE},  // ORDER_WIDGET_GOTO
    00762   { WWT_PUSHTXTBTN,   RESIZE_TB,      14,   212,   264,    76,    87, STR_FULLLOAD_OR_SERVICE, STR_NULL},                            // ORDER_WIDGET_FULL_LOAD
    00763   { WWT_PUSHTXTBTN,   RESIZE_TB,      14,   265,   319,    76,    87, STR_8828_UNLOAD,         STR_8858_MAKE_THE_HIGHLIGHTED_ORDER}, // ORDER_WIDGET_UNLOAD
    00764   { WWT_PUSHTXTBTN,   RESIZE_TB,      14,   265,   319,    76,    87, STR_REFIT,               STR_REFIT_TIP},                       // ORDER_WIDGET_REFIT
    00765   { WWT_PUSHTXTBTN,   RESIZE_TB,      14,   320,   372,    76,    87, STR_TRANSFER,            STR_MAKE_THE_HIGHLIGHTED_ORDER},      // ORDER_WIDGET_TRANSFER
    00766
    00767   { WWT_PUSHIMGBTN,   RESIZE_TB,      14,   373,   386,    76,    87, SPR_SHARED_ORDERS_ICON,  STR_VEH_WITH_SHARED_ORDERS_LIST_TIP}, // ORDER_WIDGET_SHARED_ORDER_LIST
    00768
    00769   {      WWT_PANEL,   RESIZE_RTB,     14,   387,   386,    76,    87, 0x0,                     STR_NULL},                            // ORDER_WIDGET_RESIZE_BAR
    00770
    00771   {  WWT_RESIZEBOX,   RESIZE_LRTB,    14,   387,   398,    76,    87, 0x0,                     STR_RESIZE_BUTTON},                   // ORDER_WIDGET_RESIZE
    00772   {   WIDGETS_END},
    00773 };
    00774
    00775 static const WindowDesc _orders_train_desc = {
    00776   WDP_AUTO, WDP_AUTO, 399, 88, 399, 88,
    00777   WC_VEHICLE_ORDERS,WC_VEHICLE_VIEW,
    00778   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE,
    00779   _orders_train_widgets,
    00780   OrdersWndProc
    00781 };
    00782
    00786 static const Widget _orders_widgets[] = {
    00787   {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,                STR_018B_CLOSE_WINDOW},               // ORDER_WIDGET_CLOSEBOX
    00788   {    WWT_CAPTION,   RESIZE_RIGHT,   14,    11,   409,     0,    13, STR_8829_ORDERS,         STR_018C_WINDOW_TITLE_DRAG_THIS},     // ORDER_WIDGET_CAPTION
    00789   { WWT_PUSHTXTBTN,   RESIZE_LR,      14,   349,   409,     0,    13, STR_TIMETABLE_VIEW,      STR_TIMETABLE_VIEW_TOOLTIP},          // ORDER_WIDGET_TIMETABLE_VIEW
    00790
    00791   {      WWT_PANEL,   RESIZE_RB,      14,     0,   397,    14,    75, 0x0,                     STR_8852_ORDERS_LIST_CLICK_ON_ORDER}, // ORDER_WIDGET_ORDER_LIST
    00792
    00793   {  WWT_SCROLLBAR,   RESIZE_LRB,     14,   398,   409,    14,    75, 0x0,                     STR_0190_SCROLL_BAR_SCROLLS_LIST},    // ORDER_WIDGET_SCROLLBAR
    00794
    00795   { WWT_PUSHTXTBTN,   RESIZE_TB,      14,     0,    63,    76,    87, STR_8823_SKIP,           STR_8853_SKIP_THE_CURRENT_ORDER},     // ORDER_WIDGET_SKIP
    00796   { WWT_PUSHTXTBTN,   RESIZE_TB,      14,    64,   128,    76,    87, STR_8824_DELETE,         STR_8854_DELETE_THE_HIGHLIGHTED},     // ORDER_WIDGET_DELETE
    00797   {      WWT_EMPTY,   RESIZE_TB,      14,     0,     0,    76,    87, 0x0,                     0x0},                                 // ORDER_WIDGET_NON_STOP
    00798   {    WWT_TEXTBTN,   RESIZE_TB,      14,   129,   192,    76,    87, STR_8826_GO_TO,          STR_8856_INSERT_A_NEW_ORDER_BEFORE},  // ORDER_WIDGET_GOTO
    00799   { WWT_PUSHTXTBTN,   RESIZE_TB,      14,   193,   256,    76,    87, STR_FULLLOAD_OR_SERVICE, STR_NULL},                            // ORDER_WIDGET_FULL_LOAD
    00800   { WWT_PUSHTXTBTN,   RESIZE_TB,      14,   257,   319,    76,    87, STR_8828_UNLOAD,         STR_8858_MAKE_THE_HIGHLIGHTED_ORDER}, // ORDER_WIDGET_UNLOAD
    00801   { WWT_PUSHTXTBTN,   RESIZE_TB,      14,   257,   319,    76,    87, STR_REFIT,               STR_REFIT_TIP},                       // ORDER_WIDGET_REFIT
    00802   { WWT_PUSHTXTBTN,   RESIZE_TB,      14,   320,   383,    76,    87, STR_TRANSFER,            STR_MAKE_THE_HIGHLIGHTED_ORDER},      // ORDER_WIDGET_TRANSFER
    00803
    00804   { WWT_PUSHIMGBTN,   RESIZE_TB,      14,   384,   397,    76,    87, SPR_SHARED_ORDERS_ICON,  STR_VEH_WITH_SHARED_ORDERS_LIST_TIP}, // ORDER_WIDGET_SHARED_ORDER_LIST
    00805
    00806   {      WWT_PANEL,   RESIZE_RTB,     14,   397,   396,    76,    87, 0x0,                     STR_NULL},                            // ORDER_WIDGET_RESIZE_BAR
    00807
    00808   {  WWT_RESIZEBOX,   RESIZE_LRTB,    14,   398,   409,    76,    87, 0x0,                     STR_RESIZE_BUTTON},                   // ORDER_WIDGET_RESIZE
    00809   {   WIDGETS_END},
    00810 };
    00811
    00812 static const WindowDesc _orders_desc = {
    00813   WDP_AUTO, WDP_AUTO, 410, 88, 410, 88,
    00814   WC_VEHICLE_ORDERS,WC_VEHICLE_VIEW,
    00815   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE,
    00816   _orders_widgets,
    00817   OrdersWndProc
    00818 };
    00819
    00823 static const Widget _other_orders_widgets[] = {
    00824   {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,           STR_018B_CLOSE_WINDOW},               // ORDER_WIDGET_CLOSEBOX
    00825   {    WWT_CAPTION,   RESIZE_RIGHT,   14,    11,   331,     0,    13, STR_A00B_ORDERS,    STR_018C_WINDOW_TITLE_DRAG_THIS},     // ORDER_WIDGET_CAPTION
    00826   { WWT_PUSHTXTBTN,   RESIZE_LR,      14,   271,   331,     0,    13, STR_TIMETABLE_VIEW, STR_TIMETABLE_VIEW_TOOLTIP},          // ORDER_WIDGET_TIMETABLE_VIEW
    00827
    00828   {      WWT_PANEL,   RESIZE_RB,      14,     0,   319,    14,    75, 0x0,                STR_8852_ORDERS_LIST_CLICK_ON_ORDER}, // ORDER_WIDGET_ORDER_LIST
    00829
    00830   {  WWT_SCROLLBAR,   RESIZE_LRB,     14,   320,   331,    14,    75, 0x0,                STR_0190_SCROLL_BAR_SCROLLS_LIST},    // ORDER_WIDGET_SCROLLBAR
    00831
    00832   {      WWT_EMPTY,   RESIZE_NONE,    14,     0,   319,    76,    87, 0x0,                STR_NULL},                            // ORDER_WIDGET_SKIP
    00833   {      WWT_EMPTY,   RESIZE_NONE,    14,     0,   319,    76,    87, 0x0,                STR_NULL},                            // ORDER_WIDGET_DELETE
    00834   {      WWT_EMPTY,   RESIZE_NONE,    14,     0,   319,    76,    87, 0x0,                STR_NULL},                            // ORDER_WIDGET_NON_STOP
    00835   {      WWT_EMPTY,   RESIZE_NONE,    14,     0,   319,    76,    87, 0x0,                STR_NULL},                            // ORDER_WIDGET_GOTO
    00836   {      WWT_EMPTY,   RESIZE_NONE,    14,     0,   319,    76,    87, 0x0,                STR_NULL},                            // ORDER_WIDGET_FULL_LOAD
    00837   {      WWT_EMPTY,   RESIZE_NONE,    14,     0,   319,    76,    87, 0x0,                STR_NULL},                            // ORDER_WIDGET_UNLOAD
    00838   {      WWT_EMPTY,   RESIZE_NONE,    14,     0,   319,    76,    87, 0x0,                STR_NULL},                            // ORDER_WIDGET_REFIT
    00839   {      WWT_EMPTY,   RESIZE_NONE,    14,     0,   319,    76,    87, 0x0,                STR_NULL},                            // ORDER_WIDGET_TRANSFER
    00840
    00841   {      WWT_EMPTY,   RESIZE_NONE,    14,     0,   319,    76,    87, 0x0,                STR_NULL},                            // ORDER_WIDGET_SHARED_ORDER_LIST
    00842
    00843   {      WWT_PANEL,   RESIZE_RTB,     14,     0,   319,    76,    87, 0x0,                STR_NULL},                            // ORDER_WIDGET_RESIZE_BAR
    00844
    00845   {  WWT_RESIZEBOX,   RESIZE_LRTB,    14,   320,   331,    76,    87, 0x0,                STR_RESIZE_BUTTON},                   // ORDER_WIDGET_RESIZE
    00846   {   WIDGETS_END},
    00847 };
    00848
    00849 static const WindowDesc _other_orders_desc = {
    00850   WDP_AUTO, WDP_AUTO, 332, 88, 332, 88,
    00851   WC_VEHICLE_ORDERS,WC_VEHICLE_VIEW,
    00852   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
    00853   _other_orders_widgets,
    00854   OrdersWndProc
    00855 };
    00856
    00857 void ShowOrdersWindow(const Vehicle *v)
    00858 {
    00859   Window *w;
    00860   VehicleID veh = v->index;
    00861
    00862   DeleteWindowById(WC_VEHICLE_ORDERS, veh);
    00863   DeleteWindowById(WC_VEHICLE_DETAILS, veh);
    00864
    00865   if (v->owner != _local_player) {
    00866     w = AllocateWindowDescFront(&_other_orders_desc, veh);
    00867   } else {
    00868     w = AllocateWindowDescFront((v->type == VEH_TRAIN) ? &_orders_train_desc : &_orders_desc, veh);
    00869   }
    00870
    00871   if (w != NULL) {
    00872     w->caption_color = v->owner;
    00873     w->vscroll.cap = 6;
    00874     w->resize.step_height = 10;
    00875     WP(w, order_d).sel = -1;
    00876   }
    00877 }