OpenTTD Source 20260311-master-g511d3794ce
signs_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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#include "stdafx.h"
11#include "company_gui.h"
12#include "company_func.h"
13#include "signs_base.h"
14#include "signs_func.h"
15#include "debug.h"
16#include "command_func.h"
17#include "strings_func.h"
18#include "window_func.h"
19#include "map_func.h"
20#include "viewport_func.h"
21#include "querystring_gui.h"
22#include "sortlist_type.h"
23#include "tilehighlight_func.h"
24#include "stringfilter_type.h"
25#include "string_func.h"
27#include "hotkeys.h"
28#include "transparency.h"
29#include "gui.h"
30#include "signs_cmd.h"
31#include "timer/timer.h"
32#include "timer/timer_window.h"
34#include "dropdown_func.h"
35
36#include "widgets/sign_widget.h"
37
38#include "table/strings.h"
39#include "table/sprites.h"
40
41#include "safeguards.h"
42
43struct SignList {
48
49 GUISignList signs;
50
52 static bool match_case;
53 static std::string default_name;
54
61
62 void BuildSignsList()
63 {
64 if (!this->signs.NeedRebuild()) return;
65
66 Debug(misc, 3, "Building sign list");
67
68 this->signs.clear();
69 this->signs.reserve(Sign::GetNumItems());
70
71 for (const Sign *si : Sign::Iterate()) this->signs.push_back(si);
72
73 this->signs.SetFilterState(true);
74 this->FilterSignList();
75 this->signs.RebuildDone();
76 }
77
79 static bool SignNameSorter(const Sign * const &a, const Sign * const &b)
80 {
81 /* Signs are very very rarely using the default text, but there can also be
82 * a lot of them. Therefore a worthwhile performance gain can be made by
83 * directly comparing Sign::name instead of going through the string
84 * system for each comparison. */
85 const std::string &a_name = a->name.empty() ? SignList::default_name : a->name;
86 const std::string &b_name = b->name.empty() ? SignList::default_name : b->name;
87
88 int r = StrNaturalCompare(a_name, b_name); // Sort by name (natural sorting).
89
90 return r != 0 ? r < 0 : (a->index < b->index);
91 }
92
93 void SortSignsList()
94 {
95 if (!this->signs.Sort(&SignNameSorter)) return;
96 }
97
99 static bool SignNameFilter(const Sign * const *item, StringFilter &filter)
100 {
101 /* Same performance benefit as above for sorting. */
102 const std::string_view name = (*item)->name.empty() ? SignList::default_name : (*item)->name;
103
104 filter.ResetState();
105 filter.AddLine(name);
106 return filter.GetState();
107 }
108
110 static bool OwnerDeityFilter(const Sign * const *item, [[maybe_unused]] StringFilter &filter)
111 {
112 /* You should never be able to edit signs of owner DEITY */
113 return (*item)->owner != OWNER_DEITY;
114 }
115
117 static bool OwnerVisibilityFilter(const Sign * const *item, [[maybe_unused]] StringFilter &filter)
118 {
120 /* Hide sign if non-own signs are hidden in the viewport */
121 return (*item)->owner == _local_company || (*item)->owner == OWNER_DEITY;
122 }
123
126 {
127 this->signs.Filter(&SignNameFilter, this->string_filter);
128 if (_game_mode != GM_EDITOR) this->signs.Filter(&OwnerDeityFilter, this->string_filter);
130 this->signs.Filter(&OwnerVisibilityFilter, this->string_filter);
131 }
132 }
133};
134
135bool SignList::match_case = false;
136std::string SignList::default_name;
137
138struct SignListWindow : Window, SignList {
140 int text_offset = 0;
141 Scrollbar *vscroll = nullptr;
142
144 {
145 this->CreateNestedTree();
146 this->vscroll = this->GetScrollbar(WID_SIL_SCROLLBAR);
147 this->FinishInitNested(window_number);
149
150 /* Initialize the text edit widget */
151 this->querystrings[WID_SIL_FILTER_TEXT] = &this->filter_editbox;
152 this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
153
154 /* Initialize the filtering variables */
155 this->SetFilterString("");
156
157 /* Create initial list. */
158 this->signs.ForceRebuild();
159 this->signs.ForceResort();
160 this->BuildSortSignList();
161 }
162
163 void OnInit() override
164 {
165 /* Default sign name, used if Sign::name is nullptr. */
166 SignList::default_name = GetString(STR_DEFAULT_SIGN_NAME);
167 this->signs.ForceResort();
168 this->SortSignsList();
169 this->SetDirty();
170 }
171
179 void SetFilterString(std::string_view new_filter_string)
180 {
181 /* check if there is a new filter string */
182 this->string_filter.SetFilterTerm(new_filter_string);
183
184 /* Rebuild the list of signs */
185 this->InvalidateData();
186 }
187
188 void OnPaint() override
189 {
190 if (!this->IsShaded() && this->signs.NeedRebuild()) this->BuildSortSignList();
191 this->DrawWidgets();
192 }
193
194 void DrawWidget(const Rect &r, WidgetID widget) const override
195 {
196 switch (widget) {
197 case WID_SIL_LIST: {
198 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
199 uint text_offset_y = (this->resize.step_height - GetCharacterHeight(FS_NORMAL) + 1) / 2;
200 /* No signs? */
201 if (this->vscroll->GetCount() == 0) {
202 DrawString(tr.left, tr.right, tr.top + text_offset_y, STR_STATION_LIST_NONE);
203 return;
204 }
205
206 Dimension d = GetSpriteSize(SPR_COMPANY_ICON);
207 bool rtl = _current_text_dir == TD_RTL;
208 int sprite_offset_y = (this->resize.step_height - d.height + 1) / 2;
209 uint icon_left = rtl ? tr.right - this->text_offset : tr.left;
210 tr = tr.Indent(this->text_offset, rtl);
211
212 /* At least one sign available. */
213 auto [first, last] = this->vscroll->GetVisibleRangeIterators(this->signs);
214 for (auto it = first; it != last; ++it) {
215 const Sign *si = *it;
216
217 if (si->owner != OWNER_NONE) DrawCompanyIcon(si->owner, icon_left, tr.top + sprite_offset_y);
218
219 DrawString(tr.left, tr.right, tr.top + text_offset_y, GetString(STR_SIGN_NAME, si->index), TC_YELLOW);
220 tr.top += this->resize.step_height;
221 }
222 break;
223 }
224 }
225 }
226
227 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
228 {
229 if (widget == WID_SIL_CAPTION) return GetString(STR_SIGN_LIST_CAPTION, this->vscroll->GetCount());
230
231 return this->Window::GetWidgetString(widget, stringid);
232 }
233
234 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
235 {
236 switch (widget) {
237 case WID_SIL_LIST: {
238 auto it = this->vscroll->GetScrolledItemFromWidget(this->signs, pt.y, this, WID_SIL_LIST, WidgetDimensions::scaled.framerect.top);
239 if (it == this->signs.end()) return;
240
241 const Sign *si = *it;
242 ScrollMainWindowToTile(TileVirtXY(si->x, si->y));
243 break;
244 }
245
247 SignList::match_case = !SignList::match_case; // Toggle match case
249 this->InvalidateData(); // Rebuild the list of signs
250 break;
251 }
252 }
253
254 void OnResize() override
255 {
256 this->vscroll->SetCapacityFromWidget(this, WID_SIL_LIST, WidgetDimensions::scaled.framerect.Vertical());
257 }
258
259 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
260 {
261 switch (widget) {
262 case WID_SIL_LIST: {
263 Dimension spr_dim = GetSpriteSize(SPR_COMPANY_ICON);
264 this->text_offset = WidgetDimensions::scaled.frametext.left + spr_dim.width + 2; // 2 pixels space between icon and the sign text.
265 fill.height = resize.height = std::max<uint>(GetCharacterHeight(FS_NORMAL), spr_dim.height + 2);
266 Dimension d = {(uint)(this->text_offset + WidgetDimensions::scaled.frametext.right), padding.height + 5 * resize.height};
267 size = maxdim(size, d);
268 break;
269 }
270
271 case WID_SIL_CAPTION:
272 size = GetStringBoundingBox(GetString(STR_SIGN_LIST_CAPTION, GetParamMaxValue(Sign::GetPoolSize(), 3)));
273 size.height += padding.height;
274 size.width += padding.width;
275 break;
276 }
277 }
278
279 void OnEditboxChanged(WidgetID widget) override
280 {
281 if (widget == WID_SIL_FILTER_TEXT) this->SetFilterString(this->filter_editbox.text.GetText());
282 }
283
284 void BuildSortSignList()
285 {
286 if (this->signs.NeedRebuild()) {
287 this->BuildSignsList();
288 this->vscroll->SetCount(this->signs.size());
290 }
291 this->SortSignsList();
292 }
293
295 const IntervalTimer<TimerWindow> rebuild_interval = {std::chrono::seconds(3), [this](auto) {
296 this->BuildSortSignList();
297 this->SetDirty();
298 }};
299
305 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
306 {
307 /* When there is a filter string, we always need to rebuild the list even if
308 * the amount of signs in total is unchanged, as the subset of signs that is
309 * accepted by the filter might has changed. */
310 if (data == 0 || data == -1 || !this->string_filter.IsEmpty()) { // New or deleted sign, changed visibility setting or there is a filter string
311 /* This needs to be done in command-scope to enforce rebuilding before resorting invalid data */
312 this->signs.ForceRebuild();
313 } else { // Change of sign contents while there is no filter string
314 this->signs.ForceResort();
315 }
316 }
317
324 {
325 if (_game_mode == GM_MENU) return ES_NOT_HANDLED;
326 Window *w = ShowSignList();
327 if (w == nullptr) return ES_NOT_HANDLED;
328 return w->OnHotkey(hotkey);
329 }
330
331 static inline HotkeyList hotkeys{"signlist", {
332 Hotkey('F', "focus_filter_box", WID_SIL_FILTER_TEXT),
334};
335
336static constexpr std::initializer_list<NWidgetPart> _nested_sign_list_widgets = {
338 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
339 NWidget(WWT_CAPTION, COLOUR_BROWN, WID_SIL_CAPTION),
340 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
341 NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
342 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
343 EndContainer(),
346 NWidget(WWT_PANEL, COLOUR_BROWN, WID_SIL_LIST), SetMinimalSize(WidgetDimensions::unscaled.frametext.Horizontal() + 16 + 255, 0),
349 NWidget(WWT_PANEL, COLOUR_BROWN), SetFill(1, 1),
350 NWidget(WWT_EDITBOX, COLOUR_BROWN, WID_SIL_FILTER_TEXT), SetMinimalSize(80, 0), SetResize(1, 0), SetFill(1, 0), SetPadding(2, 2, 2, 2),
351 SetStringTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
352 EndContainer(),
353 NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_SIL_FILTER_MATCH_CASE_BTN), SetStringTip(STR_SIGN_LIST_MATCH_CASE, STR_SIGN_LIST_MATCH_CASE_TOOLTIP),
354 EndContainer(),
355 EndContainer(),
358 NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
359 EndContainer(),
360 EndContainer(),
361};
362
363static WindowDesc _sign_list_desc(
364 WDP_AUTO, "list_signs", 358, 138,
366 {},
367 _nested_sign_list_widgets,
368 &SignListWindow::hotkeys
369);
370
377{
378 return AllocateWindowDescFront<SignListWindow>(_sign_list_desc, 0);
379}
380
388static bool RenameSign(SignID index, std::string_view text, Colours text_colour)
389{
390 bool remove = text.empty();
391 Command<Commands::RenameSign>::Post(remove ? STR_ERROR_CAN_T_DELETE_SIGN : STR_ERROR_CAN_T_CHANGE_SIGN_NAME, index, std::string{text}, text_colour);
392 return remove;
393}
394
400void MoveSign(SignID index, TileIndex tile)
401{
402 Command<Commands::MoveSign>::Post(STR_ERROR_CAN_T_PLACE_SIGN_HERE, index, tile);
403}
404
405struct SignWindow : Window, SignList {
406 QueryString name_editbox;
407 SignID cur_sign{};
409 std::optional<Colours> new_colour;
410
411 SignWindow(WindowDesc &desc, const Sign *si) : Window(desc), name_editbox(MAX_LENGTH_SIGN_NAME_CHARS * MAX_CHAR_LENGTH, MAX_LENGTH_SIGN_NAME_CHARS), cur_sign(si->index)
412 {
413 this->querystrings[WID_QES_TEXT] = &this->name_editbox;
414 this->name_editbox.caption = STR_EDIT_SIGN_CAPTION;
415 this->name_editbox.cancel_button = WID_QES_CANCEL;
416 this->name_editbox.ok_button = WID_QES_OK;
417
419
420 if (_game_mode != GameMode::GM_EDITOR) {
422 this->ReInit();
423 }
424
425 UpdateSignEditWindow(si);
427 }
428
429 void UpdateSignEditWindow(const Sign *si)
430 {
431 /* Display an empty string when the sign hasn't been edited yet */
432 if (!si->name.empty()) {
433 this->name_editbox.text.Assign(GetString(STR_SIGN_NAME, si->index));
434 } else {
435 this->name_editbox.text.DeleteAll();
436 }
437
438 this->cur_sign = si->index;
439 this->new_colour.reset();
440
444 }
445
451 const Sign *PrevNextSign(bool next)
452 {
453 /* Rebuild the sign list */
454 this->signs.ForceRebuild();
455 this->signs.NeedResort();
456 this->BuildSignsList();
457 this->SortSignsList();
458
459 /* Search through the list for the current sign, excluding
460 * - the first sign if we want the previous sign or
461 * - the last sign if we want the next sign */
462 size_t end = this->signs.size() - (next ? 1 : 0);
463 for (uint i = next ? 0 : 1; i < end; i++) {
464 if (this->cur_sign == this->signs[i]->index) {
465 /* We've found the current sign, so return the sign before/after it */
466 return this->signs[i + (next ? 1 : -1)];
467 }
468 }
469 /* If we haven't found the current sign by now, return the last/first sign */
470 return next ? this->signs.front() : this->signs.back();
471 }
472
473 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
474 {
475 switch (widget) {
476 case WID_QES_CAPTION:
477 return GetString(this->name_editbox.caption);
478
479 case WID_QES_COLOUR:
480 return GetString(STR_COLOUR_DARK_BLUE + this->new_colour.value_or(Sign::Get(this->cur_sign)->text_colour));
481
482 default:
483 return this->Window::GetWidgetString(widget, stringid);
484 }
485 }
486
487 void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
488 {
489 if (widget == WID_QES_COLOUR) {
490 const Dimension square_size = GetSpriteSize(SPR_SQUARE);
491 const uint string_padding = square_size.width + WidgetDimensions::scaled.hsep_normal + padding.width;
492 for (Colours colour = COLOUR_BEGIN; colour != COLOUR_END; ++colour) {
493 size.width = std::max(size.width, GetStringBoundingBox(STR_COLOUR_DARK_BLUE + colour).width + string_padding);
494 }
495 size.width = std::max(size.width, GetStringBoundingBox(STR_COLOUR_DEFAULT).width + string_padding);
496 return;
497 }
498
499 Window::UpdateWidgetSize(widget, size, padding, fill, resize);
500 }
501
502 void ShowColourDropDownMenu()
503 {
504 DropDownList list;
505 for (Colours colour = COLOUR_BEGIN; colour != COLOUR_END; ++colour) {
506 list.emplace_back(MakeDropDownListIconItem(SPR_SQUARE, GetColourPalette(colour), STR_COLOUR_DARK_BLUE + colour, colour));
507 }
508 const int selected = this->new_colour.value_or(Sign::Get(this->cur_sign)->text_colour);
509 ShowDropDownList(this, std::move(list), selected, WID_QES_COLOUR);
510 }
511
512 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
513 {
514 switch (widget) {
515 case WID_QES_COLOUR: {
516 ShowColourDropDownMenu();
517 break;
518 }
519
520 case WID_QES_LOCATION: {
521 const Sign *si = Sign::Get(this->cur_sign);
522 TileIndex tile = TileVirtXY(si->x, si->y);
523 if (_ctrl_pressed) {
525 } else {
527 }
528 break;
529 }
530
531 case WID_QES_PREVIOUS:
532 case WID_QES_NEXT: {
533 const Sign *si = this->PrevNextSign(widget == WID_QES_NEXT);
534
535 /* Rebuild the sign list */
536 this->signs.ForceRebuild();
537 this->signs.NeedResort();
538 this->BuildSignsList();
539 this->SortSignsList();
540
541 /* Scroll to sign and reopen window */
542 ScrollMainWindowToTile(TileVirtXY(si->x, si->y));
543 UpdateSignEditWindow(si);
544 break;
545 }
546
547 case WID_QES_OK:
548 if (RenameSign(this->cur_sign, this->name_editbox.text.GetText(), this->new_colour.value_or(INVALID_COLOUR))) break;
549 [[fallthrough]];
550
551 case WID_QES_CANCEL:
552 this->Close();
553 break;
554
555 case WID_QES_DELETE:
556 /* Only need to set the buffer to null, the rest is handled as the OK button */
557 RenameSign(this->cur_sign, "", INVALID_COLOUR);
558 /* don't delete this, we are deleted in Sign::~Sign() -> DeleteRenameSignWindow() */
559 break;
560
561 case WID_QES_MOVE:
562 HandlePlacePushButton(this, WID_QES_MOVE, SPR_CURSOR_SIGN, HT_RECT);
563 this->last_user_action = widget;
564 break;
565 }
566 }
567
568 void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
569 {
570 switch (this->last_user_action) {
571 case WID_QES_MOVE: // Place sign button
572 RenameSign(this->cur_sign, this->name_editbox.text.GetText(), this->new_colour.value_or(INVALID_COLOUR));
573 MoveSign(this->cur_sign, tile);
574 this->Close();
575 break;
576
577 default: NOT_REACHED();
578 }
579 }
580
581 void OnPlaceObjectAbort() override
582 {
583 this->RaiseButtons();
584 }
585
586 void OnDropdownSelect(WidgetID widget, int index, int) override
587 {
588 if (widget == WID_QES_COLOUR) this->new_colour = static_cast<Colours>(index);
589 }
590};
591
592static constexpr std::initializer_list<NWidgetPart> _nested_query_sign_edit_widgets = {
594 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
595 NWidget(WWT_CAPTION, COLOUR_GREY, WID_QES_CAPTION), SetTextStyle(TC_WHITE),
596 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_QES_LOCATION), SetAspect(WidgetDimensions::ASPECT_LOCATION), SetSpriteTip(SPR_GOTO_LOCATION, STR_EDIT_SIGN_LOCATION_TOOLTIP),
597 EndContainer(),
598 NWidget(WWT_PANEL, COLOUR_GREY),
599 NWidget(WWT_EDITBOX, COLOUR_GREY, WID_QES_TEXT), SetMinimalSize(256, 0), SetStringTip(STR_EDIT_SIGN_SIGN_OSKTITLE), SetPadding(2, 2, 2, 2),
600 EndContainer(),
602 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_QES_OK), SetMinimalSize(61, 12), SetStringTip(STR_BUTTON_OK),
603 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_QES_CANCEL), SetMinimalSize(60, 12), SetStringTip(STR_BUTTON_CANCEL),
604 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_QES_DELETE), SetMinimalSize(60, 12), SetStringTip(STR_TOWN_VIEW_DELETE_BUTTON),
605 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_QES_MOVE), SetMinimalSize(60, 12), SetStringTip(STR_BUTTON_MOVE),
607 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_QES_COLOUR), SetMinimalSize(60, 12), SetToolTip(STR_EDIT_SIGN_TEXT_COLOUR_TOOLTIP),
608 EndContainer(),
609 NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 1), EndContainer(),
610 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_QES_PREVIOUS), SetMinimalSize(11, 12), SetArrowWidgetTypeTip(AWV_DECREASE, STR_EDIT_SIGN_PREVIOUS_SIGN_TOOLTIP),
611 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_QES_NEXT), SetMinimalSize(11, 12), SetArrowWidgetTypeTip(AWV_INCREASE, STR_EDIT_SIGN_NEXT_SIGN_TOOLTIP),
612 EndContainer(),
613};
614
615static WindowDesc _query_sign_edit_desc(
616 WDP_CENTER, {}, 0, 0,
619 _nested_query_sign_edit_widgets
620);
621
626void HandleClickOnSign(const Sign *si)
627{
628 /* If we can't edit the sign, don't even open the rename GUI. */
629 if (!CompanyCanEditSign(si)) return;
630
631 if (_ctrl_pressed && (si->owner == _local_company || (si->owner == OWNER_DEITY && _game_mode == GM_EDITOR))) {
632 RenameSign(si->index, "", INVALID_COLOUR);
633 return;
634 }
635
637}
638
644{
645 /* Delete all other edit windows */
647
648 new SignWindow(_query_sign_edit_desc, si);
649}
650
656{
658
659 if (w != nullptr && w->cur_sign == sign) w->Close();
660}
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
List template of 'things' T to sort in a GUI.
bool Filter(FilterFunction *decide, F filter_data)
Filter the list.
void RebuildDone()
Notify the sortlist that the rebuild is done.
void SetFilterState(bool state)
Enable or disable the filter.
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.
bool NeedResort()
Check if a resort is needed next loop If used the resort timer will decrease every call till 0.
An interval timer will fire every interval, and will continue to fire until it is deleted.
Definition timer.h:76
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:2504
size_type GetCount() const
Gets the number of elements in the list.
auto GetVisibleRangeIterators(Tcontainer &container) const
Get a pair of iterators for the range of visible elements in a container.
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:30
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:93
Functions related to commands.
void DrawCompanyIcon(CompanyID c, int x, int y)
Draw the icon of a company.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Functions related to companies.
GUI Functions related to companies.
static constexpr Owner OWNER_DEITY
The object is owned by a superuser / goal script.
static constexpr Owner OWNER_NONE
The tile has no ownership.
Functions related to debugging.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
std::unique_ptr< DropDownListItem > MakeDropDownListIconItem(SpriteID sprite, PaletteID palette, StringID str, int value, bool masked, bool shaded)
Creates new DropDownListIconItem.
Definition dropdown.cpp:70
void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID button, uint width, DropDownOptions options, std::string *const persistent_filter_text)
Show a drop down list.
Definition dropdown.cpp:585
Common drop down list components.
Functions related to the drop down widget.
std::vector< std::unique_ptr< const DropDownListItem > > DropDownList
A drop down list is a collection of drop down list items.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:87
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:972
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:900
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:669
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:39
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:249
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 SetPadding(uint8_t top, uint8_t right, uint8_t bottom, uint8_t left)
Widget part function for setting additional space around 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 SetTextStyle(TextColour colour, FontSize size=FS_NORMAL)
Widget part function for setting the text style.
constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
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 SetArrowWidgetTypeTip(ArrowWidgetValues widget_type, StringID tip={})
Widget part function for setting the arrow widget type and tooltip.
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=INVALID_WIDGET)
Widget part function for starting a new 'real' widget.
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
void SetDirty() const
Mark entire window as dirty (in need of re-paint).
Definition window.cpp:980
GUI functions that shouldn't be here.
void ShowExtraViewportWindow(TileIndex tile=INVALID_TILE)
Show a new Extra Viewport window.
Hotkey related functions.
#define Point
Macro that prevents name conflicts between included headers.
bool HandlePlacePushButton(Window *w, WidgetID widget, CursorID cursor, HighLightStyle mode)
This code is shared for the majority of the pushbuttons.
Definition main_gui.cpp:63
Functions related to maps.
static TileIndex TileVirtXY(uint x, uint y)
Get a tile from the virtual XY-coordinate.
Definition map_func.h:407
@ DO_SHOW_COMPETITOR_SIGNS
Display signs, station names and waypoint names of opponent companies. Buoys and oilrig-stations are ...
Definition openttd.h:52
Base for the GUIs that have an edit box in them.
A number of safeguards to prevent using unsafe methods.
Types related to the sign widgets.
@ WID_QES_PREVIOUS
Previous button.
Definition sign_widget.h:34
@ WID_QES_MOVE
Move Sign button.
Definition sign_widget.h:33
@ WID_QES_LOCATION
Scroll to sign location.
Definition sign_widget.h:26
@ WID_QES_CANCEL
Cancel button.
Definition sign_widget.h:29
@ WID_QES_OK
OK button.
Definition sign_widget.h:28
@ WID_QES_COLOUR_PANE
Pane to show/hide the color dropdown.
Definition sign_widget.h:31
@ WID_QES_COLOUR
Colour selection dropdown.
Definition sign_widget.h:32
@ WID_QES_NEXT
Next button.
Definition sign_widget.h:35
@ WID_QES_DELETE
Delete button.
Definition sign_widget.h:30
@ WID_QES_TEXT
Text of the query.
Definition sign_widget.h:27
@ WID_QES_CAPTION
Caption of the window.
Definition sign_widget.h:25
@ WID_SIL_SCROLLBAR
Scrollbar of list.
Definition sign_widget.h:18
@ WID_SIL_FILTER_MATCH_CASE_BTN
Button to toggle if case sensitive filtering should be used.
Definition sign_widget.h:20
@ WID_SIL_FILTER_TEXT
Text box for typing a filter string.
Definition sign_widget.h:19
@ WID_SIL_CAPTION
Caption of the window.
Definition sign_widget.h:16
@ WID_SIL_LIST
List of signs.
Definition sign_widget.h:17
bool CompanyCanEditSign(const Sign *si)
Check if the current company can rename or move a given sign.
Definition signs.cpp:62
Base class for signs.
Command definitions related to signs.
Functions related to signs.
void HandleClickOnSign(const Sign *si)
Handle clicking on a sign.
void DeleteRenameSignWindow(SignID sign)
Close the sign window associated with the given sign.
void MoveSign(SignID index, TileIndex tile)
Actually move the sign.
static bool RenameSign(SignID index, std::string_view text, Colours text_colour)
Actually rename the sign.
void ShowRenameSignWindow(const Sign *si)
Show the window to change the text of a sign.
Window * ShowSignList()
Open the sign list window.
PoolID< uint16_t, struct SignIDTag, 64000, 0xFFFF > SignID
The type of the IDs of signs.
Definition signs_type.h:16
static const uint MAX_LENGTH_SIGN_NAME_CHARS
The maximum length of a sign name in characters including '\0'.
Definition signs_type.h:20
Base types for having sorted lists in GUIs.
static PaletteID GetColourPalette(Colours colour)
Get recolour palette for a colour.
Definition sprite.h:221
This file contains all sprite-related enums and defines.
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:429
Functions related to low-level strings.
Searching and filtering using a stringterm.
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:236
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:56
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.
static const int MAX_CHAR_LENGTH
Max. length of UTF-8 encoded unicode character.
Dimensions (a width and height) of a rectangle in 2D.
List of hotkeys for a window.
Definition hotkeys.h:46
All data for a single hotkey.
Definition hotkeys.h:22
static Pool::IterateWrapper< Sign > Iterate(size_t from=0)
static Sign * Get(auto index)
Data stored about a string that can be modified in the GUI.
int ok_button
Widget button of parent window to simulate when pressing OK in OSK.
int cancel_button
Widget button of parent window to simulate when pressing CANCEL in OSK.
static const int ACTION_CLEAR
Clear editbox.
Specification of a rectangle with absolute coordinates of all edges.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
Rect Indent(int indent, bool end) const
Copy Rect and indent it from its position.
const IntervalTimer< TimerWindow > rebuild_interval
Resort the sign listing on a regular interval.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
void OnEditboxChanged(WidgetID widget) override
The text in an editbox has been edited.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
int text_offset
Offset of the sign text relative to the left edge of the WID_SIL_LIST widget.
QueryString filter_editbox
Filter editbox;.
void OnPaint() override
The window must be repainted.
void OnInit() override
Notification that the nested widget tree gets initialized.
static EventState SignListGlobalHotkeys(int hotkey)
Handler for global hotkeys of the SignListWindow.
void SetFilterString(std::string_view new_filter_string)
This function sets the filter string of the sign 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.
void OnResize() override
Called after the window got resized.
GUIList< const Sign *, std::nullptr_t, StringFilter & > GUISignList
A GUIList contains signs and uses a StringFilter for filtering.
Definition signs_gui.cpp:47
static bool SignNameFilter(const Sign *const *item, StringFilter &filter)
Filter sign list by sign name.
Definition signs_gui.cpp:99
static bool SignNameSorter(const Sign *const &a, const Sign *const &b)
Sort signs by their name.
Definition signs_gui.cpp:79
SignList()
Creates a SignList with filtering disabled by default.
Definition signs_gui.cpp:58
void FilterSignList()
Filter out signs from the sign list that does not match the name filter.
static bool match_case
Should case sensitive matching be used?
Definition signs_gui.cpp:52
static bool OwnerVisibilityFilter(const Sign *const *item, StringFilter &filter)
Filter sign list by owner.
static std::string default_name
Default sign name, used if Sign::name is nullptr.
Definition signs_gui.cpp:53
StringFilter string_filter
The match string to be used when the GUIList is (re)-sorted.
Definition signs_gui.cpp:51
static bool OwnerDeityFilter(const Sign *const *item, StringFilter &filter)
Filter sign list excluding OWNER_DEITY.
void OnPlaceObject(Point pt, TileIndex tile) override
The user clicked some place on the map when a tile highlight mode has been set.
std::optional< Colours > new_colour
New colour selected by the user. Will be assigned when the OK button is clicked.
void OnPlaceObjectAbort() override
The user cancelled a tile highlight mode that has been set.
void OnDropdownSelect(WidgetID widget, int index, int) override
A dropdown option associated to this window has been selected.
const Sign * PrevNextSign(bool next)
Returns a pointer to the (alphabetically) previous or next sign of the current sign.
WidgetID last_user_action
Last started user action.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
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.
Owner owner
Placed by this company. Anyone can delete them though. OWNER_NONE for gray signs from old games.
Definition signs_base.h:27
String filter and state.
bool IsEmpty() const
Check whether any filter words were entered.
void SetFilterTerm(std::string_view str)
Set the term to filter on.
void ResetState()
Reset the matching state to process a new item.
bool GetState() const
Get the matching state of the current item.
std::string_view GetText() const
Get the current text.
Definition textbuf.cpp:284
void Assign(std::string_view text)
Copy a string into the textbuffer.
Definition textbuf.cpp:420
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
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition window.cpp:992
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1117
virtual void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize)
Update size and resize step of a widget in the window.
Definition window_gui.h:624
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1822
std::map< WidgetID, QueryString * > querystrings
QueryString associated to WWT_EDITBOX widgets.
Definition window_gui.h:321
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:768
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing).
Definition window.cpp:3261
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:570
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:518
ResizeInfo resize
Resize information.
Definition window_gui.h:315
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1812
bool SetFocusedWidget(WidgetID widget_index)
Set focus within this window to the given widget.
Definition window.cpp:499
void RaiseButtons(bool autoraise=false)
Raise the buttons of the window.
Definition window.cpp:544
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition window_gui.h:442
bool IsShaded() const
Is window shaded currently?
Definition window_gui.h:563
Window(WindowDesc &desc)
Empty constructor, initialization has been moved to InitNested() called from the constructor of the d...
Definition window.cpp:1845
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:990
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition window.cpp:1835
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:327
virtual EventState OnHotkey(int hotkey)
A hotkey has been pressed.
Definition window.cpp:584
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
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
Definition tile_type.h:92
Functions related to tile highlights.
@ HT_RECT
rectangle (stations, depots, ...)
Definition of Interval and OneShot timers.
Definition of the Window system.
Functions related to transparency.
uint8_t _display_opt
What do we want to draw/do?
bool ScrollMainWindowToTile(TileIndex tile, bool instant)
Scrolls the viewport of the main window to a given location.
Functions related to (drawing on) viewports.
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
@ WWT_PUSHIMGBTN
Normal push-button (no toggle button) with image caption.
@ WWT_PUSHARROWBTN
Normal push-button (no toggle button) with arrow caption.
@ WWT_EDITBOX
a textbox for typing
Definition widget_type.h:62
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:66
@ WWT_TEXTBTN
(Toggle) Button with text
Definition widget_type.h:44
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:39
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX).
Definition widget_type.h:57
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX).
Definition widget_type.h:55
@ WWT_CAPTION
Window caption (window title between closebox and stickybox).
Definition widget_type.h:52
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:76
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:68
@ WWT_CLOSEBOX
Close box (at top-left of a window).
Definition widget_type.h:60
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window).
Definition widget_type.h:59
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX).
Definition widget_type.h:56
@ WWT_DROPDOWN
Drop down list.
Definition widget_type.h:61
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:71
@ SZSP_VERTICAL
Display plane with zero size horizontally, and filling and resizing vertically.
@ AWV_DECREASE
Arrow to the left or in case of RTL to the right.
Definition widget_type.h:20
@ AWV_INCREASE
Arrow to the right or in case of RTL to the left.
Definition widget_type.h:21
void CloseWindowByClass(WindowClass cls, int data)
Close all windows of a given class.
Definition window.cpp:1222
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition window.cpp:1166
Window functions not directly related to making/drawing windows.
@ Construction
This window is used for construction; close it whenever changing company.
Definition window_gui.h:153
Twindow * AllocateWindowDescFront(WindowDesc &desc, WindowNumber window_number, Targs... extra_arguments)
Open a new window.
@ WDP_CENTER
Center the window.
Definition window_gui.h:145
@ WDP_AUTO
Find a place automatically.
Definition window_gui.h:144
int WidgetID
Widget ID.
Definition window_type.h:20
@ WN_QUERY_STRING_SIGN
Query string for signs.
Definition window_type.h:35
EventState
State of handling an event.
@ ES_NOT_HANDLED
The passed event is not handled.
static constexpr WidgetID INVALID_WIDGET
An invalid widget index.
Definition window_type.h:23
@ WC_SIGN_LIST
Sign list; Window numbers:
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:50
@ WC_QUERY_STRING
Query string window; Window numbers: