(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.
This commit is contained in:
darkvater
2004-09-06 18:15:13 +00:00
parent df1397a47e
commit bf0652d3fc
28 changed files with 1282 additions and 612 deletions

View File

@@ -9,7 +9,6 @@
#include "station.h"
#include "command.h"
#include "player.h"
//#include "town.h"
#include "engine.h"
@@ -868,100 +867,175 @@ static void DrawSmallShipSchedule(Vehicle *v, int x, int y) {
}
}
// used to get a sorted list of the vehicles
static SortStruct _ship_sort[NUM_NORMAL_VEHICLES];
static uint16 _num_ship_sort[MAX_PLAYERS];
static void MakeSortedShiptList(byte owner)
{
SortStruct *firstelement;
Vehicle *v;
uint32 n = 0;
uint16 *i;
if (_vehicle_sort_dirty[VEHSHIP]) { // only resort the whole array if vehicles have been added/removed
// reset to 0 just to be sure
for (i = _num_ship_sort; i != endof(_num_ship_sort); i++) {*i = 0;}
FOR_ALL_VEHICLES(v) {
if(v->type == VEH_Ship) {
_ship_sort[n].index = v->index;
_ship_sort[n++].owner = v->owner;
_num_ship_sort[v->owner]++; // add number of trains of player
}
}
// create cumulative ship-ownage
// ships 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_ship_sort[1]; i != endof(_num_ship_sort); i++) {*i += *(i-1);}
// sort by owner, then only subsort the requested owner-vehicles
qsort(_ship_sort, n, sizeof(_ship_sort[0]), GeneralOwnerSorter);
_last_vehicle_idx = 0; // used for "cache" in namesorting
_vehicle_sort_dirty[VEHSHIP] = false;
}
if (owner == 0) { // first element starts at 0th element and has n elements as described above
firstelement = &_ship_sort[0];
n = _num_ship_sort[0];
} else { // nth element starts at the end of the previous one, and has n elements as described above
firstelement = &_ship_sort[_num_ship_sort[owner-1]];
n = _num_ship_sort[owner] - _num_ship_sort[owner-1];
}
_internal_sort_type = _ship_sort_type[owner];
_internal_sort_order = _ship_sort_order[owner];
_internal_name_sorter_id = STR_SV_SHIP_NAME;
// only name sorting needs a different procedure, all others are handled by the general sorter
qsort(firstelement, n, sizeof(_ship_sort[0]), (_internal_sort_type == SORT_BY_NAME) ? VehicleNameSorter : GeneralVehicleSorter);
DEBUG(misc, 1) ("Resorting Ships list player %d...", owner+1);
}
static void PlayerShipsWndProc(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;
case WE_PAINT: {
uint32 i;
const byte window_number = (byte)w->window_number;
FOR_ALL_VEHICLES(v) {
if (v->type == VEH_Ship && v->owner == owner)
num++;
}
SetVScrollCount(w, num);
if (_ship_sort_type[window_number] == SORT_BY_UNSORTED) // disable 'Sort By' tooltip on Unsorted sorting criteria
w->disabled_state |= (1 << 3);
if (_ship_sort_dirty[window_number] || _vehicle_sort_dirty[VEHSHIP]) {
_ship_sort_dirty[window_number] = false;
MakeSortedShiptList(window_number);
/* reset sorting timeout */
w->custom[0] = DAY_TICKS;
w->custom[1] = PERIODIC_RESORT_DAYS;
}
// ships are stored as a cummulative index, eg 25, 41, 43. This means
// Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2 ships
i = (window_number == 0) ? 0 : _num_ship_sort[window_number-1];
SetVScrollCount(w, _num_ship_sort[window_number] - i);
/* draw the widgets */
{
Player *p = DEREF_PLAYER(w->window_number);
Player *p = DEREF_PLAYER(window_number);
/* Company Name -- (###) Ships */
SET_DPARAM16(0, p->name_1);
SET_DPARAM32(1, p->name_2);
SET_DPARAM16(2, w->vscroll.count);
SET_DPARAM16(3, _vehicle_sort_listing[_ship_sort_type[window_number]]);
DrawWindowWidgets(w);
}
/* draw arrow pointing up/down for ascending/descending soring */
DoDrawString(_ship_sort_order[window_number] & 1 ? "\xAA" : "\xA0", 85, 15, 0x10);
/* draw the ships vehicles */
/* draw the ship vehicles */
{
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_Ship && v->owner == owner &&
--pos < 0 && pos >= -4) {
StringID str;
DrawShipImage(v, x + 19, y + 6, INVALID_VEHICLE);
DrawVehicleProfitButton(v, x, y+13);
SET_DPARAM16(0, v->unitnumber);
if (IsShipDepotTile(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 ship list of current player
SET_DPARAM32(0, v->profit_this_year);
SET_DPARAM32(1, v->profit_last_year);
DrawString(x + 12, y + 28, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0);
if (v->string_id != STR_SV_SHIP_NAME) {
SET_DPARAM16(0, v->string_id);
DrawString(x+12, y, STR_01AB, 0);
}
while (i < _num_ship_sort[window_number]) {
StringID str;
v = DEREF_VEHICLE(_ship_sort[i].index);
DrawSmallShipSchedule(v, x+138, y);
DrawShipImage(v, x + 19, y + 6, INVALID_VEHICLE);
DrawVehicleProfitButton(v, x, y+13);
y += 36;
}
}
}
break;
case WE_CLICK:
switch(e->click.widget) {
case 2: { /* click ship */
int sel;
Vehicle *v;
byte owner;
sel = (e->click.pt.y - 14) / 36;
if ((uint)sel >= 4)
break;
sel += w->vscroll.pos;
owner = (byte)w->window_number;
FOR_ALL_VEHICLES(v) {
if (v->type == VEH_Ship && v->owner == owner && --sel < 0) {
ShowShipViewWindow(v);
break;
SET_DPARAM16(0, v->unitnumber);
if (IsShipDepotTile(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 + 12, y + 28, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0);
if (v->string_id != STR_SV_SHIP_NAME) {
SET_DPARAM16(0, v->string_id);
DrawString(x+12, y, STR_01AB, 0);
}
DrawSmallShipSchedule(v, x+138, y);
y += PLY_WND_PRC__SIZE_OF_ROW_BIG;
i++; // next ship
if (++n == w->vscroll.cap) { break;} // max number of ships in the window
}
break;
}
case 4: {/* click buy */
} break;
case WE_CLICK: {
switch(e->click.widget) {
case 3: /* Flip sorting method ascending/descending */
_ship_sort_order[(byte)w->window_number] ^= 1;
_ship_sort_dirty[(byte)w->window_number] = true;
SetWindowDirty(w);
break;
case 4: case 5:/* Select sorting criteria dropdown menu */
ShowDropDownMenu(w, _vehicle_sort_listing, _ship_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
id_v += w->vscroll.pos;
{
byte owner = (byte)w->window_number;
uint16 adder = (owner == 0) ? 0 : _num_ship_sort[owner - 1]; // first element in list
Vehicle *v;
if (id_v + adder >= _num_ship_sort[owner]) { return;} // click out of vehicle bound
v = DEREF_VEHICLE(_ship_sort[adder+id_v].index); // add the offset id_x to that
assert(v->type == VEH_Ship && v->owner == owner && v->owner == _ship_sort[adder+id_v].owner);
ShowShipViewWindow(v);
}
} break;
case 8: { /* Build new Vehicle */
uint tile;
tile = _last_built_ship_depot_tile;
do {
if (_map_owner[tile] == _local_player &&
IsShipDepotTile(tile)) {
if (_map_owner[tile] == _local_player && IsShipDepotTile(tile)) {
ShowShipDepotWindow(tile);
ShowBuildShipWindow(tile);
return;
@@ -973,38 +1047,74 @@ static void PlayerShipsWndProc(Window *w, WindowEvent *e)
ShowBuildShipWindow(0);
} break;
}
} break;
case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
if (_ship_sort_type[(byte)w->window_number] != e->dropdown.index) // if value hasn't changed, dont resort list
_ship_sort_dirty[(byte)w->window_number] = true;
_ship_sort_type[(byte)w->window_number] = e->dropdown.index;
if (_ship_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;
_ship_sort_dirty[(byte)w->window_number] = true;
DEBUG(misc, 1) ("Periodic resort Ships list player %d...", w->window_number+1);
SetWindowDirty(w);
}
}
break;
}
}
static const Widget _player_ships_widgets[] = {
{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9805_SHIPS, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_MATRIX, 14, 0, 248, 14, 157, 0x401, STR_9823_SHIPS_CLICK_ON_SHIP_FOR},
{ WWT_SCROLLBAR, 14, 249, 259, 14, 157, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
{ WWT_PUSHTXTBTN, 14, 0, 129, 158, 169, STR_9804_NEW_SHIPS, STR_9824_BUILD_NEW_SHIPS_REQUIRES},
{ WWT_IMGBTN, 14, 130, 259, 158, 169, 0x0},
{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9805_SHIPS, 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_9823_SHIPS_CLICK_ON_SHIP_FOR},
{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
{ WWT_PUSHTXTBTN, 14, 0, 129, 170, 181, STR_9804_NEW_SHIPS, STR_9824_BUILD_NEW_SHIPS_REQUIRES},
{ WWT_PANEL, 14, 130, 259, 170, 181, 0x0, 0},
{ WWT_LAST},
};
static const WindowDesc _player_ships_desc = {
-1, -1, 260, 170,
-1, -1, 260, 182,
WC_SHIPS_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_ships_widgets,
PlayerShipsWndProc
};
static const Widget _other_player_ships_widgets[] = {
{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9805_SHIPS, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_MATRIX, 14, 0, 248, 14, 157, 0x401, STR_9823_SHIPS_CLICK_ON_SHIP_FOR},
{ 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_9805_SHIPS, 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_9823_SHIPS_CLICK_ON_SHIP_FOR},
{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
{ WWT_LAST},
};
static const WindowDesc _other_player_ships_desc = {
-1, -1, 260, 158,
-1, -1, 260, 170,
WC_SHIPS_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,
_other_player_ships_widgets,
PlayerShipsWndProc
};