OpenTTD Source 20260531-master-g0e951f3528
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
9
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{
52 switch (_settings_client.gui.timetable_mode) {
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{
67 switch (_settings_client.gui.timetable_mode) {
69 return Ticks::DAY_TICKS;
73 return 1;
74 default:
75 NOT_REACHED();
76 }
77}
78
86{
87 switch (_settings_client.gui.timetable_mode) {
89 return ticks > Ticks::DAY_TICKS;
91 return ticks > Ticks::TICKS_PER_SECOND;
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
174struct TimetableWindow : Window {
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
183 TimetableWindow(WindowDesc &desc, WindowNumber window_number) :
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, FontSize::Small);
230 size.width = std::max(
231 GetStringBoundingBox(GetString(STR_TIMETABLE_ARRIVAL_SECONDS_IN_FUTURE, TextColour::Black, max_digits)).width,
232 GetStringBoundingBox(GetString(STR_TIMETABLE_DEPARTURE_SECONDS_IN_FUTURE, TextColour::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, TextColour::Black, max_value)).width,
238 GetStringBoundingBox(GetString(STR_TIMETABLE_DEPARTURE_DATE, TextColour::Black, max_value)).width)
239 + WidgetDimensions::scaled.hsep_wide + padding.width;
240 }
241 [[fallthrough]];
242
244 fill.height = resize.height = GetCharacterHeight(FontSize::Normal);
245 size.height = 8 * resize.height + padding.height;
246 break;
247
249 size.height = 2 * GetCharacterHeight(FontSize::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::GoVia)) && !order->IsType(OT_CONDITIONAL));
352 }
353 }
354 bool disable_speed = disable || selected % 2 == 0 || v->type == VehicleType::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
397 std::string GetTimetableTravelString(const Order &order, int i, ExtendedTextColour &colour) const
398 {
399 colour = (i == this->sel_index) ? TextColour::White : TextColour::Black;
400
401 if (order.IsType(OT_CONDITIONAL)) {
402 return GetString(STR_TIMETABLE_NO_TRAVEL);
403 }
404
405 if (order.IsType(OT_IMPLICIT)) {
407 return GetString(STR_TIMETABLE_NOT_TIMETABLEABLE);
408 }
409
410 if (order.IsTravelTimetabled()) {
411 auto [str, value] = GetTimetableParameters(order.GetTimetabledTravel());
412 return order.GetMaxSpeed() != UINT16_MAX
413 ? GetString(STR_TIMETABLE_TRAVEL_FOR_SPEED, str, value, PackVelocity(order.GetMaxSpeed(), this->vehicle->type))
414 : GetString(STR_TIMETABLE_TRAVEL_FOR, str, value);
415 }
416
417 if (order.GetTravelTime() > 0) {
418 auto [str, value] = GetTimetableParameters(order.GetTravelTime());
419 return order.GetMaxSpeed() != UINT16_MAX
420 ? GetString(STR_TIMETABLE_TRAVEL_FOR_SPEED_ESTIMATED, str, value, PackVelocity(order.GetMaxSpeed(), this->vehicle->type))
421 : GetString(STR_TIMETABLE_TRAVEL_FOR_ESTIMATED, str, value);
422 }
423
424 return order.GetMaxSpeed() != UINT16_MAX
425 ? GetString(STR_TIMETABLE_TRAVEL_NOT_TIMETABLED_SPEED, PackVelocity(order.GetMaxSpeed(), this->vehicle->type))
426 : GetString(STR_TIMETABLE_TRAVEL_NOT_TIMETABLED);
427 }
428
433 void DrawTimetablePanel(const Rect &r) const
434 {
435 const Vehicle *v = this->vehicle;
436 if (v->GetNumOrders() == 0) return;
437 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
438 int i = this->vscroll->GetPosition();
439 VehicleOrderID order_id = (i + 1) / 2;
440 bool final_order = false;
441 int selected = this->sel_index;
442
443 bool rtl = _current_text_dir == TD_RTL;
444 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;
445 int middle = rtl ? tr.right - index_column_width : tr.left + index_column_width;
446
447 auto orders = v->Orders();
448 while (true) {
449 /* Don't draw anything if it extends past the end of the window. */
450 if (!this->vscroll->IsVisible(i)) break;
451
452 if (i % 2 == 0) {
453 DrawOrderString(v, &orders[order_id], order_id, tr.top, i == selected, true, tr.left, middle, tr.right);
454 if (v->orders->GetNext(order_id) == 0) final_order = true;
455 order_id = v->orders->GetNext(order_id);
456 } else {
457 ExtendedTextColour colour;
458 std::string string = GetTimetableTravelString(orders[order_id], i, colour);
459
460 DrawString(rtl ? tr.left : middle, rtl ? middle : tr.right, tr.top, string, colour);
461
462 if (final_order) break;
463 }
464
465 i++;
467 }
468 }
469
474 void DrawArrivalDeparturePanel(const Rect &r) const
475 {
476 const Vehicle *v = this->vehicle;
477
478 /* Arrival and departure times are handled in an all-or-nothing approach,
479 * i.e. are only shown if we can calculate all times.
480 * Excluding order lists with only one order makes some things easier. */
481 TimerGameTick::Ticks total_time = v->orders != nullptr ? v->orders->GetTimetableDurationIncomplete() : 0;
482 if (total_time <= 0 || v->GetNumOrders() <= 1 || !v->vehicle_flags.Test(VehicleFlag::TimetableStarted)) return;
483
484 std::vector<TimetableArrivalDeparture> arr_dep(v->GetNumOrders());
485 const VehicleOrderID cur_order = v->cur_real_order_index % v->GetNumOrders();
486
488 int selected = this->sel_index;
489
490 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
491 bool show_late = this->show_expected && VehicleIsAboveLatenessThreshold(v->lateness_counter, true);
492 TimerGameTick::Ticks offset = show_late ? 0 : -v->lateness_counter;
493
494 for (int i = this->vscroll->GetPosition(); i / 2 < v->GetNumOrders(); ++i) { // note: i is also incremented in the loop
495 /* Don't draw anything if it extends past the end of the window. */
496 if (!this->vscroll->IsVisible(i)) break;
497
498 /* TextColour::Invalid will skip the colour change. */
500 if (i % 2 == 0) {
501 /* Draw an arrival time. */
502 if (arr_dep[i / 2].arrival != Ticks::INVALID_TICKS) {
503 /* First set the offset and text colour based on the expected/scheduled mode and some other things. */
504 TimerGameTick::Ticks this_offset;
505 if (this->show_expected && i / 2 == early_id) {
506 /* Show expected arrival. */
507 this_offset = 0;
509 } else {
510 /* Show scheduled arrival. */
511 this_offset = offset;
512 }
513
514 /* Now actually draw the arrival time. */
515 if (_settings_client.gui.timetable_mode == TimetableMode::Seconds) {
516 /* Display seconds from now. */
517 DrawString(tr,
518 GetString(STR_TIMETABLE_ARRIVAL_SECONDS_IN_FUTURE, tc, (arr_dep[i / 2].arrival + offset) / Ticks::TICKS_PER_SECOND),
519 i == selected ? TextColour::White : TextColour::Black);
520 } else {
521 /* Show a date. */
522 DrawString(tr,
523 GetString(STR_TIMETABLE_ARRIVAL_DATE, tc, TimerGameEconomy::date + (arr_dep[i / 2].arrival + this_offset) / Ticks::DAY_TICKS),
524 i == selected ? TextColour::White : TextColour::Black);
525 }
526 }
527 } else {
528 /* Draw a departure time. */
529 if (arr_dep[i / 2].departure != Ticks::INVALID_TICKS) {
530 if (_settings_client.gui.timetable_mode == TimetableMode::Seconds) {
531 /* Display seconds from now. */
532 DrawString(tr,
533 GetString(STR_TIMETABLE_DEPARTURE_SECONDS_IN_FUTURE, tc, (arr_dep[i / 2].departure + offset) / Ticks::TICKS_PER_SECOND),
534 i == selected ? TextColour::White : TextColour::Black);
535 } else {
536 /* Show a date. */
537 DrawString(tr,
538 GetString(STR_TIMETABLE_DEPARTURE_DATE, tc, TimerGameEconomy::date + (arr_dep[i / 2].departure + offset) / Ticks::DAY_TICKS),
539 i == selected ? TextColour::White : TextColour::Black);
540 }
541 }
542 }
544 }
545 }
546
547 std::string GetTimetableTotalTimeString(TimerGameTick::Ticks total_time) const
548 {
549 auto [str, value] = GetTimetableParameters(total_time);
550 if (!this->vehicle->orders->IsCompleteTimetable()) return GetString(STR_TIMETABLE_TOTAL_TIME_INCOMPLETE, str, value);
551 if (total_time % TicksPerTimetableUnit() == 0) return GetString(STR_TIMETABLE_TOTAL_TIME, str, value);
552 return GetString(STR_TIMETABLE_APPROX_TIME, str, value);
553 }
554
559 void DrawSummaryPanel(const Rect &r) const
560 {
561 const Vehicle *v = this->vehicle;
562 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
563
564 TimerGameTick::Ticks total_time = v->orders != nullptr ? v->orders->GetTimetableDurationIncomplete() : 0;
565 if (total_time != 0) {
566 DrawString(tr, GetTimetableTotalTimeString(total_time));
567 }
569
570 /* Draw the lateness display, or indicate that the timetable has not started yet. */
571 if (v->timetable_start != 0) {
572 /* We are running towards the first station so we can start the
573 * timetable at the given time. */
574 if (_settings_client.gui.timetable_mode == TimetableMode::Seconds) {
575 /* Real time units use seconds relative to now. */
576 DrawString(tr, GetString(STR_TIMETABLE_STATUS_START_IN_SECONDS, static_cast<TimerGameTick::Ticks>(v->timetable_start - TimerGameTick::counter) / Ticks::TICKS_PER_SECOND));
577 } else {
578 /* Other units use dates. */
579 DrawString(tr, GetString(STR_TIMETABLE_STATUS_START_AT_DATE, STR_JUST_DATE_TINY, GetDateFromStartTick(v->timetable_start)));
580 }
582 /* We aren't running on a timetable yet. */
583 DrawString(tr, STR_TIMETABLE_STATUS_NOT_STARTED);
584 } else if (!VehicleIsAboveLatenessThreshold(abs(v->lateness_counter), false)) {
585 /* We are on time. */
586 DrawString(tr, STR_TIMETABLE_STATUS_ON_TIME);
587 } else {
588 /* We are late. */
589 auto [str, value] = GetTimetableParameters(abs(v->lateness_counter));
590 DrawString(tr, GetString(v->lateness_counter < 0 ? STR_TIMETABLE_STATUS_EARLY : STR_TIMETABLE_STATUS_LATE, str, value));
591 }
592 }
593
594 void DrawWidget(const Rect &r, WidgetID widget) const override
595 {
596 switch (widget) {
598 this->DrawTimetablePanel(r);
599 break;
600 }
601
604 break;
605 }
606
608 this->DrawSummaryPanel(r);
609 break;
610 }
611 }
612 }
613
614 static inline std::tuple<VehicleOrderID, ModifyTimetableFlags> PackTimetableArgs(const Vehicle *v, uint selected, bool speed)
615 {
616 uint order_number = (selected + 1) / 2;
617 ModifyTimetableFlags mtf = (selected % 2 != 0) ? (speed ? MTF_TRAVEL_SPEED : MTF_TRAVEL_TIME) : MTF_WAIT_TIME;
618
619 if (order_number >= v->GetNumOrders()) order_number = 0;
620
621 return { order_number, mtf };
622 }
623
624 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
625 {
626 const Vehicle *v = this->vehicle;
627
628 switch (widget) {
629 case WID_VT_ORDER_VIEW: // Order view button
630 ShowOrdersWindow(v);
631 break;
632
633 case WID_VT_TIMETABLE_PANEL: { // Main panel.
634 int selected = GetOrderFromTimetableWndPt(pt.y, v);
635
636 this->CloseChildWindows();
637 this->sel_index = (selected == INT32_MAX || selected == this->sel_index) ? -1 : selected;
638 break;
639 }
640
641 case WID_VT_START_DATE: // Change the date that the timetable starts.
642 if (_settings_client.gui.timetable_mode == TimetableMode::Seconds) {
643 this->query_widget = WID_VT_START_DATE;
644 this->change_timetable_all = _ctrl_pressed;
645 ShowQueryString({}, STR_TIMETABLE_START_SECONDS_QUERY, 6, this, CS_NUMERAL, QueryStringFlag::AcceptUnchanged);
646 } else {
648 [ctrl=_ctrl_pressed](const Window *w, TimerGameEconomy::Date date) {
649 Command<Commands::SetTimetableStart>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, w->window_number, ctrl, GetStartTickFromDate(date));
650 }
651 );
652 }
653 break;
654
655 case WID_VT_CHANGE_TIME: { // "Wait For" button.
656 this->query_widget = WID_VT_CHANGE_TIME;
657 int selected = this->sel_index;
658 VehicleOrderID real = (selected + 1) / 2;
659
660 if (real >= v->GetNumOrders()) real = 0;
661
662 const Order *order = v->GetOrder(real);
663 std::string current;
664
665 if (order != nullptr) {
666 uint time = (selected % 2 != 0) ? order->GetTravelTime() : order->GetWaitTime();
667 time /= TicksPerTimetableUnit();
668
669 if (time != 0) {
670 current = GetString(STR_JUST_INT, time);
671 }
672 }
673
674 this->change_timetable_all = _ctrl_pressed && (order != nullptr);
675 ShowQueryString(current, STR_TIMETABLE_CHANGE_TIME_QUERY, 31, this, CS_NUMERAL, QueryStringFlag::AcceptUnchanged);
676 break;
677 }
678
679 case WID_VT_CHANGE_SPEED: { // Change max speed button.
680 this->query_widget = WID_VT_CHANGE_SPEED;
681 int selected = this->sel_index;
682 VehicleOrderID real = (selected + 1) / 2;
683
684 if (real >= v->GetNumOrders()) real = 0;
685
686 std::string current;
687 const Order *order = v->GetOrder(real);
688 if (order != nullptr) {
689 if (order->GetMaxSpeed() != UINT16_MAX) {
690 current = GetString(STR_JUST_INT, ConvertKmhishSpeedToDisplaySpeed(order->GetMaxSpeed(), v->type));
691 }
692 }
693
694 this->change_timetable_all = _ctrl_pressed && (order != nullptr);
695 ShowQueryString(current, STR_TIMETABLE_CHANGE_SPEED_QUERY, 31, this, CS_NUMERAL, {});
696 break;
697 }
698
699 case WID_VT_CLEAR_TIME: { // Clear waiting time.
700 auto [order_id, mtf] = PackTimetableArgs(v, this->sel_index, false);
701 if (_ctrl_pressed) {
702 Command<Commands::ChangeTimetableBulk>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, mtf, 0);
703 } else {
704 Command<Commands::ChangeTimetable>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, order_id, mtf, 0);
705 }
706 break;
707 }
708
709 case WID_VT_CLEAR_SPEED: { // Clear max speed button.
710 auto [order_id, mtf] = PackTimetableArgs(v, this->sel_index, true);
711 if (_ctrl_pressed) {
712 Command<Commands::ChangeTimetableBulk>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, mtf, UINT16_MAX);
713 } else {
714 Command<Commands::ChangeTimetable>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, order_id, mtf, UINT16_MAX);
715 }
716 break;
717 }
718
719 case WID_VT_RESET_LATENESS: // Reset the vehicle's late counter.
720 Command<Commands::SetVehicleOnTime>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, _ctrl_pressed);
721 break;
722
723 case WID_VT_AUTOFILL: { // Autofill the timetable.
724 Command<Commands::AutofillTimetable>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, !v->vehicle_flags.Test(VehicleFlag::AutofillTimetable), _ctrl_pressed);
725 break;
726 }
727
728 case WID_VT_EXPECTED:
729 this->show_expected = !this->show_expected;
730 break;
731
733 ShowVehicleListWindow(v);
734 break;
735 }
736
737 this->SetDirty();
738 }
739
740 void OnQueryTextFinished(std::optional<std::string> str) override
741 {
742 if (!str.has_value()) return;
743
744 const Vehicle *v = this->vehicle;
745 uint64_t val = ParseInteger<uint64_t>(*str, 10, true).value_or(0);
746 auto [order_id, mtf] = PackTimetableArgs(v, this->sel_index, query_widget == WID_VT_CHANGE_SPEED);
747
748 switch (query_widget) {
749 case WID_VT_CHANGE_SPEED: {
751
752 if (this->change_timetable_all) {
753 Command<Commands::ChangeTimetableBulk>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, mtf, ClampTo<uint16_t>(val));
754 } else {
755 Command<Commands::ChangeTimetable>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, order_id, mtf, ClampTo<uint16_t>(val));
756 }
757 break;
758 }
759
761 val *= TicksPerTimetableUnit();
762
763 if (this->change_timetable_all) {
764 Command<Commands::ChangeTimetableBulk>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, mtf, ClampTo<uint16_t>(val));
765 } else {
766 Command<Commands::ChangeTimetable>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, order_id, mtf, ClampTo<uint16_t>(val));
767 }
768 break;
769
770 case WID_VT_START_DATE: {
772 Command<Commands::SetTimetableStart>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, this->change_timetable_all, start_tick);
773 break;
774 }
775
776 default:
777 NOT_REACHED();
778 }
779 }
780
781 void OnResize() override
782 {
783 /* Update the scroll bar */
784 this->vscroll->SetCapacityFromWidget(this, WID_VT_TIMETABLE_PANEL, WidgetDimensions::scaled.framerect.Vertical());
785 }
786
791 {
792 this->GetWidget<NWidgetStacked>(WID_VT_ARRIVAL_DEPARTURE_SELECTION)->SetDisplayedPlane(_settings_client.gui.timetable_arrival_departure ? 0 : SZSP_NONE);
793 this->GetWidget<NWidgetStacked>(WID_VT_EXPECTED_SELECTION)->SetDisplayedPlane(_settings_client.gui.timetable_arrival_departure ? 0 : 1);
794 }
795
800 if (_settings_client.gui.timetable_mode == TimetableMode::Seconds) {
801 this->SetDirty();
802 }
803 }};
804};
805
806static constexpr std::initializer_list<NWidgetPart> _nested_timetable_widgets = {
810 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_VT_ORDER_VIEW), SetMinimalSize(61, 14), SetStringTip(STR_TIMETABLE_ORDER_VIEW, STR_TIMETABLE_ORDER_VIEW_TOOLTIP),
814 EndContainer(),
819 EndContainer(),
821 EndContainer(),
826 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_VT_CHANGE_TIME), SetResize(1, 0), SetFill(1, 1), SetStringTip(STR_TIMETABLE_CHANGE_TIME, STR_TIMETABLE_WAIT_TIME_TOOLTIP),
827 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_VT_CLEAR_TIME), SetResize(1, 0), SetFill(1, 1), SetStringTip(STR_TIMETABLE_CLEAR_TIME, STR_TIMETABLE_CLEAR_TIME_TOOLTIP),
828 EndContainer(),
830 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_VT_CHANGE_SPEED), SetResize(1, 0), SetFill(1, 1), SetStringTip(STR_TIMETABLE_CHANGE_SPEED, STR_TIMETABLE_CHANGE_SPEED_TOOLTIP),
831 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_VT_CLEAR_SPEED), SetResize(1, 0), SetFill(1, 1), SetStringTip(STR_TIMETABLE_CLEAR_SPEED, STR_TIMETABLE_CLEAR_SPEED_TOOLTIP),
832 EndContainer(),
834 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_VT_START_DATE), SetResize(1, 0), SetFill(1, 1), SetStringTip(STR_TIMETABLE_START, STR_TIMETABLE_START_TOOLTIP),
835 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_VT_RESET_LATENESS), SetResize(1, 0), SetFill(1, 1), SetStringTip(STR_TIMETABLE_RESET_LATENESS, STR_TIMETABLE_RESET_LATENESS_TOOLTIP),
836 EndContainer(),
838 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_VT_AUTOFILL), SetResize(1, 0), SetFill(1, 1), SetStringTip(STR_TIMETABLE_AUTOFILL, STR_TIMETABLE_AUTOFILL_TOOLTIP),
840 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_VT_EXPECTED), SetResize(1, 0), SetFill(1, 1), SetToolTip(STR_TIMETABLE_EXPECTED_TOOLTIP),
842 EndContainer(),
843 EndContainer(),
844 EndContainer(),
846 NWidget(WWT_PUSHIMGBTN, Colours::Grey, WID_VT_SHARED_ORDER_LIST), SetFill(0, 1), SetSpriteTip(SPR_SHARED_ORDERS_ICON, STR_ORDERS_VEH_WITH_SHARED_ORDERS_LIST_TOOLTIP),
848 EndContainer(),
849 EndContainer(),
850};
851
854 WindowPosition::Automatic, "view_vehicle_timetable", 400, 130,
855 WindowClass::VehicleTimetable, WindowClass::VehicleView,
857 _nested_timetable_widgets
858);
859
865{
866 CloseWindowById(WindowClass::VehicleDetails, v->index, false);
867 CloseWindowById(WindowClass::VehicleOrders, v->index, false);
869}
@ 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:2457
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:2531
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
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)
StrongType::Typedef< int32_t, DateTag< struct Economy >, StrongType::Compare, StrongType::Integer > Date
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:30
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.
Definition fontcache.cpp:88
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:971
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:899
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:39
int DrawString(int left, int right, int top, std::string_view str, ExtendedTextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition gfx.cpp:668
Functions related to the gfx engine.
@ Small
Index of the small font in the font tables.
Definition gfx_type.h:250
@ Normal
Index of the normal font in the font tables.
Definition gfx_type.h:249
@ Invalid
Invalid marker.
Definition gfx_type.h:302
@ Grey
Grey.
Definition gfx_type.h:299
@ NoShade
Do not add shading to this text colour.
Definition gfx_type.h:342
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:315
@ White
White colour.
Definition gfx_type.h:330
@ Invalid
Invalid colour.
Definition gfx_type.h:336
@ Grey
Grey colour.
Definition gfx_type.h:332
@ Green
Green colour.
Definition gfx_type.h:325
@ Black
Black colour.
Definition gfx_type.h:334
@ Red
Red colour.
Definition gfx_type.h:321
@ Silver
Silver colour.
Definition gfx_type.h:319
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:980
GUI functions that shouldn't be here.
#define Point
Macro that prevents name conflicts between included headers.
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
constexpr To ClampTo(From value)
Clamp the given value down to lie within the requested type.
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.
@ GoVia
The vehicle will stop at any station it passes except the destination, aka via.
Definition order_type.h:89
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:187
@ MTF_TRAVEL_TIME
Set travel time.
Definition order_type.h:189
@ MTF_WAIT_TIME
Set wait time.
Definition order_type.h:188
@ MTF_TRAVEL_SPEED
Set max travel speed.
Definition order_type.h:190
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.
static std::optional< T > ParseInteger(std::string_view arg, int base=10, bool clamp=false)
Change a string into its number representation.
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:1005
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:994
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.
Dimensions (a width and height) of a rectangle in 2D.
Container for the text colour and some text colour related flags for drawing.
Definition gfx_type.h:348
TimerGameTick::Ticks GetTimetableDurationIncomplete() const
Gets the known duration of the vehicles timetable even if the timetable is not complete.
Definition order_base.h:541
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:476
If you change this, keep in mind that it is also saved in 2 other places:
Definition order_base.h:34
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:288
uint16_t GetMaxSpeed() const
Get the maximum speed in km-ish/h a vehicle is allowed to reach on the way to the destination.
Definition order_base.h:307
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition order_base.h:67
uint16_t GetWaitTime() const
Get the time in ticks a vehicle will probably wait at the destination (timetabled or not).
Definition order_base.h:294
bool IsWaitTimetabled() const
Does this order have an explicit wait time set?
Definition order_base.h:271
bool IsTravelTimetabled() const
Does this order have an explicit travel time set?
Definition order_base.h:277
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:300
OrderNonStopFlags GetNonStopType() const
At which stations must we stop?
Definition order_base.h:158
static Vehicle * Get(auto index)
Specification of a rectangle with absolute coordinates of all edges.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
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.
std::string GetTimetableTravelString(const Order &order, int i, ExtendedTextColour &colour) const
Get the time table travel string.
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.
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition window.cpp:992
void CloseChildWindows(WindowClass wc=WindowClass::Invalid) const
Close all children a window might have in a head-recursive manner.
Definition window.cpp:1089
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1822
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:786
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:518
ResizeInfo resize
Resize information.
Definition window_gui.h:315
void 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:1812
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
Window(WindowDesc &desc)
Empty constructor, initialization has been moved to InitNested() called from the constructor of the d...
Definition window.cpp:1846
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:990
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:327
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 textbuf_gui.h:19
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.
@ Ticks
In game ticks.
Definition timetable.h:24
@ Seconds
In wall clock seconds.
Definition timetable.h:23
@ Days
In in-game days.
Definition timetable.h:22
Command definitions related to timetables.
static TimerGameTick::Ticks TicksPerTimetableUnit()
Get the number of ticks in the current timetable display unit.
static WindowDesc _timetable_desc(WindowPosition::Automatic, "view_vehicle_timetable", 400, 130, WindowClass::VehicleTimetable, WindowClass::VehicleView, WindowDefaultFlag::Construction, _nested_timetable_widgets)
Window definition for the timetable window.
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
@ 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:1209
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.
Definition window_gui.h:153
Twindow * AllocateWindowDescFront(WindowDesc &desc, WindowNumber window_number, Targs... extra_arguments)
Open a new window.
@ Automatic
Find a place automatically.
Definition window_gui.h:144
int WidgetID
Widget ID.
Definition window_type.h:21