OpenTTD
vehicle_gui.cpp
Go to the documentation of this file.
1 /* $Id$ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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/>.
8  */
9 
12 #include "stdafx.h"
13 #include "debug.h"
14 #include "company_func.h"
15 #include "gui.h"
16 #include "textbuf_gui.h"
17 #include "command_func.h"
18 #include "vehicle_gui_base.h"
19 #include "viewport_func.h"
20 #include "newgrf_text.h"
21 #include "newgrf_debug.h"
22 #include "roadveh.h"
23 #include "train.h"
24 #include "aircraft.h"
25 #include "depot_map.h"
26 #include "group_gui.h"
27 #include "strings_func.h"
28 #include "vehicle_func.h"
29 #include "autoreplace_gui.h"
30 #include "string_func.h"
31 #include "widgets/dropdown_func.h"
32 #include "timetable.h"
33 #include "articulated_vehicles.h"
34 #include "spritecache.h"
35 #include "core/geometry_func.hpp"
36 #include "company_base.h"
37 #include "engine_func.h"
38 #include "station_base.h"
39 #include "tilehighlight_func.h"
40 #include "zoom_func.h"
41 
42 #include "safeguards.h"
43 
44 
45 Sorting _sorting;
46 
60 
61 GUIVehicleList::SortFunction * const BaseVehicleListWindow::vehicle_sorter_funcs[] = {
75 };
76 
77 const StringID BaseVehicleListWindow::vehicle_sorter_names[] = {
78  STR_SORT_BY_NUMBER,
79  STR_SORT_BY_NAME,
80  STR_SORT_BY_AGE,
81  STR_SORT_BY_PROFIT_THIS_YEAR,
82  STR_SORT_BY_PROFIT_LAST_YEAR,
83  STR_SORT_BY_TOTAL_CAPACITY_PER_CARGOTYPE,
84  STR_SORT_BY_RELIABILITY,
85  STR_SORT_BY_MAX_SPEED,
86  STR_SORT_BY_MODEL,
87  STR_SORT_BY_VALUE,
88  STR_SORT_BY_LENGTH,
89  STR_SORT_BY_LIFE_TIME,
90  STR_SORT_BY_TIMETABLE_DELAY,
92 };
93 
94 const StringID BaseVehicleListWindow::vehicle_depot_name[] = {
95  STR_VEHICLE_LIST_SEND_TRAIN_TO_DEPOT,
96  STR_VEHICLE_LIST_SEND_ROAD_VEHICLE_TO_DEPOT,
97  STR_VEHICLE_LIST_SEND_SHIP_TO_DEPOT,
98  STR_VEHICLE_LIST_SEND_AIRCRAFT_TO_HANGAR
99 };
100 
107 {
108  uint unitnumber = 0;
109  for (const Vehicle **v = vehicles.Begin(); v != vehicles.End(); v++) {
110  unitnumber = max<uint>(unitnumber, (*v)->unitnumber);
111  }
112 
113  if (unitnumber >= 10000) return 5;
114  if (unitnumber >= 1000) return 4;
115  if (unitnumber >= 100) return 3;
116 
117  /*
118  * When the smallest unit number is less than 10, it is
119  * quite likely that it will expand to become more than
120  * 10 quite soon.
121  */
122  return 2;
123 }
124 
125 void BaseVehicleListWindow::BuildVehicleList()
126 {
127  if (!this->vehicles.NeedRebuild()) return;
128 
129  DEBUG(misc, 3, "Building vehicle list type %d for company %d given index %d", this->vli.type, this->vli.company, this->vli.index);
130 
131  GenerateVehicleSortList(&this->vehicles, this->vli);
132 
134 
135  this->vehicles.RebuildDone();
136  this->vscroll->SetCount(this->vehicles.Length());
137 }
138 
145 Dimension BaseVehicleListWindow::GetActionDropdownSize(bool show_autoreplace, bool show_group)
146 {
147  Dimension d = {0, 0};
148 
149  if (show_autoreplace) d = maxdim(d, GetStringBoundingBox(STR_VEHICLE_LIST_REPLACE_VEHICLES));
150  d = maxdim(d, GetStringBoundingBox(STR_VEHICLE_LIST_SEND_FOR_SERVICING));
151  d = maxdim(d, GetStringBoundingBox(this->vehicle_depot_name[this->vli.vtype]));
152 
153  if (show_group) {
154  d = maxdim(d, GetStringBoundingBox(STR_GROUP_ADD_SHARED_VEHICLE));
155  d = maxdim(d, GetStringBoundingBox(STR_GROUP_REMOVE_ALL_VEHICLES));
156  }
157 
158  return d;
159 }
160 
167 DropDownList *BaseVehicleListWindow::BuildActionDropdownList(bool show_autoreplace, bool show_group)
168 {
169  DropDownList *list = new DropDownList();
170 
171  if (show_autoreplace) *list->Append() = new DropDownListStringItem(STR_VEHICLE_LIST_REPLACE_VEHICLES, ADI_REPLACE, false);
172  *list->Append() = new DropDownListStringItem(STR_VEHICLE_LIST_SEND_FOR_SERVICING, ADI_SERVICE, false);
173  *list->Append() = new DropDownListStringItem(this->vehicle_depot_name[this->vli.vtype], ADI_DEPOT, false);
174 
175  if (show_group) {
176  *list->Append() = new DropDownListStringItem(STR_GROUP_ADD_SHARED_VEHICLE, ADI_ADD_SHARED, false);
177  *list->Append() = new DropDownListStringItem(STR_GROUP_REMOVE_ALL_VEHICLES, ADI_REMOVE_ALL, false);
178  }
179 
180  return list;
181 }
182 
183 /* cached values for VehicleNameSorter to spare many GetString() calls */
184 static const Vehicle *_last_vehicle[2] = { NULL, NULL };
185 
186 void BaseVehicleListWindow::SortVehicleList()
187 {
188  if (this->vehicles.Sort()) return;
189 
190  /* invalidate cached values for name sorter - vehicle names could change */
191  _last_vehicle[0] = _last_vehicle[1] = NULL;
192 }
193 
194 void DepotSortList(VehicleList *list)
195 {
196  if (list->Length() < 2) return;
197  QSortT(list->Begin(), list->Length(), &VehicleNumberSorter);
198 }
199 
201 static void DrawVehicleProfitButton(const Vehicle *v, int x, int y)
202 {
203  SpriteID spr;
204 
205  /* draw profit-based coloured icons */
206  if (v->age <= VEHICLE_PROFIT_MIN_AGE) {
207  spr = SPR_PROFIT_NA;
208  } else if (v->GetDisplayProfitLastYear() < 0) {
209  spr = SPR_PROFIT_NEGATIVE;
211  spr = SPR_PROFIT_SOME;
212  } else {
213  spr = SPR_PROFIT_LOT;
214  }
215  DrawSprite(spr, PAL_NONE, x, y);
216 }
217 
219 static const uint MAX_REFIT_CYCLE = 256;
220 
230 byte GetBestFittingSubType(Vehicle *v_from, Vehicle *v_for, CargoID dest_cargo_type)
231 {
232  v_from = v_from->GetFirstEnginePart();
233  v_for = v_for->GetFirstEnginePart();
234 
235  /* Create a list of subtypes used by the various parts of v_for */
236  static SmallVector<StringID, 4> subtypes;
237  subtypes.Clear();
238  for (; v_from != NULL; v_from = v_from->HasArticulatedPart() ? v_from->GetNextArticulatedPart() : NULL) {
239  const Engine *e_from = v_from->GetEngine();
240  if (!e_from->CanCarryCargo() || !HasBit(e_from->info.callback_mask, CBM_VEHICLE_CARGO_SUFFIX)) continue;
241  subtypes.Include(GetCargoSubtypeText(v_from));
242  }
243 
244  byte ret_refit_cyc = 0;
245  bool success = false;
246  if (subtypes.Length() > 0) {
247  /* Check whether any articulated part is refittable to 'dest_cargo_type' with a subtype listed in 'subtypes' */
248  for (Vehicle *v = v_for; v != NULL; v = v->HasArticulatedPart() ? v->GetNextArticulatedPart() : NULL) {
249  const Engine *e = v->GetEngine();
250  if (!e->CanCarryCargo() || !HasBit(e->info.callback_mask, CBM_VEHICLE_CARGO_SUFFIX)) continue;
251  if (!HasBit(e->info.refit_mask, dest_cargo_type) && v->cargo_type != dest_cargo_type) continue;
252 
253  CargoID old_cargo_type = v->cargo_type;
254  byte old_cargo_subtype = v->cargo_subtype;
255 
256  /* Set the 'destination' cargo */
257  v->cargo_type = dest_cargo_type;
258 
259  /* Cycle through the refits */
260  for (uint refit_cyc = 0; refit_cyc < MAX_REFIT_CYCLE; refit_cyc++) {
261  v->cargo_subtype = refit_cyc;
262 
263  /* Make sure we don't pick up anything cached. */
264  v->First()->InvalidateNewGRFCache();
265  v->InvalidateNewGRFCache();
266 
267  StringID subtype = GetCargoSubtypeText(v);
268  if (subtype == STR_EMPTY) break;
269 
270  if (!subtypes.Contains(subtype)) continue;
271 
272  /* We found something matching. */
273  ret_refit_cyc = refit_cyc;
274  success = true;
275  break;
276  }
277 
278  /* Reset the vehicle's cargo type */
279  v->cargo_type = old_cargo_type;
280  v->cargo_subtype = old_cargo_subtype;
281 
282  /* Make sure we don't taint the vehicle. */
283  v->First()->InvalidateNewGRFCache();
284  v->InvalidateNewGRFCache();
285 
286  if (success) break;
287  }
288  }
289 
290  return ret_refit_cyc;
291 }
292 
294 struct RefitOption {
296  byte subtype;
298 
304  inline bool operator != (const RefitOption &other) const
305  {
306  return other.cargo != this->cargo || other.string != this->string;
307  }
308 
314  inline bool operator == (const RefitOption &other) const
315  {
316  return other.cargo == this->cargo && other.string == this->string;
317  }
318 };
319 
321 
331 static void DrawVehicleRefitWindow(const SubtypeList list[NUM_CARGO], const int sel[2], uint pos, uint rows, uint delta, const Rect &r)
332 {
333  uint y = r.top + WD_MATRIX_TOP;
334  uint current = 0;
335 
336  bool rtl = _current_text_dir == TD_RTL;
337  uint iconwidth = max(GetSpriteSize(SPR_CIRCLE_FOLDED).width, GetSpriteSize(SPR_CIRCLE_UNFOLDED).width);
338  uint iconheight = GetSpriteSize(SPR_CIRCLE_FOLDED).height;
339  int linecolour = _colour_gradient[COLOUR_ORANGE][4];
340 
341  int iconleft = rtl ? r.right - WD_MATRIX_RIGHT - iconwidth : r.left + WD_MATRIX_LEFT;
342  int iconcenter = rtl ? r.right - WD_MATRIX_RIGHT - iconwidth / 2 : r.left + WD_MATRIX_LEFT + iconwidth / 2;
343  int iconinner = rtl ? r.right - WD_MATRIX_RIGHT - iconwidth : r.left + WD_MATRIX_LEFT + iconwidth;
344 
345  int textleft = r.left + WD_MATRIX_LEFT + (rtl ? 0 : iconwidth + 4);
346  int textright = r.right - WD_MATRIX_RIGHT - (rtl ? iconwidth + 4 : 0);
347 
348  /* Draw the list of subtypes for each cargo, and find the selected refit option (by its position). */
349  for (uint i = 0; current < pos + rows && i < NUM_CARGO; i++) {
350  for (uint j = 0; current < pos + rows && j < list[i].Length(); j++) {
351  const RefitOption &refit = list[i][j];
352 
353  /* Hide subtypes if sel[0] does not match */
354  if (sel[0] != (int)i && refit.subtype != 0xFF) continue;
355 
356  /* Refit options with a position smaller than pos don't have to be drawn. */
357  if (current < pos) {
358  current++;
359  continue;
360  }
361 
362  if (list[i].Length() > 1) {
363  if (refit.subtype != 0xFF) {
364  /* Draw tree lines */
365  int ycenter = y + FONT_HEIGHT_NORMAL / 2;
366  GfxDrawLine(iconcenter, y - WD_MATRIX_TOP, iconcenter, j == list[i].Length() - 1 ? ycenter : y - WD_MATRIX_TOP + delta - 1, linecolour);
367  GfxDrawLine(iconcenter, ycenter, iconinner, ycenter, linecolour);
368  } else {
369  /* Draw expand/collapse icon */
370  DrawSprite(sel[0] == (int)i ? SPR_CIRCLE_UNFOLDED : SPR_CIRCLE_FOLDED, PAL_NONE, iconleft, y + (FONT_HEIGHT_NORMAL - iconheight) / 2);
371  }
372  }
373 
374  TextColour colour = (sel[0] == (int)i && (uint)sel[1] == j) ? TC_WHITE : TC_BLACK;
375  /* Get the cargo name. */
376  SetDParam(0, CargoSpec::Get(refit.cargo)->name);
377  SetDParam(1, refit.string);
378  DrawString(textleft, textright, y, STR_JUST_STRING_STRING, colour);
379 
380  y += delta;
381  current++;
382  }
383  }
384 }
385 
387 struct RefitWindow : public Window {
388  int sel[2];
399  int click_x;
401  uint8 num_vehicles;
402  bool auto_refit;
403 
408  {
409  for (uint i = 0; i < NUM_CARGO; i++) this->list[i].Clear();
410  Vehicle *v = Vehicle::Get(this->window_number);
411 
412  /* Check only the selected vehicles. */
413  VehicleSet vehicles_to_refit;
414  GetVehicleSet(vehicles_to_refit, Vehicle::Get(this->selected_vehicle), this->num_vehicles);
415 
416  do {
417  if (v->type == VEH_TRAIN && !vehicles_to_refit.Contains(v->index)) continue;
418  const Engine *e = v->GetEngine();
419  CargoTypes cmask = e->info.refit_mask;
420  byte callback_mask = e->info.callback_mask;
421 
422  /* Skip this engine if it does not carry anything */
423  if (!e->CanCarryCargo()) continue;
424  /* Skip this engine if we build the list for auto-refitting and engine doesn't allow it. */
425  if (this->auto_refit && !HasBit(e->info.misc_flags, EF_AUTO_REFIT)) continue;
426 
427  /* Loop through all cargoes in the refit mask */
428  int current_index = 0;
429  const CargoSpec *cs;
431  CargoID cid = cs->Index();
432  /* Skip cargo type if it's not listed */
433  if (!HasBit(cmask, cid)) {
434  current_index++;
435  continue;
436  }
437 
438  bool first_vehicle = this->list[current_index].Length() == 0;
439  if (first_vehicle) {
440  /* Keeping the current subtype is always an option. It also serves as the option in case of no subtypes */
441  RefitOption *option = this->list[current_index].Append();
442  option->cargo = cid;
443  option->subtype = 0xFF;
444  option->string = STR_EMPTY;
445  }
446 
447  /* Check the vehicle's callback mask for cargo suffixes.
448  * This is not supported for ordered refits, since subtypes only have a meaning
449  * for a specific vehicle at a specific point in time, which conflicts with shared orders,
450  * autoreplace, autorenew, clone, order restoration, ... */
451  if (this->order == INVALID_VEH_ORDER_ID && HasBit(callback_mask, CBM_VEHICLE_CARGO_SUFFIX)) {
452  /* Make a note of the original cargo type. It has to be
453  * changed to test the cargo & subtype... */
454  CargoID temp_cargo = v->cargo_type;
455  byte temp_subtype = v->cargo_subtype;
456 
457  v->cargo_type = cid;
458 
459  for (uint refit_cyc = 0; refit_cyc < MAX_REFIT_CYCLE; refit_cyc++) {
460  v->cargo_subtype = refit_cyc;
461 
462  /* Make sure we don't pick up anything cached. */
465 
466  StringID subtype = GetCargoSubtypeText(v);
467 
468  if (first_vehicle) {
469  /* Append new subtype (don't add duplicates though) */
470  if (subtype == STR_EMPTY) break;
471 
472  RefitOption option;
473  option.cargo = cid;
474  option.subtype = refit_cyc;
475  option.string = subtype;
476  this->list[current_index].Include(option);
477  } else {
478  /* Intersect the subtypes of earlier vehicles with the subtypes of this vehicle */
479  if (subtype == STR_EMPTY) {
480  /* No more subtypes for this vehicle, delete all subtypes >= refit_cyc */
481  SubtypeList &l = this->list[current_index];
482  /* 0xFF item is in front, other subtypes are sorted. So just truncate the list in the right spot */
483  for (uint i = 1; i < l.Length(); i++) {
484  if (l[i].subtype >= refit_cyc) {
485  l.Resize(i);
486  break;
487  }
488  }
489  break;
490  } else {
491  /* Check whether the subtype matches with the subtype of earlier vehicles. */
492  uint pos = 1;
493  SubtypeList &l = this->list[current_index];
494  while (pos < l.Length() && l[pos].subtype != refit_cyc) pos++;
495  if (pos < l.Length() && l[pos].string != subtype) {
496  /* String mismatch, remove item keeping the order */
497  l.ErasePreservingOrder(pos);
498  }
499  }
500  }
501  }
502 
503  /* Reset the vehicle's cargo type */
504  v->cargo_type = temp_cargo;
505  v->cargo_subtype = temp_subtype;
506 
507  /* And make sure we haven't tainted the cache */
510  }
511  current_index++;
512  }
513  } while (v->IsGroundVehicle() && (v = v->Next()) != NULL);
514  }
515 
520  {
521  uint scroll_row = 0;
522  uint row = 0;
523 
524  for (uint i = 0; i < NUM_CARGO; i++) {
525  for (uint j = 0; j < this->list[i].Length(); j++) {
526  const RefitOption &refit = this->list[i][j];
527 
528  /* Hide subtypes if sel[0] does not match */
529  if (this->sel[0] != (int)i && refit.subtype != 0xFF) continue;
530 
531  if (this->sel[0] == (int)i && (uint)this->sel[1] == j) scroll_row = row;
532 
533  row++;
534  }
535  }
536 
537  this->vscroll->SetCount(row);
538  if (scroll_row < row) this->vscroll->ScrollTowards(scroll_row);
539  }
540 
545  void SetSelection(uint click_row)
546  {
547  uint row = 0;
548 
549  for (uint i = 0; i < NUM_CARGO; i++) {
550  for (uint j = 0; j < this->list[i].Length(); j++) {
551  const RefitOption &refit = this->list[i][j];
552 
553  /* Hide subtypes if sel[0] does not match */
554  if (this->sel[0] != (int)i && refit.subtype != 0xFF) continue;
555 
556  if (row == click_row) {
557  this->sel[0] = i;
558  this->sel[1] = j;
559  return;
560  }
561 
562  row++;
563  }
564  }
565 
566  this->sel[0] = -1;
567  this->sel[1] = 0;
568  }
569 
575  {
576  if (this->sel[0] < 0) return NULL;
577 
578  SubtypeList &l = this->list[this->sel[0]];
579  if ((uint)this->sel[1] >= l.Length()) return NULL;
580 
581  return &l[this->sel[1]];
582  }
583 
584  RefitWindow(WindowDesc *desc, const Vehicle *v, VehicleOrderID order, bool auto_refit) : Window(desc)
585  {
586  this->sel[0] = -1;
587  this->sel[1] = 0;
588  this->auto_refit = auto_refit;
589  this->order = order;
590  this->CreateNestedTree();
591 
592  this->vscroll = this->GetScrollbar(WID_VR_SCROLLBAR);
593  this->hscroll = (v->IsGroundVehicle() ? this->GetScrollbar(WID_VR_HSCROLLBAR) : NULL);
594  this->GetWidget<NWidgetCore>(WID_VR_SELECT_HEADER)->tool_tip = STR_REFIT_TRAIN_LIST_TOOLTIP + v->type;
595  this->GetWidget<NWidgetCore>(WID_VR_MATRIX)->tool_tip = STR_REFIT_TRAIN_LIST_TOOLTIP + v->type;
596  NWidgetCore *nwi = this->GetWidget<NWidgetCore>(WID_VR_REFIT);
597  nwi->widget_data = STR_REFIT_TRAIN_REFIT_BUTTON + v->type;
598  nwi->tool_tip = STR_REFIT_TRAIN_REFIT_TOOLTIP + v->type;
599  this->GetWidget<NWidgetStacked>(WID_VR_SHOW_HSCROLLBAR)->SetDisplayedPlane(v->IsGroundVehicle() ? 0 : SZSP_HORIZONTAL);
600  this->GetWidget<NWidgetCore>(WID_VR_VEHICLE_PANEL_DISPLAY)->tool_tip = (v->type == VEH_TRAIN) ? STR_REFIT_SELECT_VEHICLES_TOOLTIP : STR_NULL;
601 
602  this->FinishInitNested(v->index);
603  this->owner = v->owner;
604 
605  this->SetWidgetDisabledState(WID_VR_REFIT, this->sel[0] < 0);
606  }
607 
608  virtual void OnInit()
609  {
610  if (this->cargo != NULL) {
611  /* Store the RefitOption currently in use. */
612  RefitOption current_refit_option = *(this->cargo);
613 
614  /* Rebuild the refit list */
615  this->BuildRefitList();
616  this->sel[0] = -1;
617  this->sel[1] = 0;
618  this->cargo = NULL;
619  for (uint i = 0; this->cargo == NULL && i < NUM_CARGO; i++) {
620  for (uint j = 0; j < list[i].Length(); j++) {
621  if (list[i][j] == current_refit_option) {
622  this->sel[0] = i;
623  this->sel[1] = j;
624  this->cargo = &list[i][j];
625  break;
626  }
627  }
628  }
629 
630  this->SetWidgetDisabledState(WID_VR_REFIT, this->sel[0] < 0);
631  this->RefreshScrollbar();
632  } else {
633  /* Rebuild the refit list */
635  }
636  }
637 
638  virtual void OnPaint()
639  {
640  /* Determine amount of items for scroller. */
641  if (this->hscroll != NULL) this->hscroll->SetCount(this->vehicle_width);
642 
643  /* Calculate sprite position. */
644  NWidgetCore *vehicle_panel_display = this->GetWidget<NWidgetCore>(WID_VR_VEHICLE_PANEL_DISPLAY);
645  int sprite_width = max(0, ((int)vehicle_panel_display->current_x - this->vehicle_width) / 2);
646  this->sprite_left = vehicle_panel_display->pos_x;
647  this->sprite_right = vehicle_panel_display->pos_x + vehicle_panel_display->current_x - 1;
648  if (_current_text_dir == TD_RTL) {
649  this->sprite_right -= sprite_width;
650  this->vehicle_margin = vehicle_panel_display->current_x - sprite_right;
651  } else {
652  this->sprite_left += sprite_width;
653  this->vehicle_margin = sprite_left;
654  }
655 
656  this->DrawWidgets();
657  }
658 
659  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
660  {
661  switch (widget) {
662  case WID_VR_MATRIX:
664  size->height = resize->height * 8;
665  break;
666 
668  size->height = ScaleGUITrad(GetVehicleHeight(Vehicle::Get(this->window_number)->type));
669  break;
670 
671  case WID_VR_INFO:
672  size->width = WD_FRAMERECT_LEFT + this->information_width + WD_FRAMERECT_RIGHT;
673  break;
674  }
675  }
676 
677  virtual void SetStringParameters(int widget) const
678  {
679  if (widget == WID_VR_CAPTION) SetDParam(0, Vehicle::Get(this->window_number)->index);
680  }
681 
689  {
690  assert(_current_company == _local_company);
691  Vehicle *v = Vehicle::Get(this->window_number);
692  CommandCost cost = DoCommand(v->tile, this->selected_vehicle, option->cargo | option->subtype << 8 | this->num_vehicles << 16 |
693  (int)this->auto_refit << 24, DC_QUERY_COST, GetCmdRefitVeh(v->type));
694 
695  if (cost.Failed()) return INVALID_STRING_ID;
696 
697  SetDParam(0, option->cargo);
699 
700  Money money = cost.GetCost();
702  SetDParam(2, CT_MAIL);
704  if (this->order != INVALID_VEH_ORDER_ID) {
705  /* No predictable cost */
706  return STR_PURCHASE_INFO_AIRCRAFT_CAPACITY;
707  } else if (money <= 0) {
708  SetDParam(4, -money);
709  return STR_REFIT_NEW_CAPACITY_INCOME_FROM_AIRCRAFT_REFIT;
710  } else {
711  SetDParam(4, money);
712  return STR_REFIT_NEW_CAPACITY_COST_OF_AIRCRAFT_REFIT;
713  }
714  } else {
715  if (this->order != INVALID_VEH_ORDER_ID) {
716  /* No predictable cost */
717  SetDParam(2, STR_EMPTY);
718  return STR_PURCHASE_INFO_CAPACITY;
719  } else if (money <= 0) {
720  SetDParam(2, -money);
721  return STR_REFIT_NEW_CAPACITY_INCOME_FROM_REFIT;
722  } else {
723  SetDParam(2, money);
724  return STR_REFIT_NEW_CAPACITY_COST_OF_REFIT;
725  }
726  }
727  }
728 
729  virtual void DrawWidget(const Rect &r, int widget) const
730  {
731  switch (widget) {
733  Vehicle *v = Vehicle::Get(this->window_number);
734  DrawVehicleImage(v, this->sprite_left + WD_FRAMERECT_LEFT, this->sprite_right - WD_FRAMERECT_RIGHT,
735  r.top + WD_FRAMERECT_TOP, INVALID_VEHICLE, EIT_IN_DETAILS, this->hscroll != NULL ? this->hscroll->GetPosition() : 0);
736 
737  /* Highlight selected vehicles. */
738  if (this->order != INVALID_VEH_ORDER_ID) break;
739  int x = 0;
740  switch (v->type) {
741  case VEH_TRAIN: {
742  VehicleSet vehicles_to_refit;
743  GetVehicleSet(vehicles_to_refit, Vehicle::Get(this->selected_vehicle), this->num_vehicles);
744 
745  int left = INT32_MIN;
746  int width = 0;
747 
748  for (Train *u = Train::From(v); u != NULL; u = u->Next()) {
749  /* Start checking. */
750  if (vehicles_to_refit.Contains(u->index) && left == INT32_MIN) {
751  left = x - this->hscroll->GetPosition() + r.left + this->vehicle_margin;
752  width = 0;
753  }
754 
755  /* Draw a selection. */
756  if ((!vehicles_to_refit.Contains(u->index) || u->Next() == NULL) && left != INT32_MIN) {
757  if (u->Next() == NULL && vehicles_to_refit.Contains(u->index)) {
758  int current_width = u->GetDisplayImageWidth();
759  width += current_width;
760  x += current_width;
761  }
762 
763  int right = Clamp(left + width, 0, r.right);
764  left = max(0, left);
765 
766  if (_current_text_dir == TD_RTL) {
767  right = this->GetWidget<NWidgetCore>(WID_VR_VEHICLE_PANEL_DISPLAY)->current_x - left;
768  left = right - width;
769  }
770 
771  if (left != right) {
772  DrawFrameRect(left, r.top + WD_FRAMERECT_TOP, right, r.top + WD_FRAMERECT_TOP + ScaleGUITrad(14) - 1, COLOUR_WHITE, FR_BORDERONLY);
773  }
774 
775  left = INT32_MIN;
776  }
777 
778  int current_width = u->GetDisplayImageWidth();
779  width += current_width;
780  x += current_width;
781  }
782  break;
783  }
784 
785  default: break;
786  }
787  break;
788  }
789 
790  case WID_VR_MATRIX:
791  DrawVehicleRefitWindow(this->list, this->sel, this->vscroll->GetPosition(), this->vscroll->GetCapacity(), this->resize.step_height, r);
792  break;
793 
794  case WID_VR_INFO:
795  if (this->cargo != NULL) {
796  StringID string = this->GetCapacityString(this->cargo);
797  if (string != INVALID_STRING_ID) {
799  r.top + WD_FRAMERECT_TOP, r.bottom - WD_FRAMERECT_BOTTOM, string);
800  }
801  }
802  break;
803  }
804  }
805 
811  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
812  {
813  switch (data) {
814  case VIWD_AUTOREPLACE: // Autoreplace replaced the vehicle; selected_vehicle became invalid.
815  case VIWD_CONSIST_CHANGED: { // The consist has changed; rebuild the entire list.
816  /* Clear the selection. */
817  Vehicle *v = Vehicle::Get(this->window_number);
818  this->selected_vehicle = v->index;
819  this->num_vehicles = UINT8_MAX;
820  FALLTHROUGH;
821  }
822 
823  case 2: { // The vehicle selection has changed; rebuild the entire list.
824  if (!gui_scope) break;
825  this->BuildRefitList();
826 
827  /* The vehicle width has changed too. */
828  this->vehicle_width = GetVehicleWidth(Vehicle::Get(this->window_number), EIT_IN_DETAILS);
829  uint max_width = 0;
830 
831  /* Check the width of all cargo information strings. */
832  for (uint i = 0; i < NUM_CARGO; i++) {
833  for (uint j = 0; j < this->list[i].Length(); j++) {
834  StringID string = this->GetCapacityString(&list[i][j]);
835  if (string != INVALID_STRING_ID) {
836  Dimension dim = GetStringBoundingBox(string);
837  max_width = max(dim.width, max_width);
838  }
839  }
840  }
841 
842  if (this->information_width < max_width) {
843  this->information_width = max_width;
844  this->ReInit();
845  }
846  FALLTHROUGH;
847  }
848 
849  case 1: // A new cargo has been selected.
850  if (!gui_scope) break;
851  this->cargo = GetRefitOption();
852  this->RefreshScrollbar();
853  break;
854  }
855  }
856 
857  int GetClickPosition(int click_x)
858  {
859  const NWidgetCore *matrix_widget = this->GetWidget<NWidgetCore>(WID_VR_VEHICLE_PANEL_DISPLAY);
860  if (_current_text_dir == TD_RTL) click_x = matrix_widget->current_x - click_x;
861  click_x -= this->vehicle_margin;
862  if (this->hscroll != NULL) click_x += this->hscroll->GetPosition();
863 
864  return click_x;
865  }
866 
867  void SetSelectedVehicles(int drag_x)
868  {
869  drag_x = GetClickPosition(drag_x);
870 
871  int left_x = min(this->click_x, drag_x);
872  int right_x = max(this->click_x, drag_x);
873  this->num_vehicles = 0;
874 
875  Vehicle *v = Vehicle::Get(this->window_number);
876  /* Find the vehicle part that was clicked. */
877  switch (v->type) {
878  case VEH_TRAIN: {
879  /* Don't select anything if we are not clicking in the vehicle. */
880  if (left_x >= 0) {
881  const Train *u = Train::From(v);
882  bool start_counting = false;
883  for (; u != NULL; u = u->Next()) {
884  int current_width = u->GetDisplayImageWidth();
885  left_x -= current_width;
886  right_x -= current_width;
887 
888  if (left_x < 0 && !start_counting) {
889  this->selected_vehicle = u->index;
890  start_counting = true;
891 
892  /* Count the first vehicle, even if articulated part */
893  this->num_vehicles++;
894  } else if (start_counting && !u->IsArticulatedPart()) {
895  /* Do not count articulated parts */
896  this->num_vehicles++;
897  }
898 
899  if (right_x < 0) break;
900  }
901  }
902 
903  /* If the selection is not correct, clear it. */
904  if (this->num_vehicles != 0) {
905  if (_ctrl_pressed) this->num_vehicles = UINT8_MAX;
906  break;
907  }
908  FALLTHROUGH;
909  }
910 
911  default:
912  /* Clear the selection. */
913  this->selected_vehicle = v->index;
914  this->num_vehicles = UINT8_MAX;
915  break;
916  }
917  }
918 
919  virtual void OnClick(Point pt, int widget, int click_count)
920  {
921  switch (widget) {
922  case WID_VR_VEHICLE_PANEL_DISPLAY: { // Vehicle image.
923  if (this->order != INVALID_VEH_ORDER_ID) break;
924  NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_VR_VEHICLE_PANEL_DISPLAY);
925  this->click_x = GetClickPosition(pt.x - nwi->pos_x);
926  this->SetSelectedVehicles(pt.x - nwi->pos_x);
928  if (!_ctrl_pressed) {
929  SetObjectToPlaceWnd(SPR_CURSOR_MOUSE, PAL_NONE, HT_DRAG, this);
930  } else {
931  /* The vehicle selection has changed. */
932  this->InvalidateData(2);
933  }
934  break;
935  }
936 
937  case WID_VR_MATRIX: { // listbox
938  this->SetSelection(this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_VR_MATRIX));
939  this->SetWidgetDisabledState(WID_VR_REFIT, this->sel[0] < 0);
940  this->InvalidateData(1);
941 
942  if (click_count == 1) break;
943  FALLTHROUGH;
944  }
945 
946  case WID_VR_REFIT: // refit button
947  if (this->cargo != NULL) {
948  const Vehicle *v = Vehicle::Get(this->window_number);
949 
950  if (this->order == INVALID_VEH_ORDER_ID) {
951  bool delete_window = this->selected_vehicle == v->index && this->num_vehicles == UINT8_MAX;
952  if (DoCommandP(v->tile, this->selected_vehicle, this->cargo->cargo | this->cargo->subtype << 8 | this->num_vehicles << 16, GetCmdRefitVeh(v)) && delete_window) delete this;
953  } else {
954  if (DoCommandP(v->tile, v->index, this->cargo->cargo | this->order << 16, CMD_ORDER_REFIT)) delete this;
955  }
956  }
957  break;
958  }
959  }
960 
961  virtual void OnMouseDrag(Point pt, int widget)
962  {
963  switch (widget) {
964  case WID_VR_VEHICLE_PANEL_DISPLAY: { // Vehicle image.
965  if (this->order != INVALID_VEH_ORDER_ID) break;
966  NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_VR_VEHICLE_PANEL_DISPLAY);
967  this->SetSelectedVehicles(pt.x - nwi->pos_x);
969  break;
970  }
971  }
972  }
973 
974  virtual void OnDragDrop(Point pt, int widget)
975  {
976  switch (widget) {
977  case WID_VR_VEHICLE_PANEL_DISPLAY: { // Vehicle image.
978  if (this->order != INVALID_VEH_ORDER_ID) break;
979  NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_VR_VEHICLE_PANEL_DISPLAY);
980  this->SetSelectedVehicles(pt.x - nwi->pos_x);
981  this->InvalidateData(2);
982  break;
983  }
984  }
985  }
986 
987  virtual void OnResize()
988  {
989  this->vehicle_width = GetVehicleWidth(Vehicle::Get(this->window_number), EIT_IN_DETAILS);
990  this->vscroll->SetCapacityFromWidget(this, WID_VR_MATRIX);
991  if (this->hscroll != NULL) this->hscroll->SetCapacityFromWidget(this, WID_VR_VEHICLE_PANEL_DISPLAY);
992  }
993 };
994 
995 static const NWidgetPart _nested_vehicle_refit_widgets[] = {
997  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
998  NWidget(WWT_CAPTION, COLOUR_GREY, WID_VR_CAPTION), SetDataTip(STR_REFIT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
999  NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1000  EndContainer(),
1001  /* Vehicle display + scrollbar. */
1004  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_VR_SHOW_HSCROLLBAR),
1005  NWidget(NWID_HSCROLLBAR, COLOUR_GREY, WID_VR_HSCROLLBAR),
1006  EndContainer(),
1007  EndContainer(),
1008  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_VR_SELECT_HEADER), SetDataTip(STR_REFIT_TITLE, STR_NULL), SetResize(1, 0),
1009  /* Matrix + scrollbar. */
1011  NWidget(WWT_MATRIX, COLOUR_GREY, WID_VR_MATRIX), SetMinimalSize(228, 112), SetResize(1, 14), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_NULL), SetScrollbar(WID_VR_SCROLLBAR),
1012  NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_VR_SCROLLBAR),
1013  EndContainer(),
1016  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VR_REFIT), SetFill(1, 0), SetResize(1, 0),
1017  NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1018  EndContainer(),
1019 };
1020 
1021 static WindowDesc _vehicle_refit_desc(
1022  WDP_AUTO, "view_vehicle_refit", 240, 174,
1025  _nested_vehicle_refit_widgets, lengthof(_nested_vehicle_refit_widgets)
1026 );
1027 
1035 void ShowVehicleRefitWindow(const Vehicle *v, VehicleOrderID order, Window *parent, bool auto_refit)
1036 {
1038  RefitWindow *w = new RefitWindow(&_vehicle_refit_desc, v, order, auto_refit);
1039  w->parent = parent;
1040 }
1041 
1043 uint ShowRefitOptionsList(int left, int right, int y, EngineID engine)
1044 {
1045  /* List of cargo types of this engine */
1046  CargoTypes cmask = GetUnionOfArticulatedRefitMasks(engine, false);
1047  /* List of cargo types available in this climate */
1048  CargoTypes lmask = _cargo_mask;
1049 
1050  /* Draw nothing if the engine is not refittable */
1051  if (HasAtMostOneBit(cmask)) return y;
1052 
1053  if (cmask == lmask) {
1054  /* Engine can be refitted to all types in this climate */
1055  SetDParam(0, STR_PURCHASE_INFO_ALL_TYPES);
1056  } else {
1057  /* Check if we are able to refit to more cargo types and unable to. If
1058  * so, invert the cargo types to list those that we can't refit to. */
1059  if (CountBits(cmask ^ lmask) < CountBits(cmask) && CountBits(cmask ^ lmask) <= 7) {
1060  cmask ^= lmask;
1061  SetDParam(0, STR_PURCHASE_INFO_ALL_BUT);
1062  } else {
1063  SetDParam(0, STR_JUST_CARGO_LIST);
1064  }
1065  SetDParam(1, cmask);
1066  }
1067 
1068  return DrawStringMultiLine(left, right, y, INT32_MAX, STR_PURCHASE_INFO_REFITTABLE_TO);
1069 }
1070 
1073 {
1074  if (HasBit(EngInfo(v->engine_type)->callback_mask, CBM_VEHICLE_CARGO_SUFFIX)) {
1075  uint16 cb = GetVehicleCallback(CBID_VEHICLE_CARGO_SUFFIX, 0, 0, v->engine_type, v);
1076  if (cb != CALLBACK_FAILED) {
1078  if (cb >= 0x400 || (v->GetGRF()->grf_version < 8 && cb == 0xFF)) cb = CALLBACK_FAILED;
1079  }
1080  if (cb != CALLBACK_FAILED) {
1081  return GetGRFStringID(v->GetGRFID(), 0xD000 + cb);
1082  }
1083  }
1084  return STR_EMPTY;
1085 }
1086 
1088 static int CDECL VehicleNumberSorter(const Vehicle * const *a, const Vehicle * const *b)
1089 {
1090  return (*a)->unitnumber - (*b)->unitnumber;
1091 }
1092 
1094 static int CDECL VehicleNameSorter(const Vehicle * const *a, const Vehicle * const *b)
1095 {
1096  static char last_name[2][64];
1097 
1098  if (*a != _last_vehicle[0]) {
1099  _last_vehicle[0] = *a;
1100  SetDParam(0, (*a)->index);
1101  GetString(last_name[0], STR_VEHICLE_NAME, lastof(last_name[0]));
1102  }
1103 
1104  if (*b != _last_vehicle[1]) {
1105  _last_vehicle[1] = *b;
1106  SetDParam(0, (*b)->index);
1107  GetString(last_name[1], STR_VEHICLE_NAME, lastof(last_name[1]));
1108  }
1109 
1110  int r = strnatcmp(last_name[0], last_name[1]); // Sort by name (natural sorting).
1111  return (r != 0) ? r : VehicleNumberSorter(a, b);
1112 }
1113 
1115 static int CDECL VehicleAgeSorter(const Vehicle * const *a, const Vehicle * const *b)
1116 {
1117  int r = (*a)->age - (*b)->age;
1118  return (r != 0) ? r : VehicleNumberSorter(a, b);
1119 }
1120 
1122 static int CDECL VehicleProfitThisYearSorter(const Vehicle * const *a, const Vehicle * const *b)
1123 {
1124  int r = ClampToI32((*a)->GetDisplayProfitThisYear() - (*b)->GetDisplayProfitThisYear());
1125  return (r != 0) ? r : VehicleNumberSorter(a, b);
1126 }
1127 
1129 static int CDECL VehicleProfitLastYearSorter(const Vehicle * const *a, const Vehicle * const *b)
1130 {
1131  int r = ClampToI32((*a)->GetDisplayProfitLastYear() - (*b)->GetDisplayProfitLastYear());
1132  return (r != 0) ? r : VehicleNumberSorter(a, b);
1133 }
1134 
1136 static int CDECL VehicleCargoSorter(const Vehicle * const *a, const Vehicle * const *b)
1137 {
1138  const Vehicle *v;
1139  CargoArray diff;
1140 
1141  /* Append the cargo of the connected waggons */
1142  for (v = *a; v != NULL; v = v->Next()) diff[v->cargo_type] += v->cargo_cap;
1143  for (v = *b; v != NULL; v = v->Next()) diff[v->cargo_type] -= v->cargo_cap;
1144 
1145  int r = 0;
1146  for (CargoID i = 0; i < NUM_CARGO; i++) {
1147  r = diff[i];
1148  if (r != 0) break;
1149  }
1150 
1151  return (r != 0) ? r : VehicleNumberSorter(a, b);
1152 }
1153 
1155 static int CDECL VehicleReliabilitySorter(const Vehicle * const *a, const Vehicle * const *b)
1156 {
1157  int r = (*a)->reliability - (*b)->reliability;
1158  return (r != 0) ? r : VehicleNumberSorter(a, b);
1159 }
1160 
1162 static int CDECL VehicleMaxSpeedSorter(const Vehicle * const *a, const Vehicle * const *b)
1163 {
1164  int r = (*a)->vcache.cached_max_speed - (*b)->vcache.cached_max_speed;
1165  return (r != 0) ? r : VehicleNumberSorter(a, b);
1166 }
1167 
1169 static int CDECL VehicleModelSorter(const Vehicle * const *a, const Vehicle * const *b)
1170 {
1171  int r = (*a)->engine_type - (*b)->engine_type;
1172  return (r != 0) ? r : VehicleNumberSorter(a, b);
1173 }
1174 
1176 static int CDECL VehicleValueSorter(const Vehicle * const *a, const Vehicle * const *b)
1177 {
1178  const Vehicle *u;
1179  Money diff = 0;
1180 
1181  for (u = *a; u != NULL; u = u->Next()) diff += u->value;
1182  for (u = *b; u != NULL; u = u->Next()) diff -= u->value;
1183 
1184  int r = ClampToI32(diff);
1185  return (r != 0) ? r : VehicleNumberSorter(a, b);
1186 }
1187 
1189 static int CDECL VehicleLengthSorter(const Vehicle * const *a, const Vehicle * const *b)
1190 {
1191  int r = (*a)->GetGroundVehicleCache()->cached_total_length - (*b)->GetGroundVehicleCache()->cached_total_length;
1192  return (r != 0) ? r : VehicleNumberSorter(a, b);
1193 }
1194 
1196 static int CDECL VehicleTimeToLiveSorter(const Vehicle * const *a, const Vehicle * const *b)
1197 {
1198  int r = ClampToI32(((*a)->max_age - (*a)->age) - ((*b)->max_age - (*b)->age));
1199  return (r != 0) ? r : VehicleNumberSorter(a, b);
1200 }
1201 
1203 static int CDECL VehicleTimetableDelaySorter(const Vehicle * const *a, const Vehicle * const *b)
1204 {
1205  int r = (*a)->lateness_counter - (*b)->lateness_counter;
1206  return (r != 0) ? r : VehicleNumberSorter(a, b);
1207 }
1208 
1209 void InitializeGUI()
1210 {
1211  MemSetT(&_sorting, 0);
1212 }
1213 
1220 static inline void ChangeVehicleWindow(WindowClass window_class, VehicleID from_index, VehicleID to_index)
1221 {
1222  Window *w = FindWindowById(window_class, from_index);
1223  if (w != NULL) {
1224  /* Update window_number */
1225  w->window_number = to_index;
1226  if (w->viewport != NULL) w->viewport->follow_vehicle = to_index;
1227 
1228  /* Update vehicle drag data */
1229  if (_thd.window_class == window_class && _thd.window_number == (WindowNumber)from_index) {
1230  _thd.window_number = to_index;
1231  }
1232 
1233  /* Notify the window. */
1234  w->InvalidateData(VIWD_AUTOREPLACE, false);
1235  }
1236 }
1237 
1243 void ChangeVehicleViewWindow(VehicleID from_index, VehicleID to_index)
1244 {
1245  ChangeVehicleWindow(WC_VEHICLE_VIEW, from_index, to_index);
1246  ChangeVehicleWindow(WC_VEHICLE_ORDERS, from_index, to_index);
1247  ChangeVehicleWindow(WC_VEHICLE_REFIT, from_index, to_index);
1248  ChangeVehicleWindow(WC_VEHICLE_DETAILS, from_index, to_index);
1249  ChangeVehicleWindow(WC_VEHICLE_TIMETABLE, from_index, to_index);
1250 }
1251 
1252 static const NWidgetPart _nested_vehicle_list[] = {
1254  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1255  NWidget(WWT_CAPTION, COLOUR_GREY, WID_VL_CAPTION),
1256  NWidget(WWT_SHADEBOX, COLOUR_GREY),
1257  NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1258  NWidget(WWT_STICKYBOX, COLOUR_GREY),
1259  EndContainer(),
1260 
1262  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VL_SORT_ORDER), SetMinimalSize(81, 12), SetFill(0, 1), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
1263  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VL_SORT_BY_PULLDOWN), SetMinimalSize(167, 12), SetFill(0, 1), SetDataTip(0x0, STR_TOOLTIP_SORT_CRITERIA),
1264  NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(12, 12), SetFill(1, 1), SetResize(1, 0),
1265  EndContainer(),
1266  EndContainer(),
1267 
1269  NWidget(WWT_MATRIX, COLOUR_GREY, WID_VL_LIST), SetMinimalSize(248, 0), SetFill(1, 0), SetResize(1, 1), SetMatrixDataTip(1, 0, STR_NULL), SetScrollbar(WID_VL_SCROLLBAR),
1270  NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_VL_SCROLLBAR),
1271  EndContainer(),
1272 
1274  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_VL_HIDE_BUTTONS),
1276  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VL_AVAILABLE_VEHICLES), SetMinimalSize(106, 12), SetFill(0, 1),
1277  SetDataTip(STR_BLACK_STRING, STR_VEHICLE_LIST_AVAILABLE_ENGINES_TOOLTIP),
1278  NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(0, 12), SetResize(1, 0), SetFill(1, 1), EndContainer(),
1280  SetDataTip(STR_VEHICLE_LIST_MANAGE_LIST, STR_VEHICLE_LIST_MANAGE_LIST_TOOLTIP),
1281  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VL_STOP_ALL), SetMinimalSize(12, 12), SetFill(0, 1),
1282  SetDataTip(SPR_FLAG_VEH_STOPPED, STR_VEHICLE_LIST_MASS_STOP_LIST_TOOLTIP),
1283  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VL_START_ALL), SetMinimalSize(12, 12), SetFill(0, 1),
1284  SetDataTip(SPR_FLAG_VEH_RUNNING, STR_VEHICLE_LIST_MASS_START_LIST_TOOLTIP),
1285  EndContainer(),
1286  /* Widget to be shown for other companies hiding the previous 5 widgets. */
1287  NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 1), SetResize(1, 0), EndContainer(),
1288  EndContainer(),
1289  NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1290  EndContainer(),
1291 };
1292 
1293 static void DrawSmallOrderList(const Vehicle *v, int left, int right, int y, VehicleOrderID start = 0)
1294 {
1295  const Order *order = v->GetOrder(start);
1296  if (order == NULL) return;
1297 
1298  bool rtl = _current_text_dir == TD_RTL;
1299  int l_offset = rtl ? 0 : ScaleGUITrad(6);
1300  int r_offset = rtl ? ScaleGUITrad(6) : 0;
1301  int i = 0;
1302  VehicleOrderID oid = start;
1303 
1304  do {
1305  if (oid == v->cur_real_order_index) DrawString(left, right, y, STR_TINY_RIGHT_ARROW, TC_BLACK);
1306 
1307  if (order->IsType(OT_GOTO_STATION)) {
1308  SetDParam(0, order->GetDestination());
1309  DrawString(left + l_offset, right - r_offset, y, STR_TINY_BLACK_STATION);
1310 
1311  y += FONT_HEIGHT_SMALL;
1312  if (++i == 4) break;
1313  }
1314 
1315  oid++;
1316  order = order->next;
1317  if (order == NULL) {
1318  order = v->orders.list->GetFirstOrder();
1319  oid = 0;
1320  }
1321  } while (oid != start);
1322 }
1323 
1333 void DrawVehicleImage(const Vehicle *v, int left, int right, int y, VehicleID selection, EngineImageType image_type, int skip)
1334 {
1335  switch (v->type) {
1336  case VEH_TRAIN: DrawTrainImage(Train::From(v), left, right, y, selection, image_type, skip); break;
1337  case VEH_ROAD: DrawRoadVehImage(v, left, right, y, selection, image_type, skip); break;
1338  case VEH_SHIP: DrawShipImage(v, left, right, y, selection, image_type); break;
1339  case VEH_AIRCRAFT: DrawAircraftImage(v, left, right, y, selection, image_type); break;
1340  default: NOT_REACHED();
1341  }
1342 }
1343 
1350 uint GetVehicleListHeight(VehicleType type, uint divisor)
1351 {
1352  /* Name + vehicle + profit */
1353  uint base = ScaleGUITrad(GetVehicleHeight(type)) + 2 * FONT_HEIGHT_SMALL;
1354  /* Drawing of the 4 small orders + profit*/
1355  if (type >= VEH_SHIP) base = max(base, 5U * FONT_HEIGHT_SMALL);
1356 
1357  if (divisor == 1) return base;
1358 
1359  /* Make sure the height is dividable by divisor */
1360  uint rem = base % divisor;
1361  return base + (rem == 0 ? 0 : divisor - rem);
1362 }
1363 
1370 void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int line_height, const Rect &r) const
1371 {
1372  int left = r.left + WD_MATRIX_LEFT;
1373  int right = r.right - WD_MATRIX_RIGHT;
1374  int width = right - left;
1375  bool rtl = _current_text_dir == TD_RTL;
1376 
1377  int text_offset = max<int>(GetSpriteSize(SPR_PROFIT_LOT).width, GetDigitWidth() * this->unitnumber_digits) + WD_FRAMERECT_RIGHT;
1378  int text_left = left + (rtl ? 0 : text_offset);
1379  int text_right = right - (rtl ? text_offset : 0);
1380 
1381  bool show_orderlist = this->vli.vtype >= VEH_SHIP;
1382  int orderlist_left = left + (rtl ? 0 : max(ScaleGUITrad(100) + text_offset, width / 2));
1383  int orderlist_right = right - (rtl ? max(ScaleGUITrad(100) + text_offset, width / 2) : 0);
1384 
1385  int image_left = (rtl && show_orderlist) ? orderlist_right : text_left;
1386  int image_right = (!rtl && show_orderlist) ? orderlist_left : text_right;
1387 
1388  int vehicle_button_x = rtl ? right - GetSpriteSize(SPR_PROFIT_LOT).width : left;
1389 
1390  int y = r.top;
1391  uint max = min(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), this->vehicles.Length());
1392  for (uint i = this->vscroll->GetPosition(); i < max; ++i) {
1393  const Vehicle *v = this->vehicles[i];
1394  StringID str;
1395 
1398 
1399  DrawVehicleImage(v, image_left, image_right, y + FONT_HEIGHT_SMALL - 1, selected_vehicle, EIT_IN_LIST, 0);
1400  DrawString(text_left, text_right, y + line_height - FONT_HEIGHT_SMALL - WD_FRAMERECT_BOTTOM - 1, STR_VEHICLE_LIST_PROFIT_THIS_YEAR_LAST_YEAR);
1401 
1402  if (v->name != NULL) {
1403  /* The vehicle got a name so we will print it */
1404  SetDParam(0, v->index);
1405  DrawString(text_left, text_right, y, STR_TINY_BLACK_VEHICLE);
1406  } else if (v->group_id != DEFAULT_GROUP) {
1407  /* The vehicle has no name, but is member of a group, so print group name */
1408  SetDParam(0, v->group_id);
1409  DrawString(text_left, text_right, y, STR_TINY_GROUP, TC_BLACK);
1410  }
1411 
1412  if (show_orderlist) DrawSmallOrderList(v, orderlist_left, orderlist_right, y, v->cur_real_order_index);
1413 
1414  if (v->IsChainInDepot()) {
1415  str = STR_BLUE_COMMA;
1416  } else {
1417  str = (v->age > v->max_age - DAYS_IN_LEAP_YEAR) ? STR_RED_COMMA : STR_BLACK_COMMA;
1418  }
1419 
1420  SetDParam(0, v->unitnumber);
1421  DrawString(left, right, y + 2, str);
1422 
1423  DrawVehicleProfitButton(v, vehicle_button_x, y + FONT_HEIGHT_NORMAL + 3);
1424 
1425  y += line_height;
1426  }
1427 }
1428 
1439 private:
1444  };
1445 
1446 public:
1448  {
1449  /* Set up sorting. Make the window-specific _sorting variable
1450  * point to the correct global _sorting struct so we are freed
1451  * from having conditionals during window operation */
1452  switch (this->vli.vtype) {
1453  case VEH_TRAIN: this->sorting = &_sorting.train; break;
1454  case VEH_ROAD: this->sorting = &_sorting.roadveh; break;
1455  case VEH_SHIP: this->sorting = &_sorting.ship; break;
1456  case VEH_AIRCRAFT: this->sorting = &_sorting.aircraft; break;
1457  default: NOT_REACHED();
1458  }
1459 
1460  this->CreateNestedTree();
1461 
1462  this->vscroll = this->GetScrollbar(WID_VL_SCROLLBAR);
1463 
1464  this->vehicles.SetListing(*this->sorting);
1465  this->vehicles.ForceRebuild();
1466  this->vehicles.NeedResort();
1467  this->BuildVehicleList();
1468  this->SortVehicleList();
1469 
1470  /* Set up the window widgets */
1471  this->GetWidget<NWidgetCore>(WID_VL_LIST)->tool_tip = STR_VEHICLE_LIST_TRAIN_LIST_TOOLTIP + this->vli.vtype;
1472 
1473  if (this->vli.type == VL_SHARED_ORDERS) {
1474  this->GetWidget<NWidgetCore>(WID_VL_CAPTION)->widget_data = STR_VEHICLE_LIST_SHARED_ORDERS_LIST_CAPTION;
1475  } else {
1476  this->GetWidget<NWidgetCore>(WID_VL_CAPTION)->widget_data = STR_VEHICLE_LIST_TRAIN_CAPTION + this->vli.vtype;
1477  }
1478 
1479  this->FinishInitNested(window_number);
1480  if (this->vli.company != OWNER_NONE) this->owner = this->vli.company;
1481  }
1482 
1484  {
1485  *this->sorting = this->vehicles.GetListing();
1486  }
1487 
1488  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1489  {
1490  switch (widget) {
1491  case WID_VL_LIST:
1492  resize->height = GetVehicleListHeight(this->vli.vtype, 1);
1493 
1494  switch (this->vli.vtype) {
1495  case VEH_TRAIN:
1496  case VEH_ROAD:
1497  size->height = 6 * resize->height;
1498  break;
1499  case VEH_SHIP:
1500  case VEH_AIRCRAFT:
1501  size->height = 4 * resize->height;
1502  break;
1503  default: NOT_REACHED();
1504  }
1505  break;
1506 
1507  case WID_VL_SORT_ORDER: {
1508  Dimension d = GetStringBoundingBox(this->GetWidget<NWidgetCore>(widget)->widget_data);
1509  d.width += padding.width + Window::SortButtonWidth() * 2; // Doubled since the string is centred and it also looks better.
1510  d.height += padding.height;
1511  *size = maxdim(*size, d);
1512  break;
1513  }
1514 
1516  Dimension d = this->GetActionDropdownSize(this->vli.type == VL_STANDARD, false);
1517  d.height += padding.height;
1518  d.width += padding.width;
1519  *size = maxdim(*size, d);
1520  break;
1521  }
1522  }
1523  }
1524 
1525  virtual void SetStringParameters(int widget) const
1526  {
1527  switch (widget) {
1529  SetDParam(0, STR_VEHICLE_LIST_AVAILABLE_TRAINS + this->vli.vtype);
1530  break;
1531 
1532  case WID_VL_CAPTION: {
1533  switch (this->vli.type) {
1534  case VL_SHARED_ORDERS: // Shared Orders
1535  if (this->vehicles.Length() == 0) {
1536  /* We can't open this window without vehicles using this order
1537  * and we should close the window when deleting the order. */
1538  NOT_REACHED();
1539  }
1540  SetDParam(0, this->vscroll->GetCount());
1541  break;
1542 
1543  case VL_STANDARD: // Company Name
1544  SetDParam(0, STR_COMPANY_NAME);
1545  SetDParam(1, this->vli.index);
1546  SetDParam(3, this->vscroll->GetCount());
1547  break;
1548 
1549  case VL_STATION_LIST: // Station/Waypoint Name
1550  SetDParam(0, Station::IsExpected(BaseStation::Get(this->vli.index)) ? STR_STATION_NAME : STR_WAYPOINT_NAME);
1551  SetDParam(1, this->vli.index);
1552  SetDParam(3, this->vscroll->GetCount());
1553  break;
1554 
1555  case VL_DEPOT_LIST:
1556  SetDParam(0, STR_DEPOT_CAPTION);
1557  SetDParam(1, this->vli.vtype);
1558  SetDParam(2, this->vli.index);
1559  SetDParam(3, this->vscroll->GetCount());
1560  break;
1561  default: NOT_REACHED();
1562  }
1563  break;
1564  }
1565  }
1566  }
1567 
1568  virtual void DrawWidget(const Rect &r, int widget) const
1569  {
1570  switch (widget) {
1571  case WID_VL_SORT_ORDER:
1572  /* draw arrow pointing up/down for ascending/descending sorting */
1573  this->DrawSortButtonState(widget, this->vehicles.IsDescSortOrder() ? SBS_DOWN : SBS_UP);
1574  break;
1575 
1576  case WID_VL_LIST:
1578  break;
1579  }
1580  }
1581 
1582  virtual void OnPaint()
1583  {
1584  this->BuildVehicleList();
1585  this->SortVehicleList();
1586 
1587  if (this->vehicles.Length() == 0 && this->IsWidgetLowered(WID_VL_MANAGE_VEHICLES_DROPDOWN)) {
1588  HideDropDownMenu(this);
1589  }
1590 
1591  /* Hide the widgets that we will not use in this window
1592  * Some windows contains actions only fit for the owner */
1593  int plane_to_show = (this->owner == _local_company) ? BP_SHOW_BUTTONS : BP_HIDE_BUTTONS;
1594  NWidgetStacked *nwi = this->GetWidget<NWidgetStacked>(WID_VL_HIDE_BUTTONS);
1595  if (plane_to_show != nwi->shown_plane) {
1596  nwi->SetDisplayedPlane(plane_to_show);
1597  nwi->SetDirty(this);
1598  }
1599  if (this->owner == _local_company) {
1600  this->SetWidgetDisabledState(WID_VL_AVAILABLE_VEHICLES, this->vli.type != VL_STANDARD);
1601  this->SetWidgetsDisabledState(this->vehicles.Length() == 0,
1605  WIDGET_LIST_END);
1606  }
1607 
1608  /* Set text of sort by dropdown widget. */
1609  this->GetWidget<NWidgetCore>(WID_VL_SORT_BY_PULLDOWN)->widget_data = this->vehicle_sorter_names[this->vehicles.SortType()];
1610 
1611  this->DrawWidgets();
1612  }
1613 
1614  virtual void OnClick(Point pt, int widget, int click_count)
1615  {
1616  switch (widget) {
1617  case WID_VL_SORT_ORDER: // Flip sorting method ascending/descending
1618  this->vehicles.ToggleSortOrder();
1619  this->SetDirty();
1620  break;
1621 
1622  case WID_VL_SORT_BY_PULLDOWN:// Select sorting criteria dropdown menu
1623  ShowDropDownMenu(this, this->vehicle_sorter_names, this->vehicles.SortType(), WID_VL_SORT_BY_PULLDOWN, 0,
1624  (this->vli.vtype == VEH_TRAIN || this->vli.vtype == VEH_ROAD) ? 0 : (1 << 10));
1625  return;
1626 
1627  case WID_VL_LIST: { // Matrix to show vehicles
1628  uint id_v = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_VL_LIST);
1629  if (id_v >= this->vehicles.Length()) return; // click out of list bound
1630 
1631  const Vehicle *v = this->vehicles[id_v];
1633  break;
1634  }
1635 
1637  ShowBuildVehicleWindow(INVALID_TILE, this->vli.vtype);
1638  break;
1639 
1641  DropDownList *list = this->BuildActionDropdownList(VehicleListIdentifier::UnPack(this->window_number).type == VL_STANDARD, false);
1643  break;
1644  }
1645 
1646  case WID_VL_STOP_ALL:
1647  case WID_VL_START_ALL:
1648  DoCommandP(0, (1 << 1) | (widget == WID_VL_START_ALL ? (1 << 0) : 0), this->window_number, CMD_MASS_START_STOP);
1649  break;
1650  }
1651  }
1652 
1653  virtual void OnDropdownSelect(int widget, int index)
1654  {
1655  switch (widget) {
1657  this->vehicles.SetSortType(index);
1658  break;
1660  assert(this->vehicles.Length() != 0);
1661 
1662  switch (index) {
1663  case ADI_REPLACE: // Replace window
1665  break;
1666  case ADI_SERVICE: // Send for servicing
1667  case ADI_DEPOT: // Send to Depots
1668  DoCommandP(0, DEPOT_MASS_SEND | (index == ADI_SERVICE ? DEPOT_SERVICE : (DepotCommand)0), this->window_number, GetCmdSendToDepot(this->vli.vtype));
1669  break;
1670 
1671  default: NOT_REACHED();
1672  }
1673  break;
1674  default: NOT_REACHED();
1675  }
1676  this->SetDirty();
1677  }
1678 
1679  virtual void OnGameTick()
1680  {
1681  if (this->vehicles.NeedResort()) {
1682  StationID station = (this->vli.type == VL_STATION_LIST) ? this->vli.index : INVALID_STATION;
1683 
1684  DEBUG(misc, 3, "Periodic resort %d list company %d at station %d", this->vli.vtype, this->owner, station);
1685  this->SetDirty();
1686  }
1687  }
1688 
1689  virtual void OnResize()
1690  {
1691  this->vscroll->SetCapacityFromWidget(this, WID_VL_LIST);
1692  }
1693 
1699  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
1700  {
1701  if (!gui_scope && HasBit(data, 31) && this->vli.type == VL_SHARED_ORDERS) {
1702  /* Needs to be done in command-scope, so everything stays valid */
1703  this->vli.index = GB(data, 0, 20);
1704  this->window_number = this->vli.Pack();
1705  this->vehicles.ForceRebuild();
1706  return;
1707  }
1708 
1709  if (data == 0) {
1710  /* This needs to be done in command-scope to enforce rebuilding before resorting invalid data */
1711  this->vehicles.ForceRebuild();
1712  } else {
1713  this->vehicles.ForceResort();
1714  }
1715  }
1716 };
1717 
1718 static WindowDesc _vehicle_list_other_desc(
1719  WDP_AUTO, "list_vehicles", 260, 246,
1721  0,
1722  _nested_vehicle_list, lengthof(_nested_vehicle_list)
1723 );
1724 
1725 static WindowDesc _vehicle_list_train_desc(
1726  WDP_AUTO, "list_vehicles_train", 325, 246,
1728  0,
1729  _nested_vehicle_list, lengthof(_nested_vehicle_list)
1730 );
1731 
1732 static void ShowVehicleListWindowLocal(CompanyID company, VehicleListType vlt, VehicleType vehicle_type, uint32 unique_number)
1733 {
1734  if (!Company::IsValidID(company) && company != OWNER_NONE) return;
1735 
1736  WindowNumber num = VehicleListIdentifier(vlt, vehicle_type, company, unique_number).Pack();
1737  if (vehicle_type == VEH_TRAIN) {
1738  AllocateWindowDescFront<VehicleListWindow>(&_vehicle_list_train_desc, num);
1739  } else {
1740  _vehicle_list_other_desc.cls = GetWindowClassForVehicleType(vehicle_type);
1741  AllocateWindowDescFront<VehicleListWindow>(&_vehicle_list_other_desc, num);
1742  }
1743 }
1744 
1745 void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type)
1746 {
1747  /* If _settings_client.gui.advanced_vehicle_list > 1, display the Advanced list
1748  * if _settings_client.gui.advanced_vehicle_list == 1, display Advanced list only for local company
1749  * if _ctrl_pressed, do the opposite action (Advanced list x Normal list)
1750  */
1751 
1752  if ((_settings_client.gui.advanced_vehicle_list > (uint)(company != _local_company)) != _ctrl_pressed) {
1753  ShowCompanyGroup(company, vehicle_type);
1754  } else {
1755  ShowVehicleListWindowLocal(company, VL_STANDARD, vehicle_type, company);
1756  }
1757 }
1758 
1759 void ShowVehicleListWindow(const Vehicle *v)
1760 {
1761  ShowVehicleListWindowLocal(v->owner, VL_SHARED_ORDERS, v->type, v->FirstShared()->index);
1762 }
1763 
1764 void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type, StationID station)
1765 {
1766  ShowVehicleListWindowLocal(company, VL_STATION_LIST, vehicle_type, station);
1767 }
1768 
1769 void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type, TileIndex depot_tile)
1770 {
1771  uint16 depot_airport_index;
1772 
1773  if (vehicle_type == VEH_AIRCRAFT) {
1774  depot_airport_index = GetStationIndex(depot_tile);
1775  } else {
1776  depot_airport_index = GetDepotIndex(depot_tile);
1777  }
1778  ShowVehicleListWindowLocal(company, VL_DEPOT_LIST, vehicle_type, depot_airport_index);
1779 }
1780 
1781 
1782 /* Unified vehicle GUI - Vehicle Details Window */
1783 
1788 
1792  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1793  NWidget(WWT_CAPTION, COLOUR_GREY, WID_VD_CAPTION), SetDataTip(STR_VEHICLE_DETAILS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1794  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VD_RENAME_VEHICLE), SetMinimalSize(40, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_VEHICLE_NAME_BUTTON, STR_NULL /* filled in later */),
1795  NWidget(WWT_SHADEBOX, COLOUR_GREY),
1796  NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1797  NWidget(WWT_STICKYBOX, COLOUR_GREY),
1798  EndContainer(),
1799  NWidget(WWT_PANEL, COLOUR_GREY, WID_VD_TOP_DETAILS), SetMinimalSize(405, 42), SetResize(1, 0), EndContainer(),
1800  NWidget(WWT_PANEL, COLOUR_GREY, WID_VD_MIDDLE_DETAILS), SetMinimalSize(405, 45), SetResize(1, 0), EndContainer(),
1803  SetDataTip(AWV_DECREASE, STR_VEHICLE_DETAILS_DECREASE_SERVICING_INTERVAL_TOOLTIP),
1805  SetDataTip(AWV_INCREASE, STR_VEHICLE_DETAILS_INCREASE_SERVICING_INTERVAL_TOOLTIP),
1807  SetDataTip(STR_EMPTY, STR_SERVICE_INTERVAL_DROPDOWN_TOOLTIP),
1808  NWidget(WWT_PANEL, COLOUR_GREY, WID_VD_SERVICING_INTERVAL), SetFill(1, 1), SetResize(1, 0), EndContainer(),
1809  NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1810  EndContainer(),
1811 };
1812 
1816  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1817  NWidget(WWT_CAPTION, COLOUR_GREY, WID_VD_CAPTION), SetDataTip(STR_VEHICLE_DETAILS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1818  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VD_RENAME_VEHICLE), SetMinimalSize(40, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_VEHICLE_NAME_BUTTON, STR_NULL /* filled in later */),
1819  NWidget(WWT_SHADEBOX, COLOUR_GREY),
1820  NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1821  NWidget(WWT_STICKYBOX, COLOUR_GREY),
1822  EndContainer(),
1823  NWidget(WWT_PANEL, COLOUR_GREY, WID_VD_TOP_DETAILS), SetResize(1, 0), SetMinimalSize(405, 42), EndContainer(),
1825  NWidget(WWT_MATRIX, COLOUR_GREY, WID_VD_MATRIX), SetResize(1, 1), SetMinimalSize(393, 45), SetMatrixDataTip(1, 0, STR_NULL), SetFill(1, 0), SetScrollbar(WID_VD_SCROLLBAR),
1826  NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_VD_SCROLLBAR),
1827  EndContainer(),
1830  SetDataTip(AWV_DECREASE, STR_VEHICLE_DETAILS_DECREASE_SERVICING_INTERVAL_TOOLTIP),
1832  SetDataTip(AWV_INCREASE, STR_VEHICLE_DETAILS_INCREASE_SERVICING_INTERVAL_TOOLTIP),
1834  SetDataTip(STR_EMPTY, STR_SERVICE_INTERVAL_DROPDOWN_TOOLTIP),
1835  NWidget(WWT_PANEL, COLOUR_GREY, WID_VD_SERVICING_INTERVAL), SetFill(1, 1), SetResize(1, 0), EndContainer(),
1836  EndContainer(),
1839  SetDataTip(STR_VEHICLE_DETAIL_TAB_CARGO, STR_VEHICLE_DETAILS_TRAIN_CARGO_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1841  SetDataTip(STR_VEHICLE_DETAIL_TAB_INFORMATION, STR_VEHICLE_DETAILS_TRAIN_INFORMATION_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1843  SetDataTip(STR_VEHICLE_DETAIL_TAB_CAPACITIES, STR_VEHICLE_DETAILS_TRAIN_CAPACITIES_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1845  SetDataTip(STR_VEHICLE_DETAIL_TAB_TOTAL_CARGO, STR_VEHICLE_DETAILS_TRAIN_TOTAL_CARGO_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1846  NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1847  EndContainer(),
1848 };
1849 
1850 
1851 extern int GetTrainDetailsWndVScroll(VehicleID veh_id, TrainDetailsWindowTabs det_tab);
1852 extern void DrawTrainDetails(const Train *v, int left, int right, int y, int vscroll_pos, uint16 vscroll_cap, TrainDetailsWindowTabs det_tab);
1853 extern void DrawRoadVehDetails(const Vehicle *v, int left, int right, int y);
1854 extern void DrawShipDetails(const Vehicle *v, int left, int right, int y);
1855 extern void DrawAircraftDetails(const Aircraft *v, int left, int right, int y);
1856 
1857 static StringID _service_interval_dropdown[] = {
1858  STR_VEHICLE_DETAILS_DEFAULT,
1859  STR_VEHICLE_DETAILS_DAYS,
1860  STR_VEHICLE_DETAILS_PERCENT,
1862 };
1863 
1867  Scrollbar *vscroll;
1868 
1871  {
1872  const Vehicle *v = Vehicle::Get(window_number);
1873 
1874  this->CreateNestedTree();
1875  this->vscroll = (v->type == VEH_TRAIN ? this->GetScrollbar(WID_VD_SCROLLBAR) : NULL);
1876  this->FinishInitNested(window_number);
1877 
1878  this->GetWidget<NWidgetCore>(WID_VD_RENAME_VEHICLE)->tool_tip = STR_VEHICLE_DETAILS_TRAIN_RENAME + v->type;
1879 
1880  this->owner = v->owner;
1881  this->tab = TDW_TAB_CARGO;
1882  }
1883 
1889  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
1890  {
1891  if (data == VIWD_AUTOREPLACE) {
1892  /* Autoreplace replaced the vehicle.
1893  * Nothing to do for this window. */
1894  return;
1895  }
1896  if (!gui_scope) return;
1897  const Vehicle *v = Vehicle::Get(this->window_number);
1898  if (v->type == VEH_ROAD) {
1899  const NWidgetBase *nwid_info = this->GetWidget<NWidgetBase>(WID_VD_MIDDLE_DETAILS);
1900  uint aimed_height = this->GetRoadVehDetailsHeight(v);
1901  /* If the number of articulated parts changes, the size of the window must change too. */
1902  if (aimed_height != nwid_info->current_y) {
1903  this->ReInit();
1904  }
1905  }
1906  }
1907 
1914  {
1915  uint desired_height;
1916  if (v->HasArticulatedPart()) {
1917  /* An articulated RV has its text drawn under the sprite instead of after it, hence 15 pixels extra. */
1918  desired_height = WD_FRAMERECT_TOP + ScaleGUITrad(15) + 3 * FONT_HEIGHT_NORMAL + 2 + WD_FRAMERECT_BOTTOM;
1919  /* Add space for the cargo amount for each part. */
1920  for (const Vehicle *u = v; u != NULL; u = u->Next()) {
1921  if (u->cargo_cap != 0) desired_height += FONT_HEIGHT_NORMAL + 1;
1922  }
1923  } else {
1924  desired_height = WD_FRAMERECT_TOP + 4 * FONT_HEIGHT_NORMAL + 3 + WD_FRAMERECT_BOTTOM;
1925  }
1926  return desired_height;
1927  }
1928 
1929  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1930  {
1931  switch (widget) {
1932  case WID_VD_TOP_DETAILS: {
1933  Dimension dim = { 0, 0 };
1935 
1936  for (uint i = 0; i < 4; i++) SetDParamMaxValue(i, INT16_MAX);
1937  static const StringID info_strings[] = {
1938  STR_VEHICLE_INFO_MAX_SPEED,
1939  STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED,
1940  STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE,
1941  STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR,
1942  STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS
1943  };
1944  for (uint i = 0; i < lengthof(info_strings); i++) {
1945  dim = maxdim(dim, GetStringBoundingBox(info_strings[i]));
1946  }
1947  SetDParam(0, STR_VEHICLE_INFO_AGE);
1948  dim = maxdim(dim, GetStringBoundingBox(STR_VEHICLE_INFO_AGE_RUNNING_COST_YR));
1949  size->width = dim.width + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1950  break;
1951  }
1952 
1953  case WID_VD_MIDDLE_DETAILS: {
1954  const Vehicle *v = Vehicle::Get(this->window_number);
1955  switch (v->type) {
1956  case VEH_ROAD:
1957  size->height = this->GetRoadVehDetailsHeight(v);
1958  break;
1959 
1960  case VEH_SHIP:
1961  size->height = WD_FRAMERECT_TOP + 4 * FONT_HEIGHT_NORMAL + 3 + WD_FRAMERECT_BOTTOM;
1962  break;
1963 
1964  case VEH_AIRCRAFT:
1965  size->height = WD_FRAMERECT_TOP + 5 * FONT_HEIGHT_NORMAL + 4 + WD_FRAMERECT_BOTTOM;
1966  break;
1967 
1968  default:
1969  NOT_REACHED(); // Train uses WID_VD_MATRIX instead.
1970  }
1971  break;
1972  }
1973 
1974  case WID_VD_MATRIX:
1976  size->height = 4 * resize->height;
1977  break;
1978 
1980  StringID *strs = _service_interval_dropdown;
1981  while (*strs != INVALID_STRING_ID) {
1982  *size = maxdim(*size, GetStringBoundingBox(*strs++));
1983  }
1984  size->width += padding.width;
1986  break;
1987  }
1988 
1990  SetDParamMaxValue(0, MAX_SERVINT_DAYS); // Roughly the maximum interval
1991  SetDParamMaxValue(1, MAX_YEAR * DAYS_IN_YEAR); // Roughly the maximum year
1992  size->width = max(GetStringBoundingBox(STR_VEHICLE_DETAILS_SERVICING_INTERVAL_PERCENT).width, GetStringBoundingBox(STR_VEHICLE_DETAILS_SERVICING_INTERVAL_DAYS).width) + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1994  break;
1995  }
1996  }
1997 
1999  static bool IsVehicleServiceIntervalEnabled(const VehicleType vehicle_type, CompanyID company_id)
2000  {
2001  const VehicleDefaultSettings *vds = &Company::Get(company_id)->settings.vehicle;
2002  switch (vehicle_type) {
2003  default: NOT_REACHED();
2004  case VEH_TRAIN: return vds->servint_trains != 0;
2005  case VEH_ROAD: return vds->servint_roadveh != 0;
2006  case VEH_SHIP: return vds->servint_ships != 0;
2007  case VEH_AIRCRAFT: return vds->servint_aircraft != 0;
2008  }
2009  }
2010 
2022  static void DrawVehicleDetails(const Vehicle *v, int left, int right, int y, int vscroll_pos, uint vscroll_cap, TrainDetailsWindowTabs det_tab)
2023  {
2024  switch (v->type) {
2025  case VEH_TRAIN: DrawTrainDetails(Train::From(v), left, right, y, vscroll_pos, vscroll_cap, det_tab); break;
2026  case VEH_ROAD: DrawRoadVehDetails(v, left, right, y); break;
2027  case VEH_SHIP: DrawShipDetails(v, left, right, y); break;
2028  case VEH_AIRCRAFT: DrawAircraftDetails(Aircraft::From(v), left, right, y); break;
2029  default: NOT_REACHED();
2030  }
2031  }
2032 
2033  virtual void SetStringParameters(int widget) const
2034  {
2035  if (widget == WID_VD_CAPTION) SetDParam(0, Vehicle::Get(this->window_number)->index);
2036  }
2037 
2038  virtual void DrawWidget(const Rect &r, int widget) const
2039  {
2040  const Vehicle *v = Vehicle::Get(this->window_number);
2041 
2042  switch (widget) {
2043  case WID_VD_TOP_DETAILS: {
2044  int y = r.top + WD_FRAMERECT_TOP;
2045 
2046  /* Draw running cost */
2047  SetDParam(1, v->age / DAYS_IN_LEAP_YEAR);
2048  SetDParam(0, (v->age + DAYS_IN_YEAR < v->max_age) ? STR_VEHICLE_INFO_AGE : STR_VEHICLE_INFO_AGE_RED);
2051  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_VEHICLE_INFO_AGE_RUNNING_COST_YR);
2052  y += FONT_HEIGHT_NORMAL;
2053 
2054  /* Draw max speed */
2055  StringID string;
2056  if (v->type == VEH_TRAIN ||
2057  (v->type == VEH_ROAD && _settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL)) {
2058  const GroundVehicleCache *gcache = v->GetGroundVehicleCache();
2059  SetDParam(2, v->GetDisplayMaxSpeed());
2060  SetDParam(1, gcache->cached_power);
2061  SetDParam(0, gcache->cached_weight);
2062  SetDParam(3, gcache->cached_max_te / 1000);
2063  if (v->type == VEH_TRAIN && (_settings_game.vehicle.train_acceleration_model == AM_ORIGINAL ||
2064  GetRailTypeInfo(Train::From(v)->railtype)->acceleration_type == 2)) {
2065  string = STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED;
2066  } else {
2067  string = STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE;
2068  }
2069  } else {
2070  SetDParam(0, v->GetDisplayMaxSpeed());
2071  if (v->type == VEH_AIRCRAFT) {
2073  if (Aircraft::From(v)->GetRange() > 0) {
2074  SetDParam(2, Aircraft::From(v)->GetRange());
2075  string = STR_VEHICLE_INFO_MAX_SPEED_TYPE_RANGE;
2076  } else {
2077  string = STR_VEHICLE_INFO_MAX_SPEED_TYPE;
2078  }
2079  } else {
2080  string = STR_VEHICLE_INFO_MAX_SPEED;
2081  }
2082  }
2083  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, string);
2084  y += FONT_HEIGHT_NORMAL;
2085 
2086  /* Draw profit */
2089  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR);
2090  y += FONT_HEIGHT_NORMAL;
2091 
2092  /* Draw breakdown & reliability */
2095  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS);
2096  break;
2097  }
2098 
2099  case WID_VD_MATRIX:
2100  /* For trains only. */
2101  DrawVehicleDetails(v, r.left + WD_MATRIX_LEFT, r.right - WD_MATRIX_RIGHT, r.top + WD_MATRIX_TOP, this->vscroll->GetPosition(), this->vscroll->GetCapacity(), this->tab);
2102  break;
2103 
2104  case WID_VD_MIDDLE_DETAILS: {
2105  /* For other vehicles, at the place of the matrix. */
2106  bool rtl = _current_text_dir == TD_RTL;
2108 
2109  uint text_left = r.left + (rtl ? 0 : sprite_width);
2110  uint text_right = r.right - (rtl ? sprite_width : 0);
2111 
2112  /* Articulated road vehicles use a complete line. */
2113  if (v->type == VEH_ROAD && v->HasArticulatedPart()) {
2114  DrawVehicleImage(v, r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, INVALID_VEHICLE, EIT_IN_DETAILS, 0);
2115  } else {
2116  uint sprite_left = rtl ? text_right : r.left;
2117  uint sprite_right = rtl ? r.right : text_left;
2118 
2119  DrawVehicleImage(v, sprite_left + WD_FRAMERECT_LEFT, sprite_right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, INVALID_VEHICLE, EIT_IN_DETAILS, 0);
2120  }
2121  DrawVehicleDetails(v, text_left + WD_FRAMERECT_LEFT, text_right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, 0, 0, this->tab);
2122  break;
2123  }
2124 
2126  /* Draw service interval text */
2127  SetDParam(0, v->GetServiceInterval());
2129  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + (r.bottom - r.top + 1 - FONT_HEIGHT_NORMAL) / 2,
2130  v->ServiceIntervalIsPercent() ? STR_VEHICLE_DETAILS_SERVICING_INTERVAL_PERCENT : STR_VEHICLE_DETAILS_SERVICING_INTERVAL_DAYS);
2131  break;
2132  }
2133  }
2134 
2136  virtual void OnPaint()
2137  {
2138  const Vehicle *v = Vehicle::Get(this->window_number);
2139 
2141 
2142  if (v->type == VEH_TRAIN) {
2143  this->DisableWidget(this->tab + WID_VD_DETAILS_CARGO_CARRIED);
2144  this->vscroll->SetCount(GetTrainDetailsWndVScroll(v->index, this->tab));
2145  }
2146 
2147  /* Disable service-scroller when interval is set to disabled */
2148  this->SetWidgetsDisabledState(!IsVehicleServiceIntervalEnabled(v->type, v->owner),
2151  WIDGET_LIST_END);
2152 
2153  StringID str = v->ServiceIntervalIsCustom() ?
2154  (v->ServiceIntervalIsPercent() ? STR_VEHICLE_DETAILS_PERCENT : STR_VEHICLE_DETAILS_DAYS) :
2155  STR_VEHICLE_DETAILS_DEFAULT;
2156  this->GetWidget<NWidgetCore>(WID_VD_SERVICE_INTERVAL_DROPDOWN)->widget_data = str;
2157 
2158  this->DrawWidgets();
2159  }
2160 
2161  virtual void OnClick(Point pt, int widget, int click_count)
2162  {
2163  switch (widget) {
2164  case WID_VD_RENAME_VEHICLE: { // rename
2165  const Vehicle *v = Vehicle::Get(this->window_number);
2166  SetDParam(0, v->index);
2167  ShowQueryString(STR_VEHICLE_NAME, STR_QUERY_RENAME_TRAIN_CAPTION + v->type,
2169  break;
2170  }
2171 
2172  case WID_VD_INCREASE_SERVICING_INTERVAL: // increase int
2173  case WID_VD_DECREASE_SERVICING_INTERVAL: { // decrease int
2174  int mod = _ctrl_pressed ? 5 : 10;
2175  const Vehicle *v = Vehicle::Get(this->window_number);
2176 
2177  mod = (widget == WID_VD_DECREASE_SERVICING_INTERVAL) ? -mod : mod;
2178  mod = GetServiceIntervalClamped(mod + v->GetServiceInterval(), v->ServiceIntervalIsPercent());
2179  if (mod == v->GetServiceInterval()) return;
2180 
2181  DoCommandP(v->tile, v->index, mod | (1 << 16) | (v->ServiceIntervalIsPercent() << 17), CMD_CHANGE_SERVICE_INT | CMD_MSG(STR_ERROR_CAN_T_CHANGE_SERVICING));
2182  break;
2183  }
2184 
2186  const Vehicle *v = Vehicle::Get(this->window_number);
2187  ShowDropDownMenu(this, _service_interval_dropdown, v->ServiceIntervalIsCustom() ? (v->ServiceIntervalIsPercent() ? 2 : 1) : 0, widget, 0, 0);
2188  break;
2189  }
2190 
2195  this->SetWidgetsDisabledState(false,
2200  widget,
2201  WIDGET_LIST_END);
2202 
2203  this->tab = (TrainDetailsWindowTabs)(widget - WID_VD_DETAILS_CARGO_CARRIED);
2204  this->SetDirty();
2205  break;
2206  }
2207  }
2208 
2209  virtual void OnDropdownSelect(int widget, int index)
2210  {
2211  switch (widget) {
2213  const Vehicle *v = Vehicle::Get(this->window_number);
2214  bool iscustom = index != 0;
2215  bool ispercent = iscustom ? (index == 2) : Company::Get(v->owner)->settings.vehicle.servint_ispercent;
2216  uint16 interval = GetServiceIntervalClamped(v->GetServiceInterval(), ispercent);
2217  DoCommandP(v->tile, v->index, interval | (iscustom << 16) | (ispercent << 17), CMD_CHANGE_SERVICE_INT | CMD_MSG(STR_ERROR_CAN_T_CHANGE_SERVICING));
2218  break;
2219  }
2220  }
2221  }
2222 
2223  virtual void OnQueryTextFinished(char *str)
2224  {
2225  if (str == NULL) return;
2226 
2227  DoCommandP(0, this->window_number, 0, CMD_RENAME_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_RENAME_TRAIN + Vehicle::Get(this->window_number)->type), NULL, str);
2228  }
2229 
2230  virtual void OnResize()
2231  {
2232  NWidgetCore *nwi = this->GetWidget<NWidgetCore>(WID_VD_MATRIX);
2233  if (nwi != NULL) {
2234  this->vscroll->SetCapacityFromWidget(this, WID_VD_MATRIX);
2235  }
2236  }
2237 };
2238 
2241  WDP_AUTO, "view_vehicle_details_train", 405, 178,
2243  0,
2244  _nested_train_vehicle_details_widgets, lengthof(_nested_train_vehicle_details_widgets)
2245 );
2246 
2249  WDP_AUTO, "view_vehicle_details", 405, 113,
2251  0,
2252  _nested_nontrain_vehicle_details_widgets, lengthof(_nested_nontrain_vehicle_details_widgets)
2253 );
2254 
2256 static void ShowVehicleDetailsWindow(const Vehicle *v)
2257 {
2260  AllocateWindowDescFront<VehicleDetailsWindow>((v->type == VEH_TRAIN) ? &_train_vehicle_details_desc : &_nontrain_vehicle_details_desc, v->index);
2261 }
2262 
2263 
2264 /* Unified vehicle GUI - Vehicle View Window */
2265 
2269  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2270  NWidget(WWT_CAPTION, COLOUR_GREY, WID_VV_CAPTION), SetDataTip(STR_VEHICLE_VIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2271  NWidget(WWT_DEBUGBOX, COLOUR_GREY),
2272  NWidget(WWT_SHADEBOX, COLOUR_GREY),
2273  NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
2274  NWidget(WWT_STICKYBOX, COLOUR_GREY),
2275  EndContainer(),
2277  NWidget(WWT_PANEL, COLOUR_GREY),
2278  NWidget(WWT_INSET, COLOUR_GREY), SetPadding(2, 2, 2, 2),
2279  NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_VV_VIEWPORT), SetMinimalSize(226, 84), SetResize(1, 1), SetPadding(1, 1, 1, 1),
2280  EndContainer(),
2281  EndContainer(),
2283  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_CENTER_MAIN_VIEW), SetMinimalSize(18, 18), SetDataTip(SPR_CENTRE_VIEW_VEHICLE, 0x0 /* filled later */),
2285  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_GOTO_DEPOT), SetMinimalSize(18, 18), SetDataTip(0x0 /* filled later */, 0x0 /* filled later */),
2286  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_CLONE), SetMinimalSize(18, 18), SetDataTip(0x0 /* filled later */, 0x0 /* filled later */),
2287  EndContainer(),
2288  /* For trains only, 'ignore signal' button. */
2290  SetDataTip(SPR_IGNORE_SIGNALS, STR_VEHICLE_VIEW_TRAIN_IGNORE_SIGNAL_TOOLTIP),
2292  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_REFIT), SetMinimalSize(18, 18), SetDataTip(SPR_REFIT_VEHICLE, 0x0 /* filled later */),
2293  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_TURN_AROUND), SetMinimalSize(18, 18),
2294  SetDataTip(SPR_FORCE_VEHICLE_TURN, STR_VEHICLE_VIEW_ROAD_VEHICLE_REVERSE_TOOLTIP),
2295  EndContainer(),
2296  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_SHOW_ORDERS), SetMinimalSize(18, 18), SetDataTip(SPR_SHOW_ORDERS, 0x0 /* filled later */),
2297  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_SHOW_DETAILS), SetMinimalSize(18, 18), SetDataTip(SPR_SHOW_VEHICLE_DETAILS, 0x0 /* filled later */),
2298  NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(18, 0), SetResize(0, 1), EndContainer(),
2299  EndContainer(),
2300  EndContainer(),
2303  NWidget(WWT_RESIZEBOX, COLOUR_GREY),
2304  EndContainer(),
2305 };
2306 
2309  WDP_AUTO, "view_vehicle", 250, 116,
2311  0,
2312  _nested_vehicle_view_widgets, lengthof(_nested_vehicle_view_widgets)
2313 );
2314 
2320  WDP_AUTO, "view_vehicle_train", 250, 134,
2322  0,
2323  _nested_vehicle_view_widgets, lengthof(_nested_vehicle_view_widgets)
2324 );
2325 
2326 
2327 /* Just to make sure, nobody has changed the vehicle type constants, as we are
2328  using them for array indexing in a number of places here. */
2329 assert_compile(VEH_TRAIN == 0);
2330 assert_compile(VEH_ROAD == 1);
2331 assert_compile(VEH_SHIP == 2);
2332 assert_compile(VEH_AIRCRAFT == 3);
2333 
2338  ZOOM_LVL_SHIP,
2340 };
2341 
2342 /* Constants for geometry of vehicle view viewport */
2343 static const int VV_INITIAL_VIEWPORT_WIDTH = 226;
2344 static const int VV_INITIAL_VIEWPORT_HEIGHT = 84;
2345 static const int VV_INITIAL_VIEWPORT_HEIGHT_TRAIN = 102;
2346 
2349  VCT_CMD_START_STOP = 0,
2350  VCT_CMD_CLONE_VEH,
2351  VCT_CMD_TURN_AROUND,
2352 };
2353 
2355 static const uint32 _vehicle_command_translation_table[][4] = {
2356  { // VCT_CMD_START_STOP
2357  CMD_START_STOP_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_STOP_START_TRAIN),
2358  CMD_START_STOP_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_STOP_START_ROAD_VEHICLE),
2359  CMD_START_STOP_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_STOP_START_SHIP),
2360  CMD_START_STOP_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_STOP_START_AIRCRAFT)
2361  },
2362  { // VCT_CMD_CLONE_VEH
2363  CMD_CLONE_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_TRAIN),
2364  CMD_CLONE_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_ROAD_VEHICLE),
2365  CMD_CLONE_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_SHIP),
2366  CMD_CLONE_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_AIRCRAFT)
2367  },
2368  { // VCT_CMD_TURN_AROUND
2369  CMD_REVERSE_TRAIN_DIRECTION | CMD_MSG(STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN),
2370  CMD_TURN_ROADVEH | CMD_MSG(STR_ERROR_CAN_T_MAKE_ROAD_VEHICLE_TURN),
2371  0xffffffff, // invalid for ships
2372  0xffffffff // invalid for aircraft
2373  },
2374 };
2375 
2383 void CcStartStopVehicle(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
2384 {
2385  if (result.Failed()) return;
2386 
2387  const Vehicle *v = Vehicle::GetIfValid(p1);
2388  if (v == NULL || !v->IsPrimaryVehicle() || v->owner != _local_company) return;
2389 
2390  StringID msg = (v->vehstatus & VS_STOPPED) ? STR_VEHICLE_COMMAND_STOPPED : STR_VEHICLE_COMMAND_STARTED;
2391  Point pt = RemapCoords(v->x_pos, v->y_pos, v->z_pos);
2392  AddTextEffect(msg, pt.x, pt.y, DAY_TICKS, TE_RISING);
2393 }
2394 
2400 void StartStopVehicle(const Vehicle *v, bool texteffect)
2401 {
2402  assert(v->IsPrimaryVehicle());
2403  DoCommandP(v->tile, v->index, 0, _vehicle_command_translation_table[VCT_CMD_START_STOP][v->type], texteffect ? CcStartStopVehicle : NULL);
2404 }
2405 
2407 static bool IsVehicleRefitable(const Vehicle *v)
2408 {
2409  if (!v->IsStoppedInDepot()) return false;
2410 
2411  do {
2412  if (IsEngineRefittable(v->engine_type)) return true;
2413  } while (v->IsGroundVehicle() && (v = v->Next()) != NULL);
2414 
2415  return false;
2416 }
2417 
2420 private:
2425 
2428 
2429  SEL_DC_BASEPLANE = SEL_DC_GOTO_DEPOT,
2430  SEL_RT_BASEPLANE = SEL_RT_REFIT,
2431  };
2432 
2438  {
2439  switch (plane) {
2440  case SEL_DC_GOTO_DEPOT:
2441  case SEL_DC_CLONE:
2442  this->GetWidget<NWidgetStacked>(WID_VV_SELECT_DEPOT_CLONE)->SetDisplayedPlane(plane - SEL_DC_BASEPLANE);
2443  break;
2444 
2445  case SEL_RT_REFIT:
2446  case SEL_RT_TURN_AROUND:
2447  this->GetWidget<NWidgetStacked>(WID_VV_SELECT_REFIT_TURN)->SetDisplayedPlane(plane - SEL_RT_BASEPLANE);
2448  break;
2449 
2450  default:
2451  NOT_REACHED();
2452  }
2453  }
2454 
2455 public:
2457  {
2458  this->flags |= WF_DISABLE_VP_SCROLL;
2459  this->CreateNestedTree();
2460 
2461  /* Sprites for the 'send to depot' button indexed by vehicle type. */
2462  static const SpriteID vehicle_view_goto_depot_sprites[] = {
2463  SPR_SEND_TRAIN_TODEPOT,
2464  SPR_SEND_ROADVEH_TODEPOT,
2465  SPR_SEND_SHIP_TODEPOT,
2466  SPR_SEND_AIRCRAFT_TODEPOT,
2467  };
2468  const Vehicle *v = Vehicle::Get(window_number);
2469  this->GetWidget<NWidgetCore>(WID_VV_GOTO_DEPOT)->widget_data = vehicle_view_goto_depot_sprites[v->type];
2470 
2471  /* Sprites for the 'clone vehicle' button indexed by vehicle type. */
2472  static const SpriteID vehicle_view_clone_sprites[] = {
2474  SPR_CLONE_ROADVEH,
2475  SPR_CLONE_SHIP,
2476  SPR_CLONE_AIRCRAFT,
2477  };
2478  this->GetWidget<NWidgetCore>(WID_VV_CLONE)->widget_data = vehicle_view_clone_sprites[v->type];
2479 
2480  switch (v->type) {
2481  case VEH_TRAIN:
2482  this->GetWidget<NWidgetCore>(WID_VV_TURN_AROUND)->tool_tip = STR_VEHICLE_VIEW_TRAIN_REVERSE_TOOLTIP;
2483  break;
2484 
2485  case VEH_ROAD:
2486  break;
2487 
2488  case VEH_SHIP:
2489  case VEH_AIRCRAFT:
2490  this->SelectPlane(SEL_RT_REFIT);
2491  break;
2492 
2493  default: NOT_REACHED();
2494  }
2495  this->FinishInitNested(window_number);
2496  this->owner = v->owner;
2497  this->GetWidget<NWidgetViewport>(WID_VV_VIEWPORT)->InitializeViewport(this, this->window_number | (1 << 31), _vehicle_view_zoom_levels[v->type]);
2498 
2499  this->GetWidget<NWidgetCore>(WID_VV_START_STOP)->tool_tip = STR_VEHICLE_VIEW_TRAIN_STATE_START_STOP_TOOLTIP + v->type;
2500  this->GetWidget<NWidgetCore>(WID_VV_CENTER_MAIN_VIEW)->tool_tip = STR_VEHICLE_VIEW_TRAIN_LOCATION_TOOLTIP + v->type;
2501  this->GetWidget<NWidgetCore>(WID_VV_REFIT)->tool_tip = STR_VEHICLE_VIEW_TRAIN_REFIT_TOOLTIP + v->type;
2502  this->GetWidget<NWidgetCore>(WID_VV_GOTO_DEPOT)->tool_tip = STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP + v->type;
2503  this->GetWidget<NWidgetCore>(WID_VV_SHOW_ORDERS)->tool_tip = STR_VEHICLE_VIEW_TRAIN_ORDERS_TOOLTIP + v->type;
2504  this->GetWidget<NWidgetCore>(WID_VV_SHOW_DETAILS)->tool_tip = STR_VEHICLE_VIEW_TRAIN_SHOW_DETAILS_TOOLTIP + v->type;
2505  this->GetWidget<NWidgetCore>(WID_VV_CLONE)->tool_tip = STR_VEHICLE_VIEW_CLONE_TRAIN_INFO + v->type;
2506 
2507  this->UpdateButtonStatus();
2508  }
2509 
2511  {
2516  }
2517 
2518  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
2519  {
2520  const Vehicle *v = Vehicle::Get(this->window_number);
2521  switch (widget) {
2522  case WID_VV_START_STOP:
2523  size->height = max(size->height, max(GetSpriteSize(SPR_FLAG_VEH_STOPPED).height, GetSpriteSize(SPR_FLAG_VEH_RUNNING).height) + WD_IMGBTN_TOP + WD_IMGBTN_BOTTOM);
2524  break;
2525 
2526  case WID_VV_FORCE_PROCEED:
2527  if (v->type != VEH_TRAIN) {
2528  size->height = 0;
2529  size->width = 0;
2530  }
2531  break;
2532 
2533  case WID_VV_VIEWPORT:
2534  size->width = VV_INITIAL_VIEWPORT_WIDTH;
2535  size->height = (v->type == VEH_TRAIN) ? VV_INITIAL_VIEWPORT_HEIGHT_TRAIN : VV_INITIAL_VIEWPORT_HEIGHT;
2536  break;
2537  }
2538  }
2539 
2540  virtual void OnPaint()
2541  {
2542  const Vehicle *v = Vehicle::Get(this->window_number);
2543  bool is_localcompany = v->owner == _local_company;
2544  bool refitable_and_stopped_in_depot = IsVehicleRefitable(v);
2545 
2546  this->SetWidgetDisabledState(WID_VV_GOTO_DEPOT, !is_localcompany);
2547  this->SetWidgetDisabledState(WID_VV_REFIT, !refitable_and_stopped_in_depot || !is_localcompany);
2548  this->SetWidgetDisabledState(WID_VV_CLONE, !is_localcompany);
2549 
2550  if (v->type == VEH_TRAIN) {
2552  this->SetWidgetDisabledState(WID_VV_FORCE_PROCEED, !is_localcompany);
2553  this->SetWidgetDisabledState(WID_VV_TURN_AROUND, !is_localcompany);
2554  }
2555 
2556  this->DrawWidgets();
2557  }
2558 
2559  virtual void SetStringParameters(int widget) const
2560  {
2561  if (widget != WID_VV_CAPTION) return;
2562 
2563  const Vehicle *v = Vehicle::Get(this->window_number);
2564  SetDParam(0, v->index);
2565  }
2566 
2567  virtual void DrawWidget(const Rect &r, int widget) const
2568  {
2569  if (widget != WID_VV_START_STOP) return;
2570 
2571  const Vehicle *v = Vehicle::Get(this->window_number);
2572  StringID str;
2573  if (v->vehstatus & VS_CRASHED) {
2574  str = STR_VEHICLE_STATUS_CRASHED;
2575  } else if (v->type != VEH_AIRCRAFT && v->breakdown_ctr == 1) { // check for aircraft necessary?
2576  str = STR_VEHICLE_STATUS_BROKEN_DOWN;
2577  } else if (v->vehstatus & VS_STOPPED) {
2578  if (v->type == VEH_TRAIN) {
2579  if (v->cur_speed == 0) {
2580  if (Train::From(v)->gcache.cached_power == 0) {
2581  str = STR_VEHICLE_STATUS_TRAIN_NO_POWER;
2582  } else {
2583  str = STR_VEHICLE_STATUS_STOPPED;
2584  }
2585  } else {
2586  SetDParam(0, v->GetDisplaySpeed());
2587  str = STR_VEHICLE_STATUS_TRAIN_STOPPING_VEL;
2588  }
2589  } else { // no train
2590  str = STR_VEHICLE_STATUS_STOPPED;
2591  }
2592  } else if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_TRAIN_STUCK) && !v->current_order.IsType(OT_LOADING)) {
2593  str = STR_VEHICLE_STATUS_TRAIN_STUCK;
2594  } else if (v->type == VEH_AIRCRAFT && HasBit(Aircraft::From(v)->flags, VAF_DEST_TOO_FAR) && !v->current_order.IsType(OT_LOADING)) {
2595  str = STR_VEHICLE_STATUS_AIRCRAFT_TOO_FAR;
2596  } else { // vehicle is in a "normal" state, show current order
2597  switch (v->current_order.GetType()) {
2598  case OT_GOTO_STATION: {
2600  SetDParam(1, v->GetDisplaySpeed());
2601  str = STR_VEHICLE_STATUS_HEADING_FOR_STATION_VEL;
2602  break;
2603  }
2604 
2605  case OT_GOTO_DEPOT: {
2606  SetDParam(0, v->type);
2608  SetDParam(2, v->GetDisplaySpeed());
2610  /* This case *only* happens when multiple nearest depot orders
2611  * follow each other (including an order list only one order: a
2612  * nearest depot order) and there are no reachable depots.
2613  * It is primarily to guard for the case that there is no
2614  * depot with index 0, which would be used as fallback for
2615  * evaluating the string in the status bar. */
2616  str = STR_EMPTY;
2617  } else if (v->current_order.GetDepotActionType() & ODATFB_HALT) {
2618  str = STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_VEL;
2619  } else {
2620  str = STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_SERVICE_VEL;
2621  }
2622  break;
2623  }
2624 
2625  case OT_LOADING:
2626  str = STR_VEHICLE_STATUS_LOADING_UNLOADING;
2627  break;
2628 
2629  case OT_GOTO_WAYPOINT: {
2630  assert(v->type == VEH_TRAIN || v->type == VEH_SHIP);
2632  str = STR_VEHICLE_STATUS_HEADING_FOR_WAYPOINT_VEL;
2633  SetDParam(1, v->GetDisplaySpeed());
2634  break;
2635  }
2636 
2637  case OT_LEAVESTATION:
2638  if (v->type != VEH_AIRCRAFT) {
2639  str = STR_VEHICLE_STATUS_LEAVING;
2640  break;
2641  }
2642  FALLTHROUGH;
2643  default:
2644  if (v->GetNumManualOrders() == 0) {
2645  str = STR_VEHICLE_STATUS_NO_ORDERS_VEL;
2646  SetDParam(0, v->GetDisplaySpeed());
2647  } else {
2648  str = STR_EMPTY;
2649  }
2650  break;
2651  }
2652  }
2653 
2654  /* Draw the flag plus orders. */
2655  bool rtl = (_current_text_dir == TD_RTL);
2656  uint text_offset = max(GetSpriteSize(SPR_FLAG_VEH_STOPPED).width, GetSpriteSize(SPR_FLAG_VEH_RUNNING).width) + WD_IMGBTN_LEFT + WD_IMGBTN_RIGHT;
2657  int text_left = r.left + (rtl ? (uint)WD_FRAMERECT_LEFT : text_offset);
2658  int text_right = r.right - (rtl ? text_offset : (uint)WD_FRAMERECT_RIGHT);
2659  int image_left = (rtl ? text_right + 1 : r.left) + WD_IMGBTN_LEFT;
2660  int image = ((v->vehstatus & VS_STOPPED) != 0) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING;
2661  int lowered = this->IsWidgetLowered(WID_VV_START_STOP) ? 1 : 0;
2662  DrawSprite(image, PAL_NONE, image_left + lowered, r.top + WD_IMGBTN_TOP + lowered);
2663  DrawString(text_left + lowered, text_right + lowered, r.top + WD_FRAMERECT_TOP + lowered, str, TC_FROMSTRING, SA_HOR_CENTER);
2664  }
2665 
2666  virtual void OnClick(Point pt, int widget, int click_count)
2667  {
2668  const Vehicle *v = Vehicle::Get(this->window_number);
2669 
2670  switch (widget) {
2671  case WID_VV_START_STOP: // start stop
2672  if (_ctrl_pressed) {
2673  /* Scroll to current order destination */
2674  TileIndex tile = v->current_order.GetLocation(v);
2675  if (tile != INVALID_TILE) ScrollMainWindowToTile(tile);
2676  } else {
2677  /* Start/Stop */
2678  StartStopVehicle(v, false);
2679  }
2680  break;
2681  case WID_VV_CENTER_MAIN_VIEW: {// center main view
2682  const Window *mainwindow = FindWindowById(WC_MAIN_WINDOW, 0);
2683  /* code to allow the main window to 'follow' the vehicle if the ctrl key is pressed */
2684  if (_ctrl_pressed && mainwindow->viewport->zoom <= ZOOM_LVL_OUT_4X) {
2685  mainwindow->viewport->follow_vehicle = v->index;
2686  } else {
2687  ScrollMainWindowTo(v->x_pos, v->y_pos, v->z_pos);
2688  }
2689  break;
2690  }
2691 
2692  case WID_VV_GOTO_DEPOT: // goto hangar
2693  DoCommandP(v->tile, v->index | (_ctrl_pressed ? DEPOT_SERVICE : 0U), 0, GetCmdSendToDepot(v));
2694  break;
2695  case WID_VV_REFIT: // refit
2697  break;
2698  case WID_VV_SHOW_ORDERS: // show orders
2699  if (_ctrl_pressed) {
2701  } else {
2702  ShowOrdersWindow(v);
2703  }
2704  break;
2705  case WID_VV_SHOW_DETAILS: // show details
2707  break;
2708  case WID_VV_CLONE: // clone vehicle
2709  /* Suppress the vehicle GUI when share-cloning.
2710  * There is no point to it except for starting the vehicle.
2711  * For starting the vehicle the player has to open the depot GUI, which is
2712  * most likely already open, but is also visible in the vehicle viewport. */
2713  DoCommandP(v->tile, v->index, _ctrl_pressed ? 1 : 0,
2714  _vehicle_command_translation_table[VCT_CMD_CLONE_VEH][v->type],
2715  _ctrl_pressed ? NULL : CcCloneVehicle);
2716  break;
2717  case WID_VV_TURN_AROUND: // turn around
2718  assert(v->IsGroundVehicle());
2719  DoCommandP(v->tile, v->index, 0,
2720  _vehicle_command_translation_table[VCT_CMD_TURN_AROUND][v->type]);
2721  break;
2722  case WID_VV_FORCE_PROCEED: // force proceed
2723  assert(v->type == VEH_TRAIN);
2724  DoCommandP(v->tile, v->index, 0, CMD_FORCE_TRAIN_PROCEED | CMD_MSG(STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL));
2725  break;
2726  }
2727  }
2728 
2729  virtual void OnResize()
2730  {
2731  if (this->viewport != NULL) {
2732  NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(WID_VV_VIEWPORT);
2733  nvp->UpdateViewportCoordinates(this);
2734  }
2735  }
2736 
2737  void UpdateButtonStatus()
2738  {
2739  const Vehicle *v = Vehicle::Get(this->window_number);
2740  bool veh_stopped = v->IsStoppedInDepot();
2741 
2742  /* Widget WID_VV_GOTO_DEPOT must be hidden if the vehicle is already stopped in depot.
2743  * Widget WID_VV_CLONE_VEH should then be shown, since cloning is allowed only while in depot and stopped.
2744  */
2745  PlaneSelections plane = veh_stopped ? SEL_DC_CLONE : SEL_DC_GOTO_DEPOT;
2746  NWidgetStacked *nwi = this->GetWidget<NWidgetStacked>(WID_VV_SELECT_DEPOT_CLONE); // Selection widget 'send to depot' / 'clone'.
2747  if (nwi->shown_plane + SEL_DC_BASEPLANE != plane) {
2748  this->SelectPlane(plane);
2750  }
2751  /* The same system applies to widget WID_VV_REFIT_VEH and VVW_WIDGET_TURN_AROUND.*/
2752  if (v->IsGroundVehicle()) {
2753  PlaneSelections plane = veh_stopped ? SEL_RT_REFIT : SEL_RT_TURN_AROUND;
2754  NWidgetStacked *nwi = this->GetWidget<NWidgetStacked>(WID_VV_SELECT_REFIT_TURN);
2755  if (nwi->shown_plane + SEL_RT_BASEPLANE != plane) {
2756  this->SelectPlane(plane);
2758  }
2759  }
2760  }
2761 
2767  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
2768  {
2769  if (data == VIWD_AUTOREPLACE) {
2770  /* Autoreplace replaced the vehicle.
2771  * Nothing to do for this window. */
2772  return;
2773  }
2774 
2775  this->UpdateButtonStatus();
2776  }
2777 
2778  virtual bool IsNewGRFInspectable() const
2779  {
2781  }
2782 
2783  virtual void ShowNewGRFInspectWindow() const
2784  {
2786  }
2787 };
2788 
2789 
2792 {
2793  AllocateWindowDescFront<VehicleViewWindow>((v->type == VEH_TRAIN) ? &_train_view_desc : &_vehicle_view_desc, v->index);
2794 }
2795 
2801 bool VehicleClicked(const Vehicle *v)
2802 {
2803  assert(v != NULL);
2804  if (!(_thd.place_mode & HT_VEHICLE)) return false;
2805 
2806  v = v->First();
2807  if (!v->IsPrimaryVehicle()) return false;
2808 
2809  return _thd.GetCallbackWnd()->OnVehicleSelect(v);
2810 }
2811 
2812 void StopGlobalFollowVehicle(const Vehicle *v)
2813 {
2815  if (w != NULL && w->viewport->follow_vehicle == v->index) {
2816  ScrollMainWindowTo(v->x_pos, v->y_pos, v->z_pos, true); // lock the main view on the vehicle's last position
2818  }
2819 }
2820 
2821 
2830 void CcBuildPrimaryVehicle(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
2831 {
2832  if (result.Failed()) return;
2833 
2834  const Vehicle *v = Vehicle::Get(_new_vehicle_id);
2836 }
2837 
2844 {
2845  switch (v->type) {
2846  case VEH_TRAIN:
2847  return Train::From(v)->GetDisplayImageWidth();
2848 
2849  case VEH_ROAD:
2851 
2852  default:
2853  bool rtl = _current_text_dir == TD_RTL;
2854  VehicleSpriteSeq seq;
2855  v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq);
2856  Rect rec;
2857  seq.GetBounds(&rec);
2858  return UnScaleGUI(rec.right - rec.left + 1);
2859  }
2860 }
2861 
2867 int GetVehicleWidth(const Vehicle *v, EngineImageType image_type)
2868 {
2869  if (v->type == VEH_TRAIN || v->type == VEH_ROAD) {
2870  int vehicle_width = 0;
2871  for (const Vehicle *u = v; u != NULL; u = u->Next()) {
2872  vehicle_width += GetSingleVehicleWidth(u, image_type);
2873  }
2874  return vehicle_width;
2875  } else {
2876  return GetSingleVehicleWidth(v, image_type);
2877  }
2878 }
2879 
2886 {
2887  bool rtl = _current_text_dir == TD_RTL;
2888 
2889  _cursor.sprite_count = 0;
2890  int total_width = 0;
2891  for (; v != NULL; v = v->HasArticulatedPart() ? v->GetNextArticulatedPart() : NULL) {
2892  if (total_width >= 2 * (int)VEHICLEINFO_FULL_VEHICLE_WIDTH) break;
2893 
2895  VehicleSpriteSeq seq;
2896  v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq);
2897 
2898  if (_cursor.sprite_count + seq.count > lengthof(_cursor.sprite_seq)) break;
2899 
2900  for (uint i = 0; i < seq.count; ++i) {
2901  PaletteID pal2 = (v->vehstatus & VS_CRASHED) || !seq.seq[i].pal ? pal : seq.seq[i].pal;
2902  _cursor.sprite_seq[_cursor.sprite_count].sprite = seq.seq[i].sprite;
2903  _cursor.sprite_seq[_cursor.sprite_count].pal = pal2;
2904  _cursor.sprite_pos[_cursor.sprite_count].x = rtl ? -total_width : total_width;
2905  _cursor.sprite_pos[_cursor.sprite_count].y = 0;
2906  _cursor.sprite_count++;
2907  }
2908 
2909  total_width += GetSingleVehicleWidth(v, image_type);
2910  }
2911 
2912  int offs = ((int)VEHICLEINFO_FULL_VEHICLE_WIDTH - total_width) / 2;
2913  if (rtl) offs = -offs;
2914  for (uint i = 0; i < _cursor.sprite_count; ++i) {
2915  _cursor.sprite_pos[i].x += offs;
2916  }
2917 
2918  UpdateCursorSize();
2919 }
Nested widget containing a viewport.
Definition: widget_type.h:81
static const uint32 _vehicle_command_translation_table[][4]
Command codes for the shared buttons indexed by VehicleCommandTranslation and vehicle type...
Functions related to OTTD&#39;s strings.
Road vehicle states.
void DrawTrainDetails(const Train *v, int left, int right, int y, int vscroll_pos, uint16 vscroll_cap, TrainDetailsWindowTabs det_tab)
Draw the details for the given vehicle at the given position.
Definition: train_gui.cpp:357
VehicleSettings vehicle
options for vehicles
Functions/types related to NewGRF debugging.
Date max_age
Maximum age.
Definition: vehicle_base.h:259
CargoID cargo
Cargo to refit to.
uint32 PaletteID
The number of the palette.
Definition: gfx_type.h:20
Default zoom level for the aircraft view.
Definition: zoom_type.h:39
WindowNumber window_number
The WindowNumber of the window that is responsible for the selection mode.
Vehicle is stopped by the player.
Definition: vehicle_base.h:33
Normal push-button (no toggle button) with image caption.
Definition: widget_type.h:105
void RebuildDone()
Notify the sortlist that the rebuild is done.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:77
DropDownList * BuildActionDropdownList(bool show_autoreplace, bool show_group)
Display the Action dropdown window.
Definition of stuff that is very close to a company, like the company struct itself.
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:257
Money value
Value of the vehicle.
Definition: vehicle_base.h:241
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
Default settings for vehicles.
uint32 widget_data
Data of the widget.
Definition: widget_type.h:305
static const RailtypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition: rail.h:298
static const int DAYS_IN_YEAR
days per year
Definition: date_type.h:31
void ChangeVehicleViewWindow(VehicleID from_index, VehicleID to_index)
Report a change in vehicle IDs (due to autoreplace) to affected vehicle windows.
virtual void OnQueryTextFinished(char *str)
The query window opened from this window has closed.
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
CompanyID company
The company associated with this list.
Definition: vehiclelist.h:34
PlaneSelections
Display planes available in the vehicle view window.
Horizontally center the text.
Definition: gfx_func.h:99
The information about a vehicle list.
Definition: vehiclelist.h:31
ResizeInfo resize
Resize information.
Definition: window_gui.h:324
virtual void OnPaint()
The window must be repainted.
CargoTypes _cargo_mask
Bitmask of cargo types available.
Definition: cargotype.cpp:31
void ScrollTowards(int position)
Scroll towards the given position; if the item is visible nothing happens, otherwise it will be shown...
Definition: widget_type.h:731
static NWidgetPart SetResize(int16 dx, int16 dy)
Widget part function for setting the resize step.
Definition: widget_type.h:930
Window(WindowDesc *desc)
Empty constructor, initialization has been moved to InitNested() called from the constructor of the d...
Definition: window.cpp:1851
static const int VEHICLE_PROFIT_MIN_AGE
Only vehicles older than this have a meaningful profit.
Definition: vehicle_func.h:29
static int CDECL VehicleNumberSorter(const Vehicle *const *a, const Vehicle *const *b)
Sort vehicles by their number.
void SetWidgetDisabledState(byte widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition: window_gui.h:394
static int CDECL VehicleProfitThisYearSorter(const Vehicle *const *a, const Vehicle *const *b)
Sort vehicles by this year profit.
Offset at right of a matrix cell.
Definition: window_gui.h:79
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
void SetWidgetLoweredState(byte widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition: window_gui.h:455
Money GetDisplayProfitThisYear() const
Gets the profit vehicle had this year.
Definition: vehicle_base.h:566
static int UnScaleGUI(int value)
Short-hand to apply GUI zoom level.
Definition: zoom_func.h:72
static WindowDesc _vehicle_view_desc(WDP_AUTO, "view_vehicle", 250, 116, WC_VEHICLE_VIEW, WC_NONE, 0, _nested_vehicle_view_widgets, lengthof(_nested_vehicle_view_widgets))
Vehicle view window descriptor for all vehicles but trains.
void DrawShipImage(const Vehicle *v, int left, int right, int y, VehicleID selection, EngineImageType image_type)
Draws an image of a ship.
Definition: ship_gui.cpp:34
Window * parent
Parent window.
Definition: window_gui.h:339
High level window description.
Definition: window_gui.h:168
Functions related to the autoreplace GUIs.
East.
Vehicle * GetFirstEnginePart()
Get the first part of an articulated engine.
Definition: vehicle_base.h:921
uint16 GetServiceIntervalClamped(uint interval, bool ispercent)
Clamp the service interval to the correct min/max.
Definition: order_cmd.cpp:1957
rename a whole vehicle
Definition: command_type.h:243
int sprite_right
Right position of the vehicle sprite.
WindowFlags flags
Window flags.
Definition: window_gui.h:312
StringID tool_tip
Tooltip of the widget.
Definition: widget_type.h:306
int left
x position of left edge of the window
Definition: window_gui.h:319
StringID GetAircraftTypeText() const
Get the name of the aircraft type for display purposes.
Definition: engine.cpp:470
Functions related to time tabling.
void DrawAircraftDetails(const Aircraft *v, int left, int right, int y)
Draw the details for the given vehicle at the given position.
bool VehicleClicked(const Vehicle *v)
Dispatch a "vehicle selected" event if any window waits for it.
void ErasePreservingOrder(uint pos, uint count=1)
Remove items from the vector while preserving the order of other items.
void DrawWidgets() const
Paint all widgets of a window.
Definition: widget.cpp:604
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:246
bool CanCarryCargo() const
Determines whether an engine can carry something.
Definition: engine.cpp:173
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
void DrawVehicleImage(const Vehicle *v, int left, int right, int y, VehicleID selection, EngineImageType image_type, int skip)
Draws an image of a vehicle chain.
static Point RemapCoords(int x, int y, int z)
Map 3D world or tile coordinate to equivalent 2D coordinate as used in the viewports and smallmap...
Definition: landscape.h:84
Header with question about the cargo to carry.
Show details of this vehicle.
Scrollbar data structure.
Definition: widget_type.h:589
Vehicle composition was changed.
Definition: vehicle_gui.h:36
Stacked widgets, widgets all occupying the same space in the window.
Definition: widget_type.h:405
Base for the train class.
Point sprite_pos[16]
relative position of individual sprites
Definition: gfx_type.h:131
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
void SetWidgetDirty(byte widget_index) const
Invalidate a widget, i.e.
Definition: window.cpp:581
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
static const VehicleOrderID INVALID_VEH_ORDER_ID
Invalid vehicle order index (sentinel)
Definition: order_type.h:23
Offset at top to draw the frame rectangular area.
Definition: window_gui.h:64
virtual void OnDropdownSelect(int widget, int index)
A dropdown option associated to this window has been selected.
Default zoom level for the ship view.
Definition: zoom_type.h:40
Sort order.
void UpdateViewportCoordinates(Window *w)
Update the position and size of the viewport (after eg a resize).
Definition: widget.cpp:1936
Functions related to debugging.
virtual void OnDragDrop(Point pt, int widget)
A dragged &#39;object&#39; has been released.
Horizontal container.
Definition: widget_type.h:75
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition: window.cpp:1114
change the server interval of a vehicle
Definition: command_type.h:231
static void DrawVehicleProfitButton(const Vehicle *v, int x, int y)
draw the vehicle profit button in the vehicle list window.
byte _colour_gradient[COLOUR_END][8]
All 16 colour gradients 8 colours per gradient from darkest (0) to lightest (7)
Definition: gfx.cpp:53
Arrow to the right or in case of RTL to the left.
Definition: widget_type.h:38
Arrow to the left or in case of RTL to the right.
Definition: widget_type.h:37
uint16 cur_speed
current speed
Definition: vehicle_base.h:293
query cost only, don&#39;t build.
Definition: command_type.h:347
void CDECL SetWidgetsDisabledState(bool disab_stat, int widgets,...)
Sets the enabled/disabled status of a list of widgets.
Definition: window.cpp:520
NewGRF debug box (at top-right of a window, between WWT_CAPTION and WWT_SHADEBOX) ...
Definition: widget_type.h:63
uint sprite_count
number of sprites to draw
Definition: gfx_type.h:132
void ShowQueryString(StringID str, StringID caption, uint maxsize, Window *parent, CharSetFilter afilter, QueryStringFlags flags)
Show a query popup window with a textbox in it.
Definition: misc_gui.cpp:1064
static int ScaleGUITrad(int value)
Scale traditional pixel dimensions to GUI zoom level.
Definition: zoom_func.h:82
Maximal number of cargo types in a game.
Definition: cargo_type.h:66
Tab with cargo capacity of the vehicles.
Definition: vehicle_gui.h:28
bool IsStoppedInDepot() const
Check whether the vehicle is in the depot and stopped.
Definition: vehicle_base.h:516
uint16 _returned_refit_capacity
Stores the capacity after a refit operation.
Definition: vehicle.cpp:87
#define FOR_ALL_SORTED_CARGOSPECS(var)
Loop header for iterating over cargoes, sorted by name.
Definition: cargotype.h:166
Specification of a cargo type.
Definition: cargotype.h:56
GUIVehicleList vehicles
The list of vehicles.
OrderList * list
Pointer to the order list for this vehicle.
Definition: vehicle_base.h:321
static WindowDesc _train_vehicle_details_desc(WDP_AUTO, "view_vehicle_details_train", 405, 178, WC_VEHICLE_DETAILS, WC_VEHICLE_VIEW, 0, _nested_train_vehicle_details_widgets, lengthof(_nested_train_vehicle_details_widgets))
Vehicle details window descriptor.
Clone this vehicle.
Default zoom level for the road vehicle view.
Definition: zoom_type.h:42
Functions related to vehicles.
Aircraft, helicopters, rotors and their shadows belong to this class.
Definition: aircraft.h:76
CargoTypes GetUnionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type)
Ors the refit_masks of all articulated parts.
static int CDECL VehicleReliabilitySorter(const Vehicle *const *a, const Vehicle *const *b)
Sort vehicles by their reliability.
Resize box (normally at bottom-right of a window)
Definition: widget_type.h:68
Pressed (inset) panel, most commonly used as combo box text area.
Definition: widget_type.h:51
Manage vehicles dropdown list.
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
Sort by dropdown list.
Show carried cargo per part of the train.
Vehicle data structure.
Definition: vehicle_base.h:212
Caption of window.
static bool IsExpected(const BaseStation *st)
Helper for checking whether the given station is of this type.
void Clear()
Remove all items from the list.
Scrollbar * vscroll
The main scrollbar.
virtual void ShowNewGRFInspectWindow() const
Show the NewGRF inspection window.
const T * Begin() const
Get the pointer to the first item (const)
Start or stop this vehicle, and show information about the current state.
Tindex index
Index of this pool item.
Definition: pool_type.hpp:147
Normal push-button (no toggle button) with custom drawing.
Definition: widget_type.h:103
virtual void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
Gets the sprite to show for the given direction.
Definition: vehicle_base.h:442
static const int DAY_TICKS
1 day is 74 ticks; _date_fract used to be uint16 and incremented by 885.
Definition: date_type.h:30
Close box (at top-left of a window)
Definition: widget_type.h:69
Offset at top of a matrix cell.
Definition: window_gui.h:80
PaletteID GetVehiclePalette(const Vehicle *v)
Get the colour map for a vehicle.
Definition: vehicle.cpp:1981
Rename this vehicle.
bool NeedResort()
Check if a resort is needed next loop If used the resort timer will decrease every call till 0...
void CcStartStopVehicle(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
This is the Callback method after attempting to start/stop a vehicle.
bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &vli)
Generate a list of vehicles based on window type.
Base for aircraft.
static NWidgetPart SetMinimalTextLines(uint8 lines, uint8 spacing, FontSize size=FS_NORMAL)
Widget part function for setting the minimal text lines.
Definition: widget_type.h:965
#define lastof(x)
Get the last element of an fixed size array.
Definition: depend.cpp:50
Horizontal scrollbar or the vehicle display.
void ReInit(int rx=0, int ry=0)
Re-initialize a window, and optionally change its size.
Definition: window.cpp:979
Show the orders of this vehicle.
StringID GetGRFStringID(uint32 grfid, StringID stringid)
Returns the index for this stringid associated with its grfID.
static int CDECL VehicleTimeToLiveSorter(const Vehicle *const *a, const Vehicle *const *b)
Sort vehicles by the time they can still live.
void RefreshScrollbar()
Refresh scrollbar after selection changed.
Money GetCost() const
The costs as made up to this moment.
Definition: command_type.h:84
Stuff related to the text buffer GUI.
WindowClass
Window classes.
Definition: window_type.h:39
byte GetDigitWidth(FontSize size)
Return the maximum width of single digit.
Definition: gfx.cpp:1164
void DisableWidget(byte widget_index)
Sets a widget to disabled.
Definition: window_gui.h:404
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
List of the vehicles.
Invalid window.
Definition: window_type.h:696
Common return value for all commands.
Definition: command_type.h:25
uint32 cached_power
Total power of the consist (valid only for the first engine).
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
GrfSpecFeature GetGrfSpecFeature(TileIndex tile)
Get the GrfSpecFeature associated with the tile.
Determine the cargo "suffixes" for each refit possibility of a cargo.
void CcBuildPrimaryVehicle(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
This is the Callback method after the construction attempt of a primary vehicle.
static const VehicleID INVALID_VEHICLE
Constant representing a non-existing vehicle.
Definition: vehicle_type.h:59
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:26
uint8 advanced_vehicle_list
use the "advanced" vehicle list
byte vehstatus
Status.
Definition: vehicle_base.h:317
EngineImageType
Visualisation contexts of vehicles and engines.
Definition: vehicle_type.h:89
WindowClass cls
Class of the window,.
Definition: window_gui.h:177
Cached, frequently calculated values.
Nested widget to display a viewport in a window.
Definition: widget_type.h:575
TileIndex GetLocation(const Vehicle *v, bool airport=false) const
Returns a tile somewhat representing the order destination (not suitable for pathfinding).
Definition: order_cmd.cpp:671
Common string list item.
Definition: dropdown_type.h:41
Option to refit a vehicle chain.
static Train * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
Display &#39;goto depot&#39; button in WID_VV_SELECT_DEPOT_CLONE stacked widget.
const T * End() const
Get the pointer behind the last valid item (const)
void CreateNestedTree(bool fill_nested=true)
Perform the first part of the initialization of a nested widget tree.
Definition: window.cpp:1812
const Engine * GetEngine() const
Retrieves the engine of the vehicle.
Definition: vehicle.cpp:744
void SetListing(Listing l)
Import sort conditions.
Window * GetCallbackWnd()
Get the window that started the current highlighting.
Definition: viewport.cpp:2206
StringID name
Name of this type of cargo.
Definition: cargotype.h:71
Display &#39;clone vehicle&#39; button in WID_VV_SELECT_DEPOT_CLONE stacked widget.
bool NeedRebuild() const
Check if a rebuild is needed.
HighLightStyle place_mode
Method which is used to place the selection.
OrderDepotActionFlags GetDepotActionType() const
What are we going to do when in the depot.
Definition: order_base.h:139
static const ZoomLevel _vehicle_view_zoom_levels[]
Zoom levels for vehicle views indexed by vehicle type.
virtual bool OnVehicleSelect(const struct Vehicle *v)
The user clicked on a vehicle while HT_VEHICLE has been set.
Definition: window_gui.h:763
Display with a representation of the vehicle to refit.
DepotCommand
Flags to add to p1 for goto depot commands.
Definition: vehicle_type.h:69
virtual void OnPaint()
Repaint vehicle details window.
uint16 servint_ships
service interval for ships
void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags)
Draw frame rectangle.
Definition: widget.cpp:177
T * Append(uint to_add=1)
Append an item and return it.
Order * next
Pointer to next order. If NULL, end of list.
Definition: order_base.h:51
Vehicle * FirstShared() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:675
void SetCount(int num)
Sets the number of elements in the list.
Definition: widget_type.h:670
CompanyByte _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
virtual void OnResize()
Called after the window got resized.
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:910
Functions related to (drawing on) viewports.
start or stop a vehicle
Definition: command_type.h:312
void ForceRebuild()
Force that a rebuild is needed.
StringID string
GRF-local String to display for the cargo.
void DrawAircraftImage(const Vehicle *v, int left, int right, int y, VehicleID selection, EngineImageType image_type)
Draws an image of an aircraft.
bool IsEngineRefittable(EngineID engine)
Check if an engine is refittable.
Definition: engine.cpp:1110
void Resize(uint num_items)
Set the size of the vector, effectively truncating items from the end or appending uninitialised ones...
Data structure for an opened window.
Definition: window_gui.h:278
byte breakdown_ctr
Counter for managing breakdown events.
Definition: vehicle_base.h:263
bool _ctrl_pressed
Is Ctrl pressed?
Definition: gfx.cpp:36
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition: window.cpp:1828
static NWidgetPart SetMatrixDataTip(uint8 cols, uint8 rows, StringID tip)
Widget part function for setting the data and tooltip of WWT_MATRIX widgets.
Definition: widget_type.h:1032
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
Autoreplace replaced the vehicle.
Definition: vehicle_gui.h:37
static NWidgetPart SetPadding(uint8 top, uint8 right, uint8 bottom, uint8 left)
Widget part function for setting additional space around a widget.
Definition: widget_type.h:1046
Vehicle drawn in vehicle details, refit window, ...
Definition: vehicle_type.h:92
dragging items in the depot windows
uint16 cargo_cap
total capacity
Definition: vehicle_base.h:307
Bottom offset of image in the button.
Definition: window_gui.h:43
Header of Action 04 "universal holder" structure and functions.
Main window; Window numbers:
Definition: window_type.h:46
enable the &#39;Default&#39; button ("\0" is returned)
Definition: textbuf_gui.h:23
Vehicle orders; Window numbers:
Definition: window_type.h:207
proceed a train to pass a red signal
Definition: command_type.h:222
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
Aircraft vehicle type.
Definition: vehicle_type.h:29
virtual int GetDisplayMaxSpeed() const
Gets the maximum speed in km-ish/h that can be sent into SetDParam for string processing.
Definition: vehicle_base.h:486
Money GetDisplayRunningCost() const
Gets the running cost of a vehicle that can be sent into SetDParam for string processing.
Definition: vehicle_base.h:560
Map related accessors for depots.
static int CDECL VehicleCargoSorter(const Vehicle *const *a, const Vehicle *const *b)
Sort vehicles by their cargo.
void SelectPlane(PlaneSelections plane)
Display a plane in the window.
Functions related to low-level strings.
Zoomed 4 times out.
Definition: zoom_type.h:26
Vehicle is crashed.
Definition: vehicle_base.h:39
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
byte GetBestFittingSubType(Vehicle *v_from, Vehicle *v_for, CargoID dest_cargo_type)
Get the best fitting subtype when &#39;cloning&#39;/&#39;replacing&#39; v_from with v_for.
virtual void OnMouseDrag(Point pt, int widget)
An &#39;object&#39; is being dragged at the provided position, highlight the target if possible.
uint GetRoadVehDetailsHeight(const Vehicle *v)
Gets the desired height for the road vehicle details panel.
virtual bool IsPrimaryVehicle() const
Whether this is the primary vehicle in the chain.
Definition: vehicle_base.h:433
Window manager class for viewing a vehicle.
Scrollbar * hscroll
Only used for long vehicles.
static const uint MAX_LENGTH_VEHICLE_NAME_CHARS
The maximum length of a vehicle name in characters including &#39;\0&#39;.
Definition: vehicle_type.h:77
Offset at bottom of a matrix cell.
Definition: window_gui.h:81
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
UnitID unitnumber
unit number, for display purposes only
Definition: vehicle_base.h:291
#define FONT_HEIGHT_SMALL
Height of characters in the small (FS_SMALL) font.
Definition: gfx_func.h:177
CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
Shorthand for calling the long DoCommand with a container.
Definition: command.cpp:440
void DrawVehicleListItems(VehicleID selected_vehicle, int line_height, const Rect &r) const
Draw all the vehicle list items.
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX) ...
Definition: widget_type.h:65
byte cargo_subtype
Used for livery refits (NewGRF variations)
Definition: vehicle_base.h:306
uint Length() const
Get the number of items in the list.
bool operator!=(const MultiMapIterator< Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare > &iter1, const MultiMapIterator< Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare > &iter2)
Inverse of operator==().
Definition: multimap.hpp:222
int GetScrolledRowFromWidget(int clickpos, const Window *const w, int widget, int padding=0, int line_height=-1) const
Compute the row of a scrolled widget that a user clicked in.
Definition: widget.cpp:1959
static int CDECL VehicleMaxSpeedSorter(const Vehicle *const *a, const Vehicle *const *b)
Sort vehicles by their max speed.
This window is used for construction; close it whenever changing company.
Definition: window_gui.h:210
West.
bool IsWidgetLowered(byte widget_index) const
Gets the lowered state of a widget.
Definition: window_gui.h:495
Listing GetListing() const
Export current sort conditions.
bool Contains(const T &item) const
Tests whether a item is present in the vector.
static bool IsVehicleServiceIntervalEnabled(const VehicleType vehicle_type, CompanyID company_id)
Checks whether service interval is enabled for the vehicle.
Turn this vehicle around.
int GetSingleVehicleWidth(const Vehicle *v, EngineImageType image_type)
Get the width of a vehicle (part) in pixels.
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
Functions related to engines.
GroundVehicleCache * GetGroundVehicleCache()
Access the ground vehicle cache of the vehicle.
Definition: vehicle.cpp:2826
VehicleType
Available vehicle types.
Definition: vehicle_type.h:23
Scrollbar for the refit options.
uint current_y
Current vertical size (after resizing).
Definition: widget_type.h:175
void DrawRoadVehDetails(const Vehicle *v, int left, int right, int y)
Draw the details for the given vehicle at the given position.
Definition: roadveh_gui.cpp:32
uint32 index
A vehicle list type specific index.
Definition: vehiclelist.h:35
virtual void OnDropdownSelect(int widget, int index)
A dropdown option associated to this window has been selected.
Sort descending.
Definition: window_gui.h:227
uint32 VehicleID
The type all our vehicle IDs have.
Definition: vehicle_type.h:18
void ShowVehicleRefitWindow(const Vehicle *v, VehicleOrderID order, Window *parent, bool auto_refit)
Show the refit window for a vehicle.
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition: order_base.h:63
static void ChangeVehicleWindow(WindowClass window_class, VehicleID from_index, VehicleID to_index)
Assign a vehicle window a new vehicle.
Options to refit to.
Viewport widget.
#define FONT_HEIGHT_NORMAL
Height of characters in the normal (FS_NORMAL) font.
Definition: gfx_func.h:180
static NWidgetPart SetDataTip(uint32 data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1014
Simple vector template class, with automatic delete.
T * Next() const
Get next vehicle in the chain.
byte callback_mask
Bitmask of vehicle callbacks that have to be called.
Definition: engine_type.h:143
Selection widget between &#39;goto depot&#39;, and &#39;clone vehicle&#39; buttons.
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:76
Display plane with zero size vertically, and filling and resizing horizontally.
Definition: widget_type.h:389
static NWidgetPart SetMinimalSize(int16 x, int16 y)
Widget part function for setting the minimal size.
Definition: widget_type.h:947
Definition of base types and functions in a cross-platform compatible way.
Show suffix after cargo name.
Decrease the servicing interval.
Tells that it&#39;s a mass send to depot command (type in VLW flag)
Definition: vehicle_type.h:71
the length of the string is counted in characters
Definition: textbuf_gui.h:24
void DrawTrainImage(const Train *v, int left, int right, int y, VehicleID selection, EngineImageType image_type, int skip, VehicleID drag_dest)
Draws an image of a whole train.
Definition: train_gui.cpp:95
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
Force this vehicle to pass a signal at danger.
void ShowCompanyGroup(CompanyID company, VehicleType vehicle_type)
Show the group window for the given company and vehicle type.
Definition: group_gui.cpp:962
bool IsArticulatedPart() const
Check if the vehicle is an articulated part of an engine.
Definition: vehicle_base.h:892
A number of safeguards to prevent using unsafe methods.
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition: gfx_type.h:247
Normal push-button (no toggle button) with text caption.
Definition: widget_type.h:104
Geometry functions.
Vehicle refit; Window numbers:
Definition: window_type.h:201
Simple depressed panel.
Definition: widget_type.h:50
Selection widget for the horizontal scrollbar.
SmallVector< RefitOption, 32 > SubtypeList
List of refit subtypes associated to a cargo.
void StartStopVehicle(const Vehicle *v, bool texteffect)
Executes CMD_START_STOP_VEHICLE for given vehicle.
bool operator==(const MultiMapIterator< Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare > &iter1, const MultiMapIterator< Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare > &iter2)
Compare two MultiMap iterators.
Definition: multimap.hpp:205
CargoID cargo_type
type of cargo this vehicle is carrying
Definition: vehicle_base.h:305
void DrawSortButtonState(int widget, SortButtonState state) const
Draw a sort button&#39;s up or down arrow symbol.
Definition: widget.cpp:638
Horizontal scrollbar.
Definition: widget_type.h:83
uint step_height
Step-size of height resize changes.
Definition: window_gui.h:220
Scrollbar for the list.
const Scrollbar * GetScrollbar(uint widnum) const
Return the Scrollbar to a widget index.
Definition: window.cpp:311
uint16 GetRange() const
Get the range of this aircraft.
Definition: aircraft.h:135
static int CDECL VehicleTimetableDelaySorter(const Vehicle *const *a, const Vehicle *const *b)
Sort vehicles by the timetable delay.
Vehicle view; Window numbers:
Definition: window_type.h:334
Offset at left of a matrix cell.
Definition: window_gui.h:78
VehicleOrderID order
If not INVALID_VEH_ORDER_ID, selection is part of a refit order (rather than execute directly)...
byte subtype
Subcargo to use.
byte misc_flags
Miscellaneous flags.
Definition: engine_type.h:142
Order * GetFirstOrder() const
Get the first order of the order chain.
Definition: order_base.h:290
static VehicleListIdentifier UnPack(uint32 data)
Decode a packed vehicle list identifier into a new one.
Definition: vehiclelist.cpp:55
TileIndex tile
Current tile index.
Definition: vehicle_base.h:230
TrainDetailsWindowTabs tab
For train vehicles: which tab is displayed.
static int CDECL VehicleNameSorter(const Vehicle *const *a, const Vehicle *const *b)
Sort vehicles by their name.
void DrawShipDetails(const Vehicle *v, int left, int right, int y)
Draw the details for the given vehicle at the given position.
Definition: ship_gui.cpp:66
static NWidgetPart NWidget(WidgetType tp, Colours col, int16 idx=-1)
Widget part function for starting a new &#39;real&#39; widget.
Definition: widget_type.h:1114
The tile has no ownership.
Definition: company_type.h:27
bool HasArticulatedPart() const
Check if an engine has an articulated part.
Definition: vehicle_base.h:901
Vehicle timetable; Window numbers:
Definition: window_type.h:219
Offset at bottom to draw the frame rectangular area.
Definition: window_gui.h:65
Baseclass for nested widgets.
Definition: widget_type.h:126
int DrawString(int left, int right, int top, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition: gfx.cpp:500
void ShowVehicleViewWindow(const Vehicle *v)
Shows the vehicle view window of the given vehicle.
int GetVehicleWidth(const Vehicle *v, EngineImageType image_type)
Get the width of a vehicle (including all parts of the consist) in pixels.
Increase the servicing interval.
Service the vehicle and then halt it.
Definition: order_type.h:110
virtual void OnGameTick()
Called once per (game) tick.
void DrawRoadVehImage(const Vehicle *v, int left, int right, int y, VehicleID selection, EngineImageType image_type, int skip)
Draws an image of a road vehicle chain.
Sprite sequence for a vehicle part.
Definition: vehicle_base.h:130
bool DoCommandP(const CommandContainer *container, bool my_cmd)
Shortcut for the long DoCommandP when having a container with the data.
Definition: command.cpp:531
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:42
Start all button.
Road vehicle type.
Definition: vehicle_type.h:27
Grid of rows and columns.
Definition: widget_type.h:59
VehicleID follow_vehicle
VehicleID to follow if following a vehicle, INVALID_VEHICLE otherwise.
Definition: window_gui.h:259
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:42
uint pos_x
Horizontal position of top-left corner of the widget in the window.
Definition: widget_type.h:177
static const NWidgetPart _nested_train_vehicle_details_widgets[]
Train details widgets.
Default zoom level for the train view.
Definition: zoom_type.h:41
Right offset of the image in the button.
Definition: window_gui.h:41
byte breakdowns_since_last_service
Counter for the amount of breakdowns.
Definition: vehicle_base.h:265
uint16 reliability
Reliability.
Definition: vehicle_base.h:261
void SetSortType(uint8 n_type)
Set the sorttype of the list.
bool Sort(SortFunction *compare)
Sort the list.
static int CDECL VehicleModelSorter(const Vehicle *const *a, const Vehicle *const *b)
Sort vehicles by model.
static int SortButtonWidth()
Get width of up/down arrow of sort button state.
Definition: widget.cpp:658
Functions to cache sprites in memory.
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:18
int GetDisplayImageWidth(Point *offset=NULL) const
Get the width of a road vehicle image in the GUI.
Definition: roadveh_cmd.cpp:92
Vehicle * First() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:594
Class for managing the vehicle details window.
bool Failed() const
Did this command fail?
Definition: command_type.h:161
Tab with cargo carried by the vehicles.
Definition: vehicle_gui.h:26
Show all parts of the train with their description.
int GetDisplayImageWidth(Point *offset=NULL) const
Get the width of a train vehicle image in the GUI.
Definition: train_cmd.cpp:435
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
bool auto_refit
Select cargo for auto-refitting.
static DepotID GetDepotIndex(TileIndex t)
Get the index of which depot is attached to the tile.
Definition: depot_map.h:54
Draw border only, no background.
Definition: window_gui.h:30
static const int WIDGET_LIST_END
indicate the end of widgets&#39; list for vararg functions
Definition: widget_type.h:22
virtual void OnResize()
Called after the window got resized.
Details for non-trains.
int vehicle_width
Width of the vehicle being drawn.
static const SpriteID SPR_CLONE_TRAIN
Clone vehicles stuff.
Definition: sprites.h:102
Ship vehicle type.
Definition: vehicle_type.h:28
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:139
Functions/classes shared between the different vehicle list GUIs.
virtual void OnResize()
Called after the window got resized.
static const NWidgetPart _nested_vehicle_view_widgets[]
Vehicle view widgets.
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition: window.cpp:968
int sprite_left
Left position of the vehicle sprite.
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:36
&#39;Train&#39; is either a loco or a wagon.
Definition: train.h:88
VehicleDetailsWindow(WindowDesc *desc, WindowNumber window_number)
Initialize a newly created vehicle details window.
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition: gfx.cpp:700
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
void ForceResort()
Force a resort next Sort call Reset the resort timer if used too.
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
No window, redirects to WC_MAIN_WINDOW.
Definition: window_type.h:40
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force)
Delete a window by its class and window number (if it is open).
Definition: window.cpp:1146
PalSpriteID sprite_seq[16]
current image of cursor
Definition: gfx_type.h:130
union Vehicle::@47 orders
The orders currently assigned to the vehicle.
static int CDECL VehicleProfitLastYearSorter(const Vehicle *const *a, const Vehicle *const *b)
Sort vehicles by last year profit.
char * name
Name of vehicle.
Definition: base_consist.h:20
Selection widget between &#39;refit&#39; and &#39;turn around&#39; buttons.
Open the refit window.
ZoomLevel
All zoom levels we know.
Definition: zoom_type.h:21
static const GroupID DEFAULT_GROUP
Ungrouped vehicles are in this group.
Definition: group_type.h:19
The vehicle will leave the depot right after arrival (serivce only)
Definition: vehicle_type.h:70
static WindowDesc _nontrain_vehicle_details_desc(WDP_AUTO, "view_vehicle_details", 405, 113, WC_VEHICLE_DETAILS, WC_VEHICLE_VIEW, 0, _nested_nontrain_vehicle_details_widgets, lengthof(_nested_nontrain_vehicle_details_widgets))
Vehicle details window descriptor for other vehicles than a train.
static int32 ClampToI32(const int64 a)
Reduce a signed 64-bit int to a signed 32-bit one.
Definition: math_func.hpp:203
Functions related to companies.
uint GetUnitNumberDigits(VehicleList &vehicles)
Get the number of digits the biggest unit number of a set of vehicles has.
Window for the (old) vehicle listing.
virtual void OnPaint()
The window must be repainted.
static StationID GetStationIndex(TileIndex t)
Get StationID from a tile.
Definition: station_map.h:29
Vehicle drawn in vehicle list, group list, ...
Definition: vehicle_type.h:93
bool IsNewGRFInspectable(GrfSpecFeature feature, uint index)
Can we inspect the data given a certain feature and index.
void SetObjectToPlaceWnd(CursorID icon, PaletteID pal, HighLightStyle mode, Window *w)
Change the cursor and mouse click/drag handling to a mode for performing special operations like tile...
Definition: viewport.cpp:3025
bool ScrollMainWindowTo(int x, int y, int z, bool instant)
Scrolls the main window to given coordinates.
TrainDetailsWindowTabs
The tabs in the train details window.
Definition: vehicle_gui.h:25
Functions related to articulated vehicles.
void ErrorUnknownCallbackResult(uint32 grfid, uint16 cbid, uint16 cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
Class for storing amounts of cargo.
Definition: cargo_type.h:83
Automatic refitting is allowed.
Definition: engine_type.h:158
Both numeric and alphabetic and spaces and stuff.
Definition: string_type.h:27
StringID GetCapacityString(RefitOption *option) const
Gets the StringID to use for displaying capacity.
Display &#39;turn around&#39; button in WID_VV_SELECT_REFIT_TURN stacked widget.
bool IsGroundVehicle() const
Check if the vehicle is a ground vehicle.
Definition: vehicle_base.h:471
Train can&#39;t get a path reservation.
Definition: train.h:34
GUISettings gui
settings related to the GUI
void SetSelection(uint click_row)
Select a row.
void SetMouseCursorVehicle(const Vehicle *v, EngineImageType image_type)
Set the mouse cursor to look like a vehicle.
DestinationID GetDestination() const
Gets the destination of this order.
Definition: order_base.h:96
void ShowTimetableWindow(const Vehicle *v)
Show the timetable for a given vehicle.
Window caption (window title between closebox and stickybox)
Definition: widget_type.h:61
int strnatcmp(const char *s1, const char *s2, bool ignore_garbage_at_front)
Compares two strings using case insensitive natural sort.
Definition: string.cpp:580
VehicleCommandTranslation
Command indices for the _vehicle_command_translation_table.
Center the main view on this vehicle.
uint32 SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition: gfx_type.h:19
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
void UpdateCursorSize()
Update cursor dimension.
Definition: gfx.cpp:1532
uint16 EngineID
Unique identification number of an engine.
Definition: engine_type.h:22
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
Definition: cargotype.h:118
CompanyByte _current_company
Company currently doing an action.
Definition: company_cmd.cpp:47
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:80
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition: sprites.h:1580
uint32 Pack() const
Pack a VehicleListIdentifier in a single uint32.
Definition: vehiclelist.cpp:23
RefitOption * cargo
Refit option selected by sel.
Available vehicles.
uint16 servint_trains
service interval for trains
Vehicle * Next() const
Get the next vehicle of this vehicle.
Definition: vehicle_base.h:581
static WindowDesc _train_view_desc(WDP_AUTO, "view_vehicle_train", 250, 134, WC_VEHICLE_VIEW, WC_NONE, 0, _nested_vehicle_view_widgets, lengthof(_nested_vehicle_view_widgets))
Vehicle view window descriptor for trains.
Date date_of_last_service
Last date the vehicle had a service at a depot.
Definition: vehicle_base.h:260
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition: strings.cpp:52
void ToggleSortOrder()
Toggle the sort order Since that is the worst condition for the sort function reverse the list here...
List of details for trains.
virtual void ShowNewGRFInspectWindow() const
Show the NewGRF inspection window.
Definition: window_gui.h:814
Sort ascending.
Definition: window_gui.h:226
Panel with generic details.
static bool HasAtMostOneBit(T value)
Test whether value has at most 1 bit set.
void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8 num_vehicles)
Calculates the set of vehicles that will be affected by a given selection.
Definition: vehicle.cpp:2889
Send the vehicle to the nearest depot.
Definition: order_type.h:111
void SetDParamMaxValue(uint n, uint64 max_value, uint min_count, FontSize size)
Set DParam n to some number that is suitable for string size computations.
Definition: strings.cpp:108
Caption of window.
Tab with sum of total cargo transported.
Definition: vehicle_gui.h:29
Display &#39;refit&#39; button in WID_VV_SELECT_REFIT_TURN stacked widget.
Order this vehicle to go to the depot.
Next destination is too far away.
Definition: aircraft.h:41
Top offset of image in the button.
Definition: window_gui.h:42
VehicleListType type
The type of vehicle list.
Definition: vehiclelist.h:32
void ShowReplaceGroupVehicleWindow(GroupID id_g, VehicleType vehicletype)
Show the autoreplace configuration window for a particular group.
Vertical container.
Definition: widget_type.h:77
OwnerByte owner
Which company owns the vehicle?
Definition: vehicle_base.h:273
int CDECL SortFunction(const T *, const T *)
Signature of sort function.
Definition: sortlist_type.h:52
turn a train around
Definition: command_type.h:223
Vehicle * GetNextArticulatedPart() const
Get the next part of an articulated engine.
Definition: vehicle_base.h:911
static NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME, WWT_INSET, or WWT_PANEL).
Definition: widget_type.h:999
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
Trains list; Window numbers:
Definition: window_type.h:303
Functions related to zooming.
uint information_width
Width required for correctly displaying all cargoes in the information panel.
VehicleListType
Vehicle List type flags.
Definition: vehiclelist.h:21
Information about the servicing interval.
int shown_plane
Plane being displayed (for NWID_SELECTION only).
Definition: widget_type.h:420
uint current_x
Current horizontal size (after resizing).
Definition: widget_type.h:174
static void ShowVehicleDetailsWindow(const Vehicle *v)
Shows the vehicle details window of the given vehicle.
int GetTrainDetailsWndVScroll(VehicleID veh_id, TrainDetailsWindowTabs det_tab)
Determines the number of lines in the train details window.
Definition: train_gui.cpp:314
static const Money VEHICLE_PROFIT_THRESHOLD
Threshold for a vehicle to be considered making good profit.
Definition: vehicle_func.h:30
change the refit information of an order (for "goto depot" )
Definition: command_type.h:270
bool Include(const T &item)
Tests whether a item is present in the vector, and appends it to the end if not.
uint16 _returned_mail_refit_capacity
Stores the mail capacity after a refit operation (Aircraft only).
Definition: vehicle.cpp:88
uint16 servint_aircraft
service interval for aircraft
Refit cargo window.
Show the capacity and carried cargo amounts aggregated per cargo of the train.
static uint GetVehicleHeight(VehicleType type)
Get the height of a single vehicle in the GUIs.
Definition: vehicle_gui.h:62
static uint ToPercent16(uint i)
Converts a "fract" value 0..65535 to "percent" value 0..100.
Definition: math_func.hpp:300
static const NWidgetPart _nested_nontrain_vehicle_details_widgets[]
Vehicle details widgets (other than train).
int32 z_pos
z coordinate.
Definition: vehicle_base.h:270
bool ScrollMainWindowToTile(TileIndex tile, bool instant)
Scrolls the viewport of the main window to a given location.
Definition: viewport.cpp:2133
VehicleListIdentifier vli
Identifier of the vehicle list we want to currently show.
Vehicle details; Window numbers:
Definition: window_type.h:195
Scrollbar for train details.
static uint CountBits(T value)
Counts the number of set bits in a variable.
Bottom offset of the dropdown widget string.
Definition: window_gui.h:137
Functions/definitions that have something to do with groups.
Functions related to commands.
Caption of window.
Coordinates of a point in 2D.
clone a vehicle
Definition: command_type.h:311
int click_x
Position of the first click while dragging.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition: gfx.cpp:769
CargoID Index() const
Determines index of this cargospec.
Definition: cargotype.h:89
void SetDisplayedPlane(int plane)
Select which plane to show (for NWID_SELECTION only).
Definition: widget.cpp:1084
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-NULL) Titem.
Definition: pool_type.hpp:235
uint32 GetGRFID() const
Retrieve the GRF ID of the NewGRF the vehicle is tied to.
Definition: vehicle.cpp:764
uint8 train_acceleration_model
realistic acceleration for trains
Make the text effect slowly go upwards.
Definition: texteff.hpp:23
Ignore next signal, after the signal ignore being stuck.
Definition: train.h:42
Drop down list.
Definition: widget_type.h:70
Normal push-button (no toggle button) with arrow caption.
Definition: widget_type.h:106
uint16 GetCapacity() const
Gets the number of visible elements of the scrollbar.
Definition: widget_type.h:622
static WindowClass GetWindowClassForVehicleType(VehicleType vt)
Get WindowClass for vehicle list of given vehicle type.
Definition: vehicle_gui.h:85
virtual void OnResize()
Called after the window got resized.
start/stop all vehicles (in a depot)
Definition: command_type.h:313
Window does not do autoscroll,.
Definition: window_gui.h:241
static int CDECL VehicleValueSorter(const Vehicle *const *a, const Vehicle *const *b)
Sort vehicles by their value.
Order * GetOrder(int index) const
Returns order &#39;index&#39; of a vehicle or NULL when it doesn&#39;t exists.
Definition: vehicle_base.h:860
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:19
Owner owner
The owner of the content shown in this window. Company colour is acquired from this variable...
Definition: window_gui.h:326
uint16 GetVehicleCallback(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v)
Evaluate a newgrf callback for vehicles.
uint8 num_vehicles
Number of selected vehicles.
virtual bool IsNewGRFInspectable() const
Is the data related to this window NewGRF inspectable?
uint8 roadveh_acceleration_model
realistic acceleration for road vehicles
vehicle is accepted as target as well (bitmask)
Offset at right to draw the frame rectangular area.
Definition: window_gui.h:63
EngineID engine_type
The type of engine used for this vehicle.
Definition: vehicle_base.h:288
ZoomLevel zoom
The zoom level of the viewport.
Definition: viewport_type.h:35
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition: widget_type.h:66
void BuildRefitList()
Collects all (cargo, subcargo) refit options of a vehicle chain.
int width
width of the window (number of pixels to the right in x direction)
Definition: window_gui.h:321
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
uint GetVehicleListHeight(VehicleType type, uint divisor)
Get the height of a vehicle in the vehicle list GUIs.
static void DrawVehicleRefitWindow(const SubtypeList list[NUM_CARGO], const int sel[2], uint pos, uint rows, uint delta, const Rect &r)
Draw the list of available refit options for a consist and highlight the selected refit option (if an...
int32 x_pos
x coordinate.
Definition: vehicle_base.h:268
byte VehicleOrderID
The index of an order within its current vehicle (not pool related)
Definition: order_type.h:17
static NWidgetPart SetFill(uint fill_x, uint fill_y)
Widget part function for setting filling.
Definition: widget_type.h:983
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
virtual void OnInit()
Notification that the nested widget tree gets initialized.
Show the capacity of all train parts.
Information about the currently selected refit option.
static const TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:85
Perform the refit.
const GRFFile * GetGRF() const
Retrieve the NewGRF the vehicle is tied to.
Definition: vehicle.cpp:754
bool IsDescSortOrder() const
Check if the sort order is descending.
#define CMD_MSG(x)
Used to combine a StringID with the command.
Definition: command_type.h:369
static bool IsVehicleRefitable(const Vehicle *v)
Checks whether the vehicle may be refitted at the moment.
int32 WindowNumber
Number to differentiate different windows of the same class.
Definition: window_type.h:707
virtual int GetDisplaySpeed() const
Gets the speed in km-ish/h that can be sent into SetDParam for string processing. ...
Definition: vehicle_base.h:480
WindowClass window_class
Window class.
Definition: window_gui.h:313
uint16 servint_roadveh
service interval for road vehicles
OrderType GetType() const
Get the type of order of this order.
Definition: order_base.h:69
void SetCapacityFromWidget(Window *w, int widget, int padding=0)
Set capacity of visible elements from the size and resize properties of a widget. ...
Definition: widget.cpp:1973
Specification of a rectangle with absolute coordinates of all edges.
Vertical scrollbar.
Definition: widget_type.h:84
WindowClass window_class
The WindowClass of the window that is responsible for the selection mode.
byte CargoID
Cargo slots to indicate a cargo type within a game.
Definition: cargo_type.h:22
int32 y_pos
y coordinate.
Definition: vehicle_base.h:269
byte unitnumber_digits
The number of digits of the highest unit number.
Text is written right-to-left by default.
Definition: strings_type.h:26
WindowNumber window_number
Window number within the window class.
Definition: window_gui.h:314
ButtonPlanes
Enumeration of planes of the button row at the bottom.
uint32 cached_max_te
Maximum tractive effort of consist (valid only for the first engine).
Functions related to tile highlights.
Owner
Enum for all companies/owners.
Definition: company_type.h:20
virtual bool IsChainInDepot() const
Check whether the whole vehicle chain is in the depot.
Definition: vehicle_base.h:510
uint ShowRefitOptionsList(int left, int right, int y, EngineID engine)
Display list of cargo types of the engine, for the purchase information window.
StringID GetCargoSubtypeText(const Vehicle *v)
Get the cargo subtype text from NewGRF for the vehicle details window.
static const uint MAX_REFIT_CYCLE
Maximum number of refit cycles we try, to prevent infinite loops.
Find a place automatically.
Definition: window_gui.h:156
Dimension GetActionDropdownSize(bool show_autoreplace, bool show_group)
Compute the size for the Action dropdown.
SpriteID sprite
The &#39;real&#39; sprite.
Definition: gfx_type.h:25
Dropdown to select default/days/percent service interval.
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition: widget_type.h:80
ViewportData * viewport
Pointer to viewport data, if present.
Definition: window_gui.h:328
GUI functions that shouldn&#39;t be here.
Listing * sorting
Pointer to the vehicle type related sorting.
static const CursorID SPR_CURSOR_MOUSE
Cursor sprite numbers.
Definition: sprites.h:1360
Base classes/functions for stations.
void CcCloneVehicle(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
This is the Callback method after the cloning attempt of a vehicle.
Definition: depot_gui.cpp:122
static void QSortT(T *base, uint num, int(CDECL *comparator)(const T *, const T *), bool desc=false)
Type safe qsort()
Definition: sort_func.hpp:28
Caption of window.
static int CDECL VehicleAgeSorter(const Vehicle *const *a, const Vehicle *const *b)
Sort vehicles by their age.
virtual void SetDirty(const Window *w) const
Mark the widget as &#39;dirty&#39; (in need of repaint).
Definition: widget.cpp:775
Left offset of the image in the button.
Definition: window_gui.h:40
VehicleType vtype
The vehicle type associated with this list.
Definition: vehiclelist.h:33
Date age
Age in days.
Definition: vehicle_base.h:258
RefitOption * GetRefitOption()
Gets the RefitOption placed in the selected index.
static NWidgetPart SetScrollbar(int index)
Attach a scrollbar to a widget.
Definition: widget_type.h:1095
static int CDECL VehicleLengthSorter(const Vehicle *const *a, const Vehicle *const *b)
Sort vehicles by their length.
VehicleOrderID cur_real_order_index
The index to the current real (non-implicit) order.
Definition: base_consist.h:29
VehicleTypeByte type
Type of vehicle.
Definition: vehicle_type.h:56
Dimensions (a width and height) of a rectangle in 2D.
Offset at left to draw the frame rectangular area.
Definition: window_gui.h:62
static const Year MAX_YEAR
MAX_YEAR, nicely rounded value of the number of years that can be encoded in a single 32 bits date...
Definition: date_type.h:94
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition: widget_type.h:64
uint32 cached_weight
Total weight of the consist (valid only for the first engine).
void InvalidateNewGRFCache()
Invalidates cached NewGRF variables.
Definition: vehicle_base.h:451
Money GetDisplayProfitLastYear() const
Gets the profit vehicle had last year.
Definition: vehicle_base.h:572
void GetBounds(Rect *bounds) const
Determine shared bounds of all sprites.
Definition: vehicle.cpp:100
uint vehicle_margin
Margin to use while selecting vehicles when the vehicle image is centered.
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition: gfx.cpp:834
turn a road vehicle around
Definition: command_type.h:253
Order current_order
The current order (+ status, like: loading)
Definition: vehicle_base.h:318
VehicleID selected_vehicle
First vehicle in the current selection.
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window&#39;s data as invalid (in need of re-computing)
Definition: window.cpp:3242
Top offset of the dropdown widget string.
Definition: window_gui.h:136
Selection to hide the buttons.
GroupID group_id
Index of group Pool array.
Definition: vehicle_base.h:326
static const int DAYS_IN_LEAP_YEAR
sometimes, you need one day more...
Definition: date_type.h:32
int height
Height of the window (number of pixels down in y direction)
Definition: window_gui.h:322
int DrawStringMultiLine(int left, int right, int top, int bottom, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition: gfx.cpp:621
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
Definition: window_gui.h:748
(Toggle) Button with text
Definition: widget_type.h:55
virtual void OnPaint()
The window must be repainted.
static void MemSetT(T *ptr, byte value, size_t num=1)
Type-safe version of memset().
Definition: mem_func.hpp:51
VehicleOrderID GetNumManualOrders() const
Get the number of manually added orders this vehicle has.
Definition: vehicle_base.h:693
uint16 GetPosition() const
Gets the position of the first visible element in the list.
Definition: widget_type.h:631
Train vehicle type.
Definition: vehicle_type.h:26
Tab with name and value of the vehicles.
Definition: vehicle_gui.h:27
uint8 SortType() const
Get the sorttype of the list.
Definition: sortlist_type.h:97
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:201
Base class for a &#39;real&#39; widget.
Definition: widget_type.h:284
static void DrawVehicleDetails(const Vehicle *v, int left, int right, int y, int vscroll_pos, uint vscroll_cap, TrainDetailsWindowTabs det_tab)
Draw the details for the given vehicle at the position of the Details windows.
static const GroupID ALL_GROUP
All vehicles are in this group.
Definition: group_type.h:18
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition: gfx_type.h:26
Stop all button.