src/vehicle_gui.cpp
branchnoai
changeset 11044 097ea3e7ec56
parent 10776 07203fc29812
child 11126 72d4c9314c72
equal deleted inserted replaced
11043:e44adcf4ed4d 11044:097ea3e7ec56
    29 #include "functions.h"
    29 #include "functions.h"
    30 #include "window_func.h"
    30 #include "window_func.h"
    31 #include "vehicle_func.h"
    31 #include "vehicle_func.h"
    32 #include "autoreplace_gui.h"
    32 #include "autoreplace_gui.h"
    33 #include "core/alloc_func.hpp"
    33 #include "core/alloc_func.hpp"
       
    34 #include "core/mem_func.hpp"
       
    35 #include "core/sort_func.hpp"
    34 #include "string_func.h"
    36 #include "string_func.h"
    35 #include "settings_type.h"
    37 #include "settings_type.h"
    36 #include "widgets/dropdown_func.h"
    38 #include "widgets/dropdown_func.h"
    37 #include "order_func.h"
    39 #include "order_func.h"
    38 #include "timetable.h"
    40 #include "timetable.h"
    40 
    42 
    41 #include "table/sprites.h"
    43 #include "table/sprites.h"
    42 #include "table/strings.h"
    44 #include "table/strings.h"
    43 
    45 
    44 Sorting _sorting;
    46 Sorting _sorting;
    45 static bool   _internal_sort_order;     // descending/ascending
    47 
    46 
    48 static GUIVehicleList::SortFunction VehicleNumberSorter;
    47 typedef int CDECL VehicleSortListingTypeFunction(const void*, const void*);
    49 static GUIVehicleList::SortFunction VehicleNameSorter;
    48 
    50 static GUIVehicleList::SortFunction VehicleAgeSorter;
    49 static VehicleSortListingTypeFunction VehicleNumberSorter;
    51 static GUIVehicleList::SortFunction VehicleProfitThisYearSorter;
    50 static VehicleSortListingTypeFunction VehicleNameSorter;
    52 static GUIVehicleList::SortFunction VehicleProfitLastYearSorter;
    51 static VehicleSortListingTypeFunction VehicleAgeSorter;
    53 static GUIVehicleList::SortFunction VehicleCargoSorter;
    52 static VehicleSortListingTypeFunction VehicleProfitThisYearSorter;
    54 static GUIVehicleList::SortFunction VehicleReliabilitySorter;
    53 static VehicleSortListingTypeFunction VehicleProfitLastYearSorter;
    55 static GUIVehicleList::SortFunction VehicleMaxSpeedSorter;
    54 static VehicleSortListingTypeFunction VehicleCargoSorter;
    56 static GUIVehicleList::SortFunction VehicleModelSorter;
    55 static VehicleSortListingTypeFunction VehicleReliabilitySorter;
    57 static GUIVehicleList::SortFunction VehicleValueSorter;
    56 static VehicleSortListingTypeFunction VehicleMaxSpeedSorter;
    58 static GUIVehicleList::SortFunction VehicleLengthSorter;
    57 static VehicleSortListingTypeFunction VehicleModelSorter;
    59 
    58 static VehicleSortListingTypeFunction VehicleValueSorter;
    60 GUIVehicleList::SortFunction* const VehicleListBase::vehicle_sorter_funcs[] = {
    59 static VehicleSortListingTypeFunction VehicleLengthSorter;
       
    60 
       
    61 static VehicleSortListingTypeFunction* const _vehicle_sorter[] = {
       
    62 	&VehicleNumberSorter,
    61 	&VehicleNumberSorter,
    63 	&VehicleNameSorter,
    62 	&VehicleNameSorter,
    64 	&VehicleAgeSorter,
    63 	&VehicleAgeSorter,
    65 	&VehicleProfitThisYearSorter,
    64 	&VehicleProfitThisYearSorter,
    66 	&VehicleProfitLastYearSorter,
    65 	&VehicleProfitLastYearSorter,
    70 	&VehicleModelSorter,
    69 	&VehicleModelSorter,
    71 	&VehicleValueSorter,
    70 	&VehicleValueSorter,
    72 	&VehicleLengthSorter,
    71 	&VehicleLengthSorter,
    73 };
    72 };
    74 
    73 
    75 const StringID _vehicle_sort_listing[] = {
    74 const StringID VehicleListBase::vehicle_sorter_names[] = {
    76 	STR_SORT_BY_NUMBER,
    75 	STR_SORT_BY_NUMBER,
    77 	STR_SORT_BY_DROPDOWN_NAME,
    76 	STR_SORT_BY_DROPDOWN_NAME,
    78 	STR_SORT_BY_AGE,
    77 	STR_SORT_BY_AGE,
    79 	STR_SORT_BY_PROFIT_THIS_YEAR,
    78 	STR_SORT_BY_PROFIT_THIS_YEAR,
    80 	STR_SORT_BY_PROFIT_LAST_YEAR,
    79 	STR_SORT_BY_PROFIT_LAST_YEAR,
    87 	INVALID_STRING_ID
    86 	INVALID_STRING_ID
    88 };
    87 };
    89 
    88 
    90 void BuildVehicleList(VehicleListBase *vl, PlayerID owner, uint16 index, uint16 window_type)
    89 void BuildVehicleList(VehicleListBase *vl, PlayerID owner, uint16 index, uint16 window_type)
    91 {
    90 {
    92 	if (!(vl->vehicles.flags & VL_REBUILD)) return;
    91 	if (!vl->vehicles.NeedRebuild()) return;
    93 
    92 
    94 	DEBUG(misc, 3, "Building vehicle list for player %d at station %d", owner, index);
    93 	DEBUG(misc, 3, "Building vehicle list for player %d at station %d", owner, index);
    95 
    94 
    96 	GenerateVehicleSortList(&vl->vehicles, vl->vehicle_type, owner, index, window_type);
    95 	GenerateVehicleSortList(&vl->vehicles, vl->vehicle_type, owner, index, window_type);
    97 
    96 
    98 	vl->vehicles.flags &= ~VL_REBUILD;
    97 	vl->vehicles.RebuildDone();
    99 	vl->vehicles.flags |= VL_RESORT;
       
   100 }
    98 }
   101 
    99 
   102 /* cached values for VehicleNameSorter to spare many GetString() calls */
   100 /* cached values for VehicleNameSorter to spare many GetString() calls */
   103 static const Vehicle *_last_vehicle[2] = { NULL, NULL };
   101 static const Vehicle *_last_vehicle[2] = { NULL, NULL };
   104 static char           _last_name[2][64] = { "", "" };
       
   105 
   102 
   106 void SortVehicleList(VehicleListBase *vl)
   103 void SortVehicleList(VehicleListBase *vl)
   107 {
   104 {
   108 	if (!(vl->vehicles.flags & VL_RESORT)) return;
   105 	if (vl->vehicles.Sort()) return;
   109 
   106 
   110 	/* invalidate cached values for name sorter - vehicle names could change */
   107 	/* invalidate cached values for name sorter - vehicle names could change */
   111 	_last_vehicle[0] = _last_vehicle[1] = NULL;
   108 	_last_vehicle[0] = _last_vehicle[1] = NULL;
   112 
       
   113 	_internal_sort_order = (vl->vehicles.flags & VL_DESC) != 0;
       
   114 	qsort((void*)vl->vehicles.Begin(), vl->vehicles.Length(), sizeof(*vl->vehicles.Begin()),
       
   115 		_vehicle_sorter[vl->vehicles.sort_type]);
       
   116 
       
   117 	vl->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
       
   118 	vl->vehicles.flags &= ~VL_RESORT;
       
   119 }
   109 }
   120 
   110 
   121 void DepotSortList(VehicleList *list)
   111 void DepotSortList(VehicleList *list)
   122 {
   112 {
   123 	_internal_sort_order = 0;
       
   124 	if (list->Length() < 2) return;
   113 	if (list->Length() < 2) return;
   125 	qsort((void*)list->Begin(), list->Length(), sizeof(*list->Begin()), _vehicle_sorter[0]);
   114 	QSortT(list->Begin(), list->Length(), &VehicleNumberSorter);
   126 }
   115 }
   127 
   116 
   128 /** draw the vehicle profit button in the vehicle list window. */
   117 /** draw the vehicle profit button in the vehicle list window. */
   129 void DrawVehicleProfitButton(const Vehicle *v, int x, int y)
   118 void DrawVehicleProfitButton(const Vehicle *v, int x, int y)
   130 {
   119 {
   505 
   494 
   506 	return DrawStringMultiLine(x, y, STR_SPEC_USERSTRING, w);
   495 	return DrawStringMultiLine(x, y, STR_SPEC_USERSTRING, w);
   507 }
   496 }
   508 
   497 
   509 
   498 
   510 /* if the sorting criteria had the same value, sort vehicle by unitnumber */
   499 /** Sort vehicles by their number */
   511 #define VEHICLEUNITNUMBERSORTER(r, a, b) {if (r == 0) {r = a->unitnumber - b->unitnumber;}}
   500 static int CDECL VehicleNumberSorter(const Vehicle* const *a, const Vehicle* const *b)
   512 
   501 {
   513 static int CDECL VehicleNumberSorter(const void *a, const void *b)
   502 	return (*a)->unitnumber - (*b)->unitnumber;
   514 {
   503 }
   515 	const Vehicle* va = *(const Vehicle**)a;
   504 
   516 	const Vehicle* vb = *(const Vehicle**)b;
   505 /** Sort vehicles by their name */
   517 	int r = va->unitnumber - vb->unitnumber;
   506 static int CDECL VehicleNameSorter(const Vehicle* const *a, const Vehicle* const *b)
   518 
   507 {
   519 	return (_internal_sort_order & 1) ? -r : r;
   508 	static char last_name[2][64];
   520 }
   509 
   521 
   510 	if (*a != _last_vehicle[0]) {
   522 static int CDECL VehicleNameSorter(const void *a, const void *b)
   511 		_last_vehicle[0] = *a;
   523 {
   512 		SetDParam(0, (*a)->index);
   524 	const Vehicle* va = *(const Vehicle**)a;
   513 		GetString(last_name[0], STR_VEHICLE_NAME, lastof(last_name[0]));
   525 	const Vehicle* vb = *(const Vehicle**)b;
   514 	}
   526 	int r;
   515 
   527 
   516 	if (*b != _last_vehicle[1]) {
   528 	if (va != _last_vehicle[0]) {
   517 		_last_vehicle[1] = *b;
   529 		_last_vehicle[0] = va;
   518 		SetDParam(0, (*b)->index);
   530 		SetDParam(0, va->index);
   519 		GetString(last_name[1], STR_VEHICLE_NAME, lastof(last_name[1]));
   531 		GetString(_last_name[0], STR_VEHICLE_NAME, lastof(_last_name[0]));
   520 	}
   532 	}
   521 
   533 
   522 	int r = strcmp(last_name[0], last_name[1]);
   534 	if (vb != _last_vehicle[1]) {
   523 	return (r != 0) ? r : VehicleNumberSorter(a, b);
   535 		_last_vehicle[1] = vb;
   524 }
   536 		SetDParam(0, vb->index);
   525 
   537 		GetString(_last_name[1], STR_VEHICLE_NAME, lastof(_last_name[1]));
   526 /** Sort vehicles by their age */
   538 	}
   527 static int CDECL VehicleAgeSorter(const Vehicle* const *a, const Vehicle* const *b)
   539 
   528 {
   540 	r = strcmp(_last_name[0], _last_name[1]); // sort by name
   529 	int r = (*a)->age - (*b)->age;
   541 
   530 	return (r != 0) ? r : VehicleNumberSorter(a, b);
   542 	VEHICLEUNITNUMBERSORTER(r, va, vb);
   531 }
   543 
   532 
   544 	return (_internal_sort_order & 1) ? -r : r;
   533 /** Sort vehicles by this year profit */
   545 }
   534 static int CDECL VehicleProfitThisYearSorter(const Vehicle* const *a, const Vehicle* const *b)
   546 
   535 {
   547 static int CDECL VehicleAgeSorter(const void *a, const void *b)
   536 	int r = ClampToI32((*a)->GetDisplayProfitThisYear() - (*b)->GetDisplayProfitThisYear());
   548 {
   537 	return (r != 0) ? r : VehicleNumberSorter(a, b);
   549 	const Vehicle* va = *(const Vehicle**)a;
   538 }
   550 	const Vehicle* vb = *(const Vehicle**)b;
   539 
   551 	int r = va->age - vb->age;
   540 /** Sort vehicles by last year profit */
   552 
   541 static int CDECL VehicleProfitLastYearSorter(const Vehicle* const *a, const Vehicle* const *b)
   553 	VEHICLEUNITNUMBERSORTER(r, va, vb);
   542 {
   554 
   543 	int r = ClampToI32((*a)->GetDisplayProfitLastYear() - (*b)->GetDisplayProfitLastYear());
   555 	return (_internal_sort_order & 1) ? -r : r;
   544 	return (r != 0) ? r : VehicleNumberSorter(a, b);
   556 }
   545 }
   557 
   546 
   558 static int CDECL VehicleProfitThisYearSorter(const void *a, const void *b)
   547 /** Sort vehicles by their cargo */
   559 {
   548 static int CDECL VehicleCargoSorter(const Vehicle* const *a, const Vehicle* const *b)
   560 	const Vehicle* va = *(const Vehicle**)a;
   549 {
   561 	const Vehicle* vb = *(const Vehicle**)b;
   550 	const Vehicle *v;
   562 	int r = ClampToI32(va->GetDisplayProfitThisYear() - vb->GetDisplayProfitThisYear());
   551 	AcceptedCargo diff;
   563 
   552 	memset(diff, 0, sizeof(diff));
   564 	VEHICLEUNITNUMBERSORTER(r, va, vb);
   553 
   565 
   554 	/* Append the cargo of the connected weagons */
   566 	return (_internal_sort_order & 1) ? -r : r;
   555 	for (v = *a; v != NULL; v = v->Next()) diff[v->cargo_type] += v->cargo_cap;
   567 }
   556 	for (v = *b; v != NULL; v = v->Next()) diff[v->cargo_type] -= v->cargo_cap;
   568 
   557 
   569 static int CDECL VehicleProfitLastYearSorter(const void *a, const void *b)
       
   570 {
       
   571 	const Vehicle* va = *(const Vehicle**)a;
       
   572 	const Vehicle* vb = *(const Vehicle**)b;
       
   573 	int r = ClampToI32(va->GetDisplayProfitLastYear() - vb->GetDisplayProfitLastYear());
       
   574 
       
   575 	VEHICLEUNITNUMBERSORTER(r, va, vb);
       
   576 
       
   577 	return (_internal_sort_order & 1) ? -r : r;
       
   578 }
       
   579 
       
   580 static int CDECL VehicleCargoSorter(const void *a, const void *b)
       
   581 {
       
   582 	const Vehicle* va = *(const Vehicle**)a;
       
   583 	const Vehicle* vb = *(const Vehicle**)b;
       
   584 	const Vehicle* v;
       
   585 	AcceptedCargo cargoa;
       
   586 	AcceptedCargo cargob;
       
   587 	int r = 0;
   558 	int r = 0;
   588 
       
   589 	memset(cargoa, 0, sizeof(cargoa));
       
   590 	memset(cargob, 0, sizeof(cargob));
       
   591 	for (v = va; v != NULL; v = v->Next()) cargoa[v->cargo_type] += v->cargo_cap;
       
   592 	for (v = vb; v != NULL; v = v->Next()) cargob[v->cargo_type] += v->cargo_cap;
       
   593 
       
   594 	for (CargoID i = 0; i < NUM_CARGO; i++) {
   559 	for (CargoID i = 0; i < NUM_CARGO; i++) {
   595 		r = cargoa[i] - cargob[i];
   560 		r = diff[i];
   596 		if (r != 0) break;
   561 		if (r != 0) break;
   597 	}
   562 	}
   598 
   563 
   599 	VEHICLEUNITNUMBERSORTER(r, va, vb);
   564 	return (r != 0) ? r : VehicleNumberSorter(a, b);
   600 
   565 }
   601 	return (_internal_sort_order & 1) ? -r : r;
   566 
   602 }
   567 /** Sort vehicles by their reliability */
   603 
   568 static int CDECL VehicleReliabilitySorter(const Vehicle* const *a, const Vehicle* const *b)
   604 static int CDECL VehicleReliabilitySorter(const void *a, const void *b)
   569 {
   605 {
   570 	int r = (*a)->reliability - (*b)->reliability;
   606 	const Vehicle* va = *(const Vehicle**)a;
   571 	return (r != 0) ? r : VehicleNumberSorter(a, b);
   607 	const Vehicle* vb = *(const Vehicle**)b;
   572 }
   608 	int r = va->reliability - vb->reliability;
   573 
   609 
   574 /** Sort vehicles by their max speed */
   610 	VEHICLEUNITNUMBERSORTER(r, va, vb);
   575 static int CDECL VehicleMaxSpeedSorter(const Vehicle* const *a, const Vehicle* const *b)
   611 
   576 {
   612 	return (_internal_sort_order & 1) ? -r : r;
   577 	int r = 0;
   613 }
   578 	if ((*a)->type == VEH_TRAIN && (*b)->type == VEH_TRAIN) {
   614 
   579 		r = (*a)->u.rail.cached_max_speed - (*b)->u.rail.cached_max_speed;
   615 static int CDECL VehicleMaxSpeedSorter(const void *a, const void *b)
       
   616 {
       
   617 	const Vehicle* va = *(const Vehicle**)a;
       
   618 	const Vehicle* vb = *(const Vehicle**)b;
       
   619 	int r;
       
   620 
       
   621 	if (va->type == VEH_TRAIN && vb->type == VEH_TRAIN) {
       
   622 		r = va->u.rail.cached_max_speed - vb->u.rail.cached_max_speed;
       
   623 	} else {
   580 	} else {
   624 		r = va->max_speed - vb->max_speed;
   581 		r = (*a)->max_speed - (*b)->max_speed;
   625 	}
   582 	}
   626 
   583 	return (r != 0) ? r : VehicleNumberSorter(a, b);
   627 	VEHICLEUNITNUMBERSORTER(r, va, vb);
   584 }
   628 
   585 
   629 	return (_internal_sort_order & 1) ? -r : r;
   586 /** Sort vehicles by model */
   630 }
   587 static int CDECL VehicleModelSorter(const Vehicle* const *a, const Vehicle* const *b)
   631 
   588 {
   632 static int CDECL VehicleModelSorter(const void *a, const void *b)
   589 	int r = (*a)->engine_type - (*b)->engine_type;
   633 {
   590 	return (r != 0) ? r : VehicleNumberSorter(a, b);
   634 	const Vehicle* va = *(const Vehicle**)a;
   591 }
   635 	const Vehicle* vb = *(const Vehicle**)b;
   592 
   636 	int r = va->engine_type - vb->engine_type;
   593 /** Sort vehciles by their value */
   637 
   594 static int CDECL VehicleValueSorter(const Vehicle* const *a, const Vehicle* const *b)
   638 	VEHICLEUNITNUMBERSORTER(r, va, vb);
   595 {
   639 
       
   640 	return (_internal_sort_order & 1) ? -r : r;
       
   641 }
       
   642 
       
   643 static int CDECL VehicleValueSorter(const void *a, const void *b)
       
   644 {
       
   645 	const Vehicle* va = *(const Vehicle**)a;
       
   646 	const Vehicle* vb = *(const Vehicle**)b;
       
   647 	const Vehicle *u;
   596 	const Vehicle *u;
   648 	Money valuea = 0, valueb = 0;
   597 	Money diff = 0;
   649 
   598 
   650 	for (u = va; u != NULL; u = u->Next()) valuea += u->value;
   599 	for (u = *a; u != NULL; u = u->Next()) diff += u->value;
   651 	for (u = vb; u != NULL; u = u->Next()) valueb += u->value;
   600 	for (u = *b; u != NULL; u = u->Next()) diff -= u->value;
   652 
   601 
   653 	int r = ClampToI32(valuea - valueb);
   602 	int r = ClampToI32(diff);
   654 
   603 	return (r != 0) ? r : VehicleNumberSorter(a, b);
   655 	VEHICLEUNITNUMBERSORTER(r, va, vb);
   604 }
   656 
   605 
   657 	return (_internal_sort_order & 1) ? -r : r;
   606 /** Sort vehicles by their length */
   658 }
   607 static int CDECL VehicleLengthSorter(const Vehicle* const *a, const Vehicle* const *b)
   659 
   608 {
   660 static int CDECL VehicleLengthSorter(const void *a, const void *b)
       
   661 {
       
   662 	const Vehicle *va = *(const Vehicle**)a;
       
   663 	const Vehicle *vb = *(const Vehicle**)b;
       
   664 	int r = 0;
   609 	int r = 0;
   665 
   610 	switch ((*a)->type) {
   666 	switch (va->type) {
       
   667 		case VEH_TRAIN:
   611 		case VEH_TRAIN:
   668 			r = va->u.rail.cached_total_length - vb->u.rail.cached_total_length;
   612 			r = (*a)->u.rail.cached_total_length - (*b)->u.rail.cached_total_length;
   669 			break;
   613 			break;
   670 
   614 
   671 		case VEH_ROAD:
   615 		case VEH_ROAD: {
   672 			for (const Vehicle *u = va; u != NULL; u = u->Next()) r += u->u.road.cached_veh_length;
   616 			const Vehicle *u;
   673 			for (const Vehicle *u = vb; u != NULL; u = u->Next()) r -= u->u.road.cached_veh_length;
   617 			for (u = *a; u != NULL; u = u->Next()) r += u->u.road.cached_veh_length;
   674 			break;
   618 			for (u = *b; u != NULL; u = u->Next()) r -= u->u.road.cached_veh_length;
       
   619 		} break;
   675 
   620 
   676 		default: NOT_REACHED();
   621 		default: NOT_REACHED();
   677 	}
   622 	}
   678 
   623 	return (r != 0) ? r : VehicleNumberSorter(a, b);
   679 	VEHICLEUNITNUMBERSORTER(r, va, vb);
       
   680 
       
   681 	return (_internal_sort_order & 1) ? -r : r;
       
   682 }
   624 }
   683 
   625 
   684 void InitializeGUI()
   626 void InitializeGUI()
   685 {
   627 {
   686 	memset(&_sorting, 0, sizeof(_sorting));
   628 	MemSetT(&_sorting, 0);
   687 }
   629 }
   688 
   630 
   689 /** Assigns an already open vehicle window to a new vehicle.
   631 /** Assigns an already open vehicle window to a new vehicle.
   690  * Assigns an already open vehicle window to a new vehicle. If the vehicle got
   632  * Assigns an already open vehicle window to a new vehicle. If the vehicle got
   691  * any sub window open (orders and so on) it will change owner too.
   633  * any sub window open (orders and so on) it will change owner too.
   913 			case VEH_SHIP:     this->sorting = &_sorting.ship; break;
   855 			case VEH_SHIP:     this->sorting = &_sorting.ship; break;
   914 			case VEH_AIRCRAFT: this->sorting = &_sorting.aircraft; break;
   856 			case VEH_AIRCRAFT: this->sorting = &_sorting.aircraft; break;
   915 			default: NOT_REACHED(); break;
   857 			default: NOT_REACHED(); break;
   916 		}
   858 		}
   917 
   859 
   918 		this->vehicles.flags = VL_REBUILD | (this->sorting->order ? VL_DESC : VL_NONE);
   860 		this->vehicles.SetListing(*this->sorting);
   919 		this->vehicles.sort_type = this->sorting->criteria;
   861 		this->vehicles.ForceRebuild();
   920 		this->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; // Set up resort timer
   862 		this->vehicles.NeedResort();
   921 
   863 
   922 		this->FindWindowPlacementAndResize(desc);
   864 		this->FindWindowPlacementAndResize(desc);
   923 	}
   865 	}
   924 
   866 
   925 	~VehicleListWindow()
   867 	~VehicleListWindow()
   926 	{
   868 	{
       
   869 		*this->sorting = this->vehicles.GetListing();
   927 	}
   870 	}
   928 
   871 
   929 	virtual void OnPaint()
   872 	virtual void OnPaint()
   930 	{
   873 	{
   931 		int x = 2;
   874 		int x = 2;
   986 			WIDGET_LIST_END);
   929 			WIDGET_LIST_END);
   987 
   930 
   988 		this->DrawWidgets();
   931 		this->DrawWidgets();
   989 
   932 
   990 		/* draw sorting criteria string */
   933 		/* draw sorting criteria string */
   991 		DrawString(85, 15, _vehicle_sort_listing[this->vehicles.sort_type], TC_BLACK);
   934 		DrawString(85, 15, this->vehicle_sorter_names[this->vehicles.SortType()], TC_BLACK);
   992 		/* draw arrow pointing up/down for ascending/descending sorting */
   935 		/* draw arrow pointing up/down for ascending/descending sorting */
   993 		this->DrawSortButtonState(VLW_WIDGET_SORT_ORDER, this->vehicles.flags & VL_DESC ? SBS_DOWN : SBS_UP);
   936 		this->DrawSortButtonState(VLW_WIDGET_SORT_ORDER, this->vehicles.IsDescSortOrder() ? SBS_DOWN : SBS_UP);
   994 
   937 
   995 		max = min(this->vscroll.pos + this->vscroll.cap, this->vehicles.Length());
   938 		max = min(this->vscroll.pos + this->vscroll.cap, this->vehicles.Length());
   996 		for (i = this->vscroll.pos; i < max; ++i) {
   939 		for (i = this->vscroll.pos; i < max; ++i) {
   997 			const Vehicle *v = this->vehicles[i];
   940 			const Vehicle *v = this->vehicles[i];
   998 			StringID str;
   941 			StringID str;
  1028 
   971 
  1029 	virtual void OnClick(Point pt, int widget)
   972 	virtual void OnClick(Point pt, int widget)
  1030 	{
   973 	{
  1031 		switch (widget) {
   974 		switch (widget) {
  1032 			case VLW_WIDGET_SORT_ORDER: /* Flip sorting method ascending/descending */
   975 			case VLW_WIDGET_SORT_ORDER: /* Flip sorting method ascending/descending */
  1033 				this->vehicles.flags ^= VL_DESC;
   976 				this->vehicles.ToggleSortOrder();
  1034 				this->vehicles.flags |= VL_RESORT;
       
  1035 
       
  1036 				this->sorting->order = !!(this->vehicles.flags & VL_DESC);
       
  1037 				this->SetDirty();
   977 				this->SetDirty();
  1038 				break;
   978 				break;
  1039 			case VLW_WIDGET_SORT_BY_PULLDOWN:/* Select sorting criteria dropdown menu */
   979 			case VLW_WIDGET_SORT_BY_PULLDOWN:/* Select sorting criteria dropdown menu */
  1040 				ShowDropDownMenu(this, _vehicle_sort_listing, this->vehicles.sort_type, VLW_WIDGET_SORT_BY_PULLDOWN, 0, (this->vehicle_type == VEH_TRAIN || this->vehicle_type == VEH_ROAD) ? 0 : (1 << 10));
   980 				ShowDropDownMenu(this, this->vehicle_sorter_names, this->vehicles.SortType(), VLW_WIDGET_SORT_BY_PULLDOWN, 0, (this->vehicle_type == VEH_TRAIN || this->vehicle_type == VEH_ROAD) ? 0 : (1 << 10));
  1041 				return;
   981 				return;
  1042 			case VLW_WIDGET_LIST: { /* Matrix to show vehicles */
   982 			case VLW_WIDGET_LIST: { /* Matrix to show vehicles */
  1043 				uint32 id_v = (pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / this->resize.step_height;
   983 				uint32 id_v = (pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / this->resize.step_height;
  1044 				const Vehicle *v;
   984 				const Vehicle *v;
  1045 
   985 
  1088 
  1028 
  1089 	virtual void OnDropdownSelect(int widget, int index)
  1029 	virtual void OnDropdownSelect(int widget, int index)
  1090 	{
  1030 	{
  1091 		switch (widget) {
  1031 		switch (widget) {
  1092 			case VLW_WIDGET_SORT_BY_PULLDOWN:
  1032 			case VLW_WIDGET_SORT_BY_PULLDOWN:
  1093 				if (this->vehicles.sort_type != index) {
  1033 				this->vehicles.SetSortType(index);
  1094 					/* value has changed -> resort */
       
  1095 					this->vehicles.flags |= VL_RESORT;
       
  1096 					this->vehicles.sort_type = index;
       
  1097 					this->sorting->criteria = this->vehicles.sort_type;
       
  1098 				}
       
  1099 				break;
  1034 				break;
  1100 			case VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN:
  1035 			case VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN:
  1101 				assert(this->vehicles.Length() != 0);
  1036 				assert(this->vehicles.Length() != 0);
  1102 
  1037 
  1103 				switch (index) {
  1038 				switch (index) {
  1126 	}
  1061 	}
  1127 
  1062 
  1128 	virtual void OnTick()
  1063 	virtual void OnTick()
  1129 	{
  1064 	{
  1130 		if (_pause_game != 0) return;
  1065 		if (_pause_game != 0) return;
  1131 		if (--this->vehicles.resort_timer == 0) {
  1066 		if (this->vehicles.NeedResort()) {
  1132 			StationID station = ((this->window_number & VLW_MASK) == VLW_STATION_LIST) ? GB(this->window_number, 16, 16) : INVALID_STATION;
  1067 			StationID station = ((this->window_number & VLW_MASK) == VLW_STATION_LIST) ? GB(this->window_number, 16, 16) : INVALID_STATION;
  1133 			PlayerID owner = (PlayerID)this->caption_color;
  1068 			PlayerID owner = (PlayerID)this->caption_color;
  1134 
  1069 
  1135 			DEBUG(misc, 3, "Periodic resort %d list player %d at station %d", this->vehicle_type, owner, station);
  1070 			DEBUG(misc, 3, "Periodic resort %d list player %d at station %d", this->vehicle_type, owner, station);
  1136 			this->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
       
  1137 			this->vehicles.flags |= VL_RESORT;
       
  1138 			this->SetDirty();
  1071 			this->SetDirty();
  1139 		}
  1072 		}
  1140 	}
  1073 	}
  1141 
  1074 
  1142 	virtual void OnResize(Point new_size, Point delta)
  1075 	virtual void OnResize(Point new_size, Point delta)
  1145 		this->widget[VLW_WIDGET_LIST].data = (this->vscroll.cap << 8) + 1;
  1078 		this->widget[VLW_WIDGET_LIST].data = (this->vscroll.cap << 8) + 1;
  1146 	}
  1079 	}
  1147 
  1080 
  1148 	virtual void OnInvalidateData(int data)
  1081 	virtual void OnInvalidateData(int data)
  1149 	{
  1082 	{
  1150 		this->vehicles.flags |= (data == 0 ? VL_REBUILD : VL_RESORT);
  1083 		if (data == 0) {
       
  1084 			this->vehicles.ForceRebuild();
       
  1085 		} else {
       
  1086 			this->vehicles.ForceResort();
       
  1087 		}
  1151 	}
  1088 	}
  1152 };
  1089 };
  1153 
  1090 
  1154 static const WindowDesc _player_vehicle_list_train_desc = {
  1091 static const WindowDesc _player_vehicle_list_train_desc = {
  1155 	WDP_AUTO, WDP_AUTO, 260, 182, 260, 182,
  1092 	WDP_AUTO, WDP_AUTO, 260, 182, 260, 182,