diff options
Diffstat (limited to 'aircraft_gui.c')
-rw-r--r-- | aircraft_gui.c | 273 |
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 } } |