OpenTTD Source 20251213-master-g1091fa6071
timetable_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
10#include "stdafx.h"
11#include "command_func.h"
12#include "gui.h"
13#include "window_gui.h"
14#include "window_func.h"
15#include "textbuf_gui.h"
16#include "strings_func.h"
17#include "vehicle_base.h"
18#include "string_func.h"
19#include "gfx_func.h"
20#include "company_func.h"
21#include "timer/timer.h"
24#include "timer/timer_window.h"
25#include "date_gui.h"
26#include "vehicle_gui.h"
27#include "settings_type.h"
28#include "timetable_cmd.h"
29#include "timetable.h"
31
33
34#include "table/sprites.h"
35#include "table/strings.h"
36
37#include "safeguards.h"
38
44
50std::pair<StringParameter, StringParameter> GetTimetableParameters(TimerGameTick::Ticks ticks)
51{
53 case TimetableMode::Days: return {STR_UNITS_DAYS, ticks / Ticks::DAY_TICKS};
54 case TimetableMode::Seconds: return {STR_UNITS_SECONDS, ticks / Ticks::TICKS_PER_SECOND};
55 case TimetableMode::Ticks: return {STR_UNITS_TICKS, ticks};
56 default:
57 NOT_REACHED();
58 }
59}
60
66{
68 case TimetableMode::Days:
69 return Ticks::DAY_TICKS;
70 case TimetableMode::Seconds:
72 case TimetableMode::Ticks:
73 return 1;
74 default:
75 NOT_REACHED();
76 }
77}
78
86{
88 case TimetableMode::Days:
89 return ticks > Ticks::DAY_TICKS;
90 case TimetableMode::Seconds:
91 return ticks > Ticks::TICKS_PER_SECOND;
92 case TimetableMode::Ticks:
93 return ticks > (round_to_day ? Ticks::DAY_TICKS : 0);
94 default:
95 NOT_REACHED();
96 }
97}
98
105static bool CanDetermineTimeTaken(const Order &order, bool travelling)
106{
107 /* Current order is conditional */
108 if (order.IsType(OT_CONDITIONAL) || order.IsType(OT_IMPLICIT)) return false;
109 /* No travel time and we have not already finished travelling */
110 if (travelling && !order.IsTravelTimetabled()) return false;
111 /* No wait time but we are loading at this timetabled station */
112 if (!travelling && !order.IsWaitTimetabled() && order.IsType(OT_GOTO_STATION) &&
114 return false;
115 }
116
117 return true;
118}
119
120
129static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID start, bool travelling, std::vector<TimetableArrivalDeparture> &table, TimerGameTick::Ticks offset)
130{
131 assert(!table.empty());
132 assert(v->GetNumOrders() >= 2);
133 assert(start < v->GetNumOrders());
134
135 /* Pre-initialize with unknown time */
136 for (int i = 0; i < v->GetNumOrders(); ++i) {
137 table[i].arrival = table[i].departure = Ticks::INVALID_TICKS;
138 }
139
140 TimerGameTick::Ticks sum = offset;
141 VehicleOrderID i = start;
142 auto orders = v->Orders();
143
144 /* Cyclically loop over all orders until we reach the current one again.
145 * As we may start at the current order, do a post-checking loop */
146 do {
147 /* Automatic orders don't influence the overall timetable;
148 * they just add some untimetabled entries, but the time till
149 * the next non-implicit order can still be known. */
150 if (!orders[i].IsType(OT_IMPLICIT)) {
151 if (travelling || i != start) {
152 if (!CanDetermineTimeTaken(orders[i], true)) return;
153 sum += orders[i].GetTimetabledTravel();
154 table[i].arrival = sum;
155 }
156
157 if (!CanDetermineTimeTaken(orders[i], false)) return;
158 sum += orders[i].GetTimetabledWait();
159 table[i].departure = sum;
160 }
161
162 i = v->orders->GetNext(i);
163 } while (i != start);
164
165 /* When loading at a scheduled station we still have to treat the
166 * travelling part of the first order. */
167 if (!travelling) {
168 if (!CanDetermineTimeTaken(orders[i], true)) return;
169 sum += orders[i].GetTimetabledTravel();
170 table[i].arrival = sum;
171 }
172}
173
175 int sel_index = -1;
177 const Vehicle *vehicle = nullptr;
178 bool show_expected = true;
179 Scrollbar *vscroll = nullptr;
180 bool set_start_date_all = false;
181 bool change_timetable_all = false;
182
184 Window(desc),
186 {
187 this->CreateNestedTree();
188 this->vscroll = this->GetScrollbar(WID_VT_SCROLLBAR);
189
190 /* When using wallclock units, we must ensure the client displays timetables in seconds. */
192 _settings_client.gui.timetable_mode = TimetableMode::Seconds;
193 }
194
195 this->UpdateSelectionStates();
196 this->FinishInitNested(window_number);
197
198 this->owner = this->vehicle->owner;
199 }
200
207 static bool BuildArrivalDepartureList(const Vehicle *v, std::vector<TimetableArrivalDeparture> &table)
208 {
210
211 bool travelling = (!v->current_order.IsType(OT_LOADING) || v->current_order.GetNonStopType().None());
213
214 /* If arrival and departure times are in days, compensate for the current date_fract. */
215 if (_settings_client.gui.timetable_mode != TimetableMode::Seconds) start_time += TimerGameEconomy::date_fract;
216
217 FillTimetableArrivalDepartureTable(v, v->cur_real_order_index % v->GetNumOrders(), travelling, table, start_time);
218
219 return (travelling && v->lateness_counter < 0);
220 }
221
222 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
223 {
224 switch (widget) {
226 /* We handle this differently depending on the timetable mode. */
227 if (_settings_client.gui.timetable_mode == TimetableMode::Seconds) {
228 /* A five-digit number would fit a timetable lasting 2.7 real-world hours, which should be plenty. */
229 uint64_t max_digits = GetParamMaxDigits(4, FS_SMALL);
230 size.width = std::max(
231 GetStringBoundingBox(GetString(STR_TIMETABLE_ARRIVAL_SECONDS_IN_FUTURE, TC_BLACK, max_digits)).width,
232 GetStringBoundingBox(GetString(STR_TIMETABLE_DEPARTURE_SECONDS_IN_FUTURE, TC_BLACK, max_digits)).width)
233 + WidgetDimensions::scaled.hsep_wide + padding.width;
234 } else {
236 size.width = std::max(
237 GetStringBoundingBox(GetString(STR_TIMETABLE_ARRIVAL_DATE, TC_BLACK, max_value)).width,
238 GetStringBoundingBox(GetString(STR_TIMETABLE_DEPARTURE_DATE, TC_BLACK, max_value)).width)
239 + WidgetDimensions::scaled.hsep_wide + padding.width;
240 }
241 [[fallthrough]];
242
244 fill.height = resize.height = GetCharacterHeight(FS_NORMAL);
245 size.height = 8 * resize.height + padding.height;
246 break;
247
249 size.height = 2 * GetCharacterHeight(FS_NORMAL) + padding.height;
250 break;
251 }
252 }
253
254 int GetOrderFromTimetableWndPt(int y, [[maybe_unused]] const Vehicle *v)
255 {
256 int32_t sel = this->vscroll->GetScrolledRowFromWidget(y, this, WID_VT_TIMETABLE_PANEL, WidgetDimensions::scaled.framerect.top);
257 if (sel == INT32_MAX) return sel;
258 assert(IsInsideBS(sel, 0, v->GetNumOrders() * 2));
259 return sel;
260 }
261
267 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
268 {
269 switch (data) {
270 case VIWD_AUTOREPLACE:
271 /* Autoreplace replaced the vehicle */
272 this->vehicle = Vehicle::Get(this->window_number);
273 break;
274
276 /* Removed / replaced all orders (after deleting / sharing) */
277 if (this->sel_index == -1) break;
278
279 this->CloseChildWindows();
280 this->sel_index = -1;
281 break;
282
284 if (!gui_scope) break;
285 this->UpdateSelectionStates();
286 this->ReInit();
287 break;
288
289 default: {
290 if (gui_scope) break; // only do this once; from command scope
291
292 /* Moving an order. If one of these is INVALID_VEH_ORDER_ID, then
293 * the order is being created / removed */
294 if (this->sel_index == -1) break;
295
296 VehicleOrderID from = GB(data, 0, 8);
297 VehicleOrderID to = GB(data, 8, 8);
298
299 if (from == to) break; // no need to change anything
300
301 /* if from == INVALID_VEH_ORDER_ID, one order was added; if to == INVALID_VEH_ORDER_ID, one order was removed */
302 uint old_num_orders = this->vehicle->GetNumOrders() - (uint)(from == INVALID_VEH_ORDER_ID) + (uint)(to == INVALID_VEH_ORDER_ID);
303
304 VehicleOrderID selected_order = (this->sel_index + 1) / 2;
305 if (selected_order == old_num_orders) selected_order = 0; // when last travel time is selected, it belongs to order 0
306
307 bool travel = HasBit(this->sel_index, 0);
308
309 if (from != selected_order) {
310 /* Moving from preceding order? */
311 selected_order -= (int)(from <= selected_order);
312 /* Moving to preceding order? */
313 selected_order += (int)(to <= selected_order);
314 } else {
315 /* Now we are modifying the selected order */
316 if (to == INVALID_VEH_ORDER_ID) {
317 /* Deleting selected order */
318 this->CloseChildWindows();
319 this->sel_index = -1;
320 break;
321 } else {
322 /* Moving selected order */
323 selected_order = to;
324 }
325 }
326
327 /* recompute new sel_index */
328 this->sel_index = 2 * selected_order - (int)travel;
329 /* travel time of first order needs special handling */
330 if (this->sel_index == -1) this->sel_index = this->vehicle->GetNumOrders() * 2 - 1;
331 break;
332 }
333 }
334 }
335
336
337 void OnPaint() override
338 {
339 const Vehicle *v = this->vehicle;
340 int selected = this->sel_index;
341
342 this->vscroll->SetCount(v->GetNumOrders() * 2);
343
344 if (v->owner == _local_company) {
345 bool disable = true;
346 if (selected != -1) {
347 const Order *order = v->GetOrder(((selected + 1) / 2) % v->GetNumOrders());
348 if (selected % 2 != 0) {
349 disable = order != nullptr && (order->IsType(OT_CONDITIONAL) || order->IsType(OT_IMPLICIT));
350 } else {
351 disable = order == nullptr || ((!order->IsType(OT_GOTO_STATION) || order->GetNonStopType().Test(OrderNonStopFlag::NoDestination)) && !order->IsType(OT_CONDITIONAL));
352 }
353 }
354 bool disable_speed = disable || selected % 2 == 0 || v->type == VEH_AIRCRAFT;
355
358 this->SetWidgetDisabledState(WID_VT_CHANGE_SPEED, disable_speed);
359 this->SetWidgetDisabledState(WID_VT_CLEAR_SPEED, disable_speed);
361
362 this->SetWidgetDisabledState(WID_VT_START_DATE, v->orders == nullptr);
364 this->SetWidgetDisabledState(WID_VT_AUTOFILL, v->orders == nullptr);
365 } else {
374 }
375
377
378 this->DrawWidgets();
379 }
380
381 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
382 {
383 switch (widget) {
384 case WID_VT_CAPTION: return GetString(STR_TIMETABLE_TITLE, this->vehicle->index);
385 case WID_VT_EXPECTED: return GetString(this->show_expected ? STR_TIMETABLE_EXPECTED : STR_TIMETABLE_SCHEDULED);
386 default: return this->Window::GetWidgetString(widget, stringid);
387 }
388 }
389
390 std::string GetTimetableTravelString(const Order &order, int i, TextColour &colour) const
391 {
392 colour = (i == this->sel_index) ? TC_WHITE : TC_BLACK;
393
394 if (order.IsType(OT_CONDITIONAL)) {
395 return GetString(STR_TIMETABLE_NO_TRAVEL);
396 }
397
398 if (order.IsType(OT_IMPLICIT)) {
399 colour = ((i == this->sel_index) ? TC_SILVER : TC_GREY) | TC_NO_SHADE;
400 return GetString(STR_TIMETABLE_NOT_TIMETABLEABLE);
401 }
402
403 if (order.IsTravelTimetabled()) {
404 auto [str, value] = GetTimetableParameters(order.GetTimetabledTravel());
405 return order.GetMaxSpeed() != UINT16_MAX
406 ? GetString(STR_TIMETABLE_TRAVEL_FOR_SPEED, str, value, PackVelocity(order.GetMaxSpeed(), this->vehicle->type))
407 : GetString(STR_TIMETABLE_TRAVEL_FOR, str, value);
408 }
409
410 if (order.GetTravelTime() > 0) {
411 auto [str, value] = GetTimetableParameters(order.GetTravelTime());
412 return order.GetMaxSpeed() != UINT16_MAX
413 ? GetString(STR_TIMETABLE_TRAVEL_FOR_SPEED_ESTIMATED, str, value, PackVelocity(order.GetMaxSpeed(), this->vehicle->type))
414 : GetString(STR_TIMETABLE_TRAVEL_FOR_ESTIMATED, str, value);
415 }
416
417 return order.GetMaxSpeed() != UINT16_MAX
418 ? GetString(STR_TIMETABLE_TRAVEL_NOT_TIMETABLED_SPEED, PackVelocity(order.GetMaxSpeed(), this->vehicle->type))
419 : GetString(STR_TIMETABLE_TRAVEL_NOT_TIMETABLED);
420 }
421
426 void DrawTimetablePanel(const Rect &r) const
427 {
428 const Vehicle *v = this->vehicle;
429 if (v->GetNumOrders() == 0) return;
430 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
431 int i = this->vscroll->GetPosition();
432 VehicleOrderID order_id = (i + 1) / 2;
433 bool final_order = false;
434 int selected = this->sel_index;
435
436 bool rtl = _current_text_dir == TD_RTL;
437 int index_column_width = GetStringBoundingBox(GetString(STR_ORDER_INDEX, GetParamMaxValue(v->GetNumOrders(), 2))).width + 2 * GetSpriteSize(rtl ? SPR_ARROW_RIGHT : SPR_ARROW_LEFT).width + WidgetDimensions::scaled.hsep_normal;
438 int middle = rtl ? tr.right - index_column_width : tr.left + index_column_width;
439
440 auto orders = v->Orders();
441 while (true) {
442 /* Don't draw anything if it extends past the end of the window. */
443 if (!this->vscroll->IsVisible(i)) break;
444
445 if (i % 2 == 0) {
446 DrawOrderString(v, &orders[order_id], order_id, tr.top, i == selected, true, tr.left, middle, tr.right);
447 if (v->orders->GetNext(order_id) == 0) final_order = true;
448 order_id = v->orders->GetNext(order_id);
449 } else {
450 TextColour colour;
451 std::string string = GetTimetableTravelString(orders[order_id], i, colour);
452
453 DrawString(rtl ? tr.left : middle, rtl ? middle : tr.right, tr.top, string, colour);
454
455 if (final_order) break;
456 }
457
458 i++;
459 tr.top += GetCharacterHeight(FS_NORMAL);
460 }
461 }
462
467 void DrawArrivalDeparturePanel(const Rect &r) const
468 {
469 const Vehicle *v = this->vehicle;
470
471 /* Arrival and departure times are handled in an all-or-nothing approach,
472 * i.e. are only shown if we can calculate all times.
473 * Excluding order lists with only one order makes some things easier. */
474 TimerGameTick::Ticks total_time = v->orders != nullptr ? v->orders->GetTimetableDurationIncomplete() : 0;
475 if (total_time <= 0 || v->GetNumOrders() <= 1 || !v->vehicle_flags.Test(VehicleFlag::TimetableStarted)) return;
476
477 std::vector<TimetableArrivalDeparture> arr_dep(v->GetNumOrders());
478 const VehicleOrderID cur_order = v->cur_real_order_index % v->GetNumOrders();
479
481 int selected = this->sel_index;
482
483 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
484 bool show_late = this->show_expected && VehicleIsAboveLatenessThreshold(v->lateness_counter, true);
485 TimerGameTick::Ticks offset = show_late ? 0 : -v->lateness_counter;
486
487 for (int i = this->vscroll->GetPosition(); i / 2 < v->GetNumOrders(); ++i) { // note: i is also incremented in the loop
488 /* Don't draw anything if it extends past the end of the window. */
489 if (!this->vscroll->IsVisible(i)) break;
490
491 /* TC_INVALID will skip the colour change. */
492 TextColour tc = show_late ? TC_RED : TC_INVALID;
493 if (i % 2 == 0) {
494 /* Draw an arrival time. */
495 if (arr_dep[i / 2].arrival != Ticks::INVALID_TICKS) {
496 /* First set the offset and text colour based on the expected/scheduled mode and some other things. */
497 TimerGameTick::Ticks this_offset;
498 if (this->show_expected && i / 2 == early_id) {
499 /* Show expected arrival. */
500 this_offset = 0;
501 tc = TC_GREEN;
502 } else {
503 /* Show scheduled arrival. */
504 this_offset = offset;
505 }
506
507 /* Now actually draw the arrival time. */
508 if (_settings_client.gui.timetable_mode == TimetableMode::Seconds) {
509 /* Display seconds from now. */
510 DrawString(tr,
511 GetString(STR_TIMETABLE_ARRIVAL_SECONDS_IN_FUTURE, tc, (arr_dep[i / 2].arrival + offset) / Ticks::TICKS_PER_SECOND),
512 i == selected ? TC_WHITE : TC_BLACK);
513 } else {
514 /* Show a date. */
515 DrawString(tr,
516 GetString(STR_TIMETABLE_ARRIVAL_DATE, tc, TimerGameEconomy::date + (arr_dep[i / 2].arrival + this_offset) / Ticks::DAY_TICKS),
517 i == selected ? TC_WHITE : TC_BLACK);
518 }
519 }
520 } else {
521 /* Draw a departure time. */
522 if (arr_dep[i / 2].departure != Ticks::INVALID_TICKS) {
523 if (_settings_client.gui.timetable_mode == TimetableMode::Seconds) {
524 /* Display seconds from now. */
525 DrawString(tr,
526 GetString(STR_TIMETABLE_DEPARTURE_SECONDS_IN_FUTURE, tc, (arr_dep[i / 2].departure + offset) / Ticks::TICKS_PER_SECOND),
527 i == selected ? TC_WHITE : TC_BLACK);
528 } else {
529 /* Show a date. */
530 DrawString(tr,
531 GetString(STR_TIMETABLE_DEPARTURE_DATE, tc, TimerGameEconomy::date + (arr_dep[i / 2].departure + offset) / Ticks::DAY_TICKS),
532 i == selected ? TC_WHITE : TC_BLACK);
533 }
534 }
535 }
536 tr.top += GetCharacterHeight(FS_NORMAL);
537 }
538 }
539
540 std::string GetTimetableTotalTimeString(TimerGameTick::Ticks total_time) const
541 {
542 auto [str, value] = GetTimetableParameters(total_time);
543 if (!this->vehicle->orders->IsCompleteTimetable()) return GetString(STR_TIMETABLE_TOTAL_TIME_INCOMPLETE, str, value);
544 if (total_time % TicksPerTimetableUnit() == 0) return GetString(STR_TIMETABLE_TOTAL_TIME, str, value);
545 return GetString(STR_TIMETABLE_APPROX_TIME, str, value);
546 }
547
552 void DrawSummaryPanel(const Rect &r) const
553 {
554 const Vehicle *v = this->vehicle;
555 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
556
557 TimerGameTick::Ticks total_time = v->orders != nullptr ? v->orders->GetTimetableDurationIncomplete() : 0;
558 if (total_time != 0) {
559 DrawString(tr, GetTimetableTotalTimeString(total_time));
560 }
561 tr.top += GetCharacterHeight(FS_NORMAL);
562
563 /* Draw the lateness display, or indicate that the timetable has not started yet. */
564 if (v->timetable_start != 0) {
565 /* We are running towards the first station so we can start the
566 * timetable at the given time. */
567 if (_settings_client.gui.timetable_mode == TimetableMode::Seconds) {
568 /* Real time units use seconds relative to now. */
569 DrawString(tr, GetString(STR_TIMETABLE_STATUS_START_IN_SECONDS, static_cast<TimerGameTick::Ticks>(v->timetable_start - TimerGameTick::counter) / Ticks::TICKS_PER_SECOND));
570 } else {
571 /* Other units use dates. */
572 DrawString(tr, GetString(STR_TIMETABLE_STATUS_START_AT_DATE, STR_JUST_DATE_TINY, GetDateFromStartTick(v->timetable_start)));
573 }
575 /* We aren't running on a timetable yet. */
576 DrawString(tr, STR_TIMETABLE_STATUS_NOT_STARTED);
577 } else if (!VehicleIsAboveLatenessThreshold(abs(v->lateness_counter), false)) {
578 /* We are on time. */
579 DrawString(tr, STR_TIMETABLE_STATUS_ON_TIME);
580 } else {
581 /* We are late. */
582 auto [str, value] = GetTimetableParameters(abs(v->lateness_counter));
583 DrawString(tr, GetString(v->lateness_counter < 0 ? STR_TIMETABLE_STATUS_EARLY : STR_TIMETABLE_STATUS_LATE, str, value));
584 }
585 }
586
587 void DrawWidget(const Rect &r, WidgetID widget) const override
588 {
589 switch (widget) {
591 this->DrawTimetablePanel(r);
592 break;
593 }
594
597 break;
598 }
599
601 this->DrawSummaryPanel(r);
602 break;
603 }
604 }
605 }
606
607 static inline std::tuple<VehicleOrderID, ModifyTimetableFlags> PackTimetableArgs(const Vehicle *v, uint selected, bool speed)
608 {
609 uint order_number = (selected + 1) / 2;
610 ModifyTimetableFlags mtf = (selected % 2 != 0) ? (speed ? MTF_TRAVEL_SPEED : MTF_TRAVEL_TIME) : MTF_WAIT_TIME;
611
612 if (order_number >= v->GetNumOrders()) order_number = 0;
613
614 return { order_number, mtf };
615 }
616
617 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
618 {
619 const Vehicle *v = this->vehicle;
620
621 switch (widget) {
622 case WID_VT_ORDER_VIEW: // Order view button
623 ShowOrdersWindow(v);
624 break;
625
626 case WID_VT_TIMETABLE_PANEL: { // Main panel.
627 int selected = GetOrderFromTimetableWndPt(pt.y, v);
628
629 this->CloseChildWindows();
630 this->sel_index = (selected == INT32_MAX || selected == this->sel_index) ? -1 : selected;
631 break;
632 }
633
634 case WID_VT_START_DATE: // Change the date that the timetable starts.
635 if (_settings_client.gui.timetable_mode == TimetableMode::Seconds) {
637 this->change_timetable_all = _ctrl_pressed;
638 ShowQueryString({}, STR_TIMETABLE_START_SECONDS_QUERY, 6, this, CS_NUMERAL, QueryStringFlag::AcceptUnchanged);
639 } else {
641 [ctrl=_ctrl_pressed](const Window *w, TimerGameEconomy::Date date) {
642 Command<CMD_SET_TIMETABLE_START>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, w->window_number, ctrl, GetStartTickFromDate(date));
643 }
644 );
645 }
646 break;
647
648 case WID_VT_CHANGE_TIME: { // "Wait For" button.
650 int selected = this->sel_index;
651 VehicleOrderID real = (selected + 1) / 2;
652
653 if (real >= v->GetNumOrders()) real = 0;
654
655 const Order *order = v->GetOrder(real);
656 std::string current;
657
658 if (order != nullptr) {
659 uint time = (selected % 2 != 0) ? order->GetTravelTime() : order->GetWaitTime();
660 time /= TicksPerTimetableUnit();
661
662 if (time != 0) {
663 current = GetString(STR_JUST_INT, time);
664 }
665 }
666
667 this->change_timetable_all = _ctrl_pressed && (order != nullptr);
668 ShowQueryString(current, STR_TIMETABLE_CHANGE_TIME_QUERY, 31, this, CS_NUMERAL, QueryStringFlag::AcceptUnchanged);
669 break;
670 }
671
672 case WID_VT_CHANGE_SPEED: { // Change max speed button.
674 int selected = this->sel_index;
675 VehicleOrderID real = (selected + 1) / 2;
676
677 if (real >= v->GetNumOrders()) real = 0;
678
679 std::string current;
680 const Order *order = v->GetOrder(real);
681 if (order != nullptr) {
682 if (order->GetMaxSpeed() != UINT16_MAX) {
683 current = GetString(STR_JUST_INT, ConvertKmhishSpeedToDisplaySpeed(order->GetMaxSpeed(), v->type));
684 }
685 }
686
687 this->change_timetable_all = _ctrl_pressed && (order != nullptr);
688 ShowQueryString(current, STR_TIMETABLE_CHANGE_SPEED_QUERY, 31, this, CS_NUMERAL, {});
689 break;
690 }
691
692 case WID_VT_CLEAR_TIME: { // Clear waiting time.
693 auto [order_id, mtf] = PackTimetableArgs(v, this->sel_index, false);
694 if (_ctrl_pressed) {
695 Command<CMD_BULK_CHANGE_TIMETABLE>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, mtf, 0);
696 } else {
697 Command<CMD_CHANGE_TIMETABLE>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, order_id, mtf, 0);
698 }
699 break;
700 }
701
702 case WID_VT_CLEAR_SPEED: { // Clear max speed button.
703 auto [order_id, mtf] = PackTimetableArgs(v, this->sel_index, true);
704 if (_ctrl_pressed) {
705 Command<CMD_BULK_CHANGE_TIMETABLE>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, mtf, UINT16_MAX);
706 } else {
707 Command<CMD_CHANGE_TIMETABLE>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, order_id, mtf, UINT16_MAX);
708 }
709 break;
710 }
711
712 case WID_VT_RESET_LATENESS: // Reset the vehicle's late counter.
713 Command<CMD_SET_VEHICLE_ON_TIME>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, _ctrl_pressed);
714 break;
715
716 case WID_VT_AUTOFILL: { // Autofill the timetable.
718 break;
719 }
720
721 case WID_VT_EXPECTED:
722 this->show_expected = !this->show_expected;
723 break;
724
726 ShowVehicleListWindow(v);
727 break;
728 }
729
730 this->SetDirty();
731 }
732
733 void OnQueryTextFinished(std::optional<std::string> str) override
734 {
735 if (!str.has_value()) return;
736
737 const Vehicle *v = this->vehicle;
738 uint64_t val = ParseInteger<uint64_t>(*str, 10, true).value_or(0);
739 auto [order_id, mtf] = PackTimetableArgs(v, this->sel_index, query_widget == WID_VT_CHANGE_SPEED);
740
741 switch (query_widget) {
742 case WID_VT_CHANGE_SPEED: {
744
745 if (this->change_timetable_all) {
746 Command<CMD_BULK_CHANGE_TIMETABLE>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, mtf, ClampTo<uint16_t>(val));
747 } else {
748 Command<CMD_CHANGE_TIMETABLE>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, order_id, mtf, ClampTo<uint16_t>(val));
749 }
750 break;
751 }
752
754 val *= TicksPerTimetableUnit();
755
756 if (this->change_timetable_all) {
757 Command<CMD_BULK_CHANGE_TIMETABLE>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, mtf, ClampTo<uint16_t>(val));
758 } else {
759 Command<CMD_CHANGE_TIMETABLE>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, order_id, mtf, ClampTo<uint16_t>(val));
760 }
761 break;
762
763 case WID_VT_START_DATE: {
765 Command<CMD_SET_TIMETABLE_START>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, this->change_timetable_all, start_tick);
766 break;
767 }
768
769 default:
770 NOT_REACHED();
771 }
772 }
773
774 void OnResize() override
775 {
776 /* Update the scroll bar */
777 this->vscroll->SetCapacityFromWidget(this, WID_VT_TIMETABLE_PANEL, WidgetDimensions::scaled.framerect.Vertical());
778 }
779
784 {
785 this->GetWidget<NWidgetStacked>(WID_VT_ARRIVAL_DEPARTURE_SELECTION)->SetDisplayedPlane(_settings_client.gui.timetable_arrival_departure ? 0 : SZSP_NONE);
786 this->GetWidget<NWidgetStacked>(WID_VT_EXPECTED_SELECTION)->SetDisplayedPlane(_settings_client.gui.timetable_arrival_departure ? 0 : 1);
787 }
788
793 if (_settings_client.gui.timetable_mode == TimetableMode::Seconds) {
794 this->SetDirty();
795 }
796 }};
797};
798
799static constexpr std::initializer_list<NWidgetPart> _nested_timetable_widgets = {
801 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
802 NWidget(WWT_CAPTION, COLOUR_GREY, WID_VT_CAPTION),
803 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_ORDER_VIEW), SetMinimalSize(61, 14), SetStringTip(STR_TIMETABLE_ORDER_VIEW, STR_TIMETABLE_ORDER_VIEW_TOOLTIP),
804 NWidget(WWT_SHADEBOX, COLOUR_GREY),
805 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
806 NWidget(WWT_STICKYBOX, COLOUR_GREY),
807 EndContainer(),
809 NWidget(WWT_PANEL, COLOUR_GREY, WID_VT_TIMETABLE_PANEL), SetMinimalSize(388, 82), SetResize(1, 10), SetToolTip(STR_TIMETABLE_TOOLTIP), SetScrollbar(WID_VT_SCROLLBAR), EndContainer(),
812 EndContainer(),
814 EndContainer(),
819 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_CHANGE_TIME), SetResize(1, 0), SetFill(1, 1), SetStringTip(STR_TIMETABLE_CHANGE_TIME, STR_TIMETABLE_WAIT_TIME_TOOLTIP),
820 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_CLEAR_TIME), SetResize(1, 0), SetFill(1, 1), SetStringTip(STR_TIMETABLE_CLEAR_TIME, STR_TIMETABLE_CLEAR_TIME_TOOLTIP),
821 EndContainer(),
823 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_CHANGE_SPEED), SetResize(1, 0), SetFill(1, 1), SetStringTip(STR_TIMETABLE_CHANGE_SPEED, STR_TIMETABLE_CHANGE_SPEED_TOOLTIP),
824 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_CLEAR_SPEED), SetResize(1, 0), SetFill(1, 1), SetStringTip(STR_TIMETABLE_CLEAR_SPEED, STR_TIMETABLE_CLEAR_SPEED_TOOLTIP),
825 EndContainer(),
827 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_START_DATE), SetResize(1, 0), SetFill(1, 1), SetStringTip(STR_TIMETABLE_START, STR_TIMETABLE_START_TOOLTIP),
828 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_RESET_LATENESS), SetResize(1, 0), SetFill(1, 1), SetStringTip(STR_TIMETABLE_RESET_LATENESS, STR_TIMETABLE_RESET_LATENESS_TOOLTIP),
829 EndContainer(),
831 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_AUTOFILL), SetResize(1, 0), SetFill(1, 1), SetStringTip(STR_TIMETABLE_AUTOFILL, STR_TIMETABLE_AUTOFILL_TOOLTIP),
833 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_EXPECTED), SetResize(1, 0), SetFill(1, 1), SetToolTip(STR_TIMETABLE_EXPECTED_TOOLTIP),
834 NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), SetFill(1, 1), EndContainer(),
835 EndContainer(),
836 EndContainer(),
837 EndContainer(),
839 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VT_SHARED_ORDER_LIST), SetFill(0, 1), SetSpriteTip(SPR_SHARED_ORDERS_ICON, STR_ORDERS_VEH_WITH_SHARED_ORDERS_LIST_TOOLTIP),
840 NWidget(WWT_RESIZEBOX, COLOUR_GREY), SetFill(0, 1),
841 EndContainer(),
842 EndContainer(),
843};
844
845static WindowDesc _timetable_desc(
846 WDP_AUTO, "view_vehicle_timetable", 400, 130,
849 _nested_timetable_widgets
850);
851
857{
860 AllocateWindowDescFront<TimetableWindow>(_timetable_desc, v->index);
861}
@ AutofillTimetable
Whether the vehicle should fill in the timetable automatically.
@ TimetableStarted
Whether the vehicle has started running on the timetable yet.
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr bool None() const
Test if none of the values are set.
An interval timer will fire every interval, and will continue to fire until it is deleted.
Definition timer.h:76
Scrollbar data structure.
bool IsVisible(size_type item) const
Checks whether given current item is visible in the list.
void SetCount(size_t num)
Sets the number of elements in the list.
size_type GetScrolledRowFromWidget(int clickpos, const Window *const w, WidgetID widget, int padding=0, int line_height=-1) const
Compute the row of a scrolled widget that a user clicked in.
Definition widget.cpp:2425
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:2499
size_type GetPosition() const
Gets the position of the first visible element in the list.
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
static constexpr TimerGameTick::Ticks INVALID_TICKS
Representation of an invalid number of ticks.
static constexpr TimerGameTick::Ticks TICKS_PER_SECOND
Estimation of how many ticks fit in a single second.
static constexpr TimerGame< struct Economy >::Year MAX_YEAR
MAX_YEAR, nicely rounded value of the number of years that can be encoded in a single 32 bits date,...
static Date date
Current date in days (day counter).
static Year year
Current year, starting at 0.
static bool UsingWallclockUnits(bool newgame=false)
Check if we are using wallclock units.
static DateFract date_fract
Fractional part of the day.
uint64_t TickCounter
The type that the tick counter is stored in.
static TickCounter counter
Monotonic counter, in ticks, since start of game.
int32_t Ticks
The type to store ticks in.
@ NONE
These timers can be executed in any order; the order is not relevant.
static constexpr Date DateAtStartOfYear(Year year)
Calculate the date of the first day of a given year.
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:30
int hsep_wide
Wide horizontal spacing.
Definition window_gui.h:62
Functions related to commands.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Functions related to companies.
void ShowSetDateWindow(Window *parent, int window_number, TimerGameEconomy::Date initial_date, TimerGameEconomy::Year min_year, TimerGameEconomy::Year max_year, SetDateCallback &&callback)
Create the new 'set date' window.
Definition date_gui.cpp:214
Functions related to the graphical selection of a date.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:962
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:891
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:662
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:38
Functions related to the gfx engine.
@ FS_SMALL
Index of the small font in the font tables.
Definition gfx_type.h:250
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:249
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:307
@ TC_NO_SHADE
Do not add shading to this text colour.
Definition gfx_type.h:331
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
constexpr NWidgetPart SetSpriteTip(SpriteID sprite, StringID tip={})
Widget part function for setting the sprite and tooltip.
constexpr NWidgetPart SetScrollbar(WidgetID index)
Attach a scrollbar to a widget.
constexpr NWidgetPart SetStringTip(StringID string, StringID tip={})
Widget part function for setting the string and tooltip.
constexpr NWidgetPart 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 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:966
GUI functions that shouldn't be here.
constexpr bool IsInsideBS(const T x, const size_t base, const size_t size)
Checks if a value is between a window started at some base point.
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition math_func.hpp:23
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 DrawOrderString(const Vehicle *v, const Order *order, VehicleOrderID order_index, int y, bool selected, bool timetable, int left, int middle, int right)
Draws an order in order or timetable GUI.
@ NoDestination
The vehicle will stop at any station it passes except the destination, aka via.
uint8_t VehicleOrderID
The index of an order within its current vehicle (not pool related)
Definition order_type.h:18
static const VehicleOrderID INVALID_VEH_ORDER_ID
Invalid vehicle order index (sentinel)
Definition order_type.h:39
ModifyTimetableFlags
Enumeration for the data to set in CmdChangeTimetable.
Definition order_type.h:186
@ MTF_TRAVEL_TIME
Set travel time.
Definition order_type.h:188
@ MTF_WAIT_TIME
Set wait time.
Definition order_type.h:187
@ MTF_TRAVEL_SPEED
Set max travel speed.
Definition order_type.h:189
A number of safeguards to prevent using unsafe methods.
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
Types related to global configuration settings.
This file contains all sprite-related enums and defines.
Definition of base types and functions in a cross-platform compatible way.
Parse strings.
Functions related to low-level strings.
@ CS_NUMERAL
Only numeric ones.
Definition string_type.h:26
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
uint ConvertDisplaySpeedToKmhishSpeed(uint speed, VehicleType type)
Convert the given display speed to the km/h-ish speed.
Definition strings.cpp:1001
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:424
uint ConvertKmhishSpeedToDisplaySpeed(uint speed, VehicleType type)
Convert the given km/h-ish speed to the display speed.
Definition strings.cpp:991
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
uint64_t GetParamMaxDigits(uint count, FontSize size)
Get some number that is suitable for string size computations.
Definition strings.cpp:218
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.
TimerGameTick::Ticks current_order_time
How many ticks have passed since this order started.
VehicleOrderID cur_real_order_index
The index to the current real (non-implicit) order.
VehicleFlags vehicle_flags
Used for gradual loading and other miscellaneous things (.
TimerGameTick::TickCounter timetable_start
At what tick of TimerGameTick::counter the vehicle should start its timetable.
TimerGameTick::Ticks lateness_counter
How many ticks late (or early if negative) this vehicle is.
VehicleType type
Type of vehicle.
GUISettings gui
settings related to the GUI
Dimensions (a width and height) of a rectangle in 2D.
bool timetable_arrival_departure
show arrivals and departures in vehicle timetables
TimetableMode timetable_mode
Time units for timetables: days, seconds, or ticks.
TimerGameTick::Ticks GetTimetableDurationIncomplete() const
Gets the known duration of the vehicles timetable even if the timetable is not complete.
Definition order_base.h:427
bool IsCompleteTimetable() const
Checks whether all orders of the list have a filled timetable.
VehicleOrderID GetNext(VehicleOrderID cur) const
Get the order after the given one or the first one, if the given one is the last one.
Definition order_base.h:362
uint16_t GetTimetabledTravel() const
Get the time in ticks a vehicle should take to reach the destination or 0 if it's not timetabled.
Definition order_base.h:196
uint16_t GetMaxSpeed() const
Get the maxmimum speed in km-ish/h a vehicle is allowed to reach on the way to the destination.
Definition order_base.h:207
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition order_base.h:66
uint16_t GetWaitTime() const
Get the time in ticks a vehicle will probably wait at the destination (timetabled or not).
Definition order_base.h:198
bool IsWaitTimetabled() const
Does this order have an explicit wait time set?
Definition order_base.h:189
bool IsTravelTimetabled() const
Does this order have an explicit travel time set?
Definition order_base.h:191
uint16_t GetTravelTime() const
Get the time in ticks a vehicle will probably take to reach the destination (timetabled or not).
Definition order_base.h:200
OrderNonStopFlags GetNonStopType() const
At which stations must we stop?
Definition order_base.h:146
static Titem * Get(auto index)
Returns Titem with given index.
Tindex index
Index of this pool item.
Specification of a rectangle with absolute coordinates of all edges.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
Templated helper to make a type-safe 'typedef' representing a single POD value.
Container for the arrival/departure dates of a vehicle.
TimerGameTick::Ticks arrival
The arrival time.
TimerGameTick::Ticks departure
The departure time.
void OnResize() override
Called after the window got resized.
void DrawTimetablePanel(const Rect &r) const
Helper function to draw the timetable panel.
bool set_start_date_all
Set start date using minutes text entry for all timetable entries (ctrl-click) action.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
void DrawSummaryPanel(const Rect &r) const
Helper function to draw the summary panel.
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.
void OnQueryTextFinished(std::optional< std::string > str) override
The query window opened from this window has closed.
const Vehicle * vehicle
Vehicle monitored by the window.
void UpdateSelectionStates()
Update the selection state of the arrival/departure data.
Scrollbar * vscroll
The scrollbar.
bool show_expected
Whether we show expected arrival or scheduled.
const IntervalTimer< TimerGameTick > redraw_interval
In real-time mode, the timetable GUI shows relative times and needs to be redrawn every second.
void OnPaint() override
The window must be repainted.
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 DrawArrivalDeparturePanel(const Rect &r) const
Helper function to draw the arrival and departure panel.
VehicleTimetableWidgets query_widget
Which button was clicked to open the query text input?
bool change_timetable_all
Set wait time or speed for all timetable entries (ctrl-click) action.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
static bool BuildArrivalDepartureList(const Vehicle *v, std::vector< TimetableArrivalDeparture > &table)
Build the arrival-departure list for a given vehicle.
Vehicle data structure.
bool IsOrderListShared() const
Check if we share our orders with another vehicle.
Order * GetOrder(int index) const
Returns order 'index' of a vehicle or nullptr when it doesn't exists.
VehicleOrderID GetNumOrders() const
Get the number of orders this vehicle has.
Order current_order
The current order (+ status, like: loading)
OrderList * orders
Pointer to the order list for this vehicle.
Owner owner
Which company owns the vehicle?
High level window description.
Definition window_gui.h:168
Number to differentiate different windows of the same class.
Data structure for an opened window.
Definition window_gui.h:274
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition window.cpp:978
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1807
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:766
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:504
void CloseChildWindows(WindowClass wc=WC_INVALID) const
Close all children a window might have in a head-recursive manner.
Definition window.cpp:1075
ResizeInfo resize
Resize information.
Definition window_gui.h:315
void DisableWidget(WidgetID widget_index)
Sets a widget to disabled.
Definition window_gui.h:392
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1797
Owner owner
The owner of the content shown in this window. Company colour is acquired from this variable.
Definition window_gui.h:317
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition window_gui.h:442
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:313
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:382
int width
width of the window (number of pixels to the right in x direction)
Definition window_gui.h:312
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:303
Stuff related to the text buffer GUI.
@ AcceptUnchanged
return success even when the text didn't change
Definition of Interval and OneShot timers.
Definition of the game-economy-timer.
Definition of the tick-based game-timer.
Definition of the Window system.
Functions related to time tabling.
static const TimerGameEconomy::Year MAX_TIMETABLE_START_YEARS
The maximum start date offset, in economy years.
Definition timetable.h:18
TimerGameEconomy::Date GetDateFromStartTick(TimerGameTick::TickCounter start_tick)
Get a date from a given start tick of timetable.
Command definitions related to timetables.
static TimerGameTick::Ticks TicksPerTimetableUnit()
Get the number of ticks in the current timetable display unit.
void ShowTimetableWindow(const Vehicle *v)
Show the timetable for a given vehicle.
static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID start, bool travelling, std::vector< TimetableArrivalDeparture > &table, TimerGameTick::Ticks offset)
Fill the table with arrivals and departures.
std::pair< StringParameter, StringParameter > GetTimetableParameters(TimerGameTick::Ticks ticks)
Get parameters to format timetable time.
bool VehicleIsAboveLatenessThreshold(TimerGameTick::Ticks ticks, bool round_to_day)
Determine if a vehicle should be shown as late or early, using a threshold depending on the timetable...
static bool CanDetermineTimeTaken(const Order &order, bool travelling)
Check whether it is possible to determine how long the order takes.
Types related to the timetable widgets.
VehicleTimetableWidgets
Widgets of the TimetableWindow class.
@ WID_VT_CHANGE_TIME
Change time button.
@ WID_VT_ARRIVAL_DEPARTURE_PANEL
Panel with the expected/scheduled arrivals.
@ WID_VT_ARRIVAL_DEPARTURE_SELECTION
Disable/hide the arrival departure panel.
@ WID_VT_CLEAR_SPEED
Clear speed limit button.
@ WID_VT_EXPECTED
Toggle between expected and scheduled arrivals.
@ WID_VT_CHANGE_SPEED
Change speed limit button.
@ WID_VT_TIMETABLE_PANEL
Timetable panel.
@ WID_VT_AUTOFILL
Autofill button.
@ WID_VT_SCROLLBAR
Scrollbar for the panel.
@ WID_VT_RESET_LATENESS
Reset lateness button.
@ WID_VT_SHARED_ORDER_LIST
Show the shared order list.
@ WID_VT_SUMMARY_PANEL
Summary panel.
@ WID_VT_CAPTION
Caption of the window.
@ WID_VT_START_DATE
Start date button.
@ WID_VT_EXPECTED_SELECTION
Disable/hide the expected selection button.
@ WID_VT_ORDER_VIEW
Order view.
@ WID_VT_CLEAR_TIME
Clear time button.
Base class for all vehicles.
Functions related to the vehicle's GUIs.
@ VIWD_AUTOREPLACE
Autoreplace replaced the vehicle.
Definition vehicle_gui.h:38
@ VIWD_MODIFY_ORDERS
Other order modifications.
Definition vehicle_gui.h:36
@ VIWD_REMOVE_ALL_ORDERS
Removed / replaced all orders (after deleting / sharing).
Definition vehicle_gui.h:35
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
@ WWT_PUSHIMGBTN
Normal push-button (no toggle button) with image caption.
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:66
@ 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
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:71
@ SZSP_NONE
Display plane with zero size in both directions (none filling and resizing).
@ 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:1193
Window functions not directly related to making/drawing windows.
Functions, definitions and such used only by the GUI.
@ Construction
This window is used for construction; close it whenever changing company.
@ WDP_AUTO
Find a place automatically.
Definition window_gui.h:144
int WidgetID
Widget ID.
Definition window_type.h:20
@ WC_VEHICLE_ORDERS
Vehicle orders; Window numbers:
@ WC_VEHICLE_DETAILS
Vehicle details; Window numbers:
@ WC_VEHICLE_VIEW
Vehicle view; Window numbers:
@ WC_VEHICLE_TIMETABLE
Vehicle timetable; Window numbers: