OpenTTD
autoreplace_gui.cpp
Go to the documentation of this file.
1 /* $Id: autoreplace_gui.cpp 27683 2016-12-08 20:21:39Z frosch $ */
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 "command_func.h"
14 #include "vehicle_gui.h"
15 #include "newgrf_engine.h"
16 #include "rail.h"
17 #include "strings_func.h"
18 #include "window_func.h"
19 #include "autoreplace_func.h"
20 #include "company_func.h"
21 #include "engine_base.h"
22 #include "window_gui.h"
23 #include "engine_gui.h"
24 #include "settings_func.h"
25 #include "core/geometry_func.hpp"
26 #include "rail_gui.h"
27 #include "widgets/dropdown_func.h"
28 
30 
31 #include "safeguards.h"
32 
33 void DrawEngineList(VehicleType type, int x, int r, int y, const GUIEngineList *eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group);
34 
35 static int CDECL EngineNumberSorter(const EngineID *a, const EngineID *b)
36 {
37  int r = Engine::Get(*a)->list_position - Engine::Get(*b)->list_position;
38 
39  return r;
40 }
41 
52 {
54  /* We don't have any of this engine type.
55  * Either we just sold the last one, we build a new one or we stopped replacing it.
56  * In all cases, we need to update the left list */
58  }
59 }
60 
66 {
67  InvalidateWindowData(WC_REPLACE_VEHICLE, type, 0); // Update the autoreplace window
68  InvalidateWindowClassesData(WC_BUILD_VEHICLE); // The build windows needs updating as well
69 }
70 
71 static const StringID _start_replace_dropdown[] = {
72  STR_REPLACE_VEHICLES_NOW,
73  STR_REPLACE_VEHICLES_WHEN_OLD,
75 };
76 
80 class ReplaceVehicleWindow : public Window {
91  Scrollbar *vscroll[2];
92 
100  bool GenerateReplaceRailList(EngineID e, bool draw_left, bool show_engines)
101  {
102  const RailVehicleInfo *rvi = RailVehInfo(e);
103 
104  /* Ensure that the wagon/engine selection fits the engine. */
105  if ((rvi->railveh_type == RAILVEH_WAGON) == show_engines) return false;
106 
107  if (draw_left && this->sel_railtype != INVALID_RAILTYPE) {
108  /* Ensure that the railtype is specific to the selected one */
109  if (rvi->railtype != this->sel_railtype) return false;
110  }
111  return true;
112  }
113 
114 
119  void GenerateReplaceVehList(bool draw_left)
120  {
121  EngineID selected_engine = INVALID_ENGINE;
122  VehicleType type = (VehicleType)this->window_number;
123  byte side = draw_left ? 0 : 1;
124 
125  GUIEngineList *list = &this->engines[side];
126  list->Clear();
127 
128  const Engine *e;
129  FOR_ALL_ENGINES_OF_TYPE(e, type) {
130  if (!draw_left && !this->show_hidden_engines && e->IsHidden(_local_company)) continue;
131  EngineID eid = e->index;
132  if (type == VEH_TRAIN && !this->GenerateReplaceRailList(eid, draw_left, this->replace_engines)) continue; // special rules for trains
133 
134  if (draw_left) {
135  const uint num_engines = GetGroupNumEngines(_local_company, this->sel_group, eid);
136 
137  /* Skip drawing the engines we don't have any of and haven't set for replacement */
138  if (num_engines == 0 && EngineReplacementForCompany(Company::Get(_local_company), eid, this->sel_group) == INVALID_ENGINE) continue;
139  } else {
140  if (!CheckAutoreplaceValidity(this->sel_engine[0], eid, _local_company)) continue;
141  }
142 
143  *list->Append() = eid;
144  if (eid == this->sel_engine[side]) selected_engine = eid; // The selected engine is still in the list
145  }
146  this->sel_engine[side] = selected_engine; // update which engine we selected (the same or none, if it's not in the list anymore)
147  if (draw_left) {
149  } else {
151  EngList_Sort(list, _engine_sort_functions[this->window_number][this->sort_criteria]);
152  }
153  }
154 
157  {
158  EngineID e = this->sel_engine[0];
159 
160  if (this->engines[0].NeedRebuild()) {
161  /* We need to rebuild the left engines list */
162  this->GenerateReplaceVehList(true);
163  this->vscroll[0]->SetCount(this->engines[0].Length());
164  if (this->reset_sel_engine && this->sel_engine[0] == INVALID_ENGINE && this->engines[0].Length() != 0) {
165  this->sel_engine[0] = this->engines[0][0];
166  }
167  }
168 
169  if (this->engines[1].NeedRebuild() || e != this->sel_engine[0]) {
170  /* Either we got a request to rebuild the right engines list, or the left engines list selected a different engine */
171  if (this->sel_engine[0] == INVALID_ENGINE) {
172  /* Always empty the right engines list when nothing is selected in the left engines list */
173  this->engines[1].Clear();
174  this->sel_engine[1] = INVALID_ENGINE;
175  } else {
176  if (this->reset_sel_engine && this->sel_engine[0] != INVALID_ENGINE) {
177  /* Select the current replacement for sel_engine[0]. */
178  const Company *c = Company::Get(_local_company);
179  this->sel_engine[1] = EngineReplacementForCompany(c, this->sel_engine[0], this->sel_group);
180  }
181  /* Regenerate the list on the right. Note: This resets sel_engine[1] to INVALID_ENGINE, if it is no longer available. */
182  this->GenerateReplaceVehList(false);
183  this->vscroll[1]->SetCount(this->engines[1].Length());
184  if (this->reset_sel_engine && this->sel_engine[1] != INVALID_ENGINE) {
185  int position = 0;
186  for (EngineID *it = this->engines[1].Begin(); it != this->engines[1].End(); ++it) {
187  if (*it == this->sel_engine[1]) break;
188  ++position;
189  }
190  this->vscroll[1]->ScrollTowards(position);
191  }
192  }
193  }
194  /* Reset the flags about needed updates */
195  this->engines[0].RebuildDone();
196  this->engines[1].RebuildDone();
197  this->reset_sel_engine = false;
198  }
199 
204  void ReplaceClick_StartReplace(bool replace_when_old)
205  {
206  EngineID veh_from = this->sel_engine[0];
207  EngineID veh_to = this->sel_engine[1];
208  DoCommandP(0, (replace_when_old ? 1 : 0) | (this->sel_group << 16), veh_from + (veh_to << 16), CMD_SET_AUTOREPLACE);
209  }
210 
211 public:
212  ReplaceVehicleWindow(WindowDesc *desc, VehicleType vehicletype, GroupID id_g) : Window(desc)
213  {
214  this->sel_railtype = INVALID_RAILTYPE;
215  this->replace_engines = true; // start with locomotives (all other vehicles will not read this bool)
216  this->engines[0].ForceRebuild();
217  this->engines[1].ForceRebuild();
218  this->reset_sel_engine = true;
219  this->details_height = ((vehicletype == VEH_TRAIN) ? 10 : 9) * FONT_HEIGHT_NORMAL + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
220  this->sel_engine[0] = INVALID_ENGINE;
221  this->sel_engine[1] = INVALID_ENGINE;
222  this->show_hidden_engines = _engine_sort_show_hidden_engines[vehicletype];
223 
224  this->CreateNestedTree();
225  this->vscroll[0] = this->GetScrollbar(WID_RV_LEFT_SCROLLBAR);
226  this->vscroll[1] = this->GetScrollbar(WID_RV_RIGHT_SCROLLBAR);
227 
228  NWidgetCore *widget = this->GetWidget<NWidgetCore>(WID_RV_SHOW_HIDDEN_ENGINES);
229  widget->widget_data = STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN + vehicletype;
230  widget->tool_tip = STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP + vehicletype;
231  widget->SetLowered(this->show_hidden_engines);
232  this->FinishInitNested(vehicletype);
233 
234  this->sort_criteria = _engine_sort_last_criteria[vehicletype];
235  this->descending_sort_order = _engine_sort_last_order[vehicletype];
236  this->owner = _local_company;
237  this->sel_group = id_g;
238  }
239 
240  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
241  {
242  switch (widget) {
244  Dimension d = GetStringBoundingBox(this->GetWidget<NWidgetCore>(widget)->widget_data);
245  d.width += padding.width + Window::SortButtonWidth() * 2; // Doubled since the string is centred and it also looks better.
246  d.height += padding.height;
247  *size = maxdim(*size, d);
248  break;
249  }
250 
251  case WID_RV_LEFT_MATRIX:
252  case WID_RV_RIGHT_MATRIX:
253  resize->height = GetEngineListHeight((VehicleType)this->window_number);
254  size->height = (this->window_number <= VEH_ROAD ? 8 : 4) * resize->height;
255  break;
256 
257  case WID_RV_LEFT_DETAILS:
259  size->height = this->details_height;
260  break;
261 
263  StringID str = this->GetWidget<NWidgetCore>(widget)->widget_data;
264  SetDParam(0, STR_CONFIG_SETTING_ON);
266  SetDParam(0, STR_CONFIG_SETTING_OFF);
267  d = maxdim(d, GetStringBoundingBox(str));
268  d.width += padding.width;
269  d.height += padding.height;
270  *size = maxdim(*size, d);
271  break;
272  }
273 
275  Dimension d = GetStringBoundingBox(STR_REPLACE_ENGINES);
276  d = maxdim(d, GetStringBoundingBox(STR_REPLACE_WAGONS));
277  d.width += padding.width;
278  d.height += padding.height;
279  *size = maxdim(*size, d);
280  break;
281  }
282 
283  case WID_RV_INFO_TAB: {
284  Dimension d = GetStringBoundingBox(STR_REPLACE_NOT_REPLACING);
285  d = maxdim(d, GetStringBoundingBox(STR_REPLACE_NOT_REPLACING_VEHICLE_SELECTED));
288  *size = maxdim(*size, d);
289  break;
290  }
291 
293  Dimension d = {0, 0};
294  for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
295  const RailtypeInfo *rti = GetRailTypeInfo(rt);
296  /* Skip rail type if it has no label */
297  if (rti->label == 0) continue;
299  }
300  d.width += padding.width;
301  d.height += padding.height;
302  *size = maxdim(*size, d);
303  break;
304  }
305 
306  case WID_RV_START_REPLACE: {
307  Dimension d = GetStringBoundingBox(STR_REPLACE_VEHICLES_START);
308  for (int i = 0; _start_replace_dropdown[i] != INVALID_STRING_ID; i++) {
309  d = maxdim(d, GetStringBoundingBox(_start_replace_dropdown[i]));
310  }
311  d.width += padding.width;
312  d.height += padding.height;
313  *size = maxdim(*size, d);
314  break;
315  }
316  }
317  }
318 
319  virtual void SetStringParameters(int widget) const
320  {
321  switch (widget) {
322  case WID_RV_CAPTION:
323  SetDParam(0, STR_REPLACE_VEHICLE_TRAIN + this->window_number);
324  switch (this->sel_group) {
325  case ALL_GROUP:
326  SetDParam(1, STR_GROUP_ALL_TRAINS + this->window_number);
327  break;
328 
329  case DEFAULT_GROUP:
330  SetDParam(1, STR_GROUP_DEFAULT_TRAINS + this->window_number);
331  break;
332 
333  default:
334  SetDParam(1, STR_GROUP_NAME);
335  SetDParam(2, sel_group);
336  break;
337  }
338  break;
339 
342  break;
343 
345  const Company *c = Company::Get(_local_company);
346  SetDParam(0, c->settings.renew_keep_length ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
347  break;
348  }
349 
351  SetDParam(0, this->replace_engines ? STR_REPLACE_ENGINES : STR_REPLACE_WAGONS);
352  break;
353  }
354  }
355 
356  virtual void DrawWidget(const Rect &r, int widget) const
357  {
358  switch (widget) {
361  break;
362 
363  case WID_RV_INFO_TAB: {
364  const Company *c = Company::Get(_local_company);
365  StringID str;
366  if (this->sel_engine[0] != INVALID_ENGINE) {
367  if (!EngineHasReplacementForCompany(c, this->sel_engine[0], this->sel_group)) {
368  str = STR_REPLACE_NOT_REPLACING;
369  } else {
370  bool when_old = false;
371  EngineID e = EngineReplacementForCompany(c, this->sel_engine[0], this->sel_group, &when_old);
372  str = when_old ? STR_REPLACE_REPLACING_WHEN_OLD : STR_ENGINE_NAME;
373  SetDParam(0, e);
374  }
375  } else {
376  str = STR_REPLACE_NOT_REPLACING_VEHICLE_SELECTED;
377  }
378 
379  DrawString(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, r.top + WD_FRAMERECT_TOP, str, TC_BLACK, SA_HOR_CENTER);
380  break;
381  }
382 
383  case WID_RV_LEFT_MATRIX:
384  case WID_RV_RIGHT_MATRIX: {
385  int side = (widget == WID_RV_LEFT_MATRIX) ? 0 : 1;
386  EngineID start = this->vscroll[side]->GetPosition(); // what is the offset for the start (scrolling)
387  EngineID end = min(this->vscroll[side]->GetCapacity() + start, this->engines[side].Length());
388 
389  /* Do the actual drawing */
391  &this->engines[side], start, end, this->sel_engine[side], side == 0, this->sel_group);
392  break;
393  }
394  }
395  }
396 
397  virtual void OnPaint()
398  {
399  if (this->engines[0].NeedRebuild() || this->engines[1].NeedRebuild()) this->GenerateLists();
400 
402 
403  /* Disable the "Start Replacing" button if:
404  * Either engines list is empty
405  * or The selected replacement engine has a replacement (to prevent loops). */
408 
409  /* Disable the "Stop Replacing" button if:
410  * The left engines list (existing vehicle) is empty
411  * or The selected vehicle has no replacement set up */
413 
414  if (this->window_number == VEH_TRAIN) {
415  /* Show the selected railtype in the pulldown menu */
416  this->GetWidget<NWidgetCore>(WID_RV_TRAIN_RAILTYPE_DROPDOWN)->widget_data = sel_railtype == INVALID_RAILTYPE ? STR_REPLACE_ALL_RAILTYPE : GetRailTypeInfo(sel_railtype)->strings.replace_text;
417  }
418 
419  this->DrawWidgets();
420 
421  if (!this->IsShaded()) {
422  int needed_height = this->details_height;
423  /* Draw details panels. */
424  for (int side = 0; side < 2; side++) {
425  if (this->sel_engine[side] != INVALID_ENGINE) {
426  NWidgetBase *nwi = this->GetWidget<NWidgetBase>(side == 0 ? WID_RV_LEFT_DETAILS : WID_RV_RIGHT_DETAILS);
428  nwi->pos_y + WD_FRAMERECT_TOP, this->sel_engine[side]);
429  needed_height = max(needed_height, text_end - (int)nwi->pos_y + WD_FRAMERECT_BOTTOM);
430  }
431  }
432  if (needed_height != this->details_height) { // Details window are not high enough, enlarge them.
433  this->details_height = needed_height;
434  this->ReInit();
435  return;
436  }
437  }
438  }
439 
440  virtual void OnClick(Point pt, int widget, int click_count)
441  {
442  switch (widget) {
444  this->descending_sort_order ^= true;
446  this->engines[1].ForceRebuild();
447  this->SetDirty();
448  break;
449 
451  this->show_hidden_engines ^= true;
453  this->engines[1].ForceRebuild();
454  this->SetWidgetLoweredState(widget, this->show_hidden_engines);
455  this->SetDirty();
456  break;
457 
459  DisplayVehicleSortDropDown(this, static_cast<VehicleType>(this->window_number), this->sort_criteria, WID_RV_SORT_DROPDOWN);
460  break;
461 
463  DropDownList *list = new DropDownList();
464  *list->Append() = new DropDownListStringItem(STR_REPLACE_ENGINES, 1, false);
465  *list->Append() = new DropDownListStringItem(STR_REPLACE_WAGONS, 0, false);
467  break;
468  }
469 
470  case WID_RV_TRAIN_RAILTYPE_DROPDOWN: // Railtype selection dropdown menu
472  break;
473 
474  case WID_RV_TRAIN_WAGONREMOVE_TOGGLE: // toggle renew_keep_length
475  DoCommandP(0, GetCompanySettingIndex("company.renew_keep_length"), Company::Get(_local_company)->settings.renew_keep_length ? 0 : 1, CMD_CHANGE_COMPANY_SETTING);
476  break;
477 
478  case WID_RV_START_REPLACE: { // Start replacing
479  if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
482  } else {
483  bool replacment_when_old = EngineHasReplacementWhenOldForCompany(Company::Get(_local_company), this->sel_engine[0], this->sel_group);
484  ShowDropDownMenu(this, _start_replace_dropdown, replacment_when_old ? 1 : 0, WID_RV_START_REPLACE, !this->replace_engines ? 1 << 1 : 0, 0);
485  }
486  break;
487  }
488 
489  case WID_RV_STOP_REPLACE: { // Stop replacing
490  EngineID veh_from = this->sel_engine[0];
491  DoCommandP(0, this->sel_group << 16, veh_from + (INVALID_ENGINE << 16), CMD_SET_AUTOREPLACE);
492  break;
493  }
494 
495  case WID_RV_LEFT_MATRIX:
496  case WID_RV_RIGHT_MATRIX: {
497  byte click_side;
498  if (widget == WID_RV_LEFT_MATRIX) {
499  click_side = 0;
500  } else {
501  click_side = 1;
502  }
503  uint i = this->vscroll[click_side]->GetScrolledRowFromWidget(pt.y, this, widget);
504  size_t engine_count = this->engines[click_side].Length();
505 
506  EngineID e = engine_count > i ? this->engines[click_side][i] : INVALID_ENGINE;
507  if (e == this->sel_engine[click_side]) break; // we clicked the one we already selected
508  this->sel_engine[click_side] = e;
509  if (click_side == 0) {
510  this->engines[1].ForceRebuild();
511  this->reset_sel_engine = true;
512  }
513  this->SetDirty();
514  break;
515  }
516  }
517  }
518 
519  virtual void OnDropdownSelect(int widget, int index)
520  {
521  switch (widget) {
523  if (this->sort_criteria != index) {
524  this->sort_criteria = index;
526  this->engines[1].ForceRebuild();
527  this->SetDirty();
528  }
529  break;
530 
532  RailType temp = (RailType)index;
533  if (temp == sel_railtype) return; // we didn't select a new one. No need to change anything
534  sel_railtype = temp;
535  /* Reset scrollbar positions */
536  this->vscroll[0]->SetPosition(0);
537  this->vscroll[1]->SetPosition(0);
538  /* Rebuild the lists */
539  this->engines[0].ForceRebuild();
540  this->engines[1].ForceRebuild();
541  this->reset_sel_engine = true;
542  this->SetDirty();
543  break;
544  }
545 
547  this->replace_engines = index != 0;
548  this->engines[0].ForceRebuild();
549  this->reset_sel_engine = true;
550  this->SetDirty();
551  break;
552  }
553 
555  this->ReplaceClick_StartReplace(index != 0);
556  break;
557  }
558  }
559 
560  virtual void OnResize()
561  {
562  this->vscroll[0]->SetCapacityFromWidget(this, WID_RV_LEFT_MATRIX);
563  this->vscroll[1]->SetCapacityFromWidget(this, WID_RV_RIGHT_MATRIX);
564  }
565 
571  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
572  {
573  if (data != 0) {
574  /* This needs to be done in command-scope to enforce rebuilding before resorting invalid data */
575  this->engines[0].ForceRebuild();
576  } else {
577  this->engines[1].ForceRebuild();
578  }
579  }
580 };
581 
582 static const NWidgetPart _nested_replace_rail_vehicle_widgets[] = {
584  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
585  NWidget(WWT_CAPTION, COLOUR_GREY, WID_RV_CAPTION), SetDataTip(STR_REPLACE_VEHICLES_WHITE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
586  NWidget(WWT_SHADEBOX, COLOUR_GREY),
587  NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
588  NWidget(WWT_STICKYBOX, COLOUR_GREY),
589  EndContainer(),
591  NWidget(WWT_PANEL, COLOUR_GREY),
592  NWidget(WWT_LABEL, COLOUR_GREY), SetDataTip(STR_REPLACE_VEHICLE_VEHICLES_IN_USE, STR_REPLACE_VEHICLE_VEHICLES_IN_USE_TOOLTIP), SetFill(1, 1), SetMinimalSize(0, 12), SetResize(1, 0),
593  EndContainer(),
594  NWidget(WWT_PANEL, COLOUR_GREY),
595  NWidget(WWT_LABEL, COLOUR_GREY), SetDataTip(STR_REPLACE_VEHICLE_AVAILABLE_VEHICLES, STR_REPLACE_VEHICLE_AVAILABLE_VEHICLES_TOOLTIP), SetFill(1, 1), SetMinimalSize(0, 12), SetResize(1, 0),
596  EndContainer(),
597  EndContainer(),
601  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_TRAIN_RAILTYPE_DROPDOWN), SetMinimalSize(136, 12), SetDataTip(0x0, STR_REPLACE_HELP_RAILTYPE), SetFill(1, 0), SetResize(1, 0),
602  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_TRAIN_ENGINEWAGON_DROPDOWN), SetDataTip(STR_BLACK_STRING, STR_REPLACE_ENGINE_WAGON_SELECT_HELP),
603  EndContainer(),
604  NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), EndContainer(),
605  EndContainer(),
608  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_SORT_ASCENDING_DESCENDING), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER), SetFill(1, 1),
609  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_SORT_DROPDOWN), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_SORT_CRITERIA),
610  EndContainer(),
612  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_RV_SHOW_HIDDEN_ENGINES), SetDataTip(STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN, STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP),
613  NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), SetFill(1, 1), EndContainer(),
614  EndContainer(),
615  EndContainer(),
616  EndContainer(),
618  NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_LEFT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_LEFT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_LEFT_SCROLLBAR),
620  NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_RIGHT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_RIGHT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_RIGHT_SCROLLBAR),
622  EndContainer(),
624  NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_LEFT_DETAILS), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(),
626  NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_RIGHT_DETAILS), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(),
627  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_TRAIN_WAGONREMOVE_TOGGLE), SetMinimalSize(138, 12), SetDataTip(STR_REPLACE_REMOVE_WAGON, STR_REPLACE_REMOVE_WAGON_HELP), SetFill(1, 0), SetResize(1, 0),
628  EndContainer(),
629  EndContainer(),
631  NWidget(NWID_PUSHBUTTON_DROPDOWN, COLOUR_GREY, WID_RV_START_REPLACE), SetMinimalSize(139, 12), SetDataTip(STR_REPLACE_VEHICLES_START, STR_REPLACE_HELP_START_BUTTON),
632  NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_INFO_TAB), SetMinimalSize(167, 12), SetDataTip(0x0, STR_REPLACE_HELP_REPLACE_INFO_TAB), SetResize(1, 0),
633  EndContainer(),
634  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_STOP_REPLACE), SetMinimalSize(150, 12), SetDataTip(STR_REPLACE_VEHICLES_STOP, STR_REPLACE_HELP_STOP_BUTTON),
635  NWidget(WWT_RESIZEBOX, COLOUR_GREY),
636  EndContainer(),
637 };
638 
639 static WindowDesc _replace_rail_vehicle_desc(
640  WDP_AUTO, "replace_vehicle_train", 500, 140,
643  _nested_replace_rail_vehicle_widgets, lengthof(_nested_replace_rail_vehicle_widgets)
644 );
645 
646 static const NWidgetPart _nested_replace_vehicle_widgets[] = {
648  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
649  NWidget(WWT_CAPTION, COLOUR_GREY, WID_RV_CAPTION), SetMinimalSize(433, 14), SetDataTip(STR_REPLACE_VEHICLES_WHITE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
650  NWidget(WWT_SHADEBOX, COLOUR_GREY),
651  NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
652  NWidget(WWT_STICKYBOX, COLOUR_GREY),
653  EndContainer(),
655  NWidget(WWT_PANEL, COLOUR_GREY),
656  NWidget(WWT_LABEL, COLOUR_GREY), SetDataTip(STR_REPLACE_VEHICLE_VEHICLES_IN_USE, STR_REPLACE_VEHICLE_VEHICLES_IN_USE_TOOLTIP), SetFill(1, 1), SetMinimalSize(0, 12), SetResize(1, 0),
657  EndContainer(),
658  NWidget(WWT_PANEL, COLOUR_GREY),
659  NWidget(WWT_LABEL, COLOUR_GREY), SetDataTip(STR_REPLACE_VEHICLE_AVAILABLE_VEHICLES, STR_REPLACE_VEHICLE_AVAILABLE_VEHICLES_TOOLTIP), SetFill(1, 1), SetMinimalSize(0, 12), SetResize(1, 0),
660  EndContainer(),
661  EndContainer(),
663  NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), EndContainer(),
666  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_SORT_ASCENDING_DESCENDING), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
667  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_SORT_DROPDOWN), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_SORT_CRITERIA),
668  EndContainer(),
670  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_RV_SHOW_HIDDEN_ENGINES), SetDataTip(STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN, STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP),
671  NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), SetFill(1, 1), EndContainer(),
672  EndContainer(),
673  EndContainer(),
674  EndContainer(),
676  NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_LEFT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_LEFT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_LEFT_SCROLLBAR),
678  NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_RIGHT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_RIGHT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_RIGHT_SCROLLBAR),
680  EndContainer(),
682  NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_LEFT_DETAILS), SetMinimalSize(228, 92), SetResize(1, 0), EndContainer(),
683  NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_RIGHT_DETAILS), SetMinimalSize(228, 92), SetResize(1, 0), EndContainer(),
684  EndContainer(),
686  NWidget(NWID_PUSHBUTTON_DROPDOWN, COLOUR_GREY, WID_RV_START_REPLACE), SetMinimalSize(139, 12), SetDataTip(STR_REPLACE_VEHICLES_START, STR_REPLACE_HELP_START_BUTTON),
687  NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_INFO_TAB), SetMinimalSize(167, 12), SetDataTip(0x0, STR_REPLACE_HELP_REPLACE_INFO_TAB), SetResize(1, 0), EndContainer(),
688  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_STOP_REPLACE), SetMinimalSize(138, 12), SetDataTip(STR_REPLACE_VEHICLES_STOP, STR_REPLACE_HELP_STOP_BUTTON),
689  NWidget(WWT_RESIZEBOX, COLOUR_GREY),
690  EndContainer(),
691 };
692 
693 static WindowDesc _replace_vehicle_desc(
694  WDP_AUTO, "replace_vehicle", 456, 118,
697  _nested_replace_vehicle_widgets, lengthof(_nested_replace_vehicle_widgets)
698 );
699 
706 {
707  DeleteWindowById(WC_REPLACE_VEHICLE, vehicletype);
708  new ReplaceVehicleWindow(vehicletype == VEH_TRAIN ? &_replace_rail_vehicle_desc : &_replace_vehicle_desc, vehicletype, id_g);
709 }
bool CheckAutoreplaceValidity(EngineID from, EngineID to, CompanyID company)
Checks some basic properties whether autoreplace is allowed.
Used for iterations.
Definition: rail_type.h:35
Functions related to OTTD&#39;s strings.
Dropdown for the sort criteria.
void RebuildDone()
Notify the sortlist that the rebuild is done.
Functions for NewGRF engines.
uint32 widget_data
Data of the widget.
Definition: widget_type.h:305
uint GetCompanySettingIndex(const char *name)
Get the index in the _company_settings array of a setting.
Definition: settings.cpp:2008
static const RailtypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition: rail.h:296
Horizontally center the text.
Definition: gfx_func.h:99
ResizeInfo resize
Resize information.
Definition: window_gui.h:317
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:1843
bool reset_sel_engine
Also reset sel_engine while updating left and/or right (#update_left and/or #update_right) and no val...
void SetWidgetDisabledState(byte widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition: window_gui.h:387
Window for the autoreplacing of vehicles.
void SetWidgetLoweredState(byte widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition: window_gui.h:448
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
RailType
Enumeration for all possible railtypes.
Definition: rail_type.h:29
High level window description.
Definition: window_gui.h:168
Toggle whether to display the hidden vehicles.
StringID tool_tip
Tooltip of the widget.
Definition: widget_type.h:306
static EngineID EngineReplacementForCompany(const Company *c, EngineID engine, GroupID group, bool *replace_when_old=NULL)
Retrieve the engine replacement for the given company and original engine type.
int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number)
Draw the purchase info details of a vehicle at a given location.
uint GetGroupNumEngines(CompanyID company, GroupID id_g, EngineID id_e)
Get the number of engines with EngineID id_e in the group with GroupID id_g and its sub-groups...
Definition: group_cmd.cpp:693
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 IsHidden(CompanyByte c) const
Check whether the engine is hidden in the GUI for the given company.
Definition: engine_base.h:121
void GenerateReplaceVehList(bool draw_left)
Generate an engines list.
Centered label.
Definition: widget_type.h:57
Scrollbar data structure.
Definition: widget_type.h:589
GroupID sel_group
Group selected to replace.
Offset at top to draw the frame rectangular area.
Definition: window_gui.h:64
Dropdown menu about the railtype.
void DisplayVehicleSortDropDown(Window *w, VehicleType vehicle_type, int selected, int button)
Display the dropdown for the vehicle sort criteria.
Horizontal container.
Definition: widget_type.h:75
byte _engine_sort_last_criteria[]
Last set sort criteria, for each vehicle type.
Replace vehicle window; Window numbers:
Definition: window_type.h:213
Rail specific functions.
Resize box (normally at bottom-right of a window)
Definition: widget_type.h:68
void SetPosition(int position)
Sets the position of the first visible element.
Definition: widget_type.h:701
change a company setting
Definition: command_type.h:305
Build vehicle; Window numbers:
Definition: window_type.h:378
void Clear()
Remove all items from the list.
Tindex index
Index of this pool item.
Definition: pool_type.hpp:147
Close box (at top-left of a window)
Definition: widget_type.h:69
uint GetEngineListHeight(VehicleType type)
Get the height of a single &#39;entry&#39; in the engine lists.
bool GenerateReplaceRailList(EngineID e, bool draw_left, bool show_engines)
Figure out if an engine should be added to a list.
void ReInit(int rx=0, int ry=0)
Re-initialize a window, and optionally change its size.
Definition: window.cpp:970
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
virtual void OnDropdownSelect(int widget, int index)
A dropdown option associated to this window has been selected.
EngList_SortTypeFunction *const _engine_sort_functions[][11]
Sort functions for the vehicle sort criteria, for each vehicle type.
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:26
struct RailtypeInfo::@39 strings
Strings associated with the rail type.
Common string list item.
Definition: dropdown_type.h:41
Ascending/descending sort order button.
CompanySettings settings
settings specific for each company
Definition: company_base.h:121
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:1804
Functions related to the vehicle&#39;s GUIs.
Functions/types etc.
bool descending_sort_order
Order of sorting vehicles.
Functions, definitions and such used only by the GUI.
virtual void OnPaint()
The window must be repainted.
This struct contains all the info that is needed to draw and construct tracks.
Definition: rail.h:116
bool _engine_sort_last_order[]
Last set direction of the sort order, for each vehicle type.
T * Append(uint to_add=1)
Append an item and return it.
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
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:910
void ForceRebuild()
Force that a rebuild is needed.
Data structure for an opened window.
Definition: window_gui.h:271
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition: window.cpp:1820
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
void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
Mark window data of all windows of a given class as invalid (in need of re-computing) Note that by de...
Definition: window.cpp:3238
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX) ...
Definition: widget_type.h:65
uint Length() const
Get the number of items in the list.
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
uint pos_y
Vertical position of top-left corner of the widget in the window.
Definition: widget_type.h:178
This window is used for construction; close it whenever changing company.
Definition: window_gui.h:210
Details of the entry on the left.
void SetLowered(bool lowered)
Lower or raise the widget.
Definition: widget_type.h:337
VehicleType
Available vehicle types.
Definition: vehicle_type.h:21
RailType sel_railtype
Type of rail tracks selected. INVALID_RAILTYPE to show all.
Sort descending.
Definition: window_gui.h:227
#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.
Functions related to setting/changing the settings.
simple wagon, not motorized
Definition: engine_type.h:30
The scrollbar for the matrix on the right.
void ReplaceClick_StartReplace(bool replace_when_old)
Handle click on the start replace button.
Types related to the autoreplace widgets.
static NWidgetPart SetMinimalSize(int16 x, int16 y)
Widget part function for setting the minimal size.
Definition: widget_type.h:947
The matrix on the right.
Definition of base types and functions in a cross-platform compatible way.
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
A number of safeguards to prevent using unsafe methods.
Dropdown to select engines and/or wagons.
void GenerateLists()
Generate the lists.
Normal push-button (no toggle button) with text caption.
Definition: widget_type.h:104
bool replace_engines
If true, engines are replaced, if false, wagons are replaced (only for trains).
Geometry functions.
Simple depressed panel.
Definition: widget_type.h:50
uint16 GroupID
Type for all group identifiers.
Definition: group_type.h:15
Engine GUI functions, used by build_vehicle_gui and autoreplace_gui
void DrawSortButtonState(int widget, SortButtonState state) const
Draw a sort button&#39;s up or down arrow symbol.
Definition: widget.cpp:638
const Scrollbar * GetScrollbar(uint widnum) const
Return the Scrollbar to a widget index.
Definition: window.cpp:307
void DrawEngineList(VehicleType type, int x, int r, int y, const GUIEngineList *eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group)
Engine drawing loop.
const StringID _engine_sort_listing[][12]
Dropdown menu strings for the vehicle sort criteria.
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
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:499
Right offset of the text of the frame.
Definition: window_gui.h:73
bool DoCommandP(const CommandContainer *container, bool my_cmd)
Shortcut for the long DoCommandP when having a container with the data.
Definition: command.cpp:527
bool renew_keep_length
sell some wagons if after autoreplace the train is longer than before
EngineID sel_engine[2]
Selected engine left and right.
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:42
Road vehicle type.
Definition: vehicle_type.h:25
Grid of rows and columns.
Definition: widget_type.h:59
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
RailTypeLabel label
Unique 32 bit rail type identifier.
Definition: rail.h:225
Left offset of the text of the frame.
Definition: window_gui.h:72
Details of the entry on the right.
static bool EngineHasReplacementWhenOldForCompany(const Company *c, EngineID engine, GroupID group)
Check if a company has a replacement set up for the given engine when it gets old.
static int SortButtonWidth()
Get width of up/down arrow of sort button state.
Definition: widget.cpp:658
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:18
void InvalidateAutoreplaceWindow(EngineID e, GroupID id_g)
Rebuild the left autoreplace list if an engine is removed or added.
The scrollbar for the matrix on the left.
Information about a rail vehicle.
Definition: engine_type.h:43
DropDownList * GetRailTypeDropDownList(bool for_replacement, bool all_option)
Create a drop down list for all the rail types of the local company.
Definition: rail_gui.cpp:1988
StringID replace_text
Text used in the autoreplace GUI.
Definition: rail.h:169
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition: window.cpp:959
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition: gfx.cpp:699
bool _engine_sort_direction
false = descending, true = ascending.
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:1137
Button to toggle removing wagons.
static const EngineID INVALID_ENGINE
Constant denoting an invalid engine.
Definition: engine_type.h:174
static int CDECL EngineNumberSorter(const EngineID *a, const EngineID *b)
Determines order of engines by engineID.
bool show_hidden_engines
Whether to show the hidden engines.
static const GroupID DEFAULT_GROUP
Ungrouped vehicles are in this group.
Definition: group_type.h:19
Functions related to companies.
Base class for engines.
Caption of the window.
Window caption (window title between closebox and stickybox)
Definition: widget_type.h:61
int details_height
Minimal needed height of the details panels (found so far).
uint16 EngineID
Unique identification number of an engine.
Definition: engine_type.h:22
Start Replacing button.
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.
Sort ascending.
Definition: window_gui.h:226
byte sort_criteria
Criteria of sorting vehicles.
void ShowReplaceGroupVehicleWindow(GroupID id_g, VehicleType vehicletype)
Show the autoreplace configuration window for a particular group.
Vertical container.
Definition: widget_type.h:77
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
virtual void OnResize()
Called after the window got resized.
uint current_x
Current horizontal size (after resizing).
Definition: widget_type.h:174
Stop Replacing button.
void EngList_Sort(GUIEngineList *el, EngList_SortTypeFunction compare)
Sort all items using quick sort and given &#39;CompareItems&#39; function.
Definition: engine_gui.cpp:326
Functions related to commands.
Coordinates of a point in 2D.
The matrix on the left.
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
Drop down list.
Definition: widget_type.h:70
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:319
void HandleButtonClick(byte widget)
Do all things to make a button look clicked and mark it to be unclicked in a few ticks.
Definition: window.cpp:615
void AddRemoveEngineFromAutoreplaceAndBuildWindows(VehicleType type)
When an engine is made buildable or is removed from being buildable, add/remove it from the build/aut...
static bool EngineHasReplacementForCompany(const Company *c, EngineID engine, GroupID group)
Check if a company has a replacement set up for the given engine.
Offset at right to draw the frame rectangular area.
Definition: window_gui.h:63
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition: widget_type.h:66
static NWidgetPart SetFill(uint fill_x, uint fill_y)
Widget part function for setting filling.
Definition: widget_type.h:983
Used for iterations.
Definition: rail_type.h:30
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
bool IsShaded() const
Is window shaded currently?
Definition: window_gui.h:519
Flag for invalid railtype.
Definition: rail_type.h:36
WindowNumber window_number
Window number within the window class.
Definition: window_gui.h:307
bool _engine_sort_show_hidden_engines[]
Last set &#39;show hidden engines&#39; setting for each vehicle type.
Window functions not directly related to making/drawing windows.
Find a place automatically.
Definition: window_gui.h:156
set an autoreplace entry
Definition: command_type.h:307
Functions related to autoreplacing.
GUIEngineList engines[2]
Left and right list of engines.
static NWidgetPart SetScrollbar(int index)
Attach a scrollbar to a widget.
Definition: widget_type.h:1095
Dimensions (a width and height) of a rectangle in 2D.
Value of the NCB_EQUALSIZE flag.
Definition: widget_type.h:429
Offset at left to draw the frame rectangular area.
Definition: window_gui.h:62
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition: widget_type.h:64
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition: window.cpp:3220
(Toggle) Button with text
Definition: widget_type.h:55
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:24
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 const GroupID ALL_GROUP
All vehicles are in this group.
Definition: group_type.h:18