OpenTTD Source 15.0-beta2
group_gui.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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/>.
6 */
7
10#include "stdafx.h"
11#include "textbuf_gui.h"
12#include "command_func.h"
13#include "vehicle_gui.h"
14#include "vehicle_base.h"
15#include "string_func.h"
16#include "strings_func.h"
17#include "window_func.h"
18#include "vehicle_func.h"
19#include "autoreplace_gui.h"
20#include "company_func.h"
21#include "dropdown_func.h"
22#include "tilehighlight_func.h"
23#include "vehicle_gui_base.h"
26#include "company_base.h"
27#include "company_gui.h"
28#include "gui.h"
29#include "group_cmd.h"
30#include "group_gui.h"
31#include "vehicle_cmd.h"
32#include "gfx_func.h"
33
35
36#include "table/sprites.h"
37#include "table/strings.h"
38
39#include "safeguards.h"
40
41static constexpr NWidgetPart _nested_group_widgets[] = {
42 NWidget(NWID_HORIZONTAL), // Window header
43 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
44 NWidget(WWT_CAPTION, COLOUR_GREY, WID_GL_CAPTION),
45 NWidget(WWT_SHADEBOX, COLOUR_GREY),
46 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
47 NWidget(WWT_STICKYBOX, COLOUR_GREY),
50 /* left part */
55 NWidget(WWT_MATRIX, COLOUR_GREY, WID_GL_LIST_GROUP), SetMatrixDataTip(1, 0, STR_GROUPS_CLICK_ON_GROUP_FOR_TOOLTIP),
59 NWidget(WWT_PANEL, COLOUR_GREY, WID_GL_INFO), SetFill(1, 1), SetMinimalTextLines(3, WidgetDimensions::unscaled.framerect.Vertical()), EndContainer(),
62 SetToolTip(STR_GROUP_CREATE_TOOLTIP),
64 SetToolTip(STR_GROUP_DELETE_TOOLTIP),
66 SetToolTip(STR_GROUP_RENAME_TOOLTIP),
68 SetToolTip(STR_GROUP_LIVERY_TOOLTIP),
69 NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 0), EndContainer(),
71 SetToolTip(STR_GROUP_REPLACE_PROTECTION_TOOLTIP),
74 /* right part */
78 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GL_GROUP_BY_ORDER), SetFill(1, 1), SetMinimalSize(0, 12), SetStringTip(STR_STATION_VIEW_GROUP, STR_TOOLTIP_GROUP_ORDER),
79 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GL_SORT_BY_ORDER), SetFill(1, 1), SetMinimalSize(0, 12), SetStringTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
82 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GL_GROUP_BY_DROPDOWN), SetFill(1, 1), SetMinimalSize(0, 12), SetToolTip(STR_TOOLTIP_GROUP_ORDER),
83 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GL_SORT_BY_DROPDOWN), SetFill(1, 1), SetMinimalSize(0, 12), SetToolTip(STR_TOOLTIP_SORT_CRITERIA),
86 NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalTextLines(1, WidgetDimensions::unscaled.framerect.Vertical()), SetFill(0, 1), SetResize(1, 0), EndContainer(),
88 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GL_FILTER_BY_CARGO), SetMinimalSize(0, 12), SetFill(0, 1), SetToolTip(STR_TOOLTIP_FILTER_CRITERIA),
89 NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(0, 1), SetResize(1, 0), EndContainer(),
97 NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(1, 0), SetFill(1, 1), SetResize(1, 0), EndContainer(),
100 SetToolTip(STR_VEHICLE_LIST_AVAILABLE_ENGINES_TOOLTIP),
101 NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetResize(1, 0), EndContainer(),
103 SetStringTip(STR_VEHICLE_LIST_MANAGE_LIST, STR_VEHICLE_LIST_MANAGE_LIST_TOOLTIP),
104 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_GL_STOP_ALL), SetAspect(WidgetDimensions::ASPECT_VEHICLE_FLAG),
105 SetSpriteTip(SPR_FLAG_VEH_STOPPED, STR_VEHICLE_LIST_MASS_STOP_LIST_TOOLTIP),
106 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_GL_START_ALL), SetAspect(WidgetDimensions::ASPECT_VEHICLE_FLAG),
107 SetSpriteTip(SPR_FLAG_VEH_RUNNING, STR_VEHICLE_LIST_MASS_START_LIST_TOOLTIP),
108 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
109 EndContainer(),
110 EndContainer(),
111 EndContainer(),
112};
113
122static void GuiGroupListAddChildren(GUIGroupList &dst, const GUIGroupList &src, bool fold, GroupID parent = GroupID::Invalid(), uint8_t indent = 0)
123{
124 for (const auto &item : src) {
125 if (item.group->parent != parent) continue;
126
127 dst.emplace_back(item.group, indent);
128
129 if (fold && item.group->folded) {
130 /* Test if this group has children at all. If not, the folded flag should be cleared to avoid lingering unfold buttons in the list. */
131 GroupID groupid = item.group->index;
132 bool has_children = std::any_of(src.begin(), src.end(), [groupid](const auto &child) { return child.group->parent == groupid; });
133 Group::Get(item.group->index)->folded = has_children;
134 } else {
135 GuiGroupListAddChildren(dst, src, fold, item.group->index, indent + 1);
136 }
137 }
138
139 if (indent > 0 || dst.empty()) return;
140
141 /* Hierarchy is complete, traverse in reverse to find where indentation levels continue. */
142 uint16_t level_mask = 0;
143 for (auto it = std::rbegin(dst); std::next(it) != std::rend(dst); ++it) {
144 auto next_it = std::next(it);
145 AssignBit(level_mask, it->indent, it->indent <= next_it->indent);
146 next_it->level_mask = level_mask;
147 }
148}
149
157void BuildGuiGroupList(GUIGroupList &dst, bool fold, Owner owner, VehicleType veh_type)
158{
159 GUIGroupList list;
160
161 for (const Group *g : Group::Iterate()) {
162 if (g->owner == owner && g->vehicle_type == veh_type) {
163 list.emplace_back(g, 0);
164 }
165 }
166
167 list.ForceResort();
168
169 /* Sort the groups by their name */
170 std::array<std::pair<const Group *, std::string>, 2> last_group{};
171
172 list.Sort([&last_group](const GUIGroupListItem &a, const GUIGroupListItem &b) -> bool {
173 if (a.group != last_group[0].first) {
174 last_group[0] = {a.group, GetString(STR_GROUP_NAME, a.group->index)};
175 }
176
177 if (b.group != last_group[1].first) {
178 last_group[1] = {b.group, GetString(STR_GROUP_NAME, b.group->index)};
179 }
180
181 int r = StrNaturalCompare(last_group[0].second, last_group[1].second); // Sort by name (natural sorting).
182 if (r == 0) return a.group->number < b.group->number;
183 return r < 0;
184 });
185
186 GuiGroupListAddChildren(dst, list, fold, GroupID::Invalid(), 0);
187}
188
190private:
191 /* Columns in the group list */
202
203 GroupID group_sel = GroupID::Invalid();
204 GroupID group_rename = GroupID::Invalid();
205 GroupID group_over = GroupID::Invalid();
206 GroupID group_confirm = GroupID::Invalid();
209 Scrollbar *group_sb = nullptr;
210
211 std::array<Dimension, VGC_END> column_size{};
212 bool last_overlay_state = false;
213
220 {
221 if (!this->groups.NeedRebuild()) return;
222
223 this->groups.clear();
224
225 BuildGuiGroupList(this->groups, true, owner, this->vli.vtype);
226
227 this->groups.RebuildDone();
228 }
229
235 {
236 this->column_size[VGC_FOLD] = maxdim(GetSpriteSize(SPR_CIRCLE_FOLDED), GetSpriteSize(SPR_CIRCLE_UNFOLDED));
237 this->tiny_step_height = this->column_size[VGC_FOLD].height;
238
239 this->column_size[VGC_NAME] = maxdim(GetStringBoundingBox(STR_GROUP_DEFAULT_TRAINS + this->vli.vtype), GetStringBoundingBox(STR_GROUP_ALL_TRAINS + this->vli.vtype));
240 this->column_size[VGC_NAME].width = std::max(170u, this->column_size[VGC_NAME].width) + WidgetDimensions::scaled.hsep_indent;
241 this->tiny_step_height = std::max(this->tiny_step_height, this->column_size[VGC_NAME].height);
242
243 this->column_size[VGC_PROTECT] = GetSpriteSize(SPR_GROUP_REPLACE_PROTECT);
244 this->tiny_step_height = std::max(this->tiny_step_height, this->column_size[VGC_PROTECT].height);
245
246 this->column_size[VGC_AUTOREPLACE] = GetSpriteSize(SPR_GROUP_REPLACE_ACTIVE);
247 this->tiny_step_height = std::max(this->tiny_step_height, this->column_size[VGC_AUTOREPLACE].height);
248
249 this->column_size[VGC_PROFIT].width = 0;
250 this->column_size[VGC_PROFIT].height = 0;
251 static const SpriteID profit_sprites[] = {SPR_PROFIT_NA, SPR_PROFIT_NEGATIVE, SPR_PROFIT_SOME, SPR_PROFIT_LOT};
252 for (const auto &profit_sprite : profit_sprites) {
253 Dimension d = GetSpriteSize(profit_sprite);
255 }
256 this->tiny_step_height = std::max(this->tiny_step_height, this->column_size[VGC_PROFIT].height);
257
258 int num_vehicle = GetGroupNumVehicle(this->vli.company, ALL_GROUP, this->vli.vtype);
259 uint64_t max_value = GetParamMaxValue(num_vehicle, 3, FS_SMALL);
260 this->column_size[VGC_NUMBER] = GetStringBoundingBox(GetString(STR_GROUP_COUNT_WITH_SUBGROUP, max_value, max_value));
261 this->tiny_step_height = std::max(this->tiny_step_height, this->column_size[VGC_NUMBER].height);
262
263 this->tiny_step_height += WidgetDimensions::scaled.framerect.Vertical();
264
271 this->column_size[VGC_NUMBER].width +
273 }
274
285 void DrawGroupInfo(int y, int left, int right, GroupID g_id, uint16_t level_mask = 0, uint8_t indent = 0, bool protection = false, bool has_children = false) const
286 {
287 /* Highlight the group if a vehicle is dragged over it */
288 if (g_id == this->group_over) {
289 GfxFillRect(left + WidgetDimensions::scaled.bevel.left, y + WidgetDimensions::scaled.framerect.top, right - WidgetDimensions::scaled.bevel.right, y + this->tiny_step_height - 1 - WidgetDimensions::scaled.framerect.bottom, GetColourGradient(COLOUR_GREY, SHADE_LIGHTEST));
290 }
291
292 if (g_id == NEW_GROUP) return;
293
294 /* draw the selected group in white, else we draw it in black */
295 TextColour colour = g_id == this->vli.ToGroupID() ? TC_WHITE : TC_BLACK;
296 const GroupStatistics &stats = GroupStatistics::Get(this->vli.company, g_id, this->vli.vtype);
297 bool rtl = _current_text_dir == TD_RTL;
298
299 const int offset = (rtl ? -(int)this->column_size[VGC_FOLD].width : (int)this->column_size[VGC_FOLD].width) / 2;
301 const int linecolour = GetColourGradient(COLOUR_ORANGE, SHADE_NORMAL);
302
303 if (indent > 0) {
304 /* Draw tree continuation lines. */
305 int tx = (rtl ? right - WidgetDimensions::scaled.framerect.right : left + WidgetDimensions::scaled.framerect.left) + offset;
306 for (uint lvl = 1; lvl <= indent; ++lvl) {
307 if (HasBit(level_mask, lvl)) GfxDrawLine(tx, y, tx, y + this->tiny_step_height - 1, linecolour, WidgetDimensions::scaled.fullbevel.top);
308 if (lvl < indent) tx += level_width;
309 }
310 /* Draw our node in the tree. */
311 int ycentre = y + this->tiny_step_height / 2 - 1;
312 if (!HasBit(level_mask, indent)) GfxDrawLine(tx, y, tx, ycentre, linecolour, WidgetDimensions::scaled.fullbevel.top);
313 GfxDrawLine(tx, ycentre, tx + offset - (rtl ? -1 : 1), ycentre, linecolour, WidgetDimensions::scaled.fullbevel.top);
314 }
315
316 /* draw fold / unfold button */
317 int x = rtl ? right - WidgetDimensions::scaled.framerect.right - this->column_size[VGC_FOLD].width + 1 : left + WidgetDimensions::scaled.framerect.left;
318 if (has_children) {
319 DrawSprite(Group::Get(g_id)->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED, PAL_NONE, x + indent * level_width, y + (this->tiny_step_height - this->column_size[VGC_FOLD].height) / 2);
320 }
321
322 /* draw group name */
323 std::string str;
324 if (IsAllGroupID(g_id)) {
325 str = GetString(STR_GROUP_ALL_TRAINS + this->vli.vtype);
326 } else if (IsDefaultGroupID(g_id)) {
327 str = GetString(STR_GROUP_DEFAULT_TRAINS + this->vli.vtype);
328 } else {
329 str = GetString(STR_GROUP_NAME, g_id);
330 }
332 DrawString(x + (rtl ? 0 : indent * WidgetDimensions::scaled.hsep_indent), x + this->column_size[VGC_NAME].width - 1 - (rtl ? indent * WidgetDimensions::scaled.hsep_indent : 0), y + (this->tiny_step_height - this->column_size[VGC_NAME].height) / 2, std::move(str), colour);
333
334 /* draw autoreplace protection */
336 if (protection) DrawSprite(SPR_GROUP_REPLACE_PROTECT, PAL_NONE, x, y + (this->tiny_step_height - this->column_size[VGC_PROTECT].height) / 2);
337
338 /* draw autoreplace status */
340 if (stats.autoreplace_defined) DrawSprite(SPR_GROUP_REPLACE_ACTIVE, stats.autoreplace_finished ? PALETTE_CRASH : PAL_NONE, x, y + (this->tiny_step_height - this->column_size[VGC_AUTOREPLACE].height) / 2);
341
342 /* draw the profit icon */
344 SpriteID spr;
345 uint num_vehicle_min_age = GetGroupNumVehicleMinAge(this->vli.company, g_id, this->vli.vtype);
346 Money profit_last_year_min_age = GetGroupProfitLastYearMinAge(this->vli.company, g_id, this->vli.vtype);
347 if (num_vehicle_min_age == 0) {
348 spr = SPR_PROFIT_NA;
349 } else if (profit_last_year_min_age < 0) {
350 spr = SPR_PROFIT_NEGATIVE;
351 } else if (profit_last_year_min_age < VEHICLE_PROFIT_THRESHOLD * num_vehicle_min_age) {
352 spr = SPR_PROFIT_SOME;
353 } else {
354 spr = SPR_PROFIT_LOT;
355 }
356 DrawSprite(spr, PAL_NONE, x, y + (this->tiny_step_height - this->column_size[VGC_PROFIT].height) / 2);
357
358 /* draw the number of vehicles of the group */
360 int num_vehicle_with_subgroups = GetGroupNumVehicle(this->vli.company, g_id, this->vli.vtype);
361 int num_vehicle = GroupStatistics::Get(this->vli.company, g_id, this->vli.vtype).num_vehicle;
362 if (IsAllGroupID(g_id) || IsDefaultGroupID(g_id) || num_vehicle_with_subgroups == num_vehicle) {
363 DrawString(x, x + this->column_size[VGC_NUMBER].width - 1, y + (this->tiny_step_height - this->column_size[VGC_NUMBER].height) / 2, GetString(STR_JUST_COMMA, num_vehicle), colour, SA_RIGHT | SA_FORCE, false, FS_SMALL);
364 } else {
365 DrawString(x, x + this->column_size[VGC_NUMBER].width - 1, y + (this->tiny_step_height - this->column_size[VGC_NUMBER].height) / 2, GetString(STR_GROUP_COUNT_WITH_SUBGROUP, num_vehicle, num_vehicle_with_subgroups - num_vehicle), colour, SA_RIGHT | SA_FORCE);
366 }
367 }
368
373 {
374 if (this->group_over == GroupID::Invalid()) return;
375
376 if (IsAllGroupID(this->group_over)) {
378 } else if (IsDefaultGroupID(this->group_over)) {
380 } else {
382 }
383 }
384
385public:
387 {
388 this->CreateNestedTree();
389
390 this->vscroll = this->GetScrollbar(WID_GL_LIST_VEHICLE_SCROLLBAR);
391 this->group_sb = this->GetScrollbar(WID_GL_LIST_GROUP_SCROLLBAR);
392
393 this->vli.SetIndex(ALL_GROUP);
394
395 this->groups.ForceRebuild();
396 this->groups.NeedResort();
397 this->BuildGroupList(vli.company);
398 this->group_sb->SetCount(this->groups.size());
399
400 this->GetWidget<NWidgetCore>(WID_GL_CAPTION)->SetString(STR_VEHICLE_LIST_TRAIN_CAPTION + this->vli.vtype);
401 this->GetWidget<NWidgetCore>(WID_GL_LIST_VEHICLE)->SetToolTip(STR_VEHICLE_LIST_TRAIN_LIST_TOOLTIP + this->vli.vtype);
402
403 this->GetWidget<NWidgetCore>(WID_GL_CREATE_GROUP)->SetSprite(SPR_GROUP_CREATE_TRAIN + this->vli.vtype);
404 this->GetWidget<NWidgetCore>(WID_GL_RENAME_GROUP)->SetSprite(SPR_GROUP_RENAME_TRAIN + this->vli.vtype);
405 this->GetWidget<NWidgetCore>(WID_GL_DELETE_GROUP)->SetSprite(SPR_GROUP_DELETE_TRAIN + this->vli.vtype);
406 this->GetWidget<NWidgetCore>(WID_GL_LIVERY_GROUP)->SetSprite(SPR_GROUP_LIVERY_TRAIN + this->vli.vtype);
407 this->GetWidget<NWidgetCore>(WID_GL_REPLACE_PROTECTION)->SetSprite(SPR_GROUP_REPLACE_OFF_TRAIN + this->vli.vtype);
408
409 this->FinishInitNested(window_number);
410 this->owner = vli.company;
411
412 this->BuildVehicleList();
413 this->SortVehicleList();
414 }
415
417 {
418 *this->sorting = this->vehgroups.GetListing();
419 }
420
421 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
422 {
423 switch (widget) {
425 size.width = this->ComputeGroupInfoSize();
426 resize.height = this->tiny_step_height;
427 fill.height = this->tiny_step_height;
428 break;
429
432 size.width = this->ComputeGroupInfoSize();
433 size.height = this->tiny_step_height;
434 break;
435
437 Dimension d = GetStringBoundingBox(this->GetWidget<NWidgetCore>(widget)->GetString());
438 d.width += padding.width + Window::SortButtonWidth() * 2; // Doubled since the string is centred and it also looks better.
439 d.height += padding.height;
440 size = maxdim(size, d);
441 break;
442 }
443
445 this->ComputeGroupInfoSize();
446 resize.height = GetVehicleListHeight(this->vli.vtype, this->tiny_step_height);
447 size.height = 4 * resize.height;
448 break;
449
451 size.width = GetStringListWidth(this->vehicle_group_by_names) + padding.width;
452 break;
453
455 size.width = GetStringListWidth(this->vehicle_group_none_sorter_names_calendar);
456 size.width = std::max(size.width, GetStringListWidth(this->vehicle_group_none_sorter_names_wallclock));
457 size.width = std::max(size.width, GetStringListWidth(this->vehicle_group_shared_orders_sorter_names_calendar));
458 size.width = std::max(size.width, GetStringListWidth(this->vehicle_group_shared_orders_sorter_names_wallclock));
459 size.width += padding.width;
460 break;
461
463 size.width = std::max(size.width, GetDropDownListDimension(this->BuildCargoDropDownList(true)).width + padding.width);
464 break;
465
467 Dimension d = this->GetActionDropdownSize(true, true, true);
468 d.height += padding.height;
469 d.width += padding.width;
470 size = maxdim(size, d);
471 break;
472 }
473 }
474 }
475
481 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
482 {
483 if (data == 0) {
484 /* This needs to be done in command-scope to enforce rebuilding before resorting invalid data */
485 this->vehgroups.ForceRebuild();
486 this->groups.ForceRebuild();
487 } else {
488 this->vehgroups.ForceResort();
489 this->groups.ForceResort();
490 }
491
492 /* Process ID-invalidation in command-scope as well */
493 if (this->group_rename != GroupID::Invalid() && !Group::IsValidID(this->group_rename)) {
495 this->group_rename = GroupID::Invalid();
496 }
497
498 GroupID group = this->vli.ToGroupID();
499 if (!(IsAllGroupID(group) || IsDefaultGroupID(group) || Group::IsValidID(group))) {
500 this->vli.SetIndex(ALL_GROUP);
502 }
503 this->SetDirty();
504 }
505
506 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
507 {
508 switch (widget) {
510 return GetString(this->GetCargoFilterLabel(this->cargo_filter_criteria));
511
513 return GetString(STR_VEHICLE_LIST_AVAILABLE_TRAINS + this->vli.vtype);
514
515 case WID_GL_CAPTION:
516 /* If selected_group == DEFAULT_GROUP || ALL_GROUP, draw the standard caption
517 * We list all vehicles or ungrouped vehicles */
518 if (IsDefaultGroupID(this->vli.ToGroupID()) || IsAllGroupID(this->vli.ToGroupID())) {
519 return GetString(stringid, STR_COMPANY_NAME, this->vli.company, this->vehicles.size(), this->vehicles.size());
520 } else {
521 uint num_vehicle = GetGroupNumVehicle(this->vli.company, this->vli.ToGroupID(), this->vli.vtype);
522
523 return GetString(stringid, STR_GROUP_NAME, this->vli.ToGroupID(), num_vehicle, num_vehicle);
524 }
525
526 default:
527 return this->Window::GetWidgetString(widget, stringid);
528 }
529 }
530
531 void OnPaint() override
532 {
533 /* If we select the all vehicles, this->list will contain all vehicles of the owner
534 * else this->list will contain all vehicles which belong to the selected group */
535 this->BuildVehicleList();
536 this->SortVehicleList();
537
538 this->BuildGroupList(this->owner);
539
540 this->group_sb->SetCount(this->groups.size());
541 this->vscroll->SetCount(this->vehgroups.size());
542
543 /* The drop down menu is out, *but* it may not be used, retract it. */
544 if (this->vehicles.empty() && this->IsWidgetLowered(WID_GL_MANAGE_VEHICLES_DROPDOWN)) {
547 }
548
549 /* Disable all lists management button when the list is empty */
550 this->SetWidgetsDisabledState(this->vehicles.empty() || _local_company != this->vli.company,
554
555 /* Disable the group specific function when we select the default group or all vehicles */
556 GroupID group = this->vli.ToGroupID();
557 this->SetWidgetsDisabledState(IsDefaultGroupID(group) || IsAllGroupID(group) || _local_company != this->vli.company,
562
563 /* Disable remaining buttons for non-local companies
564 * Needed while changing _local_company, eg. by cheats
565 * All procedures (eg. move vehicle to another group)
566 * verify, whether you are the owner of the vehicle,
567 * so it doesn't have to be disabled
568 */
572
573 /* If not a default group and the group has replace protection, show an enabled replace sprite. */
574 uint16_t protect_sprite = SPR_GROUP_REPLACE_OFF_TRAIN;
575 if (!IsDefaultGroupID(group) && !IsAllGroupID(group) && Group::Get(group)->flags.Test(GroupFlag::ReplaceProtection)) protect_sprite = SPR_GROUP_REPLACE_ON_TRAIN;
576 this->GetWidget<NWidgetCore>(WID_GL_REPLACE_PROTECTION)->SetSprite(protect_sprite + this->vli.vtype);
577
578 /* Set text of "group by" dropdown widget. */
579 this->GetWidget<NWidgetCore>(WID_GL_GROUP_BY_DROPDOWN)->SetString(std::data(this->vehicle_group_by_names)[this->grouping]);
580
581 /* Set text of "sort by" dropdown widget. */
582 this->GetWidget<NWidgetCore>(WID_GL_SORT_BY_DROPDOWN)->SetString(this->GetVehicleSorterNames()[this->vehgroups.SortType()]);
583
584 this->DrawWidgets();
585 }
586
587 void DrawWidget(const Rect &r, WidgetID widget) const override
588 {
589 switch (widget) {
591 DrawGroupInfo(r.top, r.left, r.right, ALL_GROUP);
592 break;
593
595 DrawGroupInfo(r.top, r.left, r.right, DEFAULT_GROUP);
596 break;
597
598 case WID_GL_INFO: {
599 Money this_year = 0;
600 Money last_year = 0;
601 uint64_t occupancy = 0;
602
603 for (const Vehicle * const v : this->vehicles) {
604 assert(v->owner == this->owner);
605
606 this_year += v->GetDisplayProfitThisYear();
607 last_year += v->GetDisplayProfitLastYear();
608 occupancy += v->trip_occupancy;
609 }
610
611 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
612
613 DrawString(tr, TimerGameEconomy::UsingWallclockUnits() ? STR_GROUP_PROFIT_THIS_PERIOD : STR_GROUP_PROFIT_THIS_YEAR, TC_BLACK);
614 DrawString(tr, GetString(STR_JUST_CURRENCY_LONG, this_year), TC_BLACK, SA_RIGHT);
615
616 tr.top += GetCharacterHeight(FS_NORMAL);
617 DrawString(tr, TimerGameEconomy::UsingWallclockUnits() ? STR_GROUP_PROFIT_LAST_PERIOD : STR_GROUP_PROFIT_LAST_YEAR, TC_BLACK);
618 DrawString(tr, GetString(STR_JUST_CURRENCY_LONG, last_year), TC_BLACK, SA_RIGHT);
619
620 tr.top += GetCharacterHeight(FS_NORMAL);
621 DrawString(tr, STR_GROUP_OCCUPANCY, TC_BLACK);
622 const size_t vehicle_count = this->vehicles.size();
623 if (vehicle_count > 0) {
624 DrawString(tr, GetString(STR_GROUP_OCCUPANCY_VALUE, occupancy / vehicle_count), TC_BLACK, SA_RIGHT);
625 }
626
627 break;
628 }
629
630 case WID_GL_LIST_GROUP: {
631 int y1 = r.top;
632 auto [first, last] = this->group_sb->GetVisibleRangeIterators(this->groups);
633 for (auto it = first; it != last; ++it) {
634 const Group *g = it->group;
635
636 assert(g->owner == this->owner);
637
638 DrawGroupInfo(y1, r.left, r.right, g->index, it->level_mask, it->indent, g->flags.Test(GroupFlag::ReplaceProtection), g->folded || (std::next(it) != std::end(this->groups) && std::next(it)->indent > it->indent));
639
640 y1 += this->tiny_step_height;
641 }
642 if ((uint)this->group_sb->GetPosition() + this->group_sb->GetCapacity() > this->groups.size()) {
643 DrawGroupInfo(y1, r.left, r.right, NEW_GROUP);
644 }
645 break;
646 }
647
650 break;
651
653 if (this->vli.ToGroupID() != ALL_GROUP && this->grouping == GB_NONE) {
654 /* Mark vehicles which are in sub-groups (only if we are not using shared order coalescing) */
655 Rect mr = r.WithHeight(this->resize.step_height);
656 auto [first, last] = this->vscroll->GetVisibleRangeIterators(this->vehgroups);
657 for (auto it = first; it != last; ++it) {
658 const Vehicle *v = it->GetSingleVehicle();
659 if (v->group_id != this->vli.ToGroupID()) {
661 }
662 mr = mr.Translate(0, this->resize.step_height);
663 }
664 }
665
666 this->DrawVehicleListItems(this->vehicle_sel, this->resize.step_height, r);
667 break;
668 }
669 }
670
671 static void DeleteGroupCallback(Window *win, bool confirmed)
672 {
673 if (confirmed) {
675 w->vli.SetIndex(ALL_GROUP);
676 Command<CMD_DELETE_GROUP>::Post(STR_ERROR_GROUP_CAN_T_DELETE, w->group_confirm);
677 }
678 }
679
680 void OnMouseLoop() override
681 {
682 if (last_overlay_state != ShowCargoIconOverlay()) {
683 last_overlay_state = ShowCargoIconOverlay();
684 this->SetDirty();
685 }
686 }
687
688 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
689 {
690 switch (widget) {
691 case WID_GL_SORT_BY_ORDER: // Flip sorting method ascending/descending
693 this->SetDirty();
694 break;
695
696 case WID_GL_GROUP_BY_DROPDOWN: // Select grouping option dropdown menu
697 ShowDropDownMenu(this, this->vehicle_group_by_names, this->grouping, WID_GL_GROUP_BY_DROPDOWN, 0, 0);
698 return;
699
700 case WID_GL_SORT_BY_DROPDOWN: // Select sorting criteria dropdown menu
701 ShowDropDownMenu(this, this->GetVehicleSorterNames(), this->vehgroups.SortType(), WID_GL_SORT_BY_DROPDOWN, 0, (this->vli.vtype == VEH_TRAIN || this->vli.vtype == VEH_ROAD) ? 0 : (1 << 10));
702 return;
703
704 case WID_GL_FILTER_BY_CARGO: // Select filtering criteria dropdown menu
705 ShowDropDownList(this, this->BuildCargoDropDownList(false), this->cargo_filter_criteria, widget);
706 break;
707
708 case WID_GL_ALL_VEHICLES: // All vehicles button
709 if (!IsAllGroupID(this->vli.ToGroupID())) {
710 this->vli.SetIndex(ALL_GROUP);
711 this->vehgroups.ForceRebuild();
712 this->SetDirty();
713 }
714 break;
715
716 case WID_GL_DEFAULT_VEHICLES: // Ungrouped vehicles button
717 if (!IsDefaultGroupID(this->vli.ToGroupID())) {
718 this->vli.SetIndex(DEFAULT_GROUP);
719 this->vehgroups.ForceRebuild();
720 this->SetDirty();
721 }
722 break;
723
724 case WID_GL_LIST_GROUP: { // Matrix Group
725 auto it = this->group_sb->GetScrolledItemFromWidget(this->groups, pt.y, this, WID_GL_LIST_GROUP);
726 if (it == this->groups.end()) return;
727
728 if (it->group->folded || (std::next(it) != std::end(this->groups) && std::next(it)->indent > it->indent)) {
729 /* The group has children, check if the user clicked the fold / unfold button. */
730 NWidgetCore *group_display = this->GetWidget<NWidgetCore>(widget);
731 int x = _current_text_dir == TD_RTL ?
732 group_display->pos_x + group_display->current_x - WidgetDimensions::scaled.framerect.right - it->indent * WidgetDimensions::scaled.hsep_indent - this->column_size[VGC_FOLD].width :
734 if (click_count > 1 || (pt.x >= x && pt.x < (int)(x + this->column_size[VGC_FOLD].width))) {
735
736 GroupID g = this->vli.ToGroupID();
737 if (!IsAllGroupID(g) && !IsDefaultGroupID(g)) {
738 do {
739 g = Group::Get(g)->parent;
740 if (g == it->group->index) {
741 this->vli.SetIndex(g);
742 break;
743 }
744 } while (g != GroupID::Invalid());
745 }
746
747 Group::Get(it->group->index)->folded = !it->group->folded;
748 this->groups.ForceRebuild();
749
750 this->SetDirty();
751 break;
752 }
753 }
754
755 this->vli.SetIndex(it->group->index);
756 this->group_sel = it->group->index;
757
759
760 this->vehgroups.ForceRebuild();
761 this->SetDirty();
762 break;
763 }
764
765 case WID_GL_LIST_VEHICLE: { // Matrix Vehicle
766 auto it = this->vscroll->GetScrolledItemFromWidget(this->vehgroups, pt.y, this, WID_GL_LIST_VEHICLE);
767 if (it == this->vehgroups.end()) return; // click out of list bound
768
769 const GUIVehicleGroup &vehgroup = *it;
770
771 const Vehicle *v = nullptr;
772
773 switch (this->grouping) {
774 case GB_NONE: {
775 const Vehicle *v2 = vehgroup.GetSingleVehicle();
776 if (VehicleClicked(v2)) break;
777 v = v2;
778 break;
779 }
780
781 case GB_SHARED_ORDERS: {
782 assert(vehgroup.NumVehicles() > 0);
783 v = vehgroup.vehicles_begin[0];
784 /*
785 * No VehicleClicked(v) support for now, because don't want
786 * to enable any contextual actions except perhaps clicking/ctrl-clicking to clone orders.
787 */
788 break;
789 }
790
791 default:
792 NOT_REACHED();
793 }
794 if (v) {
795 if (_ctrl_pressed && this->grouping == GB_SHARED_ORDERS) {
796 ShowOrdersWindow(v);
797 } else {
798 this->vehicle_sel = v->index;
799
800 if (_ctrl_pressed && this->grouping == GB_NONE) {
801 /*
802 * It only makes sense to select a group if not using shared orders
803 * since two vehicles sharing orders can be from different groups.
804 */
805 this->SelectGroup(v->group_id);
806 }
807
810 _cursor.vehchain = true;
811
812 this->SetDirty();
813 }
814 }
815
816 break;
817 }
818
819 case WID_GL_CREATE_GROUP: { // Create a new group
820 Command<CMD_CREATE_GROUP>::Post(STR_ERROR_GROUP_CAN_T_CREATE, CcCreateGroup, this->vli.vtype, this->vli.ToGroupID());
821 break;
822 }
823
824 case WID_GL_DELETE_GROUP: { // Delete the selected group
825 this->group_confirm = this->vli.ToGroupID();
826 ShowQuery(
827 GetEncodedString(STR_QUERY_GROUP_DELETE_CAPTION),
828 GetEncodedString(STR_GROUP_DELETE_QUERY_TEXT),
829 this, DeleteGroupCallback);
830 break;
831 }
832
833 case WID_GL_RENAME_GROUP: // Rename the selected roup
834 this->ShowRenameGroupWindow(this->vli.ToGroupID(), false);
835 break;
836
837 case WID_GL_LIVERY_GROUP: // Set group livery
838 ShowCompanyLiveryWindow(this->owner, this->vli.ToGroupID());
839 break;
840
842 ShowBuildVehicleWindow(INVALID_TILE, this->vli.vtype);
843 break;
844
846 ShowDropDownList(this, this->BuildActionDropdownList(true, Group::IsValidID(this->vli.ToGroupID()), IsDefaultGroupID(this->vli.ToGroupID())), -1, WID_GL_MANAGE_VEHICLES_DROPDOWN);
847 break;
848 }
849
850 case WID_GL_START_ALL:
851 case WID_GL_STOP_ALL: { // Start/stop all vehicles of the list
853 break;
854 }
855
857 const Group *g = Group::GetIfValid(this->vli.ToGroupID());
858 if (g != nullptr) {
860 }
861 break;
862 }
863 }
864 }
865
866 void OnDragDrop_Group(Point pt, WidgetID widget)
867 {
868 const Group *g = Group::Get(this->group_sel);
869
870 switch (widget) {
871 case WID_GL_ALL_VEHICLES: // All vehicles
872 case WID_GL_DEFAULT_VEHICLES: // Ungrouped vehicles
873 if (g->parent != GroupID::Invalid()) {
874 Command<CMD_ALTER_GROUP>::Post(STR_ERROR_GROUP_CAN_T_SET_PARENT, AlterGroupMode::SetParent, this->group_sel, GroupID::Invalid(), {});
875 }
876
877 this->group_sel = GroupID::Invalid();
878 this->group_over = GroupID::Invalid();
879 this->SetDirty();
880 break;
881
882 case WID_GL_LIST_GROUP: { // Matrix group
883 auto it = this->group_sb->GetScrolledItemFromWidget(this->groups, pt.y, this, WID_GL_LIST_GROUP);
884 GroupID new_g = it == this->groups.end() ? GroupID::Invalid() : it->group->index;
885
886 if (this->group_sel != new_g && g->parent != new_g) {
887 Command<CMD_ALTER_GROUP>::Post(STR_ERROR_GROUP_CAN_T_SET_PARENT, AlterGroupMode::SetParent, this->group_sel, new_g, {});
888 }
889
890 this->group_sel = GroupID::Invalid();
891 this->group_over = GroupID::Invalid();
892 this->SetDirty();
893 break;
894 }
895 }
896 }
897
898 void OnDragDrop_Vehicle(Point pt, WidgetID widget)
899 {
900 switch (widget) {
901 case WID_GL_DEFAULT_VEHICLES: // Ungrouped vehicles
902 Command<CMD_ADD_VEHICLE_GROUP>::Post(STR_ERROR_GROUP_CAN_T_ADD_VEHICLE, DEFAULT_GROUP, this->vehicle_sel, _ctrl_pressed || this->grouping == GB_SHARED_ORDERS, VehicleListIdentifier{});
903
904 this->vehicle_sel = VehicleID::Invalid();
905 this->group_over = GroupID::Invalid();
906
907 this->SetDirty();
908 break;
909
910 case WID_GL_LIST_GROUP: { // Matrix group
911 const VehicleID vindex = this->vehicle_sel;
912 this->vehicle_sel = VehicleID::Invalid();
913 this->group_over = GroupID::Invalid();
914 this->SetDirty();
915
916 auto it = this->group_sb->GetScrolledItemFromWidget(this->groups, pt.y, this, WID_GL_LIST_GROUP);
917 GroupID new_g = it == this->groups.end() ? NEW_GROUP : it->group->index;
918
919 Command<CMD_ADD_VEHICLE_GROUP>::Post(STR_ERROR_GROUP_CAN_T_ADD_VEHICLE, new_g == NEW_GROUP ? CcAddVehicleNewGroup : nullptr, new_g, vindex, _ctrl_pressed || this->grouping == GB_SHARED_ORDERS, VehicleListIdentifier{});
920 break;
921 }
922
923 case WID_GL_LIST_VEHICLE: { // Matrix vehicle
924 const VehicleID vindex = this->vehicle_sel;
925 this->vehicle_sel = VehicleID::Invalid();
926 this->group_over = GroupID::Invalid();
927 this->SetDirty();
928
929 auto it = this->vscroll->GetScrolledItemFromWidget(this->vehgroups, pt.y, this, WID_GL_LIST_VEHICLE);
930 if (it == this->vehgroups.end()) return; // click out of list bound
931
932 const GUIVehicleGroup &vehgroup = *it;
933 switch (this->grouping) {
934 case GB_NONE: {
935 const Vehicle *v = vehgroup.GetSingleVehicle();
936 if (!VehicleClicked(v) && vindex == v->index) {
938 }
939 break;
940 }
941
942 case GB_SHARED_ORDERS: {
943 if (!VehicleClicked(vehgroup)) {
944 const Vehicle *v = vehgroup.vehicles_begin[0];
945 if (vindex == v->index) {
946 if (vehgroup.NumVehicles() == 1) {
948 } else {
949 ShowVehicleListWindow(v);
950 }
951 }
952 }
953 break;
954 }
955
956 default:
957 NOT_REACHED();
958 }
959 break;
960 }
961 }
962 }
963
964 void OnDragDrop(Point pt, WidgetID widget) override
965 {
966 if (this->vehicle_sel != VehicleID::Invalid()) OnDragDrop_Vehicle(pt, widget);
967 if (this->group_sel != GroupID::Invalid()) OnDragDrop_Group(pt, widget);
968
969 _cursor.vehchain = false;
970 }
971
972 void OnQueryTextFinished(std::optional<std::string> str) override
973 {
974 if (str.has_value()) Command<CMD_ALTER_GROUP>::Post(STR_ERROR_GROUP_CAN_T_RENAME, AlterGroupMode::Rename, this->group_rename, GroupID::Invalid(), *str);
975 this->group_rename = GroupID::Invalid();
976 }
977
978 void OnResize() override
979 {
980 this->group_sb->SetCapacityFromWidget(this, WID_GL_LIST_GROUP);
981 this->vscroll->SetCapacityFromWidget(this, WID_GL_LIST_VEHICLE);
982 }
983
984 void OnDropdownSelect(WidgetID widget, int index) override
985 {
986 switch (widget) {
988 this->UpdateVehicleGroupBy(static_cast<GroupBy>(index));
989 break;
990
992 this->vehgroups.SetSortType(index);
993 break;
994
995 case WID_GL_FILTER_BY_CARGO: // Select a cargo filter criteria
996 this->SetCargoFilter(index);
997 break;
998
1000 assert(!this->vehicles.empty());
1001
1002 switch (index) {
1003 case ADI_REPLACE: // Replace window
1004 ShowReplaceGroupVehicleWindow(this->vli.ToGroupID(), this->vli.vtype);
1005 break;
1006 case ADI_SERVICE: // Send for servicing
1007 case ADI_DEPOT: { // Send to Depots
1008 Command<CMD_SEND_VEHICLE_TO_DEPOT>::Post(GetCmdSendToDepotMsg(this->vli.vtype), VehicleID::Invalid(), (index == ADI_SERVICE ? DepotCommandFlag::Service : DepotCommandFlags{}) | DepotCommandFlag::MassSend, this->vli);
1009 break;
1010 }
1011
1012 case ADI_CREATE_GROUP: // Create group
1013 Command<CMD_ADD_VEHICLE_GROUP>::Post(CcAddVehicleNewGroup, NEW_GROUP, VehicleID::Invalid(), false, this->vli);
1014 break;
1015
1016 case ADI_ADD_SHARED: // Add shared Vehicles
1017 assert(Group::IsValidID(this->vli.ToGroupID()));
1018
1019 Command<CMD_ADD_SHARED_VEHICLE_GROUP>::Post(STR_ERROR_GROUP_CAN_T_ADD_SHARED_VEHICLE, this->vli.ToGroupID(), this->vli.vtype);
1020 break;
1021 case ADI_REMOVE_ALL: // Remove all Vehicles from the selected group
1022 assert(Group::IsValidID(this->vli.ToGroupID()));
1023
1024 Command<CMD_REMOVE_ALL_VEHICLES_GROUP>::Post(STR_ERROR_GROUP_CAN_T_REMOVE_ALL_VEHICLES, this->vli.ToGroupID());
1025 break;
1026 default: NOT_REACHED();
1027 }
1028 break;
1029
1030 default: NOT_REACHED();
1031 }
1032
1033 this->SetDirty();
1034 }
1035
1036 void OnGameTick() override
1037 {
1038 if (this->groups.NeedResort() || this->vehgroups.NeedResort()) {
1039 this->SetDirty();
1040 }
1041 }
1042
1043 void OnPlaceObjectAbort() override
1044 {
1045 /* abort drag & drop */
1046 this->vehicle_sel = VehicleID::Invalid();
1048 this->group_sel = GroupID::Invalid();
1049 this->group_over = GroupID::Invalid();
1051 }
1052
1053 void OnMouseDrag(Point pt, WidgetID widget) override
1054 {
1055 if (this->vehicle_sel == VehicleID::Invalid() && this->group_sel == GroupID::Invalid()) return;
1056
1057 /* A vehicle is dragged over... */
1058 GroupID new_group_over = GroupID::Invalid();
1059 switch (widget) {
1060 case WID_GL_DEFAULT_VEHICLES: // ... the 'default' group.
1061 new_group_over = DEFAULT_GROUP;
1062 break;
1063
1064 case WID_GL_LIST_GROUP: { // ... the list of custom groups.
1065 auto it = this->group_sb->GetScrolledItemFromWidget(this->groups, pt.y, this, WID_GL_LIST_GROUP);
1066 new_group_over = it == this->groups.end() ? NEW_GROUP : it->group->index;
1067 break;
1068 }
1069 }
1070
1071 /* Do not highlight when dragging over the current group */
1072 if (this->vehicle_sel != VehicleID::Invalid()) {
1073 if (Vehicle::Get(vehicle_sel)->group_id == new_group_over) new_group_over = GroupID::Invalid();
1074 } else if (this->group_sel != GroupID::Invalid()) {
1075 if (this->group_sel == new_group_over || Group::Get(this->group_sel)->parent == new_group_over) new_group_over = GroupID::Invalid();
1076 }
1077
1078 /* Mark widgets as dirty if the group changed. */
1079 if (new_group_over != this->group_over) {
1081 this->group_over = new_group_over;
1083 }
1084 }
1085
1086 void ShowRenameGroupWindow(GroupID group, bool empty)
1087 {
1088 assert(Group::IsValidID(group));
1089 this->group_rename = group;
1090
1091 /* Show empty query for new groups */
1092 std::string str;
1093 if (!empty) str = GetString(STR_GROUP_NAME, group);
1094
1096 }
1097
1104 {
1105 if (this->vehicle_sel == vehicle) ResetObjectToPlace();
1106 }
1107
1113 void SelectGroup(const GroupID g_id)
1114 {
1115 if (g_id == GroupID::Invalid() || g_id == this->vli.ToGroupID()) return;
1116
1117 this->vli.SetIndex(g_id);
1118 if (g_id != ALL_GROUP && g_id != DEFAULT_GROUP) {
1119 const Group *g = Group::Get(g_id);
1120
1121 auto found = std::ranges::find(this->groups, g, &GUIGroupListItem::group);
1122 if (found == std::end(this->groups)) {
1123 /* The group's branch is maybe collapsed, so try to expand it. */
1124 for (auto pg = Group::GetIfValid(g->parent); pg != nullptr; pg = Group::GetIfValid(pg->parent)) {
1125 pg->folded = false;
1126 }
1127 this->groups.ForceRebuild();
1128 this->BuildGroupList(this->owner);
1129 this->group_sb->SetCount(this->groups.size());
1130 found = std::ranges::find(this->groups, g, &GUIGroupListItem::group);
1131 }
1132 if (found != std::end(this->groups)) this->group_sb->ScrollTowards(std::distance(std::begin(this->groups), found));
1133 }
1134 this->vehgroups.ForceRebuild();
1135 this->SetDirty();
1136 }
1137
1138};
1139
1140static WindowDesc _vehicle_group_desc[] = {
1141 {
1142 WDP_AUTO, "list_groups_train", 525, 246,
1144 {},
1145 _nested_group_widgets
1146 },
1147 {
1148 WDP_AUTO, "list_groups_roadveh", 460, 246,
1150 {},
1151 _nested_group_widgets
1152 },
1153 {
1154 WDP_AUTO, "list_groups_ship", 460, 246,
1156 {},
1157 _nested_group_widgets
1158 },
1159 {
1160 WDP_AUTO, "list_groups_aircraft", 460, 246,
1162 {},
1163 _nested_group_widgets
1164 },
1165};
1166
1174template <bool Tneed_existing_window>
1175static void ShowCompanyGroupInternal(CompanyID company, VehicleType vehicle_type, GroupID group)
1176{
1177 if (!Company::IsValidID(company)) return;
1178
1179 assert(vehicle_type < std::size(_vehicle_group_desc));
1180 VehicleListIdentifier vli(VL_GROUP_LIST, vehicle_type, company);
1181 VehicleGroupWindow *w = AllocateWindowDescFront<VehicleGroupWindow, Tneed_existing_window>(_vehicle_group_desc[vehicle_type], vli.ToWindowNumber(), vli);
1182 if (w != nullptr) w->SelectGroup(group);
1183}
1184
1191void ShowCompanyGroup(CompanyID company, VehicleType vehicle_type, GroupID group)
1192{
1193 ShowCompanyGroupInternal<false>(company, vehicle_type, group);
1194}
1195
1201{
1202 ShowCompanyGroupInternal<true>(v->owner, v->type, v->group_id);
1203}
1204
1212{
1213 return dynamic_cast<VehicleGroupWindow *>(FindWindowById(GetWindowClassForVehicleType(vt), VehicleListIdentifier(VL_GROUP_LIST, vt, owner).ToWindowNumber()));
1214}
1215
1220static void CcCreateGroup(GroupID gid, VehicleType veh_type)
1221{
1223 if (w != nullptr) w->ShowRenameGroupWindow(gid, true);
1224}
1225
1233void CcCreateGroup(Commands, const CommandCost &result, GroupID new_group, VehicleType vt, GroupID)
1234{
1235 if (result.Failed()) return;
1236
1237 assert(vt <= VEH_AIRCRAFT);
1238 CcCreateGroup(new_group, vt);
1239}
1240
1247{
1248 if (result.Failed()) return;
1249
1250 const Group *g = Group::Get(new_group);
1251 CcCreateGroup(new_group, g->vehicle_type);
1252}
1253
1259{
1260 /* If we haven't got any vehicles on the mouse pointer, we haven't got any highlighted in any group windows either
1261 * If that is the case, we can skip looping though the windows and save time
1262 */
1263 if (_special_mouse_mode != WSM_DRAGDROP) return;
1264
1266 if (w != nullptr) w->UnselectVehicle(v->index);
1267}
void ShowReplaceGroupVehicleWindow(GroupID id_g, VehicleType vehicletype)
Show the autoreplace configuration window for a particular group.
Functions related to the autoreplace GUIs.
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T AssignBit(T &x, const uint8_t y, bool value)
Assigns a bit in a variable.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
Common return value for all commands.
bool Failed() const
Did this command fail?
Enum-as-bit-set wrapper.
void RebuildDone()
Notify the sortlist that the rebuild is done.
bool IsDescSortOrder() const
Check if the sort order is descending.
void ToggleSortOrder()
Toggle the sort order Since that is the worst condition for the sort function reverse the list here.
bool NeedRebuild() const
Check if a rebuild is needed.
void ForceRebuild()
Force that a rebuild is needed.
bool Sort(Comp compare)
Sort the list.
void ForceResort()
Force a resort next Sort call Reset the resort timer if used too.
uint8_t SortType() const
Get the sorttype of the list.
Listing GetListing() const
Export current sort conditions.
bool NeedResort()
Check if a resort is needed next loop If used the resort timer will decrease every call till 0.
void SetSortType(uint8_t n_type)
Set the sorttype of the list.
uint current_x
Current horizontal size (after resizing).
int pos_x
Horizontal position of top-left corner of the widget in the window.
Base class for a 'real' widget.
Scrollbar data structure.
void SetCount(size_t num)
Sets the number of elements in the list.
auto GetScrolledItemFromWidget(Tcontainer &container, int clickpos, const Window *const w, WidgetID widget, int padding=0, int line_height=-1) const
Return an iterator pointing to the element of a scrolled widget that a user clicked in.
void SetCapacityFromWidget(Window *w, WidgetID widget, int padding=0)
Set capacity of visible elements from the size and resize properties of a widget.
Definition widget.cpp:2523
void ScrollTowards(size_type position)
Scroll towards the given position; if the item is visible nothing happens, otherwise it will be shown...
auto GetVisibleRangeIterators(Tcontainer &container) const
Get a pair of iterators for the range of visible elements in a container.
size_type GetPosition() const
Gets the position of the first visible element in the list.
static bool UsingWallclockUnits(bool newgame=false)
Check if we are using wallclock units.
void UnselectVehicle(VehicleID vehicle)
Tests whether a given vehicle is selected in the window, and unselects it if necessary.
void DirtyHighlightedGroupWidget()
Mark the widget containing the currently highlighted group as dirty.
GroupID group_sel
Selected group (for drag/drop)
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
void OnDragDrop(Point pt, WidgetID widget) override
A dragged 'object' has been released.
GroupID group_rename
Group being renamed, GroupID::Invalid() if none.
void OnMouseDrag(Point pt, WidgetID widget) override
An 'object' is being dragged at the provided position, highlight the target if possible.
void BuildGroupList(Owner owner)
(Re)Build the group list.
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
uint tiny_step_height
Step height for the group list.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
void OnResize() override
Called after the window got resized.
void OnGameTick() override
Called once per (game) tick.
@ VGC_PROFIT
Profit icon.
@ VGC_AUTOREPLACE
Autoreplace active icon.
@ VGC_FOLD
Fold / Unfold button.
@ VGC_NAME
Group name.
@ VGC_PROTECT
Autoreplace protect icon.
@ VGC_NUMBER
Number of vehicles in the group.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
void OnPlaceObjectAbort() override
The user cancelled a tile highlight mode that has been set.
GroupID group_confirm
Group awaiting delete confirmation.
std::array< Dimension, VGC_END > column_size
Size of the columns in the group list.
GUIGroupList groups
List of groups.
GroupID group_over
Group over which a vehicle is dragged, GroupID::Invalid() if none.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
uint ComputeGroupInfoSize()
Compute tiny_step_height and column_size.
void DrawGroupInfo(int y, int left, int right, GroupID g_id, uint16_t level_mask=0, uint8_t indent=0, bool protection=false, bool has_children=false) const
Draw a row in the group list.
void OnQueryTextFinished(std::optional< std::string > str) override
The query window opened from this window has closed.
void OnMouseLoop() override
Called for every mouse loop run, which is at least once per (game) tick.
void OnDropdownSelect(WidgetID widget, int index) override
A dropdown option associated to this window has been selected.
void SelectGroup(const GroupID g_id)
Selects the specified group in the list.
void OnPaint() override
The window must be repainted.
RectPadding framerect
Standard padding inside many panels.
Definition window_gui.h:40
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:29
int hsep_wide
Wide horizontal spacing.
Definition window_gui.h:62
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:94
int hsep_normal
Normal horizontal spacing.
Definition window_gui.h:61
RectPadding bevel
Bevel thickness, affected by "scaled bevels" game option.
Definition window_gui.h:38
int hsep_indent
Width of indentation for tree layouts.
Definition window_gui.h:63
Functions related to commands.
Commands
List of commands.
Definition of stuff that is very close to a company, like the company struct itself.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
CompanyID _current_company
Company currently doing an action.
Functions related to companies.
GUI Functions related to companies.
Some simple functions to help with accessing containers.
void ShowDropDownMenu(Window *w, std::span< const StringID > strings, int selected, WidgetID button, uint32_t disabled_mask, uint32_t hidden_mask, uint width)
Show a dropdown menu window near a widget of the parent window.
Definition dropdown.cpp:444
void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID button, uint width, bool instant_close, bool persist)
Show a drop down list.
Definition dropdown.cpp:407
Dimension GetDropDownListDimension(const DropDownList &list)
Determine width and height required to fully display a DropDownList.
Definition dropdown.cpp:366
Functions related to the drop down widget.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:77
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
Geometry functions.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:923
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:852
int DrawString(int left, int right, int top, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition gfx.cpp:658
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:38
uint GetStringListWidth(std::span< const StringID > list, FontSize fontsize)
Get maximum width of a list of strings.
Definition gfx.cpp:875
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen.
Definition gfx.cpp:115
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:989
Functions related to the gfx engine.
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
@ FS_SMALL
Index of the small font in the font tables.
Definition gfx_type.h:246
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:245
@ SA_RIGHT
Right align the text (must be a single bit).
Definition gfx_type.h:379
@ SA_FORCE
Force the alignment, i.e. don't swap for RTL languages.
Definition gfx_type.h:389
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:296
@ FILLRECT_CHECKER
Draw only every second pixel, used for greying-out.
Definition gfx_type.h:335
Money GetGroupProfitLastYearMinAge(CompanyID company, GroupID id_g, VehicleType type)
Get last year's profit of vehicles above minimum age for the group with GroupID id_g and its sub-grou...
@ ReplaceProtection
If set, the global autoreplace has no effect on the group.
bool IsAllGroupID(GroupID id_g)
Checks if a GroupID stands for all vehicles of a company.
Definition group.h:101
uint GetGroupNumVehicle(CompanyID company, GroupID id_g, VehicleType type)
Get the number of vehicles in the group with GroupID id_g and its sub-groups.
uint GetGroupNumVehicleMinAge(CompanyID company, GroupID id_g, VehicleType type)
Get the number of vehicles above profit minimum age in the group with GroupID id_g and its sub-groups...
constexpr NWidgetPart SetMatrixDataTip(uint32_t cols, uint32_t rows, StringID tip={})
Widget part function for setting the data and tooltip of WWT_MATRIX widgets.
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
constexpr NWidgetPart SetSpriteTip(SpriteID sprite, StringID tip={})
Widget part function for setting the sprite and tooltip.
constexpr NWidgetPart SetScrollbar(WidgetID index)
Attach a scrollbar to a widget.
constexpr NWidgetPart SetStringTip(StringID string, StringID tip={})
Widget part function for setting the string and tooltip.
constexpr NWidgetPart SetAspect(float ratio, AspectFlags flags=AspectFlag::ResizeX)
Widget part function for setting the aspect ratio.
constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
constexpr NWidgetPart SetToolTip(StringID tip)
Widget part function for setting tooltip and clearing the widget data.
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
constexpr NWidgetPart SetMinimalTextLines(uint8_t lines, uint8_t spacing, FontSize size=FS_NORMAL)
Widget part function for setting the minimal text lines.
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
Command definitions related to engine groups.
@ Rename
Change group name.
@ SetParent
Change group parent.
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition window.cpp:945
void ShowCompanyGroup(CompanyID company, VehicleType vehicle_type, GroupID group)
Show the group window for the given company and vehicle type.
void DeleteGroupHighlightOfVehicle(const Vehicle *v)
Removes the highlight of a vehicle in a group window.
static void GuiGroupListAddChildren(GUIGroupList &dst, const GUIGroupList &src, bool fold, GroupID parent=GroupID::Invalid(), uint8_t indent=0)
Add children to GUI group list to build a hierarchical tree.
void CcAddVehicleNewGroup(Commands, const CommandCost &result, GroupID new_group, GroupID, VehicleID, bool, const VehicleListIdentifier &)
Open rename window after adding a vehicle to a new group via drag and drop.
static VehicleGroupWindow * FindVehicleGroupWindow(VehicleType vt, Owner owner)
Finds a group list window determined by vehicle type and owner.
static void ShowCompanyGroupInternal(CompanyID company, VehicleType vehicle_type, GroupID group)
Show the group window for the given company and vehicle type.
void ShowCompanyGroupForVehicle(const Vehicle *v)
Show the group window for the given vehicle.
static void CcCreateGroup(GroupID gid, VehicleType veh_type)
Opens a 'Rename group' window for newly created group.
void BuildGuiGroupList(GUIGroupList &dst, bool fold, Owner owner, VehicleType veh_type)
Build GUI group list, a sorted hierarchical list of groups for owner and vehicle type.
Functions/definitions that have something to do with groups.
static constexpr GroupID DEFAULT_GROUP
Ungrouped vehicles are in this group.
Definition group_type.h:18
static constexpr GroupID ALL_GROUP
All vehicles are in this group.
Definition group_type.h:17
static constexpr GroupID NEW_GROUP
Sentinel for a to-be-created group.
Definition group_type.h:16
static const uint MAX_LENGTH_GROUP_NAME_CHARS
The maximum length of a group name in characters including '\0'.
Definition group_type.h:20
Types related to the group widgets.
@ WID_GL_LIST_GROUP
List of the groups.
@ WID_GL_STOP_ALL
Stop all button.
@ WID_GL_REPLACE_PROTECTION
Replace protection button.
@ WID_GL_MANAGE_VEHICLES_DROPDOWN
Manage vehicles dropdown list.
@ WID_GL_GROUP_BY_ORDER
Group order.
@ WID_GL_SORT_BY_ORDER
Sort order.
@ WID_GL_GROUP_BY_DROPDOWN
Group by dropdown list.
@ WID_GL_CAPTION
Caption of the window.
@ WID_GL_START_ALL
Start all button.
@ WID_GL_ALL_VEHICLES
All vehicles entry.
@ WID_GL_DELETE_GROUP
Delete group button.
@ WID_GL_AVAILABLE_VEHICLES
Available vehicles.
@ WID_GL_RENAME_GROUP
Rename group button.
@ WID_GL_LIST_VEHICLE_SCROLLBAR
Scrollbar for the list.
@ WID_GL_LIVERY_GROUP
Group livery button.
@ WID_GL_SORT_BY_DROPDOWN
Sort by dropdown list.
@ WID_GL_LIST_VEHICLE
List of the vehicles.
@ WID_GL_FILTER_BY_CARGO
Filter vehicles by cargo type.
@ WID_GL_CREATE_GROUP
Create group button.
@ WID_GL_LIST_GROUP_SCROLLBAR
Scrollbar for the list.
@ WID_GL_INFO
Group info.
@ WID_GL_DEFAULT_VEHICLES
Default vehicles entry.
GUI functions that shouldn't be here.
void ShowQuery(EncodedString &&caption, EncodedString &&message, Window *parent, QueryCallbackProc *callback, bool focus)
Show a confirmation window with standard 'yes' and 'no' buttons The window is aligned to the centre o...
void ShowQueryString(std::string_view str, StringID caption, uint maxsize, Window *parent, CharSetFilter afilter, QueryStringFlags flags)
Show a query popup window with a textbox in it.
uint8_t GetColourGradient(Colours colour, ColourShade shade)
Get colour gradient palette index.
Definition palette.cpp:387
A number of safeguards to prevent using unsafe methods.
This file contains all sprite-related enums and defines.
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition sprites.h:1609
static const CursorID SPR_CURSOR_MOUSE
Cursor sprite numbers.
Definition sprites.h:1394
Definition of base types and functions in a cross-platform compatible way.
int StrNaturalCompare(std::string_view s1, std::string_view s2, bool ignore_garbage_at_front)
Compares two strings using case insensitive natural sort.
Definition string.cpp:514
Functions related to low-level strings.
@ CS_ALPHANUMERAL
Both numeric and alphabetic and spaces and stuff.
Definition string_type.h:25
uint64_t GetParamMaxValue(uint64_t max_value, uint min_count, FontSize size)
Get some number that is suitable for string size computations.
Definition strings.cpp:246
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:91
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:424
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:57
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
@ TD_RTL
Text is written right-to-left by default.
VehicleListIdentifier vli
Identifier of the vehicle list we want to currently show.
void DrawVehicleListItems(VehicleID selected_vehicle, int line_height, const Rect &r) const
Draw all the vehicle list items.
VehicleID vehicle_sel
Selected vehicle.
Listing * sorting
Pointer to the vehicle type related sorting.
void SetCargoFilter(uint8_t index)
Set cargo filter for the vehicle group list.
GroupBy grouping
How we want to group the list.
Dimension GetActionDropdownSize(bool show_autoreplace, bool show_group, bool show_create)
Compute the size for the Action dropdown.
DropDownList BuildActionDropdownList(bool show_autoreplace, bool show_group, bool show_create)
Display the Action dropdown window.
VehicleList vehicles
List of vehicles. This is the buffer for vehgroups to point into; if this is structurally modified,...
GUIVehicleGroupList vehgroups
List of (groups of) vehicles. This stores iterators of vehicles, and should be rebuilt if vehicles is...
DropDownList BuildCargoDropDownList(bool full) const
Build drop down list for cargo filter selection.
CargoType cargo_filter_criteria
Selected cargo filter index.
VehicleType type
Type of vehicle.
bool vehchain
vehicle chain is dragged
Definition gfx_type.h:151
Dimensions (a width and height) of a rectangle in 2D.
VehicleList::const_iterator vehicles_begin
Pointer to beginning element of this vehicle group.
Statistics and caches on the vehicles in a group.
Definition group.h:24
uint16_t num_vehicle
Number of vehicles.
Definition group.h:28
bool autoreplace_defined
Are any autoreplace rules set?
Definition group.h:30
static GroupStatistics & Get(CompanyID company, GroupID id_g, VehicleType type)
Returns the GroupStatistics for a specific group.
Definition group_cmd.cpp:63
bool autoreplace_finished
Have all autoreplacement finished?
Definition group.h:31
Group data.
Definition group.h:72
GroupFlags flags
Group flags.
Definition group.h:77
GroupID parent
Parent group.
Definition group.h:83
VehicleType vehicle_type
Vehicle type of the group.
Definition group.h:75
bool folded
NOSAVE: Is this group folded in the group view?
Definition group.h:81
uint16_t number
Per-company group number.
Definition group.h:84
Owner owner
Group Owner.
Definition group.h:74
Partial widget specification to allow NWidgets to be written nested.
Coordinates of a point in 2D.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static Titem * Get(auto index)
Returns Titem with given index.
Tindex index
Index of this pool item.
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static Titem * GetIfValid(auto index)
Returns Titem with given index.
constexpr uint Vertical() const
Get total vertical padding of RectPadding.
Specification of a rectangle with absolute coordinates of all edges.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
Rect WithHeight(int height, bool end=false) const
Copy Rect and set its height.
Rect Translate(int x, int y) const
Copy and translate Rect by x,y pixels.
uint step_height
Step-size of height resize changes.
Definition window_gui.h:213
The information about a vehicle list.
Definition vehiclelist.h:32
CompanyID company
The company associated with this list.
Definition vehiclelist.h:35
WindowNumber ToWindowNumber() const
Pack a VehicleListIdentifier in 32 bits so it can be used as unique WindowNumber.
VehicleType vtype
The vehicle type associated with this list.
Definition vehiclelist.h:34
Vehicle data structure.
GroupID group_id
Index of group Pool array.
Owner owner
Which company owns the vehicle?
High level window description.
Definition window_gui.h:168
Number to differentiate different windows of the same class.
Data structure for an opened window.
Definition window_gui.h:274
static int SortButtonWidth()
Get width of up/down arrow of sort button state.
Definition widget.cpp:793
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1736
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:744
Window * parent
Parent window.
Definition window_gui.h:329
void RaiseWidget(WidgetID widget_index)
Marks a widget as raised.
Definition window_gui.h:470
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:556
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:504
void DrawSortButtonState(WidgetID widget, SortButtonState state) const
Draw a sort button's up or down arrow symbol.
Definition widget.cpp:776
void CloseChildWindows(WindowClass wc=WC_INVALID) const
Close all children a window might have in a head-recursive manner.
Definition window.cpp:1040
ResizeInfo resize
Resize information.
Definition window_gui.h:315
void SetWidgetsDisabledState(bool disab_stat, Args... widgets)
Sets the enabled/disabled status of a list of widgets.
Definition window_gui.h:516
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1726
Owner owner
The owner of the content shown in this window. Company colour is acquired from this variable.
Definition window_gui.h:317
int left
x position of left edge of the window
Definition window_gui.h:310
WindowFlags flags
Window flags.
Definition window_gui.h:301
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:313
int height
Height of the window (number of pixels down in y direction)
Definition window_gui.h:313
int width
width of the window (number of pixels to the right in x direction)
Definition window_gui.h:312
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:303
Stuff related to the text buffer GUI.
@ EnableDefault
enable the 'Default' button ("\0" is returned)
@ LengthIsInChars
the length of the string is counted in characters
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
Functions related to tile highlights.
void ResetObjectToPlace()
Reset the cursor and mouse mode handling back to default (normal cursor, only clicking in windows).
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...
@ HT_DRAG
dragging items in the depot windows
Base class for all vehicles.
Command definitions for vehicles.
Functions related to vehicles.
static const Money VEHICLE_PROFIT_THRESHOLD
Threshold for a vehicle to be considered making good profit.
void ShowVehicleViewWindow(const Vehicle *v)
Shows the vehicle view window of the given vehicle.
bool VehicleClicked(const Vehicle *v)
Dispatch a "vehicle selected" event if any window waits for it.
uint GetVehicleListHeight(VehicleType type, uint divisor)
Get the height of a vehicle in the vehicle list GUIs.
void SetMouseCursorVehicle(const Vehicle *v, EngineImageType image_type)
Set the mouse cursor to look like a vehicle.
bool ShowCargoIconOverlay()
Test if cargo icon overlays should be drawn.
Functions related to the vehicle's GUIs.
WindowClass GetWindowClassForVehicleType(VehicleType vt)
Get WindowClass for vehicle list of given vehicle type.
Definition vehicle_gui.h:97
Functions/classes shared between the different vehicle list GUIs.
@ EIT_IN_LIST
Vehicle drawn in vehicle list, group list, ...
VehicleType
Available vehicle types.
@ VEH_ROAD
Road vehicle type.
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ VEH_TRAIN
Train vehicle type.
@ MassSend
Tells that it's a mass send to depot command (type in VLW flag)
@ Service
The vehicle will leave the depot right after arrival (service only)
@ VL_GROUP_LIST
Index is the group.
Definition vehiclelist.h:27
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
@ WWT_PUSHIMGBTN
Normal push-button (no toggle button) with image caption.
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:65
@ WWT_TEXTBTN
(Toggle) Button with text
Definition widget_type.h:45
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:40
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition widget_type.h:56
@ WWT_MATRIX
Grid of rows and columns.
Definition widget_type.h:49
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition widget_type.h:54
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:51
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:75
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:67
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:59
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition widget_type.h:58
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition widget_type.h:55
@ WWT_DROPDOWN
Drop down list.
Definition widget_type.h:60
@ EqualSize
Containers should keep all their (resizing) children equally large.
@ BigFirst
Allocate space to biggest resize first.
void CloseWindowByClass(WindowClass cls, int data)
Close all windows of a given class.
Definition window.cpp:1155
SpecialMouseMode _special_mouse_mode
Mode of the mouse.
Definition window.cpp:95
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition window.cpp:1101
Window functions not directly related to making/drawing windows.
@ SBS_DOWN
Sort ascending.
Definition window_gui.h:219
@ SBS_UP
Sort descending.
Definition window_gui.h:220
@ WSM_DRAGDROP
Drag&drop an object.
@ WDP_AUTO
Find a place automatically.
Definition window_gui.h:145
int WidgetID
Widget ID.
Definition window_type.h:20
@ WC_ROADVEH_LIST
Road vehicle list; Window numbers:
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:47
@ WC_SHIPS_LIST
Ships list; Window numbers:
@ WC_TRAINS_LIST
Trains list; Window numbers:
@ WC_DROPDOWN_MENU
Drop down menu; Window numbers:
@ WC_QUERY_STRING
Query string window; Window numbers:
@ WC_AIRCRAFT_LIST
Aircraft list; Window numbers: