summaryrefslogtreecommitdiff
path: root/roadveh_gui.c
diff options
context:
space:
mode:
authordarkvater <darkvater@openttd.org>2004-09-06 18:15:13 +0000
committerdarkvater <darkvater@openttd.org>2004-09-06 18:15:13 +0000
commitbf0652d3fce57024fe56f75d43898a261fea7570 (patch)
treeff59ad94248c5c270741fe954c139e1f953b197c /roadveh_gui.c
parentdf1397a47e68cf07d0a0d4fe02758f4b4f8c469f (diff)
downloadopenttd-bf0652d3fce57024fe56f75d43898a261fea7570.tar.xz
(svn r165) -Feature: Option to sort vehicles in vehicle-list window by different criteria. Total independent sort for all types and players. Periodic resort of list every 10 TTD days. Thank you for your graphical inspiration follow and buxo (since none of you provided any code).
-Fix: Sorter icon pointing down 'v' sorts in every window lowest value first, '^' highest value first -CodeChange: move Dropdownlist from settings_gui.c to widget.c. More in place there.
Diffstat (limited to 'roadveh_gui.c')
-rw-r--r--roadveh_gui.c269
1 files changed, 188 insertions, 81 deletions
diff --git a/roadveh_gui.c b/roadveh_gui.c
index 8c77b081c..a48b727ed 100644
--- a/roadveh_gui.c
+++ b/roadveh_gui.c
@@ -9,7 +9,6 @@
#include "station.h"
#include "command.h"
#include "player.h"
-//#include "town.h"
#include "engine.h"
extern const byte _roadveh_price[88];
@@ -704,100 +703,172 @@ void ShowRoadDepotWindow(uint tile)
}
}
+// used to get a sorted list of the vehicles
+static SortStruct _road_sort[NUM_NORMAL_VEHICLES];
+static uint16 _num_road_sort[MAX_PLAYERS];
+
+static void MakeSortedRoadList(byte owner)
+{
+ SortStruct *firstelement;
+ Vehicle *v;
+ uint32 n = 0;
+ uint16 *i;
+
+ if (_vehicle_sort_dirty[VEHROAD]) { // only resort the whole array if vehicles have been added/removed
+ // reset to 0 just to be sure
+ for (i = _num_road_sort; i != endof(_num_road_sort); i++) {*i = 0;}
+
+ FOR_ALL_VEHICLES(v) {
+ if(v->type == VEH_Road) {
+ _road_sort[n].index = v->index;
+ _road_sort[n++].owner = v->owner;
+ _num_road_sort[v->owner]++; // add number of roads of player
+ }
+ }
+
+ // create cumulative road-ownage
+ // roads are stored as a cummulative index, eg 25, 41, 43. This means
+ // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2
+ for (i = &_num_road_sort[1]; i != endof(_num_road_sort); i++) {*i += *(i-1);}
+
+
+ // sort by owner, then only subsort the requested owner-vehicles
+ qsort(_road_sort, n, sizeof(_road_sort[0]), GeneralOwnerSorter);
+
+ _last_vehicle_idx = 0; // used for "cache" in namesorting
+ _vehicle_sort_dirty[VEHROAD] = false;
+ }
+
+ if (owner == 0) { // first element starts at 0th element and has n elements as described above
+ firstelement = &_road_sort[0];
+ n = _num_road_sort[0];
+ } else { // nth element starts at the end of the previous one, and has n elements as described above
+ firstelement = &_road_sort[_num_road_sort[owner-1]];
+ n = _num_road_sort[owner] - _num_road_sort[owner-1];
+ }
+
+ _internal_sort_type = _road_sort_type[owner];
+ _internal_sort_order = _road_sort_order[owner];
+ _internal_name_sorter_id = STR_SV_ROADVEH_NAME;
+ // only name sorting needs a different procedure, all others are handled by the general sorter
+ qsort(firstelement, n, sizeof(_road_sort[0]), (_internal_sort_type == SORT_BY_NAME) ? VehicleNameSorter : GeneralVehicleSorter);
+
+ DEBUG(misc, 1) ("Resorting Roadvehicles list player %d...", owner+1);
+}
+
static void PlayerRoadVehWndProc(Window *w, WindowEvent *e)
{
switch(e->event) {
- case WE_PAINT:
- /* determine amount of items for scroller */
- {
- Vehicle *v;
- int num = 0;
- byte owner = (byte)w->window_number;
-
- FOR_ALL_VEHICLES(v) {
- if (v->type == VEH_Road && v->owner == owner)
- num++;
- }
- SetVScrollCount(w, num);
+ case WE_PAINT: {
+ uint32 i;
+ const byte window_number = (byte)w->window_number;
+
+ if (_road_sort_type[window_number] == SORT_BY_UNSORTED) // disable 'Sort By' tooltip on Unsorted sorting criteria
+ w->disabled_state |= (1 << 3);
+
+ if (_road_sort_dirty[window_number] || _vehicle_sort_dirty[VEHROAD]) {
+ _road_sort_dirty[window_number] = false;
+ MakeSortedRoadList(window_number);
+ /* reset sorting timeout */
+ w->custom[0] = DAY_TICKS;
+ w->custom[1] = PERIODIC_RESORT_DAYS;
}
+ // roads are stored as a cummulative index, eg 25, 41, 43. This means
+ // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2 roads
+ i = (window_number == 0) ? 0 : _num_road_sort[window_number-1];
+ SetVScrollCount(w, _num_road_sort[window_number] - i);
+
/* draw the widgets */
{
- Player *p = DEREF_PLAYER(w->window_number);
+ Player *p = DEREF_PLAYER(window_number);
+ /* Company Name -- (###) Roadvehicles */
SET_DPARAM16(0, p->name_1);
SET_DPARAM32(1, p->name_2);
+ SET_DPARAM16(2, w->vscroll.count);
+ SET_DPARAM16(3, _vehicle_sort_listing[_road_sort_type[window_number]]);
DrawWindowWidgets(w);
}
+ /* draw arrow pointing up/down for ascending/descending soring */
+ DoDrawString(_road_sort_order[window_number] & 1 ? "\xAA" : "\xA0", 85, 15, 0x10);
- /* draw the road vehicles */
+ /* draw the roadvehicles */
{
Vehicle *v;
- int pos = w->vscroll.pos;
- byte owner = (byte)w->window_number;
- int x = 2;
- int y = 15;
-
- FOR_ALL_VEHICLES(v) {
- if (v->type == VEH_Road && v->owner == owner &&
- --pos < 0 && pos >= -7) {
- StringID str;
-
- DrawRoadVehImage(v, x + 22, y + 6, INVALID_VEHICLE);
- DrawVehicleProfitButton(v, x, y+13);
-
- SET_DPARAM16(0, v->unitnumber);
- if (IsRoadDepotTile(v->tile)) {
- str = STR_021F;
- } else {
- str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2;
- }
- DrawString(x, y+2, str, 0);
-
- SET_DPARAM32(0, v->profit_this_year);
- SET_DPARAM32(1, v->profit_last_year);
- DrawString(x + 24, y + 18, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0);
-
- if (v->string_id != STR_SV_ROADVEH_NAME) {
- SET_DPARAM16(0, v->string_id);
- DrawString(x+24, y, STR_01AB, 0);
- }
- y += 26;
- }
+ int n = 0;
+ const int x = 2; // offset from left side of widget
+ int y = PLY_WND_PRC__OFFSET_TOP_WIDGET; // offset from top of widget
+ i += w->vscroll.pos; // offset from sorted roads list of current player
+
+ while (i < _num_road_sort[window_number]) {
+ StringID str;
+ v = DEREF_VEHICLE(_road_sort[i].index);
+
+ DrawRoadVehImage(v, x + 22, y + 6, INVALID_VEHICLE);
+ DrawVehicleProfitButton(v, x, y+13);
+
+ SET_DPARAM16(0, v->unitnumber);
+ if (IsRoadDepotTile(v->tile)) {
+ str = STR_021F;
+ } else {
+ str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2;
+ }
+ DrawString(x, y+2, str, 0);
+
+ SET_DPARAM32(0, v->profit_this_year);
+ SET_DPARAM32(1, v->profit_last_year);
+ DrawString(x + 24, y + 18, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0);
+
+ if (v->string_id != STR_SV_ROADVEH_NAME) {
+ SET_DPARAM16(0, v->string_id);
+ DrawString(x+24, y, STR_01AB, 0);
+ }
+
+ y += PLY_WND_PRC__SIZE_OF_ROW_SMALL;
+ i++; // next road
+ if (++n == w->vscroll.cap) { break;} // max number of roads in the window
}
}
- break;
+ } break;
- case WE_CLICK:
+ case WE_CLICK: {
switch(e->click.widget) {
- case 2: {
- int idx = (e->click.pt.y - 14) / 26;
- Vehicle *v;
- byte owner;
+ case 3: /* Flip sorting method ascending/descending */
+ _road_sort_order[(byte)w->window_number] ^= 1;
+ _road_sort_dirty[(byte)w->window_number] = true;
+ SetWindowDirty(w);
+ break;
+ case 4: case 5:/* Select sorting criteria dropdown menu */
+ ShowDropDownMenu(w, _vehicle_sort_listing, _road_sort_type[(byte)w->window_number], 5, 0); // do it for widget 5
+ return;
+ case 6: { /* Matrix to show vehicles */
+ int id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_SMALL;
+
+ if ((uint)id_v >= w->vscroll.cap) { return;} // click out of bounds
- if ((uint)idx >= 7)
- break;
+ id_v += w->vscroll.pos;
+
+ {
+ byte owner = (byte)w->window_number;
+ uint16 adder = (owner == 0) ? 0 : _num_road_sort[owner - 1]; // first element in list
+ Vehicle *v;
- idx += w->vscroll.pos;
+ if (id_v + adder >= _num_road_sort[owner]) { return;} // click out of vehicle bound
- owner = (byte)w->window_number;
+ v = DEREF_VEHICLE(_road_sort[adder+id_v].index); // add the offset id_x to that
- FOR_ALL_VEHICLES(v) {
- if (v->type == VEH_Road && v->owner == owner &&
- --idx < 0) {
- ShowRoadVehViewWindow(v);
- break;
- }
+ assert(v->type == VEH_Road && v->owner == owner && v->owner == _road_sort[adder+id_v].owner);
+
+ ShowRoadVehViewWindow(v);
}
} break;
- case 4: {
+ case 8: { /* Build new Vehicle */
uint tile;
tile = _last_built_road_depot_tile;
do {
- if (_map_owner[tile] == _local_player &&
- IsRoadDepotTile(tile)) {
-
+ if (_map_owner[tile] == _local_player && IsRoadDepotTile(tile)) {
ShowRoadDepotWindow(tile);
ShowBuildRoadVehWindow(tile);
return;
@@ -808,40 +879,76 @@ static void PlayerRoadVehWndProc(Window *w, WindowEvent *e)
ShowBuildRoadVehWindow(0);
} break;
- } break;
+ }
+ } break;
+
+ case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
+ if (_road_sort_type[(byte)w->window_number] != e->dropdown.index) // if value hasn't changed, dont resort list
+ _road_sort_dirty[(byte)w->window_number] = true;
+
+ _road_sort_type[(byte)w->window_number] = e->dropdown.index;
+
+ if (_road_sort_type[(byte)w->window_number] != SORT_BY_UNSORTED) // enable 'Sort By' if a sorter criteria is chosen
+ w->disabled_state &= ~(1 << 3);
+
+ SetWindowDirty(w);
+ break;
+ case WE_CREATE: /* set up resort timer */
+ w->custom[0] = DAY_TICKS;
+ w->custom[1] = PERIODIC_RESORT_DAYS;
+ break;
+ case WE_TICK: /* resort the list every 20 seconds orso (10 days) */
+ if (--w->custom[0] == 0) {
+ w->custom[0] = DAY_TICKS;
+ if (--w->custom[1] == 0) {
+ w->custom[1] = PERIODIC_RESORT_DAYS;
+ _road_sort_dirty[(byte)w->window_number] = true;
+ DEBUG(misc, 1) ("Periodic resort Roadvehicles list player %d...", w->window_number+1);
+ SetWindowDirty(w);
+ }
+ }
+ break;
}
}
static const Widget _player_roadveh_widgets[] = {
-{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9001_ROAD_VEHICLES, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{ WWT_MATRIX, 14, 0, 248, 14, 195, 0x701, STR_901A_ROAD_VEHICLES_CLICK_ON},
-{ WWT_SCROLLBAR, 14, 249, 259, 14, 195, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
-{ WWT_PUSHTXTBTN, 14, 0, 129, 196, 207, STR_9004_NEW_VEHICLES, STR_901B_BUILD_NEW_ROAD_VEHICLES},
-{ WWT_IMGBTN, 14, 130, 259, 196, 207, 0x0, 0},
+{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9001_ROAD_VEHICLES, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_PANEL, 14, 0, 15, 14, 25, 0x0, 0},
+{ WWT_PUSHTXTBTN, 14, 16, 96, 14, 25, SRT_SORT_BY, STR_SORT_TIP},
+{ WWT_TEXTBTN, 14, 97, 248, 14, 25, STR_02E7, 0},
+{ WWT_CLOSEBOX, 14, 249, 259, 14, 25, STR_0225, STR_SORT_TIP},
+{ WWT_MATRIX, 14, 0, 248, 26, 207, 0x701, STR_901A_ROAD_VEHICLES_CLICK_ON},
+{ WWT_SCROLLBAR, 14, 249, 259, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WWT_PUSHTXTBTN, 14, 0, 129, 208, 219, STR_9004_NEW_VEHICLES, STR_901B_BUILD_NEW_ROAD_VEHICLES},
+{ WWT_IMGBTN, 14, 130, 259, 208, 219, 0x0, 0},
{ WWT_LAST},
};
static const WindowDesc _player_roadveh_desc = {
- -1, -1, 260, 208,
+ -1, -1, 260, 220,
WC_ROADVEH_LIST,0,
- WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
+ WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESTORE_DPARAM,
_player_roadveh_widgets,
PlayerRoadVehWndProc
};
static const Widget _other_player_roadveh_widgets[] = {
-{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9001_ROAD_VEHICLES, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{ WWT_MATRIX, 14, 0, 248, 14, 195, 0x701, STR_901A_ROAD_VEHICLES_CLICK_ON},
-{ WWT_SCROLLBAR, 14, 249, 259, 14, 195, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9001_ROAD_VEHICLES, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_PANEL, 14, 0, 15, 14, 25, 0x0, 0},
+{ WWT_PUSHTXTBTN, 14, 16, 96, 14, 25, SRT_SORT_BY, STR_SORT_TIP},
+{ WWT_TEXTBTN, 14, 97, 248, 14, 25, STR_02E7, 0},
+{ WWT_CLOSEBOX, 14, 249, 259, 14, 25, STR_0225, STR_SORT_TIP},
+{ WWT_MATRIX, 14, 0, 248, 26, 207, 0x701, STR_901A_ROAD_VEHICLES_CLICK_ON},
+{ WWT_SCROLLBAR, 14, 249, 259, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
{ WWT_LAST},
};
static const WindowDesc _other_player_roadveh_desc = {
- -1, -1, 260, 196,
+ -1, -1, 260, 208,
WC_ROADVEH_LIST,0,
- WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
+ WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESTORE_DPARAM,
_other_player_roadveh_widgets,
PlayerRoadVehWndProc
};