summaryrefslogtreecommitdiff
path: root/aircraft_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 /aircraft_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 'aircraft_gui.c')
-rw-r--r--aircraft_gui.c273
1 files changed, 191 insertions, 82 deletions
diff --git a/aircraft_gui.c b/aircraft_gui.c
index 450c612cd..0a723f895 100644
--- a/aircraft_gui.c
+++ b/aircraft_gui.c
@@ -864,102 +864,175 @@ static void DrawSmallSchedule(Vehicle *v, int x, int y) {
}
}
-static void PlayerAircraftWndProc(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;
+// used to get a sorted list of the vehicles
+static SortStruct _aircraft_sort[NUM_NORMAL_VEHICLES];
+static uint16 _num_aircraft_sort[MAX_PLAYERS];
- FOR_ALL_VEHICLES(v) {
- if (v->type == VEH_Aircraft && v->subtype <= 2 && v->owner == owner)
- num++;
+static void MakeSortedAircraftList(byte owner)
+{
+ SortStruct *firstelement;
+ Vehicle *v;
+ uint32 n = 0;
+ uint16 *i;
+
+ if (_vehicle_sort_dirty[VEHAIRCRAFT]) { // only resort the whole array if vehicles have been added/removed
+ // reset to 0 just to be sure
+ for (i = _num_aircraft_sort; i != endof(_num_aircraft_sort); i++) {*i = 0;}
+
+ FOR_ALL_VEHICLES(v) {
+ if(v->type == VEH_Aircraft && v->subtype <= 2) {
+ _aircraft_sort[n].index = v->index;
+ _aircraft_sort[n++].owner = v->owner;
+ _num_aircraft_sort[v->owner]++; // add number of aircraft of player
}
+ }
+
+ // create cumulative aircraft-ownage
+ // aircraft 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_aircraft_sort[1]; i != endof(_num_aircraft_sort); i++) {*i += *(i-1);}
+
+
+ // sort by owner, then only subsort the requested owner-vehicles
+ qsort(_aircraft_sort, n, sizeof(_aircraft_sort[0]), GeneralOwnerSorter);
+
+ _last_vehicle_idx = 0; // used for "cache" in namesorting
+ _vehicle_sort_dirty[VEHAIRCRAFT] = false;
+ }
+
+ if (owner == 0) { // first element starts at 0th element and has n elements as described above
+ firstelement = &_aircraft_sort[0];
+ n = _num_aircraft_sort[0];
+ } else { // nth element starts at the end of the previous one, and has n elements as described above
+ firstelement = &_aircraft_sort[_num_aircraft_sort[owner-1]];
+ n = _num_aircraft_sort[owner] - _num_aircraft_sort[owner-1];
+ }
+
+ _internal_sort_type = _aircraft_sort_type[owner];
+ _internal_sort_order = _aircraft_sort_order[owner];
+ _internal_name_sorter_id = STR_SV_AIRCRAFT_NAME;
+ // only name sorting needs a different procedure, all others are handled by the general sorter
+ qsort(firstelement, n, sizeof(_aircraft_sort[0]), (_internal_sort_type == SORT_BY_NAME) ? VehicleNameSorter : GeneralVehicleSorter);
- SetVScrollCount(w, num);
+ DEBUG(misc, 1) ("Resorting Aircraft list player %d...", owner+1);
+}
+
+static void PlayerAircraftWndProc(Window *w, WindowEvent *e)
+{
+ switch(e->event) {
+ case WE_PAINT: {
+ uint32 i;
+ const byte window_number = (byte)w->window_number;
+
+ if (_aircraft_sort_type[window_number] == SORT_BY_UNSORTED) // disable 'Sort By' tooltip on Unsorted sorting criteria
+ w->disabled_state |= (1 << 3);
+
+ if (_aircraft_sort_dirty[window_number] || _vehicle_sort_dirty[VEHAIRCRAFT]) {
+ _aircraft_sort_dirty[window_number] = false;
+ MakeSortedAircraftList(window_number);
+ /* reset sorting timeout */
+ w->custom[0] = DAY_TICKS;
+ w->custom[1] = PERIODIC_RESORT_DAYS;
}
+ // aircraft are stored as a cummulative index, eg 25, 41, 43. This means
+ // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2 aircraft
+ i = (window_number == 0) ? 0 : _num_aircraft_sort[window_number-1];
+ SetVScrollCount(w, _num_aircraft_sort[window_number] - i);
+
/* draw the widgets */
{
- Player *p = DEREF_PLAYER(w->window_number);
+ Player *p = DEREF_PLAYER(window_number);
+ /* Company Name -- (###) Aircraft */
SET_DPARAM16(0, p->name_1);
SET_DPARAM32(1, p->name_2);
+ SET_DPARAM16(2, w->vscroll.count);
+ SET_DPARAM16(3, _vehicle_sort_listing[_aircraft_sort_type[window_number]]);
DrawWindowWidgets(w);
}
+ /* draw arrow pointing up/down for ascending/descending soring */
+ DoDrawString(_aircraft_sort_order[window_number] & 1 ? "\xAA" : "\xA0", 85, 15, 0x10);
/* draw the aircraft */
{
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_Aircraft && v->subtype <= 2 && v->owner == owner &&
- --pos < 0 && pos >= -4) {
- StringID str;
-
- DrawAircraftImage(v, x + 19, y + 6, INVALID_VEHICLE);
- DrawVehicleProfitButton(v, x, y+13);
-
- SET_DPARAM16(0, v->unitnumber);
- if (IsAircraftHangarTile(v->tile)) {
- str = STR_021F;
- } else {
- str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2;
- }
- DrawString(x, y+2, str, 0);
+ 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 aircraft list of current player
+
+ while (i < _num_aircraft_sort[window_number]) {
+ StringID str;
+ v = DEREF_VEHICLE(_aircraft_sort[i].index);
+
+ DrawAircraftImage(v, x + 19, y + 6, INVALID_VEHICLE);
+ DrawVehicleProfitButton(v, x, y+13);
+
+ SET_DPARAM16(0, v->unitnumber);
+ if (IsAircraftHangarTile(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+19, y + 28, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0);
- if (v->string_id != STR_SV_AIRCRAFT_NAME) {
- SET_DPARAM16(0, v->string_id);
- DrawString(x+19, y, STR_01AB, 0);
- }
+ SET_DPARAM32(0, v->profit_this_year);
+ SET_DPARAM32(1, v->profit_last_year);
+ DrawString(x+19, y + 28, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0);
+
+ if (v->string_id != STR_SV_AIRCRAFT_NAME) {
+ SET_DPARAM16(0, v->string_id);
+ DrawString(x+19, y, STR_01AB, 0);
+ }
- DrawSmallSchedule(v, x+136, y);
+ DrawSmallSchedule(v, x+136, y);
- y += 36;
- }
+ y += PLY_WND_PRC__SIZE_OF_ROW_BIG;
+ i++; // next aircraft
+ if (++n == w->vscroll.cap) { break;} // max number of aircraft in the window
}
}
- break;
+ } break;
- case WE_CLICK:
+ case WE_CLICK: {
switch(e->click.widget) {
- case 2: { /* click on aircraft */
- int sel;
- Vehicle *v;
- byte owner;
+ case 3: /* Flip sorting method ascending/descending */
+ _aircraft_sort_order[(byte)w->window_number] ^= 1;
+ _aircraft_sort_dirty[(byte)w->window_number] = true;
+ SetWindowDirty(w);
+ break;
+ case 4: case 5:/* Select sorting criteria dropdown menu */
+ ShowDropDownMenu(w, _vehicle_sort_listing, _aircraft_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_BIG;
+
+ if ((uint)id_v >= w->vscroll.cap) { return;} // click out of bounds
- sel = (e->click.pt.y - 14) / 36;
+ id_v += w->vscroll.pos;
- if ((uint)sel >= 4)
- break;
- sel += w->vscroll.pos;
- owner = (byte)w->window_number;
- FOR_ALL_VEHICLES(v) {
- if (v->type == VEH_Aircraft && v->subtype <= 2 && v->owner == owner &&
- --sel < 0) {
- ShowAircraftViewWindow(v);
- break;
- }
+ {
+ byte owner = (byte)w->window_number;
+ uint16 adder = (owner == 0) ? 0 : _num_aircraft_sort[owner - 1]; // first element in list
+ Vehicle *v;
+
+ if (id_v + adder >= _num_aircraft_sort[owner]) { return;} // click out of vehicle bound
+
+ v = DEREF_VEHICLE(_aircraft_sort[adder+id_v].index); // add the offset id_x to that
+
+ assert(v->type == VEH_Aircraft && v->subtype <= 2 && v->owner == owner && v->owner == _aircraft_sort[adder+id_v].owner);
+
+ ShowAircraftViewWindow(v);
}
- break;
- }
- case 4: { /* build new */
+ } break;
+
+ case 8: { /* Build new Vehicle */
uint tile;
tile = _last_built_aircraft_depot_tile;
do {
- if (_map_owner[tile] == _local_player &&
- IsAircraftHangarTile(tile)) {
+ if (_map_owner[tile] == _local_player && IsAircraftHangarTile(tile)) {
ShowAircraftDepotWindow(tile);
ShowBuildAircraftWindow(tile);
return;
@@ -967,43 +1040,79 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e)
tile = TILE_MASK(tile + 1);
} while(tile != _last_built_aircraft_depot_tile);
+
ShowBuildAircraftWindow(0);
} break;
}
+ } break;
+
+ case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
+ if (_aircraft_sort_type[(byte)w->window_number] != e->dropdown.index) // if value hasn't changed, dont resort list
+ _aircraft_sort_dirty[(byte)w->window_number] = true;
+
+ _aircraft_sort_type[(byte)w->window_number] = e->dropdown.index;
+
+ if (_aircraft_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;
+ _aircraft_sort_dirty[(byte)w->window_number] = true;
+ DEBUG(misc, 1) ("Periodic resort Aircraft list player %d...", w->window_number+1);
+ SetWindowDirty(w);
+ }
+ }
break;
}
}
static const Widget _player_aircraft_widgets[] = {
-{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_A009_AIRCRAFT, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{ WWT_MATRIX, 14, 0, 248, 14, 157, 0x401, STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT},
-{ WWT_SCROLLBAR, 14, 249, 259, 14, 157, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
-{ WWT_PUSHTXTBTN, 14, 0, 129, 158, 169, STR_A003_NEW_AIRCRAFT, STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES},
-{ WWT_IMGBTN, 14, 130, 259, 158, 169, 0x0, 0},
+{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_A009_AIRCRAFT, 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, 169, 0x401, STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT},
+{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WWT_PUSHTXTBTN, 14, 0, 129, 170, 181, STR_A003_NEW_AIRCRAFT, STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES},
+{ WWT_PANEL, 14, 130, 259, 170, 181, 0x0, 0},
{ WWT_LAST},
};
static const WindowDesc _player_aircraft_desc = {
- -1, -1, 260, 170,
+ -1, -1, 260, 182,
WC_AIRCRAFT_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_aircraft_widgets,
PlayerAircraftWndProc
};
static const Widget _other_player_aircraft_widgets[] = {
-{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_A009_AIRCRAFT, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{ WWT_MATRIX, 14, 0, 248, 14, 157, 0x401, STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT},
-{ WWT_SCROLLBAR, 14, 249, 259, 14, 157, 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_A009_AIRCRAFT, 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, 169, 0x401, STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT},
+{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
{ WWT_LAST},
};
static const WindowDesc _other_player_aircraft_desc = {
- -1, -1, 260, 158,
+ -1, -1, 260, 170,
WC_AIRCRAFT_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_aircraft_widgets,
PlayerAircraftWndProc
};
@@ -1012,7 +1121,7 @@ void ShowPlayerAircraft(int player)
{
Window *w;
- if ( player == _local_player) {
+ if (player == _local_player) {
w = AllocateWindowDescFront(&_player_aircraft_desc, player);
} else {
w = AllocateWindowDescFront(&_other_player_aircraft_desc, player);
@@ -1020,6 +1129,6 @@ void ShowPlayerAircraft(int player)
if (w) {
w->caption_color = w->window_number;
- w->vscroll.cap = 4;
+ w->vscroll.cap = 4; // maximum number of vehicles shown
}
}