00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "debug.h"
00014 #include "gui.h"
00015 #include "textbuf_gui.h"
00016 #include "strings_func.h"
00017 #include "window_func.h"
00018 #include "vehicle_func.h"
00019 #include "string_func.h"
00020 #include "window_gui.h"
00021 #include "timetable.h"
00022 #include "vehiclelist.h"
00023 #include "company_base.h"
00024 #include "date_func.h"
00025 #include "departures_gui.h"
00026 #include "station_base.h"
00027 #include "vehicle_gui_base.h"
00028 #include "vehicle_base.h"
00029 #include "vehicle_gui.h"
00030 #include "order_base.h"
00031 #include "settings_type.h"
00032 #include "core/smallvec_type.hpp"
00033 #include "date_type.h"
00034 #include "company_type.h"
00035 #include "departures_func.h"
00036 #include "cargotype.h"
00037
00038 #include "table/sprites.h"
00039 #include "table/strings.h"
00040
00041 static const NWidgetPart _nested_departures_list[] = {
00042 NWidget(NWID_HORIZONTAL),
00043 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
00044 NWidget(WWT_CAPTION, COLOUR_GREY, DW_WIDGET_CAPTION), SetDataTip(STR_DEPARTURES_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
00045 NWidget(WWT_SHADEBOX, COLOUR_GREY),
00046 NWidget(WWT_STICKYBOX, COLOUR_GREY),
00047 EndContainer(),
00048
00049 NWidget(NWID_HORIZONTAL),
00050 NWidget(WWT_MATRIX, COLOUR_GREY, DW_WIDGET_LIST), SetMinimalSize(0, 0), SetFill(1, 0), SetResize(1, 1),
00051 NWidget(NWID_VSCROLLBAR, COLOUR_GREY, DW_WIDGET_SCROLLBAR),
00052 EndContainer(),
00053
00054 NWidget(NWID_HORIZONTAL),
00055 NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(0, 12), SetResize(1, 0), SetFill(1, 1), EndContainer(),
00056 NWidget(WWT_TEXTBTN, COLOUR_GREY, DW_SHOW_ARRS), SetMinimalSize(6, 12), SetFill(0, 1), SetDataTip(STR_DEPARTURES_ARRIVALS, STR_DEPARTURES_ARRIVALS_TOOLTIP),
00057 NWidget(WWT_TEXTBTN, COLOUR_GREY, DW_SHOW_DEPS), SetMinimalSize(6, 12), SetFill(0, 1), SetDataTip(STR_DEPARTURES_DEPARTURES, STR_DEPARTURES_DEPARTURES_TOOLTIP),
00058 NWidget(WWT_TEXTBTN, COLOUR_GREY, DW_SHOW_VIA), SetMinimalSize(11, 12), SetFill(0, 1), SetDataTip(STR_DEPARTURES_VIA_BUTTON, STR_DEPARTURES_VIA_TOOLTIP),
00059 NWidget(WWT_TEXTBTN, COLOUR_GREY, DW_SHOW_TRAINS), SetMinimalSize(14, 12), SetFill(0, 1), SetDataTip(STR_TRAIN, STR_STATION_VIEW_SCHEDULED_TRAINS_TOOLTIP),
00060 NWidget(WWT_TEXTBTN, COLOUR_GREY, DW_SHOW_ROADVEHS), SetMinimalSize(14, 12), SetFill(0, 1), SetDataTip(STR_LORRY, STR_STATION_VIEW_SCHEDULED_ROAD_VEHICLES_TOOLTIP),
00061 NWidget(WWT_TEXTBTN, COLOUR_GREY, DW_SHOW_SHIPS), SetMinimalSize(14, 12), SetFill(0, 1), SetDataTip(STR_SHIP, STR_STATION_VIEW_SCHEDULED_SHIPS_TOOLTIP),
00062 NWidget(WWT_TEXTBTN, COLOUR_GREY, DW_SHOW_PLANES), SetMinimalSize(14, 12), SetFill(0, 1), SetDataTip(STR_PLANE, STR_STATION_VIEW_SCHEDULED_AIRCRAFT_TOOLTIP),
00063 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
00064 EndContainer(),
00065 };
00066
00067 static WindowDesc _departures_desc(
00068 WDP_AUTO, 260, 246,
00069 WC_DEPARTURES_BOARD, WC_NONE,
00070 WDF_UNCLICK_BUTTONS,
00071 _nested_departures_list, lengthof(_nested_departures_list)
00072 );
00073
00074 static uint cached_date_width = 0;
00075 static uint cached_status_width = 0;
00076 static uint cached_date_arrow_width = 0;
00077 static bool cached_date_display_method;
00078 static bool cached_arr_dep_display_method;
00079
00080 template<bool Twaypoint = false>
00081 struct DeparturesWindow : public Window {
00082 protected:
00083 StationID station;
00084 DepartureList *departures;
00085 DepartureList *arrivals;
00086 uint entry_height;
00087 uint tick_count;
00088 int calc_tick_countdown;
00089 bool show_types[4];
00090 bool departure_types[3];
00091 uint min_width;
00092 Scrollbar *vscroll;
00093
00094 virtual uint GetMinWidth() const;
00095 static void RecomputeDateWidth();
00096 virtual void DrawDeparturesListItems(const Rect &r) const;
00097 void DeleteDeparturesList(DepartureList* list);
00098 public:
00099
00100 DeparturesWindow(const WindowDesc *desc, WindowNumber window_number) : Window(),
00101 station(window_number),
00102 departures(new DepartureList()),
00103 arrivals(new DepartureList()),
00104 entry_height(1 + FONT_HEIGHT_NORMAL + 1 + (_settings_client.gui.departure_larger_font ? FONT_HEIGHT_NORMAL : FONT_HEIGHT_SMALL) + 1 + 1),
00105 tick_count(0),
00106 calc_tick_countdown(0),
00107 min_width(400)
00108 {
00109 this->CreateNestedTree(desc);
00110 this->vscroll = this->GetScrollbar(DW_WIDGET_SCROLLBAR);
00111 this->FinishInitNested(desc, window_number);
00112
00113
00114 departure_types[0] = true;
00115 departure_types[1] = false;
00116 departure_types[2] = false;
00117 this->LowerWidget(DW_SHOW_DEPS);
00118 this->RaiseWidget(DW_SHOW_ARRS);
00119 this->RaiseWidget(DW_SHOW_VIA);
00120
00121 for (uint i = 0; i < 4; ++i) {
00122 show_types[i] = true;
00123 this->LowerWidget(DW_SHOW_TRAINS + i);
00124 }
00125
00126 if (Twaypoint) {
00127 this->GetWidget<NWidgetCore>(DW_WIDGET_CAPTION)->SetDataTip(STR_DEPARTURES_CAPTION_WAYPOINT, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS);
00128
00129 for (uint i = 0; i < 4; ++i) {
00130 this->DisableWidget(DW_SHOW_TRAINS + i);
00131 }
00132
00133 this->DisableWidget(DW_SHOW_ARRS);
00134 this->DisableWidget(DW_SHOW_DEPS);
00135 this->DisableWidget(DW_SHOW_VIA);
00136
00137 departure_types[2] = true;
00138
00139 this->LowerWidget(DW_SHOW_VIA);
00140 }
00141 }
00142
00143 virtual ~DeparturesWindow()
00144 {
00145 this->DeleteDeparturesList(departures);
00146 this->DeleteDeparturesList(this->arrivals);
00147 }
00148
00149 virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
00150 {
00151 switch (widget) {
00152 case DW_WIDGET_LIST:
00153 resize->height = DeparturesWindow::entry_height;
00154 size->height = 2 * resize->height;
00155 break;
00156 }
00157 }
00158
00159 virtual void SetStringParameters(int widget) const
00160 {
00161 if (widget == DW_WIDGET_CAPTION) {
00162 const Station *st = Station::Get(this->station);
00163 SetDParam(0, st->index);
00164 }
00165 }
00166
00167 virtual void OnClick(Point pt, int widget, int click_count)
00168 {
00169 switch (widget) {
00170 case DW_SHOW_TRAINS:
00171 case DW_SHOW_ROADVEHS:
00172 case DW_SHOW_SHIPS:
00173 case DW_SHOW_PLANES:
00174 this->show_types[widget - DW_SHOW_TRAINS] = !this->show_types[widget - DW_SHOW_TRAINS];
00175 if (this->show_types[widget - DW_SHOW_TRAINS]) {
00176 this->LowerWidget(widget);
00177 } else {
00178 this->RaiseWidget(widget);
00179 }
00180
00181 this->calc_tick_countdown = 0;
00182
00183 this->SetWidgetDirty(widget);
00184 break;
00185
00186 case DW_SHOW_DEPS:
00187 case DW_SHOW_ARRS:
00188 if (_settings_client.gui.departure_show_both) break;
00189
00190
00191 case DW_SHOW_VIA:
00192
00193 this->departure_types[widget - DW_SHOW_DEPS] = !this->departure_types[widget - DW_SHOW_DEPS];
00194 if (this->departure_types[widget - DW_SHOW_DEPS]) {
00195 this->LowerWidget(widget);
00196 } else {
00197 this->RaiseWidget(widget);
00198 }
00199
00200 if (!this->departure_types[0]) {
00201 this->RaiseWidget(DW_SHOW_VIA);
00202 this->DisableWidget(DW_SHOW_VIA);
00203 } else {
00204 this->EnableWidget(DW_SHOW_VIA);
00205
00206 if (this->departure_types[2]) {
00207 this->LowerWidget(DW_SHOW_VIA);
00208 }
00209 }
00210
00211 this->calc_tick_countdown = 0;
00212
00213 this->SetWidgetDirty(widget);
00214 break;
00215
00216 case DW_WIDGET_LIST:
00217
00218 uint32 id_v = (pt.y - this->GetWidget<NWidgetBase>(DW_WIDGET_LIST)->pos_y) / this->entry_height;
00219
00220 if (id_v >= this->vscroll->GetCapacity()) return;
00221
00222 id_v += this->vscroll->GetPosition();
00223
00224 if (id_v >= (this->departures->Length() + this->arrivals->Length())) return;
00225
00226 uint departure = 0;
00227 uint arrival = 0;
00228
00229
00230 for (uint i = 0; i <= id_v; ++i) {
00231 const Departure *d;
00232
00233 if (arrival == this->arrivals->Length()) {
00234 d = (*(this->departures))[departure++];
00235 } else if (departure == this->departures->Length()) {
00236 d = (*(this->arrivals))[arrival++];
00237 } else {
00238 d = (*(this->departures))[departure];
00239 const Departure *a = (*(this->arrivals))[arrival];
00240
00241 if (a->scheduled_date < d->scheduled_date) {
00242 d = a;
00243 arrival++;
00244 } else {
00245 departure++;
00246 }
00247 }
00248
00249 if (i == id_v) {
00250 ShowVehicleViewWindow(d->vehicle);
00251 break;
00252 }
00253 }
00254
00255 break;
00256 }
00257 }
00258
00259 virtual void OnTick()
00260 {
00261 if (_pause_mode == PM_UNPAUSED) {
00262 this->tick_count += 1;
00263 this->calc_tick_countdown -= 1;
00264 }
00265
00266
00267 if (cached_date_width == 0 ||
00268 _settings_client.gui.time_in_minutes != cached_date_display_method ||
00269 _settings_client.gui.departure_show_both != cached_arr_dep_display_method) {
00270 this->RecomputeDateWidth();
00271 }
00272
00273
00274 this->SetWidgetDirty(DW_WIDGET_LIST);
00275
00276
00277 if (this->calc_tick_countdown <= 0) {
00278 this->calc_tick_countdown = _settings_client.gui.departure_calc_frequency;
00279 this->DeleteDeparturesList(this->departures);
00280 this->DeleteDeparturesList(this->arrivals);
00281 this->departures = (this->departure_types[0] ? MakeDepartureList(this->station, this->show_types, D_DEPARTURE, Twaypoint || this->departure_types[2]) : new DepartureList());
00282 this->arrivals = (this->departure_types[1] && !_settings_client.gui.departure_show_both ? MakeDepartureList(this->station, this->show_types, D_ARRIVAL ) : new DepartureList());
00283 this->SetWidgetDirty(DW_WIDGET_LIST);
00284 }
00285
00286 uint new_width = this->GetMinWidth();
00287
00288 if (new_width != this->min_width) {
00289 NWidgetCore *n = this->GetWidget<NWidgetCore>(DW_WIDGET_LIST);
00290 n->SetMinimalSize(new_width, 0);
00291 this->ReInit();
00292 this->min_width = new_width;
00293 }
00294
00295 uint new_height = 1 + FONT_HEIGHT_NORMAL + 1 + (_settings_client.gui.departure_larger_font ? FONT_HEIGHT_NORMAL : FONT_HEIGHT_SMALL) + 1 + 1;
00296
00297 if (new_height != this->entry_height) {
00298 this->entry_height = new_height;
00299 this->SetWidgetDirty(DW_WIDGET_LIST);
00300 this->ReInit();
00301 }
00302 }
00303
00304 virtual void OnPaint()
00305 {
00306 if (Twaypoint || _settings_client.gui.departure_show_both) {
00307 this->DisableWidget(DW_SHOW_ARRS);
00308 this->DisableWidget(DW_SHOW_DEPS);
00309 } else {
00310 this->EnableWidget(DW_SHOW_ARRS);
00311 this->EnableWidget(DW_SHOW_DEPS);
00312 }
00313
00314 this->vscroll->SetCount(min(_settings_client.gui.max_departures, this->departures->Length() + this->arrivals->Length()));
00315 this->DrawWidgets();
00316 }
00317
00318 virtual void DrawWidget(const Rect &r, int widget) const
00319 {
00320 switch (widget) {
00321 case DW_WIDGET_LIST:
00322 this->DrawDeparturesListItems(r);
00323 break;
00324 }
00325 }
00326
00327 virtual void OnResize()
00328 {
00329 this->vscroll->SetCapacityFromWidget(this, DW_WIDGET_LIST);
00330 this->GetWidget<NWidgetCore>(DW_WIDGET_LIST)->widget_data = (this->vscroll->GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
00331 }
00332 };
00333
00338 void ShowStationDepartures(StationID station)
00339 {
00340 AllocateWindowDescFront<DeparturesWindow<> >(&_departures_desc, station);
00341 }
00342
00347 void ShowWaypointDepartures(StationID waypoint)
00348 {
00349 AllocateWindowDescFront<DeparturesWindow<true> >(&_departures_desc, waypoint);
00350 }
00351
00352 template<bool Twaypoint>
00353 void DeparturesWindow<Twaypoint>::RecomputeDateWidth()
00354 {
00355 cached_date_width = 0;
00356 cached_status_width = 0;
00357 cached_date_display_method = _settings_client.gui.time_in_minutes;
00358 cached_arr_dep_display_method = _settings_client.gui.departure_show_both;
00359
00360 cached_status_width = max((GetStringBoundingBox(STR_DEPARTURES_ON_TIME)).width, cached_status_width);
00361 cached_status_width = max((GetStringBoundingBox(STR_DEPARTURES_DELAYED)).width, cached_status_width);
00362 cached_status_width = max((GetStringBoundingBox(STR_DEPARTURES_CANCELLED)).width, cached_status_width);
00363
00364 uint interval = cached_date_display_method ? _settings_client.gui.ticks_per_minute : DAY_TICKS;
00365 uint count = cached_date_display_method ? 24*60 : 365;
00366
00367 for (uint i = 0; i < count; ++i) {
00368 SetDParam(0, INT_MAX - (i*interval));
00369 SetDParam(1, INT_MAX - (i*interval));
00370 cached_date_width = max(GetStringBoundingBox(cached_arr_dep_display_method ? STR_DEPARTURES_TIME_BOTH : STR_DEPARTURES_TIME_DEP).width, cached_date_width);
00371 cached_status_width = max((GetStringBoundingBox(STR_DEPARTURES_EXPECTED)).width, cached_status_width);
00372 }
00373
00374 SetDParam(0, 0);
00375 cached_date_arrow_width = GetStringBoundingBox(STR_DEPARTURES_TIME_DEP).width - GetStringBoundingBox(STR_DEPARTURES_TIME).width;
00376
00377 if (!_settings_client.gui.departure_show_both) {
00378 cached_date_width -= cached_date_arrow_width;
00379 }
00380 }
00381
00382 template<bool Twaypoint>
00383 uint DeparturesWindow<Twaypoint>::GetMinWidth() const
00384 {
00385 uint result = 0;
00386
00387
00388 result = cached_date_width;
00389
00390
00391 result += _settings_client.gui.departure_show_vehicle_type ? (GetStringBoundingBox(STR_DEPARTURES_TYPE_PLANE)).width : 0;
00392
00393
00394 result += cached_status_width;
00395
00396
00397 int toc_width = 0;
00398
00399
00400 int group_width = 0;
00401
00402
00403 int veh_width = 0;
00404
00405 if (_settings_client.gui.departure_show_vehicle || _settings_client.gui.departure_show_company || _settings_client.gui.departure_show_group) {
00406 for (uint i = 0; i < 4; ++i) {
00407 VehicleList vehicles;
00408
00409
00410 if (!GenerateVehicleSortList(&vehicles, VehicleListIdentifier(VL_STATION_LIST, (VehicleType)(VEH_TRAIN + i), MAX_COMPANIES, station).Pack())) {
00411
00412 continue;
00413 }
00414
00415 for (const Vehicle **v = vehicles.Begin(); v != vehicles.End(); v++) {
00416 SetDParam(0, (uint64)((*v)->index));
00417 int width = (GetStringBoundingBox(STR_DEPARTURES_VEH)).width;
00418 if (_settings_client.gui.departure_show_vehicle && width > veh_width) veh_width = width;
00419
00420 if ((*v)->group_id != INVALID_GROUP && (*v)->group_id != DEFAULT_GROUP) {
00421 SetDParam(0, (uint64)((*v)->group_id));
00422 width = (GetStringBoundingBox(STR_DEPARTURES_GROUP)).width;
00423 if (_settings_client.gui.departure_show_group && width > group_width) group_width = width;
00424 }
00425
00426 SetDParam(0, (uint64)((*v)->owner));
00427 width = (GetStringBoundingBox(STR_DEPARTURES_TOC)).width;
00428 if (_settings_client.gui.departure_show_company && width > toc_width) toc_width = width;
00429 }
00430 }
00431 }
00432
00433 result += toc_width + veh_width + group_width;
00434
00435 return result + 140;
00436 }
00437
00441 template<bool Twaypoint>
00442 void DeparturesWindow<Twaypoint>::DeleteDeparturesList(DepartureList *list)
00443 {
00444
00445 for (uint i = 0; i < list->Length(); ++i) {
00446 Departure **d = list->Get(i);
00447 delete *d;
00448
00449 *d = NULL;
00450 }
00451 list->Reset();
00452 delete list;
00453 list = NULL;
00454 }
00455
00459 template<bool Twaypoint>
00460 void DeparturesWindow<Twaypoint>::DrawDeparturesListItems(const Rect &r) const
00461 {
00462 int left = r.left + WD_MATRIX_LEFT;
00463 int right = r.right - WD_MATRIX_RIGHT;
00464
00465 bool rtl = _current_text_dir == TD_RTL;
00466 bool ltr = !rtl;
00467
00468 int text_offset = WD_FRAMERECT_RIGHT;
00469 int text_left = left + (rtl ? 0 : text_offset);
00470 int text_right = right - (rtl ? text_offset : 0);
00471
00472 int y = r.top + 1;
00473 uint max_departures = min(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), this->departures->Length() + this->arrivals->Length());
00474
00475 if (max_departures > _settings_client.gui.max_departures) {
00476 max_departures = _settings_client.gui.max_departures;
00477 }
00478
00479 byte small_font_size = _settings_client.gui.departure_larger_font ? FONT_HEIGHT_NORMAL : FONT_HEIGHT_SMALL;
00480
00481
00482 GfxFillRect(r.left + 1, r.top, r.right - 1, r.bottom, PC_BLACK);
00483
00484
00485 bool none_selected[2] = {true, true};
00486 for (uint i = 0; i < 4; ++i)
00487 {
00488 if (this->show_types[i]) {
00489 none_selected[0] = false;
00490 break;
00491 }
00492 }
00493
00494 for (uint i = 0; i < 2; ++i)
00495 {
00496 if (this->departure_types[i]) {
00497 none_selected[1] = false;
00498 break;
00499 }
00500 }
00501
00502 if (none_selected[0] || none_selected[1]) {
00503 DrawString(text_left, text_right, y + 1, STR_DEPARTURES_NONE_SELECTED);
00504 return;
00505 }
00506
00507
00508 if (max_departures == 0) {
00509 DrawString(text_left, text_right, y + 1, STR_DEPARTURES_EMPTY);
00510 return;
00511 }
00512
00513
00514 int time_width = cached_date_width;
00515
00516 if (!_settings_client.gui.departure_show_both) {
00517 time_width += (departure_types[0] && departure_types[1] ? cached_date_arrow_width : 0);
00518 }
00519
00520
00521 int type_width = _settings_client.gui.departure_show_vehicle_type ? (GetStringBoundingBox(STR_DEPARTURES_TYPE_PLANE)).width : 0;
00522
00523
00524 int status_width = cached_status_width;
00525
00526
00527 int calling_at_width = (GetStringBoundingBox(_settings_client.gui.departure_larger_font ? STR_DEPARTURES_CALLING_AT_LARGE : STR_DEPARTURES_CALLING_AT)).width;
00528
00529
00530 int toc_width = 0;
00531
00532
00533 int group_width = 0;
00534
00535
00536 int veh_width = 0;
00537
00538 if (_settings_client.gui.departure_show_vehicle || _settings_client.gui.departure_show_company || _settings_client.gui.departure_show_group) {
00539 for (uint i = 0; i < 4; ++i) {
00540 VehicleList vehicles;
00541
00542
00543 if (!GenerateVehicleSortList(&vehicles, VehicleListIdentifier(VL_STATION_LIST, (VehicleType)(VEH_TRAIN + i), MAX_COMPANIES, station).Pack())) {
00544
00545 continue;
00546 }
00547
00548 for (const Vehicle **v = vehicles.Begin(); v != vehicles.End(); v++) {
00549 SetDParam(0, (uint64)((*v)->index));
00550 int width = (GetStringBoundingBox(STR_DEPARTURES_VEH)).width;
00551 if (_settings_client.gui.departure_show_vehicle && width > veh_width) veh_width = width;
00552
00553 if ((*v)->group_id != INVALID_GROUP && (*v)->group_id != DEFAULT_GROUP) {
00554 SetDParam(0, (uint64)((*v)->group_id));
00555 width = (GetStringBoundingBox(STR_DEPARTURES_GROUP)).width;
00556 if (_settings_client.gui.departure_show_group && width > group_width) group_width = width;
00557 }
00558
00559 SetDParam(0, (uint64)((*v)->owner));
00560 width = (GetStringBoundingBox(STR_DEPARTURES_TOC)).width;
00561 if (_settings_client.gui.departure_show_company && width > toc_width) toc_width = width;
00562 }
00563 }
00564 }
00565
00566 uint departure = 0;
00567 uint arrival = 0;
00568
00569
00570 for (uint i = 0; i < max_departures; ++i) {
00571 const Departure *d;
00572
00573 if (arrival == this->arrivals->Length()) {
00574 d = (*(this->departures))[departure++];
00575 } else if (departure == this->departures->Length()) {
00576 d = (*(this->arrivals))[arrival++];
00577 } else {
00578 d = (*(this->departures))[departure];
00579 const Departure *a = (*(this->arrivals))[arrival];
00580
00581 if (a->scheduled_date < d->scheduled_date) {
00582 d = a;
00583 arrival++;
00584 } else {
00585 departure++;
00586 }
00587 }
00588
00589 if (i < this->vscroll->GetPosition()) {
00590 continue;
00591 }
00592
00593
00594 if ((d->scheduled_date / DAY_TICKS) > (_date + _settings_client.gui.max_departure_time) ||
00595 d->scheduled_date < 0) {
00596 continue;
00597 }
00598
00599 if (d->terminus == INVALID_STATION) continue;
00600
00601 StringID time_str = (departure_types[0] && departure_types[1]) ? (d->type == D_DEPARTURE ? STR_DEPARTURES_TIME_DEP : STR_DEPARTURES_TIME_ARR) : STR_DEPARTURES_TIME;
00602
00603 if (_settings_client.gui.departure_show_both) time_str = STR_DEPARTURES_TIME_BOTH;
00604
00605
00606 SetDParam(0, d->scheduled_date);
00607 SetDParam(1, d->scheduled_date - d->order->wait_time);
00608 ltr ? DrawString( text_left, text_left + time_width, y + 1, time_str)
00609 : DrawString(text_right - time_width, text_right, y + 1, time_str);
00610
00611
00612 if (_settings_client.gui.departure_show_vehicle_type) {
00613 StringID type = STR_DEPARTURES_TYPE_TRAIN;
00614 int offset = (_settings_client.gui.departure_show_vehicle_color ? 1 : 0);
00615
00616 switch (d->vehicle->type) {
00617 case VEH_TRAIN:
00618 type = STR_DEPARTURES_TYPE_TRAIN;
00619 break;
00620 case VEH_ROAD:
00621 type = IsCargoInClass(d->vehicle->cargo_type, CC_PASSENGERS) ? STR_DEPARTURES_TYPE_BUS : STR_DEPARTURES_TYPE_LORRY;
00622 break;
00623 case VEH_SHIP:
00624 type = STR_DEPARTURES_TYPE_SHIP;
00625 break;
00626 case VEH_AIRCRAFT:
00627 type = STR_DEPARTURES_TYPE_PLANE;
00628 break;
00629 default:
00630 break;
00631 }
00632
00633 type += offset;
00634
00635 DrawString(text_left + time_width + 3, text_left + time_width + type_width + 3, y, type);
00636 }
00637
00638
00639 StringID icon = STR_DEPARTURES_STATION_NONE;
00640 StringID icon_via = STR_DEPARTURES_STATION_NONE;
00641
00642 if (_settings_client.gui.departure_destination_type) {
00643 Station *t = Station::Get(d->terminus);
00644
00645 if (t->facilities & FACIL_DOCK &&
00646 t->facilities & FACIL_AIRPORT &&
00647 d->vehicle->type != VEH_SHIP &&
00648 d->vehicle->type != VEH_AIRCRAFT) {
00649 icon = STR_DEPARTURES_STATION_PORTAIRPORT;
00650 } else if (t->facilities & FACIL_DOCK &&
00651 d->vehicle->type != VEH_SHIP) {
00652 icon = STR_DEPARTURES_STATION_PORT;
00653 } else if (t->facilities & FACIL_AIRPORT &&
00654 d->vehicle->type != VEH_AIRCRAFT) {
00655 icon = STR_DEPARTURES_STATION_AIRPORT;
00656 }
00657 }
00658
00659 if (_settings_client.gui.departure_destination_type && d->via != INVALID_STATION) {
00660 Station *t = Station::Get(d->via);
00661
00662 if (t->facilities & FACIL_DOCK &&
00663 t->facilities & FACIL_AIRPORT &&
00664 d->vehicle->type != VEH_SHIP &&
00665 d->vehicle->type != VEH_AIRCRAFT) {
00666 icon_via = STR_DEPARTURES_STATION_PORTAIRPORT;
00667 } else if (t->facilities & FACIL_DOCK &&
00668 d->vehicle->type != VEH_SHIP) {
00669 icon_via = STR_DEPARTURES_STATION_PORT;
00670 } else if (t->facilities & FACIL_AIRPORT &&
00671 d->vehicle->type != VEH_AIRCRAFT) {
00672 icon_via = STR_DEPARTURES_STATION_AIRPORT;
00673 }
00674 }
00675
00676
00677 if (d->via == INVALID_STATION) {
00678
00679 SetDParam(0, d->terminus);
00680 SetDParam(1, icon);
00681 ltr ? DrawString( text_left + time_width + type_width + 6, text_right - status_width - (toc_width + veh_width + group_width + 2) - 2, y + 1, STR_DEPARTURES_TERMINUS)
00682 : DrawString(text_left + status_width + (toc_width + veh_width + group_width + 2) + 2, text_right - time_width - type_width - 6, y + 1, STR_DEPARTURES_TERMINUS);
00683 } else {
00684
00685 SetDParam(0, d->terminus);
00686 SetDParam(1, icon);
00687 SetDParam(2, d->via);
00688 SetDParam(3, icon_via);
00689 int text_width = (GetStringBoundingBox(STR_DEPARTURES_TERMINUS_VIA_STATION)).width;
00690
00691 if (text_width < text_right - status_width - (toc_width + veh_width + group_width + 2) - 2 - (text_left + time_width + type_width + 6)) {
00692
00693 SetDParam(0, d->terminus);
00694 SetDParam(1, icon);
00695 SetDParam(2, d->via);
00696 SetDParam(3, icon_via);
00697 ltr ? DrawString( text_left + time_width + type_width + 6, text_right - status_width - (toc_width + veh_width + group_width + 2) - 2, y + 1, STR_DEPARTURES_TERMINUS_VIA_STATION)
00698 : DrawString(text_left + status_width + (toc_width + veh_width + group_width + 2) + 2, text_right - time_width - type_width - 6, y + 1, STR_DEPARTURES_TERMINUS_VIA_STATION);
00699 } else {
00700
00701 if (this->tick_count & (1 << 7)) {
00702 SetDParam(0, d->via);
00703 SetDParam(1, icon_via);
00704 ltr ? DrawString( text_left + time_width + type_width + 6, text_right - status_width - (toc_width + veh_width + group_width + 2) - 2, y + 1, STR_DEPARTURES_VIA)
00705 : DrawString(text_left + status_width + (toc_width + veh_width + group_width + 2) + 2, text_right - time_width - type_width - 6, y + 1, STR_DEPARTURES_VIA);
00706 } else {
00707 SetDParam(0, d->terminus);
00708 SetDParam(1, icon);
00709 ltr ? DrawString( text_left + time_width + type_width + 6, text_right - status_width - (toc_width + veh_width + group_width + 2) - 2, y + 1, STR_DEPARTURES_TERMINUS_VIA)
00710 : DrawString(text_left + status_width + (toc_width + veh_width + group_width + 2) + 2, text_right - time_width - type_width - 6, y + 1, STR_DEPARTURES_TERMINUS_VIA);
00711 }
00712 }
00713 }
00714
00715
00716 {
00717 int status_left = ltr ? text_right - status_width - 2 - (toc_width + veh_width + group_width + 2) : text_left + (toc_width + veh_width + group_width + 2) + 2;
00718 int status_right = ltr ? text_right - (toc_width + veh_width + group_width + 2) + 2 : text_left + status_width + 2 + (toc_width + veh_width + group_width + 2);
00719
00720 if (d->status == D_ARRIVED) {
00721
00722 DrawString(status_left, status_right, y + 1, STR_DEPARTURES_ARRIVED);
00723 } else if(d->status == D_CANCELLED) {
00724
00725 DrawString(status_left, status_right, y + 1, STR_DEPARTURES_CANCELLED);
00726 } else {
00727 if (d->lateness <= DAY_TICKS && d->scheduled_date > ((_date * DAY_TICKS) + _date_fract)) {
00728
00729 DrawString(status_left, status_right, y + 1, STR_DEPARTURES_ON_TIME);
00730 } else {
00731 if ((d->scheduled_date + d->lateness) < ((_date * DAY_TICKS) + _date_fract)) {
00732
00733
00734 DrawString(status_left, status_right, y + 1, STR_DEPARTURES_DELAYED);
00735 } else {
00736
00737 SetDParam(0, d->scheduled_date + d->lateness);
00738 DrawString(status_left, status_right, y + 1, STR_DEPARTURES_EXPECTED);
00739 }
00740 }
00741 }
00742 }
00743
00744
00745
00746 if (_settings_client.gui.departure_show_vehicle) {
00747 SetDParam(0, (uint64)(d->vehicle->index));
00748 ltr ? DrawString(text_right - (toc_width + veh_width + group_width + 2), text_right - toc_width - group_width - 2, y + 1, STR_DEPARTURES_VEH)
00749 : DrawString( text_left + toc_width + group_width + 2, text_left + (toc_width + veh_width + group_width + 2), y + 1, STR_DEPARTURES_VEH);
00750 }
00751
00752
00753
00754 if (_settings_client.gui.departure_show_group && d->vehicle->group_id != INVALID_GROUP && d->vehicle->group_id != DEFAULT_GROUP) {
00755 SetDParam(0, (uint64)(d->vehicle->group_id));
00756 ltr ? DrawString(text_right - (toc_width + group_width + 2), text_right - toc_width - 2, y + 1, STR_DEPARTURES_GROUP)
00757 : DrawString( text_left + toc_width + 2, text_left + (toc_width + group_width + 2), y + 1, STR_DEPARTURES_GROUP);
00758 }
00759
00760
00761 if (_settings_client.gui.departure_show_company) {
00762 SetDParam(0, (uint64)(d->vehicle->owner));
00763 ltr ? DrawString(text_right - toc_width, text_right, y + 1, STR_DEPARTURES_TOC, TC_FROMSTRING, SA_RIGHT)
00764 : DrawString( text_left, text_left + toc_width, y + 1, STR_DEPARTURES_TOC, TC_FROMSTRING, SA_LEFT);
00765 }
00766
00767 int bottom_y = y + this->entry_height - small_font_size - (_settings_client.gui.departure_larger_font ? 1 : 3);
00768
00769
00770 ltr ? DrawString( text_left, text_left + calling_at_width, bottom_y, _settings_client.gui.departure_larger_font ? STR_DEPARTURES_CALLING_AT_LARGE : STR_DEPARTURES_CALLING_AT)
00771 : DrawString(text_right - calling_at_width, text_right, bottom_y, _settings_client.gui.departure_larger_font ? STR_DEPARTURES_CALLING_AT_LARGE : STR_DEPARTURES_CALLING_AT);
00772
00773
00774
00775
00776
00777 char buffer[512], scratch[512];
00778
00779 if (d->calling_at.Length() != 0) {
00780 SetDParam(0, (uint64)(*d->calling_at.Get(0)));
00781 GetString(scratch, STR_DEPARTURES_CALLING_AT_FIRST_STATION, lastof(scratch));
00782
00783 if (d->calling_at.Length() > 1) {
00784
00785
00786
00787 for (uint i = 1; i < d->calling_at.Length() - 1; ++i) {
00788 SetDParam(0, (uint64)scratch);
00789 SetDParam(1, (uint64)(*d->calling_at.Get(i)));
00790 GetString(buffer, STR_DEPARTURES_CALLING_AT_STATION, lastof(buffer));
00791 strncpy(scratch, buffer, sizeof(scratch)); }
00792
00793
00794 SetDParam(0, (uint64)scratch);
00795 SetDParam(1, (uint64)(*d->calling_at.Get(d->calling_at.Length()-1)));
00796 GetString(buffer, STR_DEPARTURES_CALLING_AT_LAST_STATION, lastof(buffer));
00797 strncpy(scratch, buffer, sizeof(scratch));
00798 }
00799
00800 SetDParam(0, (uint64)scratch);
00801 GetString(buffer, _settings_client.gui.departure_larger_font ? STR_DEPARTURES_CALLING_AT_LIST_LARGE : STR_DEPARTURES_CALLING_AT_LIST, lastof(buffer));
00802 } else {
00803 buffer[0] = 0;
00804
00805
00806 }
00807
00808 int list_width = (GetStringBoundingBox(buffer, _settings_client.gui.departure_larger_font ? FS_NORMAL : FS_SMALL)).width;
00809
00810
00811 if (list_width < text_right - (text_left + calling_at_width + 2)) {
00812 ltr ? DrawString(text_left + calling_at_width + 2, text_right, bottom_y, buffer)
00813 : DrawString( text_left, text_right - calling_at_width - 2, bottom_y, buffer);
00814 } else {
00815 DrawPixelInfo tmp_dpi;
00816 if (ltr
00817 ? !FillDrawPixelInfo(&tmp_dpi, text_left + calling_at_width + 2, bottom_y, text_right - (text_left + calling_at_width + 2), small_font_size + 3)
00818 : !FillDrawPixelInfo(&tmp_dpi, text_left , bottom_y, text_right - (text_left + calling_at_width + 2), small_font_size + 3)) {
00819 y += this->entry_height;
00820 continue;
00821 }
00822 DrawPixelInfo *old_dpi = _cur_dpi;
00823 _cur_dpi = &tmp_dpi;
00824
00825
00826 int pos = ltr
00827 ? text_right - (this->tick_count % (list_width + text_right - text_left))
00828 : text_left + (this->tick_count % (list_width + text_right - text_left));
00829
00830 ltr ? DrawString( pos, INT16_MAX, 0, buffer, TC_FROMSTRING, SA_LEFT | SA_FORCE)
00831 : DrawString(-INT16_MAX, pos, 0, buffer, TC_FROMSTRING, SA_RIGHT | SA_FORCE);
00832
00833 _cur_dpi = old_dpi;
00834 }
00835
00836 y += this->entry_height;
00837 }
00838 }