OpenTTD Source 20250318-master-gb98a7ff303
misc_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 "debug.h"
12#include "landscape.h"
13#include "error.h"
14#include "gui.h"
15#include "gfx_layout.h"
16#include "command_func.h"
17#include "company_func.h"
18#include "town.h"
19#include "string_func.h"
20#include "company_base.h"
21#include "texteff.hpp"
22#include "strings_func.h"
23#include "window_func.h"
24#include "querystring_gui.h"
26#include "newgrf_debug.h"
27#include "zoom_func.h"
28#include "viewport_func.h"
29#include "landscape_cmd.h"
30#include "rev.h"
31#include "timer/timer.h"
32#include "timer/timer_window.h"
34
35#include "widgets/misc_widget.h"
36
37#include "table/strings.h"
38
39#include <sstream>
40#include <iomanip>
41
42#include "safeguards.h"
43
51
52
53static constexpr NWidgetPart _nested_land_info_widgets[] = {
55 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
56 NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_LAND_AREA_INFORMATION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
57 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_LI_LOCATION), SetAspect(WidgetDimensions::ASPECT_LOCATION), SetSpriteTip(SPR_GOTO_LOCATION, STR_LAND_AREA_INFORMATION_LOCATION_TOOLTIP),
58 NWidget(WWT_DEBUGBOX, COLOUR_GREY),
61};
62
63static WindowDesc _land_info_desc(
64 WDP_AUTO, nullptr, 0, 0,
66 {},
67 _nested_land_info_widgets
68);
69
70class LandInfoWindow : public Window {
72 std::string cargo_acceptance{};
73
74public:
76
77 void DrawWidget(const Rect &r, WidgetID widget) const override
78 {
79 if (widget != WID_LI_BACKGROUND) return;
80
82 for (size_t i = 0; i < this->landinfo_data.size(); i++) {
83 DrawString(ir, this->landinfo_data[i], i == 0 ? TC_LIGHT_BLUE : TC_FROMSTRING, SA_HOR_CENTER);
85 }
86
87 if (!this->cargo_acceptance.empty()) {
89 }
90 }
91
93 {
94 if (widget != WID_LI_BACKGROUND) return;
95
97 for (size_t i = 0; i < this->landinfo_data.size(); i++) {
99 size.width = std::max(size.width, width);
100
102 }
103
104 if (!this->cargo_acceptance.empty()) {
106 size.width = std::max(size.width, std::min(static_cast<uint>(ScaleGUITrad(300)), width));
108 }
109 }
110
111 LandInfoWindow(Tile tile) : Window(_land_info_desc), tile(tile)
112 {
113 this->InitNested();
114
115#if defined(_DEBUG)
116# define LANDINFOD_LEVEL 0
117#else
118# define LANDINFOD_LEVEL 1
119#endif
120 Debug(misc, LANDINFOD_LEVEL, "TILE: {0} (0x{0:x}) ({1},{2})", (TileIndex)tile, TileX(tile), TileY(tile));
121 Debug(misc, LANDINFOD_LEVEL, "type = 0x{:x}", tile.type());
122 Debug(misc, LANDINFOD_LEVEL, "height = 0x{:x}", tile.height());
123 Debug(misc, LANDINFOD_LEVEL, "m1 = 0x{:x}", tile.m1());
124 Debug(misc, LANDINFOD_LEVEL, "m2 = 0x{:x}", tile.m2());
125 Debug(misc, LANDINFOD_LEVEL, "m3 = 0x{:x}", tile.m3());
126 Debug(misc, LANDINFOD_LEVEL, "m4 = 0x{:x}", tile.m4());
127 Debug(misc, LANDINFOD_LEVEL, "m5 = 0x{:x}", tile.m5());
128 Debug(misc, LANDINFOD_LEVEL, "m6 = 0x{:x}", tile.m6());
129 Debug(misc, LANDINFOD_LEVEL, "m7 = 0x{:x}", tile.m7());
130 Debug(misc, LANDINFOD_LEVEL, "m8 = 0x{:x}", tile.m8());
131
132 PrintWaterRegionDebugInfo(tile);
133#undef LANDINFOD_LEVEL
134 }
135
136 void OnInit() override
137 {
139
140 TileDesc td{};
141 td.owner_type[0] = STR_LAND_AREA_INFORMATION_OWNER; // At least one owner is displayed, though it might be "N/A".
142
143 CargoArray acceptance{};
144 AddAcceptedCargo(tile, acceptance, nullptr);
145 GetTileDesc(tile, td);
146
147 this->landinfo_data.clear();
148
149 /* Tiletype */
150 this->landinfo_data.push_back(GetString(td.str, td.dparam));
151
152 /* Up to four owners */
153 for (uint i = 0; i < 4; i++) {
154 if (td.owner_type[i] == STR_NULL) continue;
155
156 if (td.owner[i] == OWNER_NONE || td.owner[i] == OWNER_WATER) {
157 this->landinfo_data.push_back(GetString(td.owner_type[i], STR_LAND_AREA_INFORMATION_OWNER_N_A, std::monostate{}));
158 } else {
159 auto params = GetParamsForOwnedBy(td.owner[i], tile);
160 this->landinfo_data.push_back(GetStringWithArgs(td.owner_type[i], params));
161 }
162 }
163
164 /* Cost to clear/revenue when cleared */
166 if (c != nullptr) {
169 if (costclear.Succeeded()) {
170 Money cost = costclear.GetCost();
171 StringID str;
172 if (cost < 0) {
173 cost = -cost; // Negate negative cost to a positive revenue
175 } else {
177 }
178 this->landinfo_data.push_back(GetString(str, cost));
179 } else {
181 }
182 } else {
184 }
185
186 /* Location */
188
189 /* Tile index */
191
192 /* Local authority */
193 if (t == nullptr) {
195 } else {
197 }
198
199 /* Build date */
200 if (td.build_date != CalendarTime::INVALID_DATE) {
201 this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_BUILD_DATE, td.build_date));
202 }
203
204 /* Station class */
205 if (td.station_class != STR_NULL) {
206 this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_STATION_CLASS, td.station_class));
207 }
208
209 /* Station type name */
210 if (td.station_name != STR_NULL) {
211 this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_STATION_TYPE, td.station_name));
212 }
213
214 /* Airport class */
215 if (td.airport_class != STR_NULL) {
216 this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_AIRPORT_CLASS, td.airport_class));
217 }
218
219 /* Airport name */
220 if (td.airport_name != STR_NULL) {
221 this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_AIRPORT_NAME, td.airport_name));
222 }
223
224 /* Airport tile name */
225 if (td.airport_tile_name != STR_NULL) {
226 this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_AIRPORTTILE_NAME, td.airport_tile_name));
227 }
228
229 /* Rail type name */
230 if (td.railtype != STR_NULL) {
231 this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_RAIL_TYPE, td.railtype));
232 }
233
234 /* Rail speed limit */
235 if (td.rail_speed != 0) {
237 }
238
239 /* Road type name */
240 if (td.roadtype != STR_NULL) {
241 this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_ROAD_TYPE, td.roadtype));
242 }
243
244 /* Road speed limit */
245 if (td.road_speed != 0) {
247 }
248
249 /* Tram type name */
250 if (td.tramtype != STR_NULL) {
251 this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_TRAM_TYPE, td.tramtype));
252 }
253
254 /* Tram speed limit */
255 if (td.tram_speed != 0) {
257 }
258
259 /* Tile protection status */
260 if (td.town_can_upgrade.has_value()) {
262 }
263
264 /* NewGRF name */
265 if (td.grf != nullptr) {
267 }
268
269 /* Cargo acceptance is displayed in a extra multiline */
271 if (line.has_value()) {
272 this->cargo_acceptance = std::move(*line);
273 } else {
274 this->cargo_acceptance.clear();
275 }
276 }
277
278 bool IsNewGRFInspectable() const override
279 {
280 return ::IsNewGRFInspectable(GetGrfSpecFeature(this->tile), this->tile.base());
281 }
282
283 void ShowNewGRFInspectWindow() const override
284 {
285 ::ShowNewGRFInspectWindow(GetGrfSpecFeature(this->tile), this->tile.base());
286 }
287
288 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
289 {
290 switch (widget) {
291 case WID_LI_LOCATION:
292 if (_ctrl_pressed) {
293 ShowExtraViewportWindow(this->tile);
294 } else {
295 ScrollMainWindowToTile(this->tile);
296 }
297 break;
298 }
299 }
300
306 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
307 {
308 if (!gui_scope) return;
309
310 /* ReInit, "debug" sprite might have changed */
311 if (data == 1) this->ReInit();
312 }
313};
314
320{
322 new LandInfoWindow(tile);
323}
324
325static constexpr NWidgetPart _nested_about_widgets[] = {
327 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
328 NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_ABOUT_OPENTTD, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
329 EndContainer(),
330 NWidget(WWT_PANEL, COLOUR_GREY), SetPIP(4, 2, 4),
331 NWidget(WWT_LABEL, INVALID_COLOUR), SetStringTip(STR_ABOUT_ORIGINAL_COPYRIGHT),
332 NWidget(WWT_LABEL, INVALID_COLOUR), SetStringTip(STR_ABOUT_VERSION),
333 NWidget(WWT_FRAME, COLOUR_GREY), SetPadding(0, 5, 1, 5),
334 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_A_SCROLLING_TEXT),
335 EndContainer(),
336 NWidget(WWT_LABEL, INVALID_COLOUR, WID_A_WEBSITE),
337 NWidget(WWT_LABEL, INVALID_COLOUR, WID_A_COPYRIGHT),
338 EndContainer(),
339};
340
341static WindowDesc _about_desc(
342 WDP_CENTER, nullptr, 0, 0,
344 {},
345 _nested_about_widgets
346);
347
348static const std::initializer_list<const std::string_view> _credits = {
349 "Original design by Chris Sawyer",
350 "Original graphics by Simon Foster",
351 "",
352 "The OpenTTD team (in alphabetical order):",
353 " Matthijs Kooijman (blathijs) - Pathfinder-guru, Debian port (since 0.3)",
354 " Christoph Elsenhans (frosch) - General coding (since 0.6)",
355 " Lo\u00efc Guilloux (glx) - General / Windows Expert (since 0.4.5)",
356 " Koen Bussemaker (Kuhnovic) - General / Ship pathfinder (since 14)",
357 " Charles Pigott (LordAro) - General / Correctness police (since 1.9)",
358 " Michael Lutz (michi_cc) - Path based signals (since 0.7)",
359 " Niels Martin Hansen (nielsm) - Music system, general coding (since 1.9)",
360 " Owen Rudge (orudge) - Forum host, OS/2 port (since 0.1)",
361 " Peter Nelson (peter1138) - Spiritual descendant from NewGRF gods (since 0.4.5)",
362 " Remko Bijker (Rubidium) - Coder and way more (since 0.4.5)",
363 " Patric Stout (TrueBrain) - NoProgrammer (since 0.3), sys op",
364 " Tyler Trahan (2TallTyler) - General / Time Lord (since 13)",
365 " Richard Wheeler (zephyris) - Precision pixel production (since 15)",
366 "",
367 "Inactive Developers:",
368 " Grzegorz Duczy\u0144ski (adf88) - General coding (1.7 - 1.8)",
369 " Albert Hofkamp (Alberth) - GUI expert (0.7 - 1.9)",
370 " Jean-Fran\u00e7ois Claeys (Belugas) - GUI, NewGRF and more (0.4.5 - 1.0)",
371 " Bjarni Corfitzen (Bjarni) - MacOSX port, coder and vehicles (0.3 - 0.7)",
372 " Victor Fischer (Celestar) - Programming everywhere you need him to (0.3 - 0.6)",
373 " Ulf Hermann (fonsinchen) - Cargo Distribution (1.3 - 1.6)",
374 " Jaroslav Mazanec (KUDr) - YAPG (Yet Another Pathfinder God) ;) (0.4.5 - 0.6)",
375 " Jonathan Coome (Maedhros) - High priest of the NewGRF Temple (0.5 - 0.6)",
376 " Attila B\u00e1n (MiHaMiX) - Developer WebTranslator 1 and 2 (0.3 - 0.5)",
377 " Ingo von Borstel (planetmaker) - General coding, Support (1.1 - 1.9)",
378 " Zden\u011bk Sojka (SmatZ) - Bug finder and fixer (0.6 - 1.3)",
379 " Jos\u00e9 Soler (Terkhen) - General coding (1.0 - 1.4)",
380 " Christoph Mallon (Tron) - Programmer, code correctness police (0.3 - 0.5)",
381 " Thijs Marinussen (Yexo) - AI Framework, General (0.6 - 1.3)",
382 " Leif Linse (Zuu) - AI/Game Script (1.2 - 1.6)",
383 "",
384 "Retired Developers:",
385 " Tam\u00e1s Farag\u00f3 (Darkvater) - Ex-Lead coder (0.3 - 0.5)",
386 " Dominik Scherer (dominik81) - Lead programmer, GUI expert (0.3 - 0.3)",
387 " Emil Djupfeld (egladil) - MacOSX (0.4.5 - 0.6)",
388 " Simon Sasburg (HackyKid) - Many bugfixes (0.4 - 0.4.5)",
389 " Ludvig Strigeus (ludde) - Original author of OpenTTD, main coder (0.1 - 0.3)",
390 " Cian Duffy (MYOB) - BeOS port / manual writing (0.1 - 0.3)",
391 " Petr Baudi\u0161 (pasky) - Many patches, NewGRF support (0.3 - 0.3)",
392 " Benedikt Br\u00fcggemeier (skidd13) - Bug fixer and code reworker (0.6 - 0.7)",
393 " Serge Paquet (vurlix) - 2nd contributor after ludde (0.1 - 0.3)",
394 "",
395 "Special thanks go out to:",
396 " Josef Drexler - For his great work on TTDPatch",
397 " Marcin Grzegorczyk - Track foundations and for describing TTD internals",
398 " Stefan Mei\u00dfner (sign_de) - For his work on the console",
399 " Mike Ragsdale - OpenTTD installer",
400 " Christian Rosentreter (tokai) - MorphOS / AmigaOS port",
401 " Richard Kempton (richK) - additional airports, initial TGP implementation",
402 " Alberto Demichelis - Squirrel scripting language \u00a9 2003-2008",
403 " L. Peter Deutsch - MD5 implementation \u00a9 1999, 2000, 2002",
404 " Michael Blunck - Pre-signals and semaphores \u00a9 2003",
405 " George - Canal/Lock graphics \u00a9 2003-2004",
406 " Andrew Parkhouse (andythenorth) - River graphics",
407 " David Dallaston (Pikka) - Tram tracks",
408 " All Translators - Who made OpenTTD a truly international game",
409 " Bug Reporters - Without whom OpenTTD would still be full of bugs!",
410 "",
411 "",
412 "And last but not least:",
413 " Chris Sawyer - For an amazing game!"
414};
415
416struct AboutWindow : public Window {
418 int line_height = 0;
419 static const int num_visible_lines = 19;
420
421 AboutWindow() : Window(_about_desc)
422 {
424
425 this->text_position = this->GetWidget<NWidgetBase>(WID_A_SCROLLING_TEXT)->pos_y + this->GetWidget<NWidgetBase>(WID_A_SCROLLING_TEXT)->current_y;
426 }
427
428 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
429 {
430 if (widget == WID_A_WEBSITE) return "Website: https://www.openttd.org";
431 if (widget == WID_A_COPYRIGHT) return GetString(STR_ABOUT_COPYRIGHT_OPENTTD, _openttd_revision_year);
432 return this->Window::GetWidgetString(widget, stringid);
433 }
434
436 {
437 if (widget != WID_A_SCROLLING_TEXT) return;
438
439 this->line_height = GetCharacterHeight(FS_NORMAL);
440
441 Dimension d;
442 d.height = this->line_height * num_visible_lines;
443
444 d.width = 0;
445 for (const auto &str : _credits) {
446 d.width = std::max(d.width, GetStringBoundingBox(str).width);
447 }
448 size = maxdim(size, d);
449 }
450
451 void DrawWidget(const Rect &r, WidgetID widget) const override
452 {
453 if (widget != WID_A_SCROLLING_TEXT) return;
454
455 int y = this->text_position;
456
457 /* Show all scrolling _credits */
458 for (const auto &str : _credits) {
459 if (y >= r.top + 7 && y < r.bottom - this->line_height) {
460 DrawString(r.left, r.right, y, str, TC_BLACK, SA_LEFT | SA_FORCE);
461 }
462 y += this->line_height;
463 }
464 }
465
471 IntervalTimer<TimerWindow> scroll_interval = {std::chrono::milliseconds(2100) / GetCharacterHeight(FS_NORMAL), [this](uint count) {
472 this->text_position -= count;
473 /* If the last text has scrolled start a new from the start */
474 if (this->text_position < (int)(this->GetWidget<NWidgetBase>(WID_A_SCROLLING_TEXT)->pos_y - std::size(_credits) * this->line_height)) {
475 this->text_position = this->GetWidget<NWidgetBase>(WID_A_SCROLLING_TEXT)->pos_y + this->GetWidget<NWidgetBase>(WID_A_SCROLLING_TEXT)->current_y;
476 }
478 }};
479};
480
481void ShowAboutWindow()
482{
484 new AboutWindow();
485}
486
493void ShowEstimatedCostOrIncome(Money cost, int x, int y)
494{
495 StringID msg = STR_MESSAGE_ESTIMATED_COST;
496
497 if (cost < 0) {
498 cost = -cost;
499 msg = STR_MESSAGE_ESTIMATED_INCOME;
500 }
501 ShowErrorMessage(GetEncodedString(msg, cost), {}, WL_INFO, x, y);
502}
503
511void ShowCostOrIncomeAnimation(int x, int y, int z, Money cost)
512{
513 if (cost == 0) {
514 return;
515 }
516 Point pt = RemapCoords(x, y, z);
517 StringID msg = STR_INCOME_FLOAT_COST;
518
519 if (cost < 0) {
520 cost = -cost;
521 msg = STR_INCOME_FLOAT_INCOME;
522 }
523 AddTextEffect(GetEncodedString(msg, cost), pt.x, pt.y, Ticks::DAY_TICKS, TE_RISING);
524}
525
534void ShowFeederIncomeAnimation(int x, int y, int z, Money transfer, Money income)
535{
536 Point pt = RemapCoords(x, y, z);
537
538 if (income == 0) {
539 AddTextEffect(GetEncodedString(STR_FEEDER, transfer), pt.x, pt.y, Ticks::DAY_TICKS, TE_RISING);
540 } else {
541 StringID msg = STR_FEEDER_COST;
542 if (income < 0) {
543 income = -income;
544 msg = STR_FEEDER_INCOME;
545 }
546 AddTextEffect(GetEncodedString(msg, transfer, income), pt.x, pt.y, Ticks::DAY_TICKS, TE_RISING);
547 }
548}
549
559TextEffectID ShowFillingPercent(int x, int y, int z, uint8_t percent, StringID string)
560{
561 Point pt = RemapCoords(x, y, z);
562
563 assert(string != STR_NULL);
564
565 return AddTextEffect(GetEncodedString(string, percent), pt.x, pt.y, 0, TE_STATIC);
566}
567
573void UpdateFillingPercent(TextEffectID te_id, uint8_t percent, StringID string)
574{
575 assert(string != STR_NULL);
576
577 UpdateTextEffect(te_id, GetEncodedString(string, percent));
578}
579
584void HideFillingPercent(TextEffectID *te_id)
585{
586 if (*te_id == INVALID_TE_ID) return;
587
588 RemoveTextEffect(*te_id);
589 *te_id = INVALID_TE_ID;
590}
591
592static constexpr NWidgetPart _nested_tooltips_widgets[] = {
593 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_TT_BACKGROUND),
594};
595
596static WindowDesc _tool_tips_desc(
597 WDP_MANUAL, nullptr, 0, 0, // Coordinates and sizes are not used,
600 _nested_tooltips_widgets
601);
602
604struct TooltipsWindow : public Window
605{
607 TooltipCloseCondition close_cond{};
608
609 TooltipsWindow(Window *parent, EncodedString &&text, TooltipCloseCondition close_tooltip) : Window(_tool_tips_desc), text(std::move(text))
610 {
611 this->parent = parent;
613
614 this->InitNested();
615
617 }
618
620 {
621 /* Find the free screen space between the main toolbar at the top, and the statusbar at the bottom.
622 * Add a fixed distance 2 so the tooltip floats free from both bars.
623 */
624 int scr_top = GetMainViewTop() + 2;
625 int scr_bot = GetMainViewBottom() - 2;
626
627 Point pt;
628
629 /* Correctly position the tooltip position, watch out for window and cursor size
630 * Clamp value to below main toolbar and above statusbar. If tooltip would
631 * go below window, flip it so it is shown above the cursor */
632 pt.y = SoftClamp(_cursor.pos.y + _cursor.total_size.y + _cursor.total_offs.y + 5, scr_top, scr_bot);
633 if (pt.y + sm_height > scr_bot) pt.y = std::min(_cursor.pos.y + _cursor.total_offs.y - 5, scr_bot) - sm_height;
634 pt.x = sm_width >= _screen.width ? 0 : SoftClamp(_cursor.pos.x - (sm_width >> 1), 0, _screen.width - sm_width);
635
636 return pt;
637 }
638
640 {
641 if (widget != WID_TT_BACKGROUND) return;
642
643 auto str = this->text.GetDecodedString();
644 size.width = std::min<uint>(GetStringBoundingBox(str).width, ScaleGUITrad(194));
645 size.height = GetStringHeight(str, size.width);
646
647 /* Increase slightly to have some space around the box. */
650 }
651
652 void DrawWidget(const Rect &r, WidgetID widget) const override
653 {
654 if (widget != WID_TT_BACKGROUND) return;
657
659 }
660
661 void OnMouseLoop() override
662 {
663 /* Always close tooltips when the cursor is not in our window. */
664 if (!_cursor.in_window) {
665 this->Close();
666 return;
667 }
668
669 /* We can show tooltips while dragging tools. These are shown as long as
670 * we are dragging the tool. Normal tooltips work with hover or rmb. */
671 switch (this->close_cond) {
672 case TCC_RIGHT_CLICK: if (!_right_button_down) this->Close(); break;
673 case TCC_HOVER: if (!_mouse_hovering) this->Close(); break;
674 case TCC_NONE: break;
675
676 case TCC_EXIT_VIEWPORT: {
677 Window *w = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y);
678 if (w == nullptr || IsPtInWindowViewport(w, _cursor.pos.x, _cursor.pos.y) == nullptr) this->Close();
679 break;
680 }
681 }
682 }
683};
684
691void GuiShowTooltips(Window *parent, EncodedString &&text, TooltipCloseCondition close_tooltip)
692{
694
695 if (text.empty() || !_cursor.in_window) return;
696
697 new TooltipsWindow(parent, std::move(text), close_tooltip);
698}
699
700void QueryString::HandleEditBox(Window *w, WidgetID wid)
701{
702 if (w->IsWidgetGloballyFocused(wid) && this->text.HandleCaret()) {
703 w->SetWidgetDirty(wid);
704
705 /* For the OSK also invalidate the parent window */
706 if (w->window_class == WC_OSK) w->InvalidateData();
707 }
708}
709
710static int GetCaretWidth()
711{
712 return GetCharacterWidth(FS_NORMAL, '_');
713}
714
722{
723 const int linewidth = tb.pixels + GetCaretWidth();
724 const int boxwidth = r.Width();
725 if (linewidth <= boxwidth) return r;
726
727 /* Extend to cover whole string. This is left-aligned, adjusted by caret position. */
728 r = r.WithWidth(linewidth, false);
729
730 /* Slide so that the caret is at the centre unless limited by bounds of the line, i.e. near either end. */
731 return r.Translate(-std::clamp(tb.caretxoffs - (boxwidth / 2), 0, linewidth - boxwidth), 0);
732}
733
734void QueryString::DrawEditBox(const Window *w, WidgetID wid) const
735{
736 const NWidgetLeaf *wi = w->GetWidget<NWidgetLeaf>(wid);
737
738 assert((wi->type & WWT_MASK) == WWT_EDITBOX);
739
740 bool rtl = _current_text_dir == TD_RTL;
741 Dimension sprite_size = GetScaledSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT);
742 int clearbtn_width = sprite_size.width + WidgetDimensions::scaled.imgbtn.Horizontal();
743
744 Rect r = wi->GetCurrentRect();
745 Rect cr = r.WithWidth(clearbtn_width, !rtl);
746 Rect fr = r.Indent(clearbtn_width, !rtl);
747
749 DrawSpriteIgnorePadding(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT, PAL_NONE, cr, SA_CENTER);
751
752 DrawFrameRect(fr, wi->colour, {FrameFlag::Lowered, FrameFlag::Darkened});
754
755 fr = fr.Shrink(WidgetDimensions::scaled.framerect);
756 /* Limit the drawing of the string inside the widget boundaries */
757 DrawPixelInfo dpi;
758 if (!FillDrawPixelInfo(&dpi, fr)) return;
759 /* Keep coordinates relative to the window. */
760 dpi.left += fr.left;
761 dpi.top += fr.top;
762
763 AutoRestoreBackup dpi_backup(_cur_dpi, &dpi);
764
765 /* We will take the current widget length as maximum width, with a small
766 * space reserved at the end for the caret to show */
767 const Textbuf *tb = &this->text;
768 fr = ScrollEditBoxTextRect(fr, *tb);
769
770 /* If we have a marked area, draw a background highlight. */
771 if (tb->marklength != 0) GfxFillRect(fr.left + tb->markxoffs, fr.top, fr.left + tb->markxoffs + tb->marklength - 1, fr.bottom, PC_GREY);
772
773 DrawString(fr.left, fr.right, CenterBounds(fr.top, fr.bottom, GetCharacterHeight(FS_NORMAL)), tb->GetText(), TC_YELLOW);
774 bool focussed = w->IsWidgetGloballyFocused(wid) || IsOSKOpenedFor(w, wid);
775 if (focussed && tb->caret) {
776 int caret_width = GetCaretWidth();
777 if (rtl) {
778 DrawString(fr.right - tb->pixels + tb->caretxoffs - caret_width, fr.right - tb->pixels + tb->caretxoffs, CenterBounds(fr.top, fr.bottom, GetCharacterHeight(FS_NORMAL)), "_", TC_WHITE);
779 } else {
780 DrawString(fr.left + tb->caretxoffs, fr.left + tb->caretxoffs + caret_width, CenterBounds(fr.top, fr.bottom, GetCharacterHeight(FS_NORMAL)), "_", TC_WHITE);
781 }
782 }
783}
784
792{
793 const NWidgetLeaf *wi = w->GetWidget<NWidgetLeaf>(wid);
794
795 assert((wi->type & WWT_MASK) == WWT_EDITBOX);
796
797 bool rtl = _current_text_dir == TD_RTL;
798 Dimension sprite_size = GetScaledSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT);
799 int clearbtn_width = sprite_size.width + WidgetDimensions::scaled.imgbtn.Horizontal();
800
801 Rect r = wi->GetCurrentRect().Indent(clearbtn_width, !rtl).Shrink(WidgetDimensions::scaled.framerect);
802
803 /* Clamp caret position to be inside out current width. */
804 const Textbuf *tb = &this->text;
805 r = ScrollEditBoxTextRect(r, *tb);
806
807 Point pt = {r.left + tb->caretxoffs, r.top};
808 return pt;
809}
810
819Rect QueryString::GetBoundingRect(const Window *w, WidgetID wid, const char *from, const char *to) const
820{
821 const NWidgetLeaf *wi = w->GetWidget<NWidgetLeaf>(wid);
822
823 assert((wi->type & WWT_MASK) == WWT_EDITBOX);
824
825 bool rtl = _current_text_dir == TD_RTL;
826 Dimension sprite_size = GetScaledSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT);
827 int clearbtn_width = sprite_size.width + WidgetDimensions::scaled.imgbtn.Horizontal();
828
829 Rect r = wi->GetCurrentRect().Indent(clearbtn_width, !rtl).Shrink(WidgetDimensions::scaled.framerect);
830
831 /* Clamp caret position to be inside our current width. */
832 const Textbuf *tb = &this->text;
833 r = ScrollEditBoxTextRect(r, *tb);
834
835 /* Get location of first and last character. */
836 const auto p1 = GetCharPosInString(tb->GetText(), from, FS_NORMAL);
837 const auto p2 = from != to ? GetCharPosInString(tb->GetText(), to, FS_NORMAL) : p1;
838
839 return { Clamp(r.left + p1.left, r.left, r.right), r.top, Clamp(r.left + p2.right, r.left, r.right), r.bottom };
840}
841
849ptrdiff_t QueryString::GetCharAtPosition(const Window *w, WidgetID wid, const Point &pt) const
850{
851 const NWidgetLeaf *wi = w->GetWidget<NWidgetLeaf>(wid);
852
853 assert((wi->type & WWT_MASK) == WWT_EDITBOX);
854
855 bool rtl = _current_text_dir == TD_RTL;
856 Dimension sprite_size = GetScaledSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT);
857 int clearbtn_width = sprite_size.width + WidgetDimensions::scaled.imgbtn.Horizontal();
858
859 Rect r = wi->GetCurrentRect().Indent(clearbtn_width, !rtl).Shrink(WidgetDimensions::scaled.framerect);
860
861 if (!IsInsideMM(pt.y, r.top, r.bottom)) return -1;
862
863 /* Clamp caret position to be inside our current width. */
864 const Textbuf *tb = &this->text;
865 r = ScrollEditBoxTextRect(r, *tb);
866
867 return ::GetCharAtPosition(tb->GetText(), pt.x - r.left);
868}
869
870void QueryString::ClickEditBox(Window *w, Point pt, WidgetID wid, int click_count, bool focus_changed)
871{
872 const NWidgetLeaf *wi = w->GetWidget<NWidgetLeaf>(wid);
873
874 assert((wi->type & WWT_MASK) == WWT_EDITBOX);
875
876 bool rtl = _current_text_dir == TD_RTL;
877 Dimension sprite_size = GetScaledSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT);
878 int clearbtn_width = sprite_size.width + WidgetDimensions::scaled.imgbtn.Horizontal();
879
880 Rect cr = wi->GetCurrentRect().WithWidth(clearbtn_width, !rtl);
881
882 if (IsInsideMM(pt.x, cr.left, cr.right)) {
883 if (!StrEmpty(this->text.GetText())) {
884 this->text.DeleteAll();
885 w->HandleButtonClick(wid);
886 w->OnEditboxChanged(wid);
887 }
888 return;
889 }
890
892 (!focus_changed || _settings_client.gui.osk_activation == OSKA_IMMEDIATELY) &&
893 (click_count == 2 || _settings_client.gui.osk_activation != OSKA_DOUBLE_CLICK)) {
894 /* Open the OSK window */
895 ShowOnScreenKeyboard(w, wid);
896 }
897}
898
901{
904
905 QueryStringWindow(std::string_view str, StringID caption, uint max_bytes, uint max_chars, WindowDesc &desc, Window *parent, CharSetFilter afilter, QueryStringFlags flags) :
906 Window(desc), editbox(max_bytes, max_chars)
907 {
908 this->editbox.text.Assign(str);
909
910 if (!flags.Test(QueryStringFlag::AcceptUnchanged)) this->editbox.orig = this->editbox.text.GetText();
911
912 this->querystrings[WID_QS_TEXT] = &this->editbox;
913 this->editbox.caption = caption;
914 this->editbox.cancel_button = WID_QS_CANCEL;
915 this->editbox.ok_button = WID_QS_OK;
916 this->editbox.text.afilter = afilter;
917 this->flags = flags;
918
920
921 this->parent = parent;
922
924 }
925
927 {
928 if (widget == WID_QS_DEFAULT && !this->flags.Test(QueryStringFlag::EnableDefault)) {
929 /* We don't want this widget to show! */
930 fill.width = 0;
931 resize.width = 0;
932 size.width = 0;
933 }
934 }
935
936 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
937 {
938 if (widget == WID_QS_CAPTION) return GetString(this->editbox.caption);
939
940 return this->Window::GetWidgetString(widget, stringid);
941 }
942
943 void OnOk()
944 {
945 if (!this->editbox.orig.has_value() || this->editbox.text.GetText() != this->editbox.orig) {
946 assert(this->parent != nullptr);
947
948 this->parent->OnQueryTextFinished(this->editbox.text.GetText());
949 this->editbox.handled = true;
950 }
951 }
952
953 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
954 {
955 switch (widget) {
956 case WID_QS_DEFAULT:
957 this->editbox.text.DeleteAll();
958 [[fallthrough]];
959
960 case WID_QS_OK:
961 this->OnOk();
962 [[fallthrough]];
963
964 case WID_QS_CANCEL:
965 this->Close();
966 break;
967 }
968 }
969
970 void Close([[maybe_unused]] int data = 0) override
971 {
972 if (!this->editbox.handled && this->parent != nullptr) {
973 Window *parent = this->parent;
974 this->parent = nullptr; // so parent doesn't try to close us again
975 parent->OnQueryTextFinished(std::nullopt);
976 }
977 this->Window::Close();
978 }
979};
980
981static constexpr NWidgetPart _nested_query_string_widgets[] = {
983 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
984 NWidget(WWT_CAPTION, COLOUR_GREY, WID_QS_CAPTION), SetTextStyle(TC_WHITE),
985 EndContainer(),
986 NWidget(WWT_PANEL, COLOUR_GREY),
987 NWidget(WWT_EDITBOX, COLOUR_GREY, WID_QS_TEXT), SetMinimalSize(256, 0), SetFill(1, 0), SetPadding(2, 2, 2, 2),
988 EndContainer(),
990 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_QS_DEFAULT), SetMinimalSize(87, 12), SetFill(1, 1), SetStringTip(STR_BUTTON_DEFAULT),
991 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_QS_CANCEL), SetMinimalSize(86, 12), SetFill(1, 1), SetStringTip(STR_BUTTON_CANCEL),
992 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_QS_OK), SetMinimalSize(87, 12), SetFill(1, 1), SetStringTip(STR_BUTTON_OK),
993 EndContainer(),
994};
995
996static WindowDesc _query_string_desc(
997 WDP_CENTER, nullptr, 0, 0,
999 {},
1000 _nested_query_string_widgets
1001);
1002
1012void ShowQueryString(std::string_view str, StringID caption, uint maxsize, Window *parent, CharSetFilter afilter, QueryStringFlags flags)
1013{
1014 assert(parent != nullptr);
1015
1017 new QueryStringWindow(str, caption, (flags.Test(QueryStringFlag::LengthIsInChars) ? MAX_CHAR_LENGTH : 1) * maxsize, maxsize, _query_string_desc, parent, afilter, flags);
1018}
1019
1023struct QueryWindow : public Window {
1027
1029 : Window(desc), proc(callback), caption(std::move(caption)), message(std::move(message))
1030 {
1031 this->parent = parent;
1032
1033 this->CreateNestedTree();
1035 }
1036
1037 void Close([[maybe_unused]] int data = 0) override
1038 {
1039 if (this->proc != nullptr) this->proc(this->parent, false);
1040 this->Window::Close();
1041 }
1042
1044 {
1045 /* Position query window over the calling window, ensuring it's within screen bounds. */
1046 this->left = SoftClamp(parent->left + (parent->width / 2) - (this->width / 2), 0, _screen.width - this->width);
1047 this->top = SoftClamp(parent->top + (parent->height / 2) - (this->height / 2), 0, _screen.height - this->height);
1048 this->SetDirty();
1049 }
1050
1051 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
1052 {
1053 switch (widget) {
1054 case WID_Q_CAPTION:
1055 return this->caption.GetDecodedString();
1056
1057 default:
1058 return this->Window::GetWidgetString(widget, stringid);
1059 }
1060 }
1061
1063 {
1064 if (widget != WID_Q_TEXT) return;
1065
1067 }
1068
1069 void DrawWidget(const Rect &r, WidgetID widget) const override
1070 {
1071 if (widget != WID_Q_TEXT) return;
1072
1073 DrawStringMultiLine(r, this->message.GetDecodedString(), TC_FROMSTRING, SA_CENTER);
1074 }
1075
1076 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1077 {
1078 switch (widget) {
1079 case WID_Q_YES: {
1080 /* in the Generate New World window, clicking 'Yes' causes
1081 * CloseNonVitalWindows() to be called - we shouldn't be in a window then */
1082 QueryCallbackProc *proc = this->proc;
1083 Window *parent = this->parent;
1084 /* Prevent the destructor calling the callback function */
1085 this->proc = nullptr;
1086 this->Close();
1087 if (proc != nullptr) {
1088 proc(parent, true);
1089 proc = nullptr;
1090 }
1091 break;
1092 }
1093 case WID_Q_NO:
1094 this->Close();
1095 break;
1096 }
1097 }
1098
1099 EventState OnKeyPress([[maybe_unused]] char32_t key, uint16_t keycode) override
1100 {
1101 /* ESC closes the window, Enter confirms the action */
1102 switch (keycode) {
1103 case WKC_RETURN:
1104 case WKC_NUM_ENTER:
1105 if (this->proc != nullptr) {
1106 this->proc(this->parent, true);
1107 this->proc = nullptr;
1108 }
1109 [[fallthrough]];
1110
1111 case WKC_ESC:
1112 this->Close();
1113 return ES_HANDLED;
1114 }
1115 return ES_NOT_HANDLED;
1116 }
1117};
1118
1119static constexpr NWidgetPart _nested_query_widgets[] = {
1121 NWidget(WWT_CLOSEBOX, COLOUR_RED),
1122 NWidget(WWT_CAPTION, COLOUR_RED, WID_Q_CAPTION),
1123 EndContainer(),
1124 NWidget(WWT_PANEL, COLOUR_RED),
1126 NWidget(WWT_TEXT, INVALID_COLOUR, WID_Q_TEXT), SetMinimalSize(200, 12),
1128 NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_Q_NO), SetMinimalSize(71, 12), SetFill(1, 1), SetStringTip(STR_QUIT_NO),
1129 NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_Q_YES), SetMinimalSize(71, 12), SetFill(1, 1), SetStringTip(STR_QUIT_YES),
1130 EndContainer(),
1131 EndContainer(),
1132 EndContainer(),
1133};
1134
1135static WindowDesc _query_desc(
1136 WDP_CENTER, nullptr, 0, 0,
1139 _nested_query_widgets
1140);
1141
1152void ShowQuery(EncodedString &&caption, EncodedString &&message, Window *parent, QueryCallbackProc *callback, bool focus)
1153{
1154 if (parent == nullptr) parent = GetMainWindow();
1155
1156 for (Window *w : Window::Iterate()) {
1157 if (w->window_class != WC_CONFIRM_POPUP_QUERY) continue;
1158
1159 QueryWindow *qw = dynamic_cast<QueryWindow *>(w);
1160 assert(qw != nullptr);
1161 if (qw->parent != parent || qw->proc != callback) continue;
1162
1163 qw->Close();
1164 break;
1165 }
1166
1167 QueryWindow *q = new QueryWindow(_query_desc, std::move(caption), std::move(message), parent, callback);
1168 if (focus) SetFocusedWindow(q);
1169}
std::optional< std::string > BuildCargoAcceptanceString(const CargoArray &acceptance, StringID label)
Build comma-separated cargo acceptance string.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Timpl & Reset(Tvalue_type value)
Reset the value-th bit.
Common return value for all commands.
Container for an encoded string, created by GetEncodedString.
std::string GetDecodedString() const
Decode the encoded string.
Definition strings.cpp:219
Enum-as-bit-set wrapper.
An interval timer will fire every interval, and will continue to fire until it is deleted.
Definition timer.h:76
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Definition misc_gui.cpp:77
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Definition misc_gui.cpp:306
StringList landinfo_data
Info lines to show.
Definition misc_gui.cpp:71
std::string cargo_acceptance
Centered multi-line string for cargo acceptance.
Definition misc_gui.cpp:72
bool IsNewGRFInspectable() const override
Is the data related to this window NewGRF inspectable?
Definition misc_gui.cpp:278
void OnInit() override
Notification that the nested widget tree gets initialized.
Definition misc_gui.cpp:136
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
Definition misc_gui.cpp:288
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.
Definition misc_gui.cpp:92
void ShowNewGRFInspectWindow() const override
Show the NewGRF inspection window.
Definition misc_gui.cpp:283
WidgetType type
Type of the widget / nested widget.
Colours colour
Colour of this widget.
bool IsLowered() const
Return whether the widget is lowered.
Leaf widget.
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
Wrapper class to abstract away the way the tiles are stored.
Definition map_func.h:25
static constexpr TimerGame< struct Calendar >::Date INVALID_DATE
Representation of an invalid date.
RectPadding framerect
Standard padding inside many panels.
Definition window_gui.h:40
RectPadding frametext
Padding inside frame with text.
Definition window_gui.h:41
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:29
RectPadding imgbtn
Padding around image button image.
Definition window_gui.h:34
int vsep_normal
Normal vertical spacing.
Definition window_gui.h:58
int vsep_wide
Wide vertical spacing.
Definition window_gui.h:60
RectPadding fullbevel
Always-scaled bevel thickness.
Definition window_gui.h:39
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:94
RectPadding bevel
Bevel thickness, affected by "scaled bevels" game option.
Definition window_gui.h:38
Functions related to commands.
@ QueryCost
query cost only, don't build.
Definition of stuff that is very close to a company, like the company struct itself.
std::array< StringParameter, 2 > GetParamsForOwnedBy(Owner owner, TileIndex tile)
Set the right DParams for STR_ERROR_OWNED_BY.
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.
static constexpr Owner OWNER_NONE
The tile has no ownership.
static constexpr Owner OWNER_WATER
The tile/execution is done by "water".
Functions related to debugging.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
Functions related to errors.
@ WL_INFO
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition error.h:24
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, CommandCost &cc)
Display an error message in a window.
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.
int GetStringHeight(std::string_view str, int maxw, FontSize fontsize)
Calculates height of string (in pixels).
Definition gfx.cpp:705
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
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
uint8_t GetCharacterWidth(FontSize size, char32_t key)
Return width of character glyph.
Definition gfx.cpp:1228
Dimension GetStringMultiLineBoundingBox(StringID str, const Dimension &suggestion)
Calculate string bounding box for multi-line strings.
Definition gfx.cpp:741
int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition gfx.cpp:775
bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int height)
Set up a clipping area for only drawing into a certain area.
Definition gfx.cpp:1519
bool _right_button_down
Is right mouse button pressed?
Definition gfx.cpp:43
Dimension GetScaledSpriteSize(SpriteID sprid)
Scale sprite size for GUI.
Definition widget.cpp:67
int CenterBounds(int min, int max, int size)
Determine where to draw a centred object inside a widget.
Definition gfx_func.h:166
ParagraphLayouter::Position GetCharPosInString(std::string_view str, const char *ch, FontSize start_fontsize)
Get the leading corner of a character in a single-line string relative to the start of the string.
Functions related to laying out the texts.
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:245
@ SA_LEFT
Left align the text.
Definition gfx_type.h:377
@ SA_HOR_CENTER
Horizontally center the text.
Definition gfx_type.h:378
@ SA_FORCE
Force the alignment, i.e. don't swap for RTL languages.
Definition gfx_type.h:389
@ SA_CENTER
Center both horizontally and vertically.
Definition gfx_type.h:387
@ FILLRECT_CHECKER
Draw only every second pixel, used for greying-out.
Definition gfx_type.h:335
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 SetPIP(uint8_t pre, uint8_t inter, uint8_t post)
Widget part function for setting a pre/inter/post spaces.
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 NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition window.cpp:943
GUI functions that shouldn't be here.
void ShowExtraViewportWindow(TileIndex tile=INVALID_TILE)
Show a new Extra Viewport window.
Functions related to OTTD's landscape.
Point RemapCoords(int x, int y, int z)
Map 3D world or tile coordinate to equivalent 2D coordinate as used in the viewports and smallmap.
Definition landscape.h:79
Command definitions related to landscape (slopes etc.).
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:424
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:414
constexpr bool IsInsideMM(const size_t x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
constexpr T SoftClamp(const T a, const T min, const T max)
Clamp a value between an interval.
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition math_func.hpp:79
void GuiShowTooltips(Window *parent, EncodedString &&text, TooltipCloseCondition close_tooltip)
Shows a tooltip.
Definition misc_gui.cpp:691
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 HideFillingPercent(TextEffectID *te_id)
Hide vehicle loading indicators.
Definition misc_gui.cpp:584
void ShowCostOrIncomeAnimation(int x, int y, int z, Money cost)
Display animated income or costs on the map.
Definition misc_gui.cpp:511
void ShowEstimatedCostOrIncome(Money cost, int x, int y)
Display estimated costs.
Definition misc_gui.cpp:493
OskActivation
Method to open the OSK.
Definition misc_gui.cpp:45
@ OSKA_SINGLE_CLICK
Single click after focus click opens OSK.
Definition misc_gui.cpp:48
@ OSKA_IMMEDIATELY
Focusing click already opens OSK.
Definition misc_gui.cpp:49
@ OSKA_DISABLED
The OSK shall not be activated at all.
Definition misc_gui.cpp:46
@ OSKA_DOUBLE_CLICK
Double click on the edit box opens OSK.
Definition misc_gui.cpp:47
void ShowLandInfo(TileIndex tile)
Show land information window.
Definition misc_gui.cpp:319
void ShowFeederIncomeAnimation(int x, int y, int z, Money transfer, Money income)
Display animated feeder income.
Definition misc_gui.cpp:534
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.
void UpdateFillingPercent(TextEffectID te_id, uint8_t percent, StringID string)
Update vehicle loading indicators.
Definition misc_gui.cpp:573
TextEffectID ShowFillingPercent(int x, int y, int z, uint8_t percent, StringID string)
Display vehicle loading indicators.
Definition misc_gui.cpp:559
static Rect ScrollEditBoxTextRect(Rect r, const Textbuf &tb)
Reposition edit text box rect based on textbuf length can caret position.
Definition misc_gui.cpp:721
Types related to the misc widgets.
@ WID_TT_BACKGROUND
Background of the window.
Definition misc_widget.h:21
@ WID_QS_DEFAULT
Default button.
Definition misc_widget.h:35
@ WID_QS_CAPTION
Caption of the window.
Definition misc_widget.h:33
@ WID_QS_TEXT
Text of the query.
Definition misc_widget.h:34
@ WID_QS_CANCEL
Cancel button.
Definition misc_widget.h:36
@ WID_QS_OK
OK button.
Definition misc_widget.h:37
@ WID_A_WEBSITE
URL of OpenTTD website.
Definition misc_widget.h:27
@ WID_A_COPYRIGHT
Copyright string.
Definition misc_widget.h:28
@ WID_A_SCROLLING_TEXT
The actually scrolling text.
Definition misc_widget.h:26
@ WID_Q_NO
Yes button.
Definition misc_widget.h:44
@ WID_Q_YES
No button.
Definition misc_widget.h:45
@ WID_Q_CAPTION
Caption of the window.
Definition misc_widget.h:42
@ WID_Q_TEXT
Text of the query.
Definition misc_widget.h:43
@ WID_LI_BACKGROUND
Background of the window.
Definition misc_widget.h:16
@ WID_LI_LOCATION
Scroll to location.
Definition misc_widget.h:15
Functions/types related to NewGRF debugging.
GrfSpecFeature GetGrfSpecFeature(TileIndex tile)
Get the GrfSpecFeature associated with the tile.
uint8_t GetColourGradient(Colours colour, ColourShade shade)
Get colour gradient palette index.
Definition palette.cpp:387
static const uint8_t PC_LIGHT_YELLOW
Light yellow palette colour.
static const uint8_t PC_GREY
Grey palette colour.
static const uint8_t PC_BLACK
Black palette colour.
Base for the GUIs that have an edit box in them.
void ShowOnScreenKeyboard(Window *parent, WidgetID button)
Show the on-screen keyboard (osk) associated with a given textbox.
Definition osk_gui.cpp:397
bool IsOSKOpenedFor(const Window *w, WidgetID button)
Check whether the OSK is opened for a specific editbox.
Definition osk_gui.cpp:428
declaration of OTTD revision dependent variables
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:58
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:57
Definition of base types and functions in a cross-platform compatible way.
Functions related to low-level strings.
bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition string_func.h:57
CharSetFilter
Valid filter types for IsValidChar.
Definition string_type.h:24
std::vector< std::string > StringList
Type for a list of strings.
Definition string_type.h:60
void GetStringWithArgs(StringBuilder &builder, StringID string, StringParameters &args, uint case_index, bool game_script)
Get a parsed string with most special stringcodes replaced by the string parameters.
Definition strings.cpp:338
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:90
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:426
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
Functions related to OTTD's strings.
int64_t PackVelocity(uint speed, VehicleType type)
Pack velocity and vehicle type for use with SCC_VELOCITY string parameter.
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.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Definition misc_gui.cpp:451
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.
Definition misc_gui.cpp:435
IntervalTimer< TimerWindow > scroll_interval
Scroll the text in the about window slow.
Definition misc_gui.cpp:471
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
Definition misc_gui.cpp:428
int text_position
The top of the scrolling text.
Definition misc_gui.cpp:417
static const int num_visible_lines
The number of lines visible simultaneously.
Definition misc_gui.cpp:419
int line_height
The height of a single line.
Definition misc_gui.cpp:418
Class to backup a specific variable and restore it upon destruction of this object to prevent stack v...
Class for storing amounts of cargo.
Definition cargo_type.h:113
GUISettings gui
settings related to the GUI
Point pos
logical mouse position
Definition gfx_type.h:126
bool in_window
mouse inside this window, determines drawing logic
Definition gfx_type.h:148
Point total_size
union of sprite properties
Definition gfx_type.h:138
Dimensions (a width and height) of a rectangle in 2D.
Data about how and where to blit pixels.
Definition gfx_type.h:158
uint8_t dist_local_authority
distance for town local authority, default 20
uint8_t osk_activation
Mouse gesture to trigger the OSK.
EconomySettings economy
settings to change the economy
Partial widget specification to allow NWidgets to be written nested.
Coordinates of a point in 2D.
Tindex index
Index of this pool item.
static Titem * GetIfValid(auto index)
Returns Titem with given index.
Class for the string query window.
Definition misc_gui.cpp:901
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
Definition misc_gui.cpp:953
void Close(int data=0) override
Hide the window and all its child windows, and mark them for a later deletion.
Definition misc_gui.cpp:970
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.
Definition misc_gui.cpp:926
QueryString editbox
Editbox.
Definition misc_gui.cpp:902
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
Definition misc_gui.cpp:936
QueryStringFlags flags
Flags controlling behaviour of the window.
Definition misc_gui.cpp:903
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.
ptrdiff_t GetCharAtPosition(const Window *w, WidgetID wid, const Point &pt) const
Get the character that is rendered at a position.
Definition misc_gui.cpp:849
Rect GetBoundingRect(const Window *w, WidgetID wid, const char *from, const char *to) const
Get the bounding rectangle for a range of the query string.
Definition misc_gui.cpp:819
Point GetCaretPosition(const Window *w, WidgetID wid) const
Get the current caret position.
Definition misc_gui.cpp:791
Window used for asking the user a YES/NO question.
void Close(int data=0) override
Hide the window and all its child windows, and mark them for a later deletion.
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.
QueryCallbackProc * proc
callback function executed on closing of popup. Window* points to parent, bool is true if 'yes' click...
EventState OnKeyPress(char32_t key, uint16_t keycode) override
A key has been pressed.
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.
EncodedString caption
caption for query window.
EncodedString message
message for query window.
void FindWindowPlacementAndResize(int def_width, int def_height) override
Resize window towards the default size.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
constexpr uint Horizontal() const
Get total horizontal padding of RectPadding.
constexpr uint Vertical() const
Get total vertical padding of RectPadding.
Specification of a rectangle with absolute coordinates of all edges.
Rect WithWidth(int width, bool end) const
Copy Rect and set its width.
int Width() const
Get width of Rect.
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.
Rect Translate(int x, int y) const
Copy and translate Rect by x,y pixels.
Helper/buffer for input fields.
uint16_t pixels
the current size of the string in pixels
uint16_t markxoffs
the start position of the marked area in pixels
void DeleteAll()
Delete every character in the textbuffer.
Definition textbuf.cpp:112
void Assign(const std::string_view text)
Copy a string into the textbuffer.
Definition textbuf.cpp:422
const char * GetText() const
Get the current text.
Definition textbuf.cpp:286
uint16_t caretxoffs
the current position of the caret in pixels
uint16_t marklength
the length of the marked area in pixels
bool caret
is the caret ("_") visible or not
CharSetFilter afilter
Allowed characters.
Tile description for the 'land area information' tool.
Definition tile_cmd.h:52
std::array< StringID, 4 > owner_type
Type of each owner.
Definition tile_cmd.h:56
Window for displaying a tooltip.
Definition misc_gui.cpp:605
TooltipCloseCondition close_cond
Condition for closing the window.
Definition misc_gui.cpp:607
EncodedString text
String to display as tooltip.
Definition misc_gui.cpp:606
void OnMouseLoop() override
Called for every mouse loop run, which is at least once per (game) tick.
Definition misc_gui.cpp:661
Point OnInitialPosition(int16_t sm_width, int16_t sm_height, int window_number) override
Compute the initial position of the window.
Definition misc_gui.cpp:619
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.
Definition misc_gui.cpp:639
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Definition misc_gui.cpp:652
Town data structure.
Definition town.h:52
High level window description.
Definition window_gui.h:168
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:955
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1050
bool IsWidgetGloballyFocused(WidgetID widget_index) const
Check if given widget has user input focus.
Definition window_gui.h:432
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1736
std::map< WidgetID, QueryString * > querystrings
QueryString associated to WWT_EDITBOX widgets.
Definition window_gui.h:321
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing)
Definition window.cpp:3164
Window * parent
Parent window.
Definition window_gui.h:329
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:554
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:502
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:1726
WindowClass window_class
Window class.
Definition window_gui.h:302
virtual void OnQueryTextFinished(std::optional< std::string > str)
The query window opened from this window has closed.
Definition window_gui.h:776
bool SetFocusedWidget(WidgetID widget_index)
Set focus within this window to the given widget.
Definition window.cpp:483
int left
x position of left edge of the window
Definition window_gui.h:310
virtual void OnEditboxChanged(WidgetID widget)
The text in an editbox has been edited.
Definition window_gui.h:768
int top
y position of top edge of the window
Definition window_gui.h:311
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:973
void HandleButtonClick(WidgetID widget)
Do all things to make a button look clicked and mark it to be unclicked in a few ticks.
Definition window.cpp:593
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition window.cpp:1749
WindowFlags flags
Window flags.
Definition window_gui.h:301
AllWindows< false > Iterate
Iterate all windows in whatever order is easiest.
Definition window_gui.h:923
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
@ AcceptUnchanged
return success even when the text didn't change
@ EnableDefault
enable the 'Default' button ("\0" is returned)
@ LengthIsInChars
the length of the string is counted in characters
void QueryCallbackProc(Window *, bool)
Callback procedure for the ShowQuery method.
Definition textbuf_gui.h:27
Functions related to text effects.
@ TE_STATIC
Keep the text effect static.
Definition texteff.hpp:23
@ TE_RISING
Make the text effect slowly go upwards.
Definition texteff.hpp:22
int GetTileZ(TileIndex tile)
Get bottom height of the tile.
Definition tile_map.cpp:116
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
Definition of Interval and OneShot timers.
Definition of the Window system.
Base of the town class.
Town * ClosestTownFromTile(TileIndex tile, uint threshold)
Return the town closest (in distance or ownership) to a given tile, within a given threshold.
@ VEH_ROAD
Road vehicle type.
@ VEH_TRAIN
Train vehicle type.
bool ScrollMainWindowToTile(TileIndex tile, bool instant)
Scrolls the viewport of the main window to a given location.
Viewport * IsPtInWindowViewport(const Window *w, int x, int y)
Is a xy position inside the viewport of the window?
Definition viewport.cpp:413
Functions related to (drawing on) viewports.
Handles dividing the water in the map into regions to assist pathfinding.
void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags)
Draw frame rectangle.
Definition widget.cpp:296
static RectPadding ScaleGUITrad(const RectPadding &r)
Scale a RectPadding to GUI zoom level.
Definition widget.cpp:48
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
@ WWT_PUSHIMGBTN
Normal push-button (no toggle button) with image caption.
@ WWT_LABEL
Centered label.
Definition widget_type.h:47
@ WWT_EDITBOX
a textbox for typing
Definition widget_type.h:61
@ 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_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:51
@ 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_FRAME
Frame.
Definition widget_type.h:50
@ WWT_EMPTY
Empty widget, place holder to reserve space in widget tree.
Definition widget_type.h:38
@ WWT_TEXT
Pure simple text.
Definition widget_type.h:48
@ WWT_DEBUGBOX
NewGRF debug box (at top-right of a window, between WWT_CAPTION and WWT_SHADEBOX)
Definition widget_type.h:53
@ EqualSize
Containers should keep all their (resizing) children equally large.
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition window.cpp:1143
Window * GetMainWindow()
Get the main window, i.e.
Definition window.cpp:1130
void SetFocusedWindow(Window *w)
Set the window that has the focus.
Definition window.cpp:419
Window * FindWindowFromPt(int x, int y)
Do a search for a window at specific coordinates.
Definition window.cpp:1771
int GetMainViewTop()
Return the top of the main view available for general use.
Definition window.cpp:2065
void CloseWindowByClass(WindowClass cls, int data)
Close all windows of a given class.
Definition window.cpp:1155
int GetMainViewBottom()
Return the bottom of the main view available for general use.
Definition window.cpp:2076
bool _mouse_hovering
The mouse is hovering over the same point.
Definition window.cpp:91
Window functions not directly related to making/drawing windows.
@ NoClose
This window can't be interactively closed.
@ NoFocus
This window won't get focus/make any other window lose focus when click.
@ Modal
The window is a modal child of some other window, meaning the parent is 'inactive'.
@ Lowered
If set the frame is lowered and the background colour brighter (ie. buttons when pressed)
@ WhiteBorder
Window white border counter bit mask.
@ WDP_CENTER
Center the window.
Definition window_gui.h:146
@ WDP_AUTO
Find a place automatically.
Definition window_gui.h:145
@ WDP_MANUAL
Manually align the window (so no automatic location finding)
Definition window_gui.h:144
int WidgetID
Widget ID.
Definition window_type.h:20
@ WN_QUERY_STRING
Query string.
Definition window_type.h:31
@ WN_GAME_OPTIONS_ABOUT
About window.
Definition window_type.h:26
@ WN_CONFIRM_POPUP_QUERY
Query popup confirm.
Definition window_type.h:34
EventState
State of handling an event.
@ ES_HANDLED
The passed event is handled.
@ ES_NOT_HANDLED
The passed event is not handled.
@ WC_LAND_INFO
Land info window; Window numbers:
@ WC_OSK
On Screen Keyboard; Window numbers:
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:47
@ WC_CONFIRM_POPUP_QUERY
Popup with confirm question; Window numbers:
@ WC_GAME_OPTIONS
Game options window; Window numbers:
@ WC_QUERY_STRING
Query string window; Window numbers:
@ WC_TOOLTIPS
Tooltip window; Window numbers:
Functions related to zooming.