order_gui.cpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include "stdafx.h"
00013 #include "command_func.h"
00014 #include "viewport_func.h"
00015 #include "depot_map.h"
00016 #include "vehicle_gui.h"
00017 #include "roadveh.h"
00018 #include "timetable.h"
00019 #include "strings_func.h"
00020 #include "window_func.h"
00021 #include "company_func.h"
00022 #include "widgets/dropdown_func.h"
00023 #include "textbuf_gui.h"
00024 #include "string_func.h"
00025 #include "tilehighlight_func.h"
00026 #include "network/network.h"
00027 #include "station_base.h"
00028 #include "waypoint_base.h"
00029 #include "core/geometry_func.hpp"
00030 #include "hotkeys.h"
00031 
00032 #include "table/strings.h"
00033 
00035 enum OrderWindowWidgets {
00036   ORDER_WIDGET_CAPTION,
00037   ORDER_WIDGET_TIMETABLE_VIEW,
00038   ORDER_WIDGET_ORDER_LIST,
00039   ORDER_WIDGET_SCROLLBAR,
00040   ORDER_WIDGET_SKIP,
00041   ORDER_WIDGET_DELETE,
00042   ORDER_WIDGET_STOP_SHARING,
00043   ORDER_WIDGET_NON_STOP,
00044   ORDER_WIDGET_GOTO,
00045   ORDER_WIDGET_FULL_LOAD,
00046   ORDER_WIDGET_UNLOAD,
00047   ORDER_WIDGET_REFIT,
00048   ORDER_WIDGET_SERVICE,
00049   ORDER_WIDGET_COND_VARIABLE,
00050   ORDER_WIDGET_COND_COMPARATOR,
00051   ORDER_WIDGET_COND_VALUE,
00052   ORDER_WIDGET_SEL_TOP_LEFT,   
00053   ORDER_WIDGET_SEL_TOP_MIDDLE, 
00054   ORDER_WIDGET_SEL_TOP_RIGHT,  
00055   ORDER_WIDGET_SEL_TOP_ROW,    
00056   ORDER_WIDGET_SEL_BOTTOM_MIDDLE, 
00057   ORDER_WIDGET_SHARED_ORDER_LIST,
00058 };
00059 
00061 static const StringID _station_load_types[][5] = {
00062   {
00063     STR_EMPTY,
00064     INVALID_STRING_ID,
00065     STR_ORDER_FULL_LOAD,
00066     STR_ORDER_FULL_LOAD_ANY,
00067     STR_ORDER_NO_LOAD,
00068   }, {
00069     STR_ORDER_UNLOAD,
00070     INVALID_STRING_ID,
00071     STR_ORDER_UNLOAD_FULL_LOAD,
00072     STR_ORDER_UNLOAD_FULL_LOAD_ANY,
00073     STR_ORDER_UNLOAD_NO_LOAD,
00074   }, {
00075     STR_ORDER_TRANSFER,
00076     INVALID_STRING_ID,
00077     STR_ORDER_TRANSFER_FULL_LOAD,
00078     STR_ORDER_TRANSFER_FULL_LOAD_ANY,
00079     STR_ORDER_TRANSFER_NO_LOAD,
00080   }, {
00081     /* Unload and transfer do not work together. */
00082     INVALID_STRING_ID,
00083     INVALID_STRING_ID,
00084     INVALID_STRING_ID,
00085     INVALID_STRING_ID,
00086   }, {
00087     STR_ORDER_NO_UNLOAD,
00088     INVALID_STRING_ID,
00089     STR_ORDER_NO_UNLOAD_FULL_LOAD,
00090     STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY,
00091     INVALID_STRING_ID,
00092   }
00093 };
00094 
00095 static const StringID _order_non_stop_drowdown[] = {
00096   STR_ORDER_GO_TO,
00097   STR_ORDER_GO_NON_STOP_TO,
00098   STR_ORDER_GO_VIA,
00099   STR_ORDER_GO_NON_STOP_VIA,
00100   INVALID_STRING_ID
00101 };
00102 
00103 static const StringID _order_full_load_drowdown[] = {
00104   STR_ORDER_DROP_LOAD_IF_POSSIBLE,
00105   STR_EMPTY,
00106   STR_ORDER_DROP_FULL_LOAD_ALL,
00107   STR_ORDER_DROP_FULL_LOAD_ANY,
00108   STR_ORDER_DROP_NO_LOADING,
00109   INVALID_STRING_ID
00110 };
00111 
00112 static const StringID _order_unload_drowdown[] = {
00113   STR_ORDER_DROP_UNLOAD_IF_ACCEPTED,
00114   STR_ORDER_DROP_UNLOAD,
00115   STR_ORDER_DROP_TRANSFER,
00116   STR_EMPTY,
00117   STR_ORDER_DROP_NO_UNLOADING,
00118   INVALID_STRING_ID
00119 };
00120 
00121 static const StringID _order_goto_dropdown[] = {
00122   STR_ORDER_GO_TO,
00123   STR_ORDER_GO_TO_NEAREST_DEPOT,
00124   STR_ORDER_CONDITIONAL,
00125   STR_ORDER_SHARE,
00126   INVALID_STRING_ID
00127 };
00128 
00129 static const StringID _order_goto_dropdown_aircraft[] = {
00130   STR_ORDER_GO_TO,
00131   STR_ORDER_GO_TO_NEAREST_HANGAR,
00132   STR_ORDER_CONDITIONAL,
00133   STR_ORDER_SHARE,
00134   INVALID_STRING_ID
00135 };
00136 
00137 static const StringID _order_conditional_variable[] = {
00138   STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE,
00139   STR_ORDER_CONDITIONAL_RELIABILITY,
00140   STR_ORDER_CONDITIONAL_MAX_SPEED,
00141   STR_ORDER_CONDITIONAL_AGE,
00142   STR_ORDER_CONDITIONAL_REQUIRES_SERVICE,
00143   STR_ORDER_CONDITIONAL_UNCONDITIONALLY,
00144   INVALID_STRING_ID,
00145 };
00146 
00147 static const StringID _order_conditional_condition[] = {
00148   STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS,
00149   STR_ORDER_CONDITIONAL_COMPARATOR_NOT_EQUALS,
00150   STR_ORDER_CONDITIONAL_COMPARATOR_LESS_THAN,
00151   STR_ORDER_CONDITIONAL_COMPARATOR_LESS_EQUALS,
00152   STR_ORDER_CONDITIONAL_COMPARATOR_MORE_THAN,
00153   STR_ORDER_CONDITIONAL_COMPARATOR_MORE_EQUALS,
00154   STR_ORDER_CONDITIONAL_COMPARATOR_IS_TRUE,
00155   STR_ORDER_CONDITIONAL_COMPARATOR_IS_FALSE,
00156   INVALID_STRING_ID,
00157 };
00158 
00159 extern uint ConvertSpeedToDisplaySpeed(uint speed);
00160 extern uint ConvertDisplaySpeedToSpeed(uint speed);
00161 
00162 static const StringID _order_depot_action_dropdown[] = {
00163   STR_ORDER_DROP_GO_ALWAYS_DEPOT,
00164   STR_ORDER_DROP_SERVICE_DEPOT,
00165   STR_ORDER_DROP_HALT_DEPOT,
00166   INVALID_STRING_ID
00167 };
00168 
00169 static int DepotActionStringIndex(const Order *order)
00170 {
00171   if (order->GetDepotActionType() & ODATFB_HALT) {
00172     return DA_STOP;
00173   } else if (order->GetDepotOrderType() & ODTFB_SERVICE) {
00174     return DA_SERVICE;
00175   } else {
00176     return DA_ALWAYS_GO;
00177   }
00178 }
00179 
00192 void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int y, bool selected, bool timetable, int left, int middle, int right)
00193 {
00194   bool rtl = _current_text_dir == TD_RTL;
00195 
00196   SpriteID sprite = rtl ? SPR_ARROW_LEFT : SPR_ARROW_RIGHT;
00197   Dimension sprite_size = GetSpriteSize(sprite);
00198   if (v->cur_order_index == order_index) {
00199     DrawSprite(sprite, PAL_NONE, rtl ? right - sprite_size.width : left, y + ((int)FONT_HEIGHT_NORMAL - (int)sprite_size.height) / 2);
00200   }
00201 
00202   TextColour colour = TC_BLACK;
00203   if (order->IsType(OT_AUTOMATIC)) {
00204     colour = (selected ? TC_SILVER : TC_GREY) | TC_NO_SHADE;
00205   } else if (selected) {
00206     colour = TC_WHITE;
00207   }
00208 
00209   SetDParam(0, order_index + 1);
00210   DrawString(left, rtl ? right - sprite_size.width - 3 : middle, y, STR_ORDER_INDEX, colour, SA_RIGHT | SA_FORCE);
00211 
00212   SetDParam(5, STR_EMPTY);
00213 
00214   switch (order->GetType()) {
00215     case OT_DUMMY:
00216       SetDParam(0, STR_INVALID_ORDER);
00217       SetDParam(1, order->GetDestination());
00218       break;
00219 
00220     case OT_AUTOMATIC:
00221       SetDParam(0, STR_ORDER_GO_TO_STATION);
00222       SetDParam(1, STR_ORDER_GO_TO);
00223       SetDParam(2, order->GetDestination());
00224       SetDParam(3, timetable ? STR_EMPTY : STR_ORDER_AUTOMATIC);
00225       break;
00226 
00227     case OT_GOTO_STATION: {
00228       OrderLoadFlags load = order->GetLoadType();
00229       OrderUnloadFlags unload = order->GetUnloadType();
00230 
00231       SetDParam(0, STR_ORDER_GO_TO_STATION);
00232       SetDParam(1, STR_ORDER_GO_TO + (v->IsGroundVehicle() ? order->GetNonStopType() : 0));
00233       SetDParam(2, order->GetDestination());
00234 
00235       if (timetable) {
00236         SetDParam(3, STR_EMPTY);
00237 
00238         if (order->wait_time > 0) {
00239           SetDParam(5, STR_TIMETABLE_STAY_FOR);
00240           SetTimetableParams(6, 7, order->wait_time);
00241         }
00242       } else {
00243         SetDParam(3, (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) ? STR_EMPTY : _station_load_types[unload][load]);
00244         if (v->type == VEH_TRAIN && (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) == 0) {
00245           SetDParam(5, order->GetStopLocation() + STR_ORDER_STOP_LOCATION_NEAR_END);
00246         }
00247       }
00248       break;
00249     }
00250 
00251     case OT_GOTO_DEPOT:
00252       if (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) {
00253         SetDParam(0, STR_ORDER_GO_TO_NEAREST_DEPOT_FORMAT);
00254         if (v->type == VEH_AIRCRAFT) {
00255           SetDParam(2, STR_ORDER_NEAREST_HANGAR);
00256           SetDParam(3, STR_EMPTY);
00257         } else {
00258           SetDParam(2, STR_ORDER_NEAREST_DEPOT);
00259           SetDParam(3, STR_ORDER_TRAIN_DEPOT + v->type);
00260         }
00261       } else {
00262         SetDParam(0, STR_ORDER_GO_TO_DEPOT_FORMAT);
00263         SetDParam(2, v->type);
00264         SetDParam(3, order->GetDestination());
00265       }
00266 
00267       if (order->GetDepotOrderType() & ODTFB_SERVICE) {
00268         SetDParam(1, (order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_ORDER_SERVICE_NON_STOP_AT : STR_ORDER_SERVICE_AT);
00269       } else {
00270         SetDParam(1, (order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_ORDER_GO_NON_STOP_TO : STR_ORDER_GO_TO);
00271       }
00272 
00273       if (!timetable && (order->GetDepotActionType() & ODATFB_HALT)) {
00274         SetDParam(5, STR_ORDER_STOP_ORDER);
00275       }
00276 
00277       if (!timetable && order->IsRefit()) {
00278         SetDParam(5, (order->GetDepotActionType() & ODATFB_HALT) ? STR_ORDER_REFIT_STOP_ORDER : STR_ORDER_REFIT_ORDER);
00279         SetDParam(6, CargoSpec::Get(order->GetRefitCargo())->name);
00280       }
00281       break;
00282 
00283     case OT_GOTO_WAYPOINT:
00284       SetDParam(0, (order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_ORDER_GO_NON_STOP_TO_WAYPOINT : STR_ORDER_GO_TO_WAYPOINT);
00285       SetDParam(1, order->GetDestination());
00286       break;
00287 
00288     case OT_CONDITIONAL:
00289       SetDParam(1, order->GetConditionSkipToOrder() + 1);
00290       if (order->GetConditionVariable() == OCV_UNCONDITIONALLY) {
00291         SetDParam(0, STR_ORDER_CONDITIONAL_UNCONDITIONAL);
00292       } else {
00293         OrderConditionComparator occ = order->GetConditionComparator();
00294         SetDParam(0, (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) ? STR_ORDER_CONDITIONAL_TRUE_FALSE : STR_ORDER_CONDITIONAL_NUM);
00295         SetDParam(2, STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + order->GetConditionVariable());
00296         SetDParam(3, STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS + occ);
00297 
00298         uint value = order->GetConditionValue();
00299         if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value);
00300         SetDParam(4, value);
00301       }
00302 
00303       if (timetable && order->wait_time > 0) {
00304         SetDParam(5, STR_TIMETABLE_AND_TRAVEL_FOR);
00305         SetTimetableParams(6, 7, order->wait_time);
00306       } else {
00307         SetDParam(5, STR_EMPTY);
00308       }
00309       break;
00310 
00311     default: NOT_REACHED();
00312   }
00313 
00314   DrawString(rtl ? left : middle, rtl ? middle : right, y, STR_ORDER_TEXT, colour);
00315 }
00316 
00317 
00318 static Order GetOrderCmdFromTile(const Vehicle *v, TileIndex tile)
00319 {
00320   Order order;
00321   order.next  = NULL;
00322   order.index = 0;
00323 
00324   /* check depot first */
00325   if (_settings_game.order.gotodepot) {
00326     switch (GetTileType(tile)) {
00327       case MP_RAILWAY:
00328         if (v->type == VEH_TRAIN && IsTileOwner(tile, _local_company)) {
00329           if (IsRailDepot(tile)) {
00330             order.MakeGoToDepot(GetDepotIndex(tile), ODTFB_PART_OF_ORDERS,
00331                 _settings_client.gui.new_nonstop ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
00332             if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
00333             return order;
00334           }
00335         }
00336         break;
00337 
00338       case MP_ROAD:
00339         if (IsRoadDepot(tile) && v->type == VEH_ROAD && IsTileOwner(tile, _local_company)) {
00340           order.MakeGoToDepot(GetDepotIndex(tile), ODTFB_PART_OF_ORDERS,
00341               _settings_client.gui.new_nonstop ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
00342           if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
00343           return order;
00344         }
00345         break;
00346 
00347       case MP_STATION:
00348         if (v->type != VEH_AIRCRAFT) break;
00349         if (IsHangar(tile) && IsTileOwner(tile, _local_company)) {
00350           order.MakeGoToDepot(GetStationIndex(tile), ODTFB_PART_OF_ORDERS, ONSF_STOP_EVERYWHERE);
00351           if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
00352           return order;
00353         }
00354         break;
00355 
00356       case MP_WATER:
00357         if (v->type != VEH_SHIP) break;
00358         if (IsShipDepot(tile) && IsTileOwner(tile, _local_company)) {
00359           order.MakeGoToDepot(GetDepotIndex(tile), ODTFB_PART_OF_ORDERS, ONSF_STOP_EVERYWHERE);
00360           if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
00361           return order;
00362         }
00363         break;
00364 
00365       default:
00366         break;
00367     }
00368   }
00369 
00370   /* check waypoint */
00371   if (IsRailWaypointTile(tile) &&
00372       v->type == VEH_TRAIN &&
00373       IsTileOwner(tile, _local_company)) {
00374     order.MakeGoToWaypoint(Waypoint::GetByTile(tile)->index);
00375     if (_settings_client.gui.new_nonstop != _ctrl_pressed) order.SetNonStopType(ONSF_NO_STOP_AT_ANY_STATION);
00376     return order;
00377   }
00378 
00379   if ((IsBuoyTile(tile) && v->type == VEH_SHIP) || (IsRailWaypointTile(tile) && v->type == VEH_TRAIN)) {
00380     order.MakeGoToWaypoint(GetStationIndex(tile));
00381     return order;
00382   }
00383 
00384   if (IsTileType(tile, MP_STATION)) {
00385     StationID st_index = GetStationIndex(tile);
00386     const Station *st = Station::Get(st_index);
00387 
00388     if (st->owner == _local_company || st->owner == OWNER_NONE) {
00389       byte facil;
00390       (facil = FACIL_DOCK, v->type == VEH_SHIP) ||
00391       (facil = FACIL_TRAIN, v->type == VEH_TRAIN) ||
00392       (facil = FACIL_AIRPORT, v->type == VEH_AIRCRAFT) ||
00393       (facil = FACIL_BUS_STOP, v->type == VEH_ROAD && RoadVehicle::From(v)->IsBus()) ||
00394       (facil = FACIL_TRUCK_STOP, 1);
00395       if (st->facilities & facil) {
00396         order.MakeGoToStation(st_index);
00397         if (_ctrl_pressed) order.SetLoadType(OLF_FULL_LOAD_ANY);
00398         if (_settings_client.gui.new_nonstop && v->IsGroundVehicle()) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
00399         order.SetStopLocation(v->type == VEH_TRAIN ? (OrderStopLocation)(_settings_client.gui.stop_location) : OSL_PLATFORM_FAR_END);
00400         return order;
00401       }
00402     }
00403   }
00404 
00405   /* not found */
00406   order.Free();
00407   return order;
00408 }
00409 
00450 struct OrdersWindow : public Window {
00451 private:
00453   enum OrderPlaceObjectState {
00454     OPOS_GOTO,
00455     OPOS_CONDITIONAL,
00456     OPOS_SHARE,
00457   };
00458 
00460   enum DisplayPane {
00461     /* ORDER_WIDGET_SEL_TOP_LEFT */
00462     DP_LEFT_NONSTOP    = 0, 
00463     DP_LEFT_CONDVAR    = 1, 
00464 
00465     /* ORDER_WIDGET_SEL_TOP_MIDDLE */
00466     DP_MIDDLE_LOAD     = 0, 
00467     DP_MIDDLE_REFIT    = 1, 
00468     DP_MIDDLE_COMPARE  = 2, 
00469 
00470     /* ORDER_WIDGET_SEL_TOP_RIGHT */
00471     DP_RIGHT_UNLOAD    = 0, 
00472     DP_RIGHT_SERVICE   = 1, 
00473     DP_RIGHT_CONDVAL   = 2, 
00474 
00475     /* ORDER_WIDGET_SEL_TOP_ROW */
00476     DP_ROW_LOAD        = 0, 
00477     DP_ROW_DEPOT       = 1, 
00478     DP_ROW_CONDITIONAL = 2, 
00479 
00480     /* ORDER_WIDGET_SEL_BOTTOM_MIDDLE */
00481     DP_BOTTOM_MIDDLE_DELETE       = 0, 
00482     DP_BOTTOM_MIDDLE_STOP_SHARING = 1, 
00483   };
00484 
00485   int selected_order;
00486   OrderID order_over;     
00487   OrderPlaceObjectState goto_type;
00488   const Vehicle *vehicle; 
00489   Scrollbar *vscroll;
00490 
00496   int OrderGetSel() const
00497   {
00498     int num = this->selected_order;
00499     return (num >= 0 && num < vehicle->GetNumOrders()) ? num : vehicle->GetNumOrders();
00500   }
00501 
00510   int GetOrderFromPt(int y)
00511   {
00512     NWidgetBase *nwid = this->GetWidget<NWidgetBase>(ORDER_WIDGET_ORDER_LIST);
00513     int sel = (y - nwid->pos_y - WD_FRAMERECT_TOP) / nwid->resize_y; // Selected line in the ORDER_WIDGET_ORDER_LIST panel.
00514 
00515     if ((uint)sel >= this->vscroll->GetCapacity()) return INVALID_ORDER;
00516 
00517     sel += this->vscroll->GetPosition();
00518 
00519     return (sel <= vehicle->GetNumOrders() && sel >= 0) ? sel : INVALID_ORDER;
00520   }
00521 
00526   void OrderClick_Goto(int i)
00527   {
00528     this->SetWidgetDirty(ORDER_WIDGET_GOTO);
00529     this->ToggleWidgetLoweredState(ORDER_WIDGET_GOTO);
00530     if (this->IsWidgetLowered(ORDER_WIDGET_GOTO)) {
00531       SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, HT_RECT | HT_VEHICLE, this);
00532       this->goto_type = OPOS_GOTO;
00533     } else {
00534       ResetObjectToPlace();
00535     }
00536   }
00537 
00542   void OrderClick_FullLoad(int load_type)
00543   {
00544     VehicleOrderID sel_ord = this->OrderGetSel();
00545     const Order *order = this->vehicle->GetOrder(sel_ord);
00546 
00547     if (order == NULL || order->GetLoadType() == load_type) return;
00548 
00549     if (load_type < 0) {
00550       load_type = order->GetLoadType() == OLF_LOAD_IF_POSSIBLE ? OLF_FULL_LOAD_ANY : OLF_LOAD_IF_POSSIBLE;
00551     }
00552     DoCommandP(this->vehicle->tile, this->vehicle->index + (sel_ord << 20), MOF_LOAD | (load_type << 4), CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER));
00553   }
00554 
00558   void OrderHotkey_NoLoad(int i)
00559   {
00560     this->OrderClick_FullLoad(OLFB_NO_LOAD);
00561   }
00562 
00566   void OrderClick_Service(int i)
00567   {
00568     VehicleOrderID sel_ord = this->OrderGetSel();
00569 
00570     if (i < 0) {
00571       const Order *order = this->vehicle->GetOrder(sel_ord);
00572       if (order == NULL) return;
00573       i = (order->GetDepotOrderType() & ODTFB_SERVICE) ? DA_ALWAYS_GO : DA_SERVICE;
00574     }
00575     DoCommandP(this->vehicle->tile, this->vehicle->index + (sel_ord << 20), MOF_DEPOT_ACTION | (i << 4), CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER));
00576   }
00577 
00582   void OrderClick_NearestDepot(int i)
00583   {
00584     Order order;
00585     order.next = NULL;
00586     order.index = 0;
00587     order.MakeGoToDepot(0, ODTFB_PART_OF_ORDERS,
00588         _settings_client.gui.new_nonstop && this->vehicle->IsGroundVehicle() ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
00589     order.SetDepotActionType(ODATFB_NEAREST_DEPOT);
00590 
00591     DoCommandP(this->vehicle->tile, this->vehicle->index + (this->OrderGetSel() << 20), order.Pack(), CMD_INSERT_ORDER | CMD_MSG(STR_ERROR_CAN_T_INSERT_NEW_ORDER));
00592   }
00593 
00598   void OrderClick_Conditional(int i)
00599   {
00600     this->LowerWidget(ORDER_WIDGET_GOTO);
00601     this->SetWidgetDirty(ORDER_WIDGET_GOTO);
00602     SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, HT_NONE, this);
00603     this->goto_type = OPOS_CONDITIONAL;
00604   }
00605 
00610   void OrderClick_Share(int i)
00611   {
00612     this->LowerWidget(ORDER_WIDGET_GOTO);
00613     this->SetWidgetDirty(ORDER_WIDGET_GOTO);
00614     SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, HT_VEHICLE, this);
00615     this->goto_type = OPOS_SHARE;
00616   }
00617 
00621   void OrderClick_Unload(int unload_type)
00622   {
00623     VehicleOrderID sel_ord = this->OrderGetSel();
00624     const Order *order = this->vehicle->GetOrder(sel_ord);
00625 
00626     if (order == NULL || order->GetUnloadType() == unload_type) return;
00627 
00628     if (unload_type < 0) {
00629       unload_type = order->GetUnloadType() == OUF_UNLOAD_IF_POSSIBLE ? OUFB_UNLOAD : OUF_UNLOAD_IF_POSSIBLE;
00630     }
00631 
00632     DoCommandP(this->vehicle->tile, this->vehicle->index + (sel_ord << 20), MOF_UNLOAD | (unload_type << 4), CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER));
00633 
00634     /* Transfer orders with leave empty as default */
00635     if (unload_type == OUFB_TRANSFER) {
00636       DoCommandP(this->vehicle->tile, this->vehicle->index + (sel_ord << 20), MOF_LOAD | (OLFB_NO_LOAD << 4), CMD_MODIFY_ORDER);
00637       this->SetWidgetDirty(ORDER_WIDGET_FULL_LOAD);
00638     }
00639   }
00640 
00644   void OrderHotkey_Transfer(int i)
00645   {
00646     this->OrderClick_Unload(OUFB_TRANSFER);
00647   }
00648 
00652   void OrderHotkey_NoUnload(int i)
00653   {
00654     this->OrderClick_Unload(OUFB_NO_UNLOAD);
00655   }
00656 
00661   void OrderClick_Nonstop(int non_stop)
00662   {
00663     if (!this->vehicle->IsGroundVehicle()) return;
00664 
00665     VehicleOrderID sel_ord = this->OrderGetSel();
00666     const Order *order = this->vehicle->GetOrder(sel_ord);
00667 
00668     if (order == NULL || order->GetNonStopType() == non_stop) return;
00669 
00670     /* Keypress if negative, so 'toggle' to the next */
00671     if (non_stop < 0) {
00672       non_stop = order->GetNonStopType() ^ ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS;
00673     }
00674 
00675     this->SetWidgetDirty(ORDER_WIDGET_NON_STOP);
00676     DoCommandP(this->vehicle->tile, this->vehicle->index + (sel_ord << 20), MOF_NON_STOP | non_stop << 4,  CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER));
00677   }
00678 
00684   void OrderClick_Skip(int i)
00685   {
00686     /* Don't skip when there's nothing to skip */
00687     if (_ctrl_pressed && this->vehicle->cur_order_index == this->OrderGetSel()) return;
00688     if (this->vehicle->GetNumOrders() <= 1) return;
00689 
00690     DoCommandP(this->vehicle->tile, this->vehicle->index, _ctrl_pressed ? this->OrderGetSel() : ((this->vehicle->cur_order_index + 1) % this->vehicle->GetNumOrders()),
00691         CMD_SKIP_TO_ORDER | CMD_MSG(_ctrl_pressed ? STR_ERROR_CAN_T_SKIP_TO_ORDER : STR_ERROR_CAN_T_SKIP_ORDER));
00692   }
00693 
00698   void OrderClick_Delete(int i)
00699   {
00700     /* When networking, move one order lower */
00701     int selected = this->selected_order + (int)_networking;
00702 
00703     if (DoCommandP(this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), CMD_DELETE_ORDER | CMD_MSG(STR_ERROR_CAN_T_DELETE_THIS_ORDER))) {
00704       this->selected_order = selected >= this->vehicle->GetNumOrders() ? -1 : selected;
00705       this->UpdateButtonState();
00706     }
00707   }
00708 
00716   void OrderClick_StopSharing(int i)
00717   {
00718     /* Don't try to stop sharing orders if 'End of Shared Orders' isn't selected. */
00719     if (!this->vehicle->IsOrderListShared() || this->selected_order != this->vehicle->GetNumOrders()) return;
00720     /* If Ctrl is pressed, delete the order list as if we clicked the 'Delete' button. */
00721     if (_ctrl_pressed) {
00722       this->OrderClick_Delete(0);
00723       return;
00724     }
00725 
00726     /* Get another vehicle that share orders with this vehicle. */
00727     Vehicle *other_shared = (this->vehicle->FirstShared() == this->vehicle) ? this->vehicle->NextShared() : this->vehicle->PreviousShared();
00728     /* Copy the order list of the other vehicle. */
00729     if (DoCommandP(this->vehicle->tile, this->vehicle->index | CO_COPY << 30, other_shared->index, CMD_CLONE_ORDER | CMD_MSG(STR_ERROR_CAN_T_STOP_SHARING_ORDER_LIST))) {
00730       this->UpdateButtonState();
00731     }
00732   }
00733 
00739   void OrderClick_Refit(int i)
00740   {
00741     if (_ctrl_pressed) {
00742       /* Cancel refitting */
00743       DoCommandP(this->vehicle->tile, this->vehicle->index, (this->OrderGetSel() << 16) | (CT_NO_REFIT << 8) | CT_NO_REFIT, CMD_ORDER_REFIT);
00744     } else {
00745       ShowVehicleRefitWindow(this->vehicle, this->OrderGetSel(), this);
00746     }
00747   }
00748 
00749 public:
00750   OrdersWindow(const WindowDesc *desc, const Vehicle *v) : Window()
00751   {
00752     this->vehicle = v;
00753 
00754     this->CreateNestedTree(desc);
00755     this->vscroll = this->GetScrollbar(ORDER_WIDGET_SCROLLBAR);
00756     this->FinishInitNested(desc, v->index);
00757 
00758     this->selected_order = -1;
00759     this->order_over = INVALID_ORDER;
00760     this->owner = v->owner;
00761 
00762     if (_settings_client.gui.quick_goto && v->owner == _local_company) {
00763       /* If there are less than 2 station, make Go To active. */
00764       int station_orders = 0;
00765       const Order *order;
00766       FOR_VEHICLE_ORDERS(v, order) {
00767         if (order->IsType(OT_GOTO_STATION)) station_orders++;
00768       }
00769 
00770       if (station_orders < 2) this->OrderClick_Goto(0);
00771     }
00772     this->OnInvalidateData(-2);
00773   }
00774 
00775   virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
00776   {
00777     switch (widget) {
00778       case ORDER_WIDGET_TIMETABLE_VIEW:
00779         if (!_settings_game.order.timetabling) size->width = 0;
00780         break;
00781 
00782       case ORDER_WIDGET_ORDER_LIST:
00783         resize->height = FONT_HEIGHT_NORMAL;
00784         size->height = 6 * resize->height + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
00785         break;
00786 
00787       case ORDER_WIDGET_COND_VARIABLE: {
00788         Dimension d = {0, 0};
00789         for (int i = 0; _order_conditional_variable[i] != INVALID_STRING_ID; i++) {
00790           d = maxdim(d, GetStringBoundingBox(_order_conditional_variable[i]));
00791         }
00792         d.width += padding.width;
00793         d.height += padding.height;
00794         *size = maxdim(*size, d);
00795         break;
00796       }
00797 
00798       case ORDER_WIDGET_COND_COMPARATOR: {
00799         Dimension d = {0, 0};
00800         for (int i = 0; _order_conditional_condition[i] != INVALID_STRING_ID; i++) {
00801           d = maxdim(d, GetStringBoundingBox(_order_conditional_condition[i]));
00802         }
00803         d.width += padding.width;
00804         d.height += padding.height;
00805         *size = maxdim(*size, d);
00806         break;
00807       }
00808     }
00809   }
00810 
00811   virtual void OnInvalidateData(int data)
00812   {
00813     VehicleOrderID from = GB(data, 0, 8);
00814     VehicleOrderID to   = GB(data, 8, 8);
00815 
00816     switch (data) {
00817       case 0:
00818         /* Autoreplace replaced the vehicle */
00819         this->vehicle = Vehicle::Get(this->window_number);
00820         break;
00821 
00822       case -1:
00823         /* Removed / replaced all orders (after deleting / sharing) */
00824         if (this->selected_order == -1) break;
00825 
00826         this->DeleteChildWindows();
00827         HideDropDownMenu(this);
00828         this->selected_order = -1;
00829         break;
00830 
00831       case -2:
00832         /* Some other order changes */
00833         break;
00834 
00835       default:
00836         /* Moving an order. If one of these is INVALID_VEH_ORDER_ID, then
00837          * the order is being created / removed */
00838         if (this->selected_order == -1) break;
00839 
00840         if (from == to) break; // no need to change anything
00841 
00842         if (from != this->selected_order) {
00843           /* Moving from preceding order? */
00844           this->selected_order -= (int)(from <= this->selected_order);
00845           /* Moving to   preceding order? */
00846           this->selected_order += (int)(to   <= this->selected_order);
00847           break;
00848         }
00849 
00850         /* Now we are modifying the selected order */
00851         if (to == INVALID_VEH_ORDER_ID) {
00852           /* Deleting selected order */
00853           this->DeleteChildWindows();
00854           HideDropDownMenu(this);
00855           this->selected_order = -1;
00856           break;
00857         }
00858 
00859         /* Moving selected order */
00860         this->selected_order = to;
00861         break;
00862     }
00863 
00864     this->vscroll->SetCount(this->vehicle->GetNumOrders() + 1);
00865     this->UpdateButtonState();
00866 
00867     /* Scroll to the new order. */
00868     if (from == INVALID_VEH_ORDER_ID && to != INVALID_VEH_ORDER_ID && !this->vscroll->IsVisible(to)) {
00869       this->vscroll->ScrollTowards(to);
00870     }
00871   }
00872 
00873   void UpdateButtonState()
00874   {
00875     if (this->vehicle->owner != _local_company) return; // No buttons are displayed with competitor order windows.
00876 
00877     bool shared_orders = this->vehicle->IsOrderListShared();
00878     int sel = this->OrderGetSel();
00879     const Order *order = this->vehicle->GetOrder(sel);
00880 
00881     /* Second row. */
00882     /* skip */
00883     this->SetWidgetDisabledState(ORDER_WIDGET_SKIP, this->vehicle->GetNumOrders() <= 1);
00884 
00885     /* delete / stop sharing */
00886     NWidgetStacked *delete_sel = this->GetWidget<NWidgetStacked>(ORDER_WIDGET_SEL_BOTTOM_MIDDLE);
00887     if (shared_orders && this->selected_order == this->vehicle->GetNumOrders()) {
00888       /* The 'End of Shared Orders' order is selected, show the 'stop sharing' button. */
00889       delete_sel->SetDisplayedPlane(DP_BOTTOM_MIDDLE_STOP_SHARING);
00890     } else {
00891       /* The 'End of Shared Orders' order isn't selected, show the 'delete' button. */
00892       delete_sel->SetDisplayedPlane(DP_BOTTOM_MIDDLE_DELETE);
00893       this->SetWidgetDisabledState(ORDER_WIDGET_DELETE,
00894         (uint)this->vehicle->GetNumOrders() + ((shared_orders || this->vehicle->GetNumOrders() != 0) ? 1 : 0) <= (uint)this->selected_order);
00895 
00896       /* Set the tooltip of the 'delete' button depending on whether the
00897        * 'End of Orders' order or a regular order is selected. */
00898       NWidgetCore *nwi = this->GetWidget<NWidgetCore>(ORDER_WIDGET_DELETE);
00899       if (this->selected_order == this->vehicle->GetNumOrders()) {
00900         nwi->SetDataTip(STR_ORDERS_DELETE_BUTTON, STR_ORDERS_DELETE_ALL_TOOLTIP);
00901       } else {
00902         nwi->SetDataTip(STR_ORDERS_DELETE_BUTTON, STR_ORDERS_DELETE_TOOLTIP);
00903       }
00904     }
00905 
00906     /* First row. */
00907     this->RaiseWidget(ORDER_WIDGET_FULL_LOAD);
00908     this->RaiseWidget(ORDER_WIDGET_UNLOAD);
00909     this->RaiseWidget(ORDER_WIDGET_SERVICE);
00910 
00911     /* Selection widgets. */
00912     /* Train or road vehicle. */
00913     NWidgetStacked *left_sel   = this->GetWidget<NWidgetStacked>(ORDER_WIDGET_SEL_TOP_LEFT);
00914     NWidgetStacked *middle_sel = this->GetWidget<NWidgetStacked>(ORDER_WIDGET_SEL_TOP_MIDDLE);
00915     NWidgetStacked *right_sel  = this->GetWidget<NWidgetStacked>(ORDER_WIDGET_SEL_TOP_RIGHT);
00916     /* Ship or airplane. */
00917     NWidgetStacked *row_sel = this->GetWidget<NWidgetStacked>(ORDER_WIDGET_SEL_TOP_ROW);
00918     assert(row_sel != NULL || (left_sel != NULL && middle_sel != NULL && right_sel != NULL));
00919 
00920 
00921     if (order == NULL) {
00922       if (row_sel != NULL) {
00923         row_sel->SetDisplayedPlane(DP_ROW_LOAD);
00924       } else {
00925         left_sel->SetDisplayedPlane(DP_LEFT_NONSTOP);
00926         middle_sel->SetDisplayedPlane(DP_MIDDLE_LOAD);
00927         right_sel->SetDisplayedPlane(DP_RIGHT_UNLOAD);
00928         this->DisableWidget(ORDER_WIDGET_NON_STOP);
00929         this->RaiseWidget(ORDER_WIDGET_NON_STOP);
00930       }
00931       this->DisableWidget(ORDER_WIDGET_FULL_LOAD);
00932       this->DisableWidget(ORDER_WIDGET_UNLOAD);
00933     } else {
00934       this->SetWidgetDisabledState(ORDER_WIDGET_FULL_LOAD, (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) != 0); // full load
00935       this->SetWidgetDisabledState(ORDER_WIDGET_UNLOAD,    (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) != 0); // unload
00936 
00937       switch (order->GetType()) {
00938         case OT_GOTO_STATION:
00939           if (row_sel != NULL) {
00940             row_sel->SetDisplayedPlane(DP_ROW_LOAD);
00941           } else {
00942             left_sel->SetDisplayedPlane(DP_LEFT_NONSTOP);
00943             middle_sel->SetDisplayedPlane(DP_MIDDLE_LOAD);
00944             right_sel->SetDisplayedPlane(DP_RIGHT_UNLOAD);
00945             this->EnableWidget(ORDER_WIDGET_NON_STOP);
00946             this->SetWidgetLoweredState(ORDER_WIDGET_NON_STOP, order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
00947           }
00948           this->SetWidgetLoweredState(ORDER_WIDGET_FULL_LOAD, order->GetLoadType() == OLF_FULL_LOAD_ANY);
00949           this->SetWidgetLoweredState(ORDER_WIDGET_UNLOAD, order->GetUnloadType() == OUFB_UNLOAD);
00950           break;
00951 
00952         case OT_GOTO_WAYPOINT:
00953           if (row_sel != NULL) {
00954             row_sel->SetDisplayedPlane(DP_ROW_LOAD);
00955           } else {
00956             left_sel->SetDisplayedPlane(DP_LEFT_NONSTOP);
00957             middle_sel->SetDisplayedPlane(DP_MIDDLE_LOAD);
00958             right_sel->SetDisplayedPlane(DP_RIGHT_UNLOAD);
00959             this->EnableWidget(ORDER_WIDGET_NON_STOP);
00960             this->SetWidgetLoweredState(ORDER_WIDGET_NON_STOP, order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
00961           }
00962           this->DisableWidget(ORDER_WIDGET_FULL_LOAD);
00963           this->DisableWidget(ORDER_WIDGET_UNLOAD);
00964           break;
00965 
00966         case OT_GOTO_DEPOT:
00967           if (row_sel != NULL) {
00968             row_sel->SetDisplayedPlane(DP_ROW_DEPOT);
00969           } else {
00970             left_sel->SetDisplayedPlane(DP_LEFT_NONSTOP);
00971             middle_sel->SetDisplayedPlane(DP_MIDDLE_REFIT);
00972             right_sel->SetDisplayedPlane(DP_RIGHT_SERVICE);
00973             this->EnableWidget(ORDER_WIDGET_NON_STOP);
00974             this->SetWidgetLoweredState(ORDER_WIDGET_NON_STOP, order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
00975           }
00976           this->SetWidgetLoweredState(ORDER_WIDGET_SERVICE, order->GetDepotOrderType() & ODTFB_SERVICE);
00977           break;
00978 
00979         case OT_CONDITIONAL: {
00980           if (row_sel != NULL) {
00981             row_sel->SetDisplayedPlane(DP_ROW_CONDITIONAL);
00982           } else {
00983             left_sel->SetDisplayedPlane(DP_LEFT_CONDVAR);
00984             middle_sel->SetDisplayedPlane(DP_MIDDLE_COMPARE);
00985             right_sel->SetDisplayedPlane(DP_RIGHT_CONDVAL);
00986           }
00987           OrderConditionVariable ocv = order->GetConditionVariable();
00988           /* Set the strings for the dropdown boxes. */
00989           this->GetWidget<NWidgetCore>(ORDER_WIDGET_COND_VARIABLE)->widget_data   = _order_conditional_variable[order == NULL ? 0 : ocv];
00990           this->GetWidget<NWidgetCore>(ORDER_WIDGET_COND_COMPARATOR)->widget_data = _order_conditional_condition[order == NULL ? 0 : order->GetConditionComparator()];
00991           this->SetWidgetDisabledState(ORDER_WIDGET_COND_COMPARATOR, ocv == OCV_UNCONDITIONALLY);
00992           this->SetWidgetDisabledState(ORDER_WIDGET_COND_VALUE, ocv == OCV_REQUIRES_SERVICE || ocv == OCV_UNCONDITIONALLY);
00993           break;
00994         }
00995 
00996         default: // every other order
00997           if (row_sel != NULL) {
00998             row_sel->SetDisplayedPlane(DP_ROW_LOAD);
00999           } else {
01000             left_sel->SetDisplayedPlane(DP_LEFT_NONSTOP);
01001             middle_sel->SetDisplayedPlane(DP_MIDDLE_LOAD);
01002             right_sel->SetDisplayedPlane(DP_RIGHT_UNLOAD);
01003             this->DisableWidget(ORDER_WIDGET_NON_STOP);
01004           }
01005           this->DisableWidget(ORDER_WIDGET_FULL_LOAD);
01006           this->DisableWidget(ORDER_WIDGET_UNLOAD);
01007           break;
01008       }
01009     }
01010 
01011     /* Disable list of vehicles with the same shared orders if there is no list */
01012     this->SetWidgetDisabledState(ORDER_WIDGET_SHARED_ORDER_LIST, !shared_orders);
01013 
01014     this->SetDirty();
01015   }
01016 
01017   virtual void OnPaint()
01018   {
01019     if (this->vehicle->owner != _local_company) this->selected_order = -1; // Disable selection any selected row at a competitor order window.
01020     this->DrawWidgets();
01021   }
01022 
01023   virtual void DrawWidget(const Rect &r, int widget) const
01024   {
01025     if (widget != ORDER_WIDGET_ORDER_LIST) return;
01026 
01027     bool rtl = _current_text_dir == TD_RTL;
01028     SetDParam(0, 99);
01029     int index_column_width = GetStringBoundingBox(STR_ORDER_INDEX).width + GetSpriteSize(rtl ? SPR_ARROW_RIGHT : SPR_ARROW_LEFT).width + 3;
01030     int middle = rtl ? r.right - WD_FRAMETEXT_RIGHT - index_column_width : r.left + WD_FRAMETEXT_LEFT + index_column_width;
01031 
01032     int y = r.top + WD_FRAMERECT_TOP;
01033     int line_height = this->GetWidget<NWidgetBase>(ORDER_WIDGET_ORDER_LIST)->resize_y;
01034 
01035     int i = this->vscroll->GetPosition();
01036     const Order *order = this->vehicle->GetOrder(i);
01037     /* First draw the highlighting underground if it exists. */
01038     if (this->order_over != INVALID_ORDER) {
01039       while (order != NULL) {
01040         /* Don't draw anything if it extends past the end of the window. */
01041         if (!this->vscroll->IsVisible(i)) break;
01042 
01043         if (i != this->selected_order && i == this->order_over) {
01044           /* Highlight dragged order destination. */
01045           int top = (this->order_over < this->selected_order ? y : y + line_height) - WD_FRAMERECT_TOP;
01046           int bottom = min(top + 2, r.bottom - WD_FRAMERECT_BOTTOM);
01047           top = max(top - 3, r.top + WD_FRAMERECT_TOP);
01048           GfxFillRect(r.left + WD_FRAMETEXT_LEFT, top, r.right - WD_FRAMETEXT_RIGHT, bottom, _colour_gradient[COLOUR_GREY][7]);
01049           break;
01050         }
01051         y += line_height;
01052 
01053         i++;
01054         order = order->next;
01055       }
01056 
01057       /* Reset counters for drawing the orders. */
01058       y = r.top + WD_FRAMERECT_TOP;
01059       i = this->vscroll->GetPosition();
01060       order = this->vehicle->GetOrder(i);
01061     }
01062 
01063     /* Draw the orders. */
01064     while (order != NULL) {
01065       /* Don't draw anything if it extends past the end of the window. */
01066       if (!this->vscroll->IsVisible(i)) break;
01067 
01068       DrawOrderString(this->vehicle, order, i, y, i == this->selected_order, false, r.left + WD_FRAMETEXT_LEFT, middle, r.right - WD_FRAMETEXT_RIGHT);
01069       y += line_height;
01070 
01071       i++;
01072       order = order->next;
01073     }
01074 
01075     if (this->vscroll->IsVisible(i)) {
01076       StringID str = this->vehicle->IsOrderListShared() ? STR_ORDERS_END_OF_SHARED_ORDERS : STR_ORDERS_END_OF_ORDERS;
01077       DrawString(rtl ? r.left + WD_FRAMETEXT_LEFT : middle, rtl ? middle : r.right - WD_FRAMETEXT_RIGHT, y, str, (i == this->selected_order) ? TC_WHITE : TC_BLACK);
01078     }
01079   }
01080 
01081   virtual void SetStringParameters(int widget) const
01082   {
01083     switch (widget) {
01084       case ORDER_WIDGET_COND_VALUE: {
01085         int sel = this->OrderGetSel();
01086         const Order *order = this->vehicle->GetOrder(sel);
01087 
01088         if (order != NULL && order->IsType(OT_CONDITIONAL)) {
01089           uint value = order->GetConditionValue();
01090           if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value);
01091           SetDParam(0, value);
01092         }
01093         break;
01094       }
01095 
01096       case ORDER_WIDGET_CAPTION:
01097         SetDParam(0, this->vehicle->index);
01098         break;
01099     }
01100   }
01101 
01102   virtual void OnClick(Point pt, int widget, int click_count)
01103   {
01104     switch (widget) {
01105       case ORDER_WIDGET_ORDER_LIST: {
01106         if (this->goto_type == OPOS_CONDITIONAL) {
01107           this->goto_type = OPOS_GOTO;
01108           int order_id = this->GetOrderFromPt(_cursor.pos.y - this->top);
01109           if (order_id != INVALID_ORDER) {
01110             Order order;
01111             order.next = NULL;
01112             order.index = 0;
01113             order.MakeConditional(order_id);
01114 
01115             DoCommandP(this->vehicle->tile, this->vehicle->index + (this->OrderGetSel() << 20), order.Pack(), CMD_INSERT_ORDER | CMD_MSG(STR_ERROR_CAN_T_INSERT_NEW_ORDER));
01116           }
01117           ResetObjectToPlace();
01118           break;
01119         }
01120 
01121         int sel = this->GetOrderFromPt(pt.y);
01122 
01123         if (_ctrl_pressed && sel < this->vehicle->GetNumOrders()) {
01124           TileIndex xy = this->vehicle->GetOrder(sel)->GetLocation(this->vehicle);
01125           if (xy != INVALID_TILE) ScrollMainWindowToTile(xy);
01126           return;
01127         }
01128 
01129         /* This order won't be selected any more, close all child windows and dropdowns */
01130         this->DeleteChildWindows();
01131         HideDropDownMenu(this);
01132 
01133         if (sel == INVALID_ORDER || this->vehicle->owner != _local_company) {
01134           /* Deselect clicked order */
01135           this->selected_order = -1;
01136         } else if (sel == this->selected_order) {
01137           if (this->vehicle->type == VEH_TRAIN && sel < this->vehicle->GetNumOrders()) {
01138             DoCommandP(this->vehicle->tile, this->vehicle->index + (sel << 20),
01139                 MOF_STOP_LOCATION | ((this->vehicle->GetOrder(sel)->GetStopLocation() + 1) % OSL_END) << 4,
01140                 CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER));
01141           }
01142         } else {
01143           /* Select clicked order */
01144           this->selected_order = sel;
01145 
01146           if (this->vehicle->owner == _local_company) {
01147             /* Activate drag and drop */
01148             SetObjectToPlaceWnd(SPR_CURSOR_MOUSE, PAL_NONE, HT_DRAG, this);
01149           }
01150         }
01151 
01152         this->UpdateButtonState();
01153         break;
01154       }
01155 
01156       case ORDER_WIDGET_SKIP:
01157         this->OrderClick_Skip(0);
01158         break;
01159 
01160       case ORDER_WIDGET_DELETE:
01161         this->OrderClick_Delete(0);
01162         break;
01163 
01164       case ORDER_WIDGET_STOP_SHARING:
01165         this->OrderClick_StopSharing(0);
01166         break;
01167 
01168       case ORDER_WIDGET_NON_STOP:
01169         if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
01170           this->OrderClick_Nonstop(-1);
01171         } else {
01172           const Order *o = this->vehicle->GetOrder(this->OrderGetSel());
01173           ShowDropDownMenu(this, _order_non_stop_drowdown, o->GetNonStopType(), ORDER_WIDGET_NON_STOP, 0,
01174                           o->IsType(OT_GOTO_STATION) ? 0 : (o->IsType(OT_GOTO_WAYPOINT) ? 3 : 12));
01175         }
01176         break;
01177 
01178       case ORDER_WIDGET_GOTO:
01179         if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
01180           this->OrderClick_Goto(0);
01181         } else {
01182           ShowDropDownMenu(this, this->vehicle->type == VEH_AIRCRAFT ? _order_goto_dropdown_aircraft : _order_goto_dropdown, 0, ORDER_WIDGET_GOTO, 0, 0);
01183         }
01184         break;
01185 
01186       case ORDER_WIDGET_FULL_LOAD:
01187         if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
01188           this->OrderClick_FullLoad(-1);
01189         } else {
01190           ShowDropDownMenu(this, _order_full_load_drowdown, this->vehicle->GetOrder(this->OrderGetSel())->GetLoadType(), ORDER_WIDGET_FULL_LOAD, 0, 2);
01191         }
01192         break;
01193 
01194       case ORDER_WIDGET_UNLOAD:
01195         if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
01196           this->OrderClick_Unload(-1);
01197         } else {
01198           ShowDropDownMenu(this, _order_unload_drowdown, this->vehicle->GetOrder(this->OrderGetSel())->GetUnloadType(), ORDER_WIDGET_UNLOAD, 0, 8);
01199         }
01200         break;
01201 
01202       case ORDER_WIDGET_REFIT:
01203         this->OrderClick_Refit(0);
01204         break;
01205 
01206       case ORDER_WIDGET_SERVICE:
01207         if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
01208           this->OrderClick_Service(-1);
01209         } else {
01210           ShowDropDownMenu(this, _order_depot_action_dropdown, DepotActionStringIndex(this->vehicle->GetOrder(this->OrderGetSel())), ORDER_WIDGET_SERVICE, 0, 0);
01211         }
01212         break;
01213 
01214       case ORDER_WIDGET_TIMETABLE_VIEW:
01215         ShowTimetableWindow(this->vehicle);
01216         break;
01217 
01218       case ORDER_WIDGET_COND_VARIABLE:
01219         ShowDropDownMenu(this, _order_conditional_variable, this->vehicle->GetOrder(this->OrderGetSel())->GetConditionVariable(), ORDER_WIDGET_COND_VARIABLE, 0, 0);
01220         break;
01221 
01222       case ORDER_WIDGET_COND_COMPARATOR: {
01223         const Order *o = this->vehicle->GetOrder(this->OrderGetSel());
01224         ShowDropDownMenu(this, _order_conditional_condition, o->GetConditionComparator(), ORDER_WIDGET_COND_COMPARATOR, 0, (o->GetConditionVariable() == OCV_REQUIRES_SERVICE) ? 0x3F : 0xC0);
01225         break;
01226       }
01227 
01228       case ORDER_WIDGET_COND_VALUE: {
01229         const Order *order = this->vehicle->GetOrder(this->OrderGetSel());
01230         uint value = order->GetConditionValue();
01231         if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value);
01232         SetDParam(0, value);
01233         ShowQueryString(STR_JUST_INT, STR_ORDER_CONDITIONAL_VALUE_CAPT, 5, 100, this, CS_NUMERAL, QSF_NONE);
01234         break;
01235       }
01236 
01237       case ORDER_WIDGET_SHARED_ORDER_LIST:
01238         ShowVehicleListWindow(this->vehicle);
01239         break;
01240     }
01241   }
01242 
01243   virtual void OnQueryTextFinished(char *str)
01244   {
01245     if (!StrEmpty(str)) {
01246       VehicleOrderID sel = this->OrderGetSel();
01247       uint value = atoi(str);
01248 
01249       switch (this->vehicle->GetOrder(sel)->GetConditionVariable()) {
01250         case OCV_MAX_SPEED:
01251           value = ConvertDisplaySpeedToSpeed(value);
01252           break;
01253 
01254         case OCV_RELIABILITY:
01255         case OCV_LOAD_PERCENTAGE:
01256           value = Clamp(value, 0, 100);
01257 
01258         default:
01259           break;
01260       }
01261       DoCommandP(this->vehicle->tile, this->vehicle->index + (sel << 20), MOF_COND_VALUE | Clamp(value, 0, 2047) << 4, CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER));
01262     }
01263   }
01264 
01265   virtual void OnDropdownSelect(int widget, int index)
01266   {
01267     switch (widget) {
01268       case ORDER_WIDGET_NON_STOP:
01269         this->OrderClick_Nonstop(index);
01270         break;
01271 
01272       case ORDER_WIDGET_FULL_LOAD:
01273         this->OrderClick_FullLoad(index);
01274         break;
01275 
01276       case ORDER_WIDGET_UNLOAD:
01277         this->OrderClick_Unload(index);
01278         break;
01279 
01280       case ORDER_WIDGET_GOTO:
01281         switch (index) {
01282           case 0: this->OrderClick_Goto(0); break;
01283           case 1: this->OrderClick_NearestDepot(0); break;
01284           case 2: this->OrderClick_Conditional(0); break;
01285           case 3: this->OrderClick_Share(0); break;
01286           default: NOT_REACHED();
01287         }
01288         break;
01289 
01290       case ORDER_WIDGET_SERVICE:
01291         this->OrderClick_Service(index);
01292         break;
01293 
01294       case ORDER_WIDGET_COND_VARIABLE:
01295         DoCommandP(this->vehicle->tile, this->vehicle->index + (this->OrderGetSel() << 20), MOF_COND_VARIABLE | index << 4,  CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER));
01296         break;
01297 
01298       case ORDER_WIDGET_COND_COMPARATOR:
01299         DoCommandP(this->vehicle->tile, this->vehicle->index + (this->OrderGetSel() << 20), MOF_COND_COMPARATOR | index << 4,  CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER));
01300         break;
01301     }
01302   }
01303 
01304   virtual void OnDragDrop(Point pt, int widget)
01305   {
01306     switch (widget) {
01307       case ORDER_WIDGET_ORDER_LIST: {
01308         int from_order = this->OrderGetSel();
01309         int to_order = this->GetOrderFromPt(pt.y);
01310 
01311         if (!(from_order == to_order || from_order == INVALID_ORDER || from_order > this->vehicle->GetNumOrders() || to_order == INVALID_ORDER || to_order > this->vehicle->GetNumOrders()) &&
01312             DoCommandP(this->vehicle->tile, this->vehicle->index, from_order | (to_order << 16), CMD_MOVE_ORDER | CMD_MSG(STR_ERROR_CAN_T_MOVE_THIS_ORDER))) {
01313           this->selected_order = -1;
01314           this->UpdateButtonState();
01315         }
01316         break;
01317       }
01318 
01319       case ORDER_WIDGET_DELETE:
01320         this->OrderClick_Delete(0);
01321         break;
01322 
01323       case ORDER_WIDGET_STOP_SHARING:
01324         this->OrderClick_StopSharing(0);
01325         break;
01326     }
01327 
01328     ResetObjectToPlace();
01329 
01330     if (this->order_over != INVALID_ORDER) {
01331       /* End of drag-and-drop, hide dragged order destination highlight. */
01332       this->order_over = INVALID_ORDER;
01333       this->SetWidgetDirty(ORDER_WIDGET_ORDER_LIST);
01334     }
01335   }
01336 
01337   virtual EventState OnKeyPress(uint16 key, uint16 keycode)
01338   {
01339 
01340     if (this->vehicle->owner != _local_company) return ES_NOT_HANDLED;
01341 
01342     return CheckHotkeyMatch<OrdersWindow>(order_hotkeys, keycode, this) != -1 ? ES_HANDLED : ES_NOT_HANDLED;
01343   }
01344 
01345   virtual void OnPlaceObject(Point pt, TileIndex tile)
01346   {
01347     if (this->goto_type == OPOS_GOTO) {
01348       const Order cmd = GetOrderCmdFromTile(this->vehicle, tile);
01349       if (cmd.IsType(OT_NOTHING)) return;
01350 
01351       if (DoCommandP(this->vehicle->tile, this->vehicle->index + (this->OrderGetSel() << 20), cmd.Pack(), CMD_INSERT_ORDER | CMD_MSG(STR_ERROR_CAN_T_INSERT_NEW_ORDER))) {
01352         /* With quick goto the Go To button stays active */
01353         if (!_settings_client.gui.quick_goto) ResetObjectToPlace();
01354       }
01355     }
01356   }
01357 
01358   virtual void OnVehicleSelect(const Vehicle *v)
01359   {
01360     /* v is vehicle getting orders. Only copy/clone orders if vehicle doesn't have any orders yet.
01361      * We disallow copying orders of other vehicles if we already have at least one order entry
01362      * ourself as it easily copies orders of vehicles within a station when we mean the station.
01363      * Obviously if you press CTRL on a non-empty orders vehicle you know what you are doing
01364      * TODO: give a warning message */
01365     bool share_order = _ctrl_pressed || this->goto_type == OPOS_SHARE;
01366     if (this->vehicle->GetNumOrders() != 0 && !share_order) return;
01367 
01368     if (DoCommandP(this->vehicle->tile, this->vehicle->index | (share_order ? CO_SHARE : CO_COPY) << 30, v->index,
01369         share_order ? CMD_CLONE_ORDER | CMD_MSG(STR_ERROR_CAN_T_SHARE_ORDER_LIST) : CMD_CLONE_ORDER | CMD_MSG(STR_ERROR_CAN_T_COPY_ORDER_LIST))) {
01370       this->selected_order = -1;
01371       ResetObjectToPlace();
01372     }
01373   }
01374 
01375   virtual void OnPlaceObjectAbort()
01376   {
01377     this->RaiseWidget(ORDER_WIDGET_GOTO);
01378     this->SetWidgetDirty(ORDER_WIDGET_GOTO);
01379 
01380     /* Remove drag highlighting if it exists. */
01381     if (this->order_over != INVALID_ORDER) {
01382       this->order_over = INVALID_ORDER;
01383       this->SetWidgetDirty(ORDER_WIDGET_ORDER_LIST);
01384     }
01385   }
01386 
01387   virtual void OnMouseDrag(Point pt, int widget)
01388   {
01389     if (this->selected_order != -1 && widget == ORDER_WIDGET_ORDER_LIST) {
01390       /* An order is dragged.. */
01391       OrderID from_order = this->OrderGetSel();
01392       OrderID to_order = this->GetOrderFromPt(pt.y);
01393       uint num_orders = this->vehicle->GetNumOrders();
01394 
01395       if (from_order != INVALID_ORDER && from_order <= num_orders) {
01396         if (to_order != INVALID_ORDER && to_order <= num_orders) { // ..over an existing order.
01397           this->order_over = to_order;
01398           this->SetWidgetDirty(widget);
01399         } else if (from_order != to_order && this->order_over != INVALID_ORDER) { // ..outside of the order list.
01400           this->order_over = INVALID_ORDER;
01401           this->SetWidgetDirty(widget);
01402         }
01403       }
01404     }
01405   }
01406 
01407   virtual void OnResize()
01408   {
01409     /* Update the scroll bar */
01410     this->vscroll->SetCapacityFromWidget(this, ORDER_WIDGET_ORDER_LIST);
01411   }
01412 
01413   virtual void OnTimeout()
01414   {
01415     static const int raise_widgets[] = {
01416       ORDER_WIDGET_TIMETABLE_VIEW, ORDER_WIDGET_SKIP, ORDER_WIDGET_DELETE, ORDER_WIDGET_STOP_SHARING, ORDER_WIDGET_REFIT, ORDER_WIDGET_SHARED_ORDER_LIST, WIDGET_LIST_END,
01417     };
01418 
01419     /* Unclick all buttons in raise_widgets[]. */
01420     for (const int *widnum = raise_widgets; *widnum != WIDGET_LIST_END; widnum++) {
01421       if (this->IsWidgetLowered(*widnum)) {
01422         this->RaiseWidget(*widnum);
01423         this->SetWidgetDirty(*widnum);
01424       }
01425     }
01426   }
01427 
01428   static Hotkey<OrdersWindow> order_hotkeys[];
01429 };
01430 
01431 Hotkey<OrdersWindow> OrdersWindow::order_hotkeys[]= {
01432   Hotkey<OrdersWindow>('D', "skip", 0, &OrdersWindow::OrderClick_Skip),
01433   Hotkey<OrdersWindow>('F', "delete", 0, &OrdersWindow::OrderClick_Delete),
01434   Hotkey<OrdersWindow>('G', "goto", 0, &OrdersWindow::OrderClick_Goto),
01435   Hotkey<OrdersWindow>('H', "nonstop", 0, &OrdersWindow::OrderClick_Nonstop),
01436   Hotkey<OrdersWindow>('J', "fullload", 0, &OrdersWindow::OrderClick_FullLoad),
01437   Hotkey<OrdersWindow>('K', "unload", 0, &OrdersWindow::OrderClick_Unload),
01438   Hotkey<OrdersWindow>((uint16)0, "nearest_depot", 0, &OrdersWindow::OrderClick_NearestDepot),
01439   Hotkey<OrdersWindow>((uint16)0, "always_service", 0, &OrdersWindow::OrderClick_Service),
01440   Hotkey<OrdersWindow>((uint16)0, "force_unload", 0, &OrdersWindow::OrderClick_Unload),
01441   Hotkey<OrdersWindow>((uint16)0, "transfer", 0, &OrdersWindow::OrderHotkey_Transfer),
01442   Hotkey<OrdersWindow>((uint16)0, "no_unload", 0, &OrdersWindow::OrderHotkey_NoUnload),
01443   Hotkey<OrdersWindow>((uint16)0, "no_load", 0, &OrdersWindow::OrderHotkey_NoLoad),
01444   HOTKEY_LIST_END(OrdersWindow)
01445 };
01446 Hotkey<OrdersWindow> *_order_hotkeys = OrdersWindow::order_hotkeys;
01447 
01449 static const NWidgetPart _nested_orders_train_widgets[] = {
01450   NWidget(NWID_HORIZONTAL),
01451     NWidget(WWT_CLOSEBOX, COLOUR_GREY),
01452     NWidget(WWT_CAPTION, COLOUR_GREY, ORDER_WIDGET_CAPTION), SetDataTip(STR_ORDERS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
01453     NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, ORDER_WIDGET_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetDataTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP),
01454     NWidget(WWT_SHADEBOX, COLOUR_GREY),
01455     NWidget(WWT_STICKYBOX, COLOUR_GREY),
01456   EndContainer(),
01457   NWidget(NWID_HORIZONTAL),
01458     NWidget(WWT_PANEL, COLOUR_GREY, ORDER_WIDGET_ORDER_LIST), SetMinimalSize(372, 62), SetDataTip(0x0, STR_ORDERS_LIST_TOOLTIP), SetResize(1, 1), SetScrollbar(ORDER_WIDGET_SCROLLBAR), EndContainer(),
01459     NWidget(NWID_VSCROLLBAR, COLOUR_GREY, ORDER_WIDGET_SCROLLBAR),
01460   EndContainer(),
01461 
01462   /* First button row. */
01463   NWidget(NWID_HORIZONTAL),
01464     NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
01465       NWidget(NWID_SELECTION, INVALID_COLOUR, ORDER_WIDGET_SEL_TOP_LEFT),
01466         NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, ORDER_WIDGET_NON_STOP), SetMinimalSize(124, 12), SetFill(1, 0),
01467                             SetDataTip(STR_ORDER_NON_STOP, STR_ORDER_TOOLTIP_NON_STOP), SetResize(1, 0),
01468         NWidget(WWT_DROPDOWN, COLOUR_GREY, ORDER_WIDGET_COND_VARIABLE), SetMinimalSize(124, 12), SetFill(1, 0),
01469                             SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_VARIABLE_TOOLTIP), SetResize(1, 0),
01470       EndContainer(),
01471       NWidget(NWID_SELECTION, INVALID_COLOUR, ORDER_WIDGET_SEL_TOP_MIDDLE),
01472         NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, ORDER_WIDGET_FULL_LOAD), SetMinimalSize(124, 12), SetFill(1, 0),
01473                             SetDataTip(STR_ORDER_TOGGLE_FULL_LOAD, STR_ORDER_TOOLTIP_FULL_LOAD), SetResize(1, 0),
01474         NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, ORDER_WIDGET_REFIT), SetMinimalSize(124, 12), SetFill(1, 0),
01475                             SetDataTip(STR_ORDER_REFIT, STR_ORDER_REFIT_TOOLTIP), SetResize(1, 0),
01476         NWidget(WWT_DROPDOWN, COLOUR_GREY, ORDER_WIDGET_COND_COMPARATOR), SetMinimalSize(124, 12), SetFill(1, 0),
01477                             SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_COMPARATOR_TOOLTIP), SetResize(1, 0),
01478       EndContainer(),
01479       NWidget(NWID_SELECTION, INVALID_COLOUR, ORDER_WIDGET_SEL_TOP_RIGHT),
01480         NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, ORDER_WIDGET_UNLOAD), SetMinimalSize(124, 12), SetFill(1, 0),
01481                             SetDataTip(STR_ORDER_TOGGLE_UNLOAD, STR_ORDER_TOOLTIP_UNLOAD), SetResize(1, 0),
01482         NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, ORDER_WIDGET_SERVICE), SetMinimalSize(124, 12), SetFill(1, 0),
01483                             SetDataTip(STR_ORDER_SERVICE, STR_ORDER_SERVICE_TOOLTIP), SetResize(1, 0),
01484         NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, ORDER_WIDGET_COND_VALUE), SetMinimalSize(124, 12), SetFill(1, 0),
01485                             SetDataTip(STR_BLACK_COMMA, STR_ORDER_CONDITIONAL_VALUE_TOOLTIP), SetResize(1, 0),
01486       EndContainer(),
01487     EndContainer(),
01488     NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, ORDER_WIDGET_SHARED_ORDER_LIST), SetMinimalSize(12, 12), SetDataTip(SPR_SHARED_ORDERS_ICON, STR_ORDERS_VEH_WITH_SHARED_ORDERS_LIST_TOOLTIP),
01489   EndContainer(),
01490 
01491   /* Second button row. */
01492   NWidget(NWID_HORIZONTAL),
01493     NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
01494       NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, ORDER_WIDGET_SKIP), SetMinimalSize(124, 12), SetFill(1, 0),
01495                           SetDataTip(STR_ORDERS_SKIP_BUTTON, STR_ORDERS_SKIP_TOOLTIP), SetResize(1, 0),
01496       NWidget(NWID_SELECTION, INVALID_COLOUR, ORDER_WIDGET_SEL_BOTTOM_MIDDLE),
01497         NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, ORDER_WIDGET_DELETE), SetMinimalSize(124, 12), SetFill(1, 0),
01498                             SetDataTip(STR_ORDERS_DELETE_BUTTON, STR_ORDERS_DELETE_TOOLTIP), SetResize(1, 0),
01499         NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, ORDER_WIDGET_STOP_SHARING), SetMinimalSize(124, 12), SetFill(1, 0),
01500                             SetDataTip(STR_ORDERS_STOP_SHARING_BUTTON, STR_ORDERS_STOP_SHARING_TOOLTIP), SetResize(1, 0),
01501       EndContainer(),
01502       NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, ORDER_WIDGET_GOTO), SetMinimalSize(124, 12), SetFill(1, 0),
01503                           SetDataTip(STR_ORDERS_GO_TO_BUTTON, STR_ORDERS_GO_TO_TOOLTIP), SetResize(1, 0),
01504     EndContainer(),
01505     NWidget(WWT_RESIZEBOX, COLOUR_GREY),
01506   EndContainer(),
01507 };
01508 
01509 static const WindowDesc _orders_train_desc(
01510   WDP_AUTO, 384, 100,
01511   WC_VEHICLE_ORDERS, WC_VEHICLE_VIEW,
01512   WDF_CONSTRUCTION,
01513   _nested_orders_train_widgets, lengthof(_nested_orders_train_widgets)
01514 );
01515 
01517 static const NWidgetPart _nested_orders_widgets[] = {
01518   NWidget(NWID_HORIZONTAL),
01519     NWidget(WWT_CLOSEBOX, COLOUR_GREY),
01520     NWidget(WWT_CAPTION, COLOUR_GREY, ORDER_WIDGET_CAPTION), SetDataTip(STR_ORDERS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
01521     NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, ORDER_WIDGET_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetDataTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP),
01522     NWidget(WWT_SHADEBOX, COLOUR_GREY),
01523     NWidget(WWT_STICKYBOX, COLOUR_GREY),
01524   EndContainer(),
01525   NWidget(NWID_HORIZONTAL),
01526     NWidget(WWT_PANEL, COLOUR_GREY, ORDER_WIDGET_ORDER_LIST), SetMinimalSize(372, 62), SetDataTip(0x0, STR_ORDERS_LIST_TOOLTIP), SetResize(1, 1), SetScrollbar(ORDER_WIDGET_SCROLLBAR), EndContainer(),
01527     NWidget(NWID_VSCROLLBAR, COLOUR_GREY, ORDER_WIDGET_SCROLLBAR),
01528   EndContainer(),
01529 
01530   /* First button row. */
01531   NWidget(NWID_HORIZONTAL),
01532     NWidget(NWID_SELECTION, INVALID_COLOUR, ORDER_WIDGET_SEL_TOP_ROW),
01533       /* load + unload buttons. */
01534       NWidget(NWID_HORIZONTAL),
01535         NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, ORDER_WIDGET_FULL_LOAD), SetMinimalSize(186, 12), SetFill(1, 0),
01536                           SetDataTip(STR_ORDER_TOGGLE_FULL_LOAD, STR_ORDER_TOOLTIP_FULL_LOAD), SetResize(1, 0),
01537         NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, ORDER_WIDGET_UNLOAD), SetMinimalSize(186, 12), SetFill(1, 0),
01538                           SetDataTip(STR_ORDER_TOGGLE_UNLOAD, STR_ORDER_TOOLTIP_UNLOAD), SetResize(1, 0),
01539       EndContainer(),
01540       /* Refit + service buttons. */
01541       NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
01542         NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, ORDER_WIDGET_REFIT), SetMinimalSize(186, 12), SetFill(1, 0),
01543                           SetDataTip(STR_ORDER_REFIT, STR_ORDER_REFIT_TOOLTIP), SetResize(1, 0),
01544         NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, ORDER_WIDGET_SERVICE), SetMinimalSize(124, 12), SetFill(1, 0),
01545                           SetDataTip(STR_ORDER_SERVICE, STR_ORDER_SERVICE_TOOLTIP), SetResize(1, 0),
01546       EndContainer(),
01547 
01548       /* Buttons for setting a condition. */
01549       NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
01550         NWidget(WWT_DROPDOWN, COLOUR_GREY, ORDER_WIDGET_COND_VARIABLE), SetMinimalSize(124, 12), SetFill(1, 0),
01551                           SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_VARIABLE_TOOLTIP), SetResize(1, 0),
01552         NWidget(WWT_DROPDOWN, COLOUR_GREY, ORDER_WIDGET_COND_COMPARATOR), SetMinimalSize(124, 12), SetFill(1, 0),
01553                           SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_COMPARATOR_TOOLTIP), SetResize(1, 0),
01554         NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, ORDER_WIDGET_COND_VALUE), SetMinimalSize(124, 12), SetFill(1, 0),
01555                           SetDataTip(STR_BLACK_COMMA, STR_ORDER_CONDITIONAL_VALUE_TOOLTIP), SetResize(1, 0),
01556       EndContainer(),
01557     EndContainer(),
01558 
01559     NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, ORDER_WIDGET_SHARED_ORDER_LIST), SetMinimalSize(12, 12), SetDataTip(SPR_SHARED_ORDERS_ICON, STR_ORDERS_VEH_WITH_SHARED_ORDERS_LIST_TOOLTIP),
01560   EndContainer(),
01561 
01562   /* Second button row. */
01563   NWidget(NWID_HORIZONTAL),
01564     NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, ORDER_WIDGET_SKIP), SetMinimalSize(124, 12), SetFill(1, 0),
01565                       SetDataTip(STR_ORDERS_SKIP_BUTTON, STR_ORDERS_SKIP_TOOLTIP), SetResize(1, 0),
01566     NWidget(NWID_SELECTION, INVALID_COLOUR, ORDER_WIDGET_SEL_BOTTOM_MIDDLE),
01567       NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, ORDER_WIDGET_DELETE), SetMinimalSize(124, 12), SetFill(1, 0),
01568                           SetDataTip(STR_ORDERS_DELETE_BUTTON, STR_ORDERS_DELETE_TOOLTIP), SetResize(1, 0),
01569       NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, ORDER_WIDGET_STOP_SHARING), SetMinimalSize(124, 12), SetFill(1, 0),
01570                           SetDataTip(STR_ORDERS_STOP_SHARING_BUTTON, STR_ORDERS_STOP_SHARING_TOOLTIP), SetResize(1, 0),
01571     EndContainer(),
01572     NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, ORDER_WIDGET_GOTO), SetMinimalSize(124, 12), SetFill(1, 0),
01573                       SetDataTip(STR_ORDERS_GO_TO_BUTTON, STR_ORDERS_GO_TO_TOOLTIP), SetResize(1, 0),
01574     NWidget(WWT_RESIZEBOX, COLOUR_GREY),
01575   EndContainer(),
01576 };
01577 
01578 static const WindowDesc _orders_desc(
01579   WDP_AUTO, 384, 100,
01580   WC_VEHICLE_ORDERS, WC_VEHICLE_VIEW,
01581   WDF_CONSTRUCTION,
01582   _nested_orders_widgets, lengthof(_nested_orders_widgets)
01583 );
01584 
01586 static const NWidgetPart _nested_other_orders_widgets[] = {
01587   NWidget(NWID_HORIZONTAL),
01588     NWidget(WWT_CLOSEBOX, COLOUR_GREY),
01589     NWidget(WWT_CAPTION, COLOUR_GREY, ORDER_WIDGET_CAPTION), SetDataTip(STR_ORDERS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
01590     NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, ORDER_WIDGET_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetDataTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP),
01591     NWidget(WWT_SHADEBOX, COLOUR_GREY),
01592     NWidget(WWT_STICKYBOX, COLOUR_GREY),
01593   EndContainer(),
01594   NWidget(NWID_HORIZONTAL),
01595     NWidget(WWT_PANEL, COLOUR_GREY, ORDER_WIDGET_ORDER_LIST), SetMinimalSize(372, 72), SetDataTip(0x0, STR_ORDERS_LIST_TOOLTIP), SetResize(1, 1), SetScrollbar(ORDER_WIDGET_SCROLLBAR), EndContainer(),
01596     NWidget(NWID_VERTICAL),
01597       NWidget(NWID_VSCROLLBAR, COLOUR_GREY, ORDER_WIDGET_SCROLLBAR),
01598       NWidget(WWT_RESIZEBOX, COLOUR_GREY),
01599     EndContainer(),
01600   EndContainer(),
01601 };
01602 
01603 static const WindowDesc _other_orders_desc(
01604   WDP_AUTO, 384, 86,
01605   WC_VEHICLE_ORDERS, WC_VEHICLE_VIEW,
01606   WDF_UNCLICK_BUTTONS | WDF_CONSTRUCTION,
01607   _nested_other_orders_widgets, lengthof(_nested_other_orders_widgets)
01608 );
01609 
01610 void ShowOrdersWindow(const Vehicle *v)
01611 {
01612   DeleteWindowById(WC_VEHICLE_DETAILS, v->index, false);
01613   DeleteWindowById(WC_VEHICLE_TIMETABLE, v->index, false);
01614   if (BringWindowToFrontById(WC_VEHICLE_ORDERS, v->index) != NULL) return;
01615 
01616   if (v->owner != _local_company) {
01617     new OrdersWindow(&_other_orders_desc, v);
01618   } else {
01619     new OrdersWindow(v->IsGroundVehicle() ? &_orders_train_desc : &_orders_desc, v);
01620   }
01621 }

Generated on Sun Jan 23 01:49:06 2011 for OpenTTD by  doxygen 1.6.1