diff options
-rw-r--r-- | aircraft_gui.c | 205 | ||||
-rw-r--r-- | lang/english.txt | 1 |
2 files changed, 188 insertions, 18 deletions
diff --git a/aircraft_gui.c b/aircraft_gui.c index 438094c50..7b501ea6a 100644 --- a/aircraft_gui.c +++ b/aircraft_gui.c @@ -24,14 +24,14 @@ #include "vehicle_gui.h" #include "newgrf_engine.h" #include "date.h" +#include "strings.h" typedef enum BuildAircraftWidgets { BUILD_AIRCRAFT_WIDGET_CLOSEBOX = 0, BUILD_AIRCRAFT_WIDGET_CAPTION, - BUILD_AIRCRAFT_WIDGET_SORT_PLACEHOLDER, -// BUILD_AIRCRAFT_WIDGET_SORT_ASSENDING_DESENTING, -// BUILD_AIRCRAFT_WIDGET_SORT_TEXT, -// BUILD_AIRCRAFT_WIDGET_SORT_DROPDOWN, + BUILD_AIRCRAFT_WIDGET_SORT_ASSENDING_DESENTING, + BUILD_AIRCRAFT_WIDGET_SORT_TEXT, + BUILD_AIRCRAFT_WIDGET_SORT_DROPDOWN, BUILD_AIRCRAFT_WIDGET_LIST, BUILD_AIRCRAFT_WIDGET_SCROLLBAR, BUILD_AIRCRAFT_WIDGET_PANEL, @@ -46,7 +46,9 @@ typedef enum BuildAircraftWidgets { static const Widget _new_aircraft_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW }, { WWT_CAPTION, RESIZE_NONE, 14, 11, 239, 0, 13, STR_A005_NEW_AIRCRAFT, STR_018C_WINDOW_TITLE_DRAG_THIS }, - { WWT_IMGBTN, RESIZE_NONE, 14, 0, 239, 14, 25, 0x0, STR_NULL }, + { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 0, 80, 14, 25, STR_SORT_BY, STR_SORT_ORDER_TIP}, + { WWT_PANEL, RESIZE_NONE, 14, 81, 227, 14, 25, 0x0, STR_SORT_CRITERIA_TIP}, + { WWT_TEXTBTN, RESIZE_NONE, 14, 228, 239, 14, 25, STR_0225, STR_SORT_CRITERIA_TIP}, { WWT_MATRIX, RESIZE_BOTTOM, 14, 0, 227, 26, 121, 0x401, STR_A025_AIRCRAFT_SELECTION_LIST }, { WWT_SCROLLBAR, RESIZE_BOTTOM, 14, 228, 239, 26, 121, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST }, { WWT_IMGBTN, RESIZE_TB, 14, 0, 239, 122, 193, 0x0, STR_NULL }, @@ -61,6 +63,150 @@ static const Widget _new_aircraft_widgets[] = { { WIDGETS_END}, }; +static bool _internal_sort_order; // descending/ascending +static byte _last_sort_criteria = 0; +static bool _last_sort_order = false; + +typedef int CDECL VehicleSortListingTypeFunction(const void*, const void*); + +static int CDECL AircraftEngineNumberSorter(const void *a, const void *b) +{ + const EngineID va = *(const EngineID*)a; + const EngineID vb = *(const EngineID*)b; + int r = va - vb; + + return _internal_sort_order ? -r : r; +} + +static int CDECL AircraftEngineCostSorter(const void *a, const void *b) +{ + const int va = AircraftVehInfo(*(const EngineID*)a)->base_cost; + const int vb = AircraftVehInfo(*(const EngineID*)b)->base_cost; + int r = va - vb; + + return _internal_sort_order ? -r : r; +} + +static int CDECL AircraftEngineSpeedSorter(const void *a, const void *b) +{ + const int va = AircraftVehInfo(*(const EngineID*)a)->max_speed; + const int vb = AircraftVehInfo(*(const EngineID*)b)->max_speed; + const int r = va - vb; + + if (r == 0) { + /* Use EngineID to sort instead since we want consistent sorting */ + return AircraftEngineNumberSorter(a, b); + } + return _internal_sort_order ? -r : r; +} + +static int CDECL AircraftEngineIntroDateSorter(const void *a, const void *b) +{ + const int va = GetEngine(*(const EngineID*)a)->intro_date; + const int vb = GetEngine(*(const EngineID*)b)->intro_date; + const int r = va - vb; + + if (r == 0) { + /* Use EngineID to sort instead since we want consistent sorting */ + return AircraftEngineNumberSorter(a, b); + } + return _internal_sort_order ? -r : r; +} + +static EngineID _last_engine; // cached vehicle to hopefully speed up name-sorting + +static char _bufcache[64]; // used together with _last_vehicle to hopefully speed up stringsorting +static int CDECL AircraftEngineNameSorter(const void *a, const void *b) +{ + const EngineID va = *(const EngineID*)a; + const EngineID vb = *(const EngineID*)b; + char buf1[64] = "\0"; + int r; + + SetDParam(0, GetCustomEngineName(va)); + GetString(buf1, STR_JUST_STRING); + + if (vb != _last_engine) { + _last_engine = vb; + _bufcache[0] = '\0'; + + SetDParam(0, GetCustomEngineName(vb)); + GetString(_bufcache, STR_JUST_STRING); + } + + r = strcmp(buf1, _bufcache); // sort by name + + if (r == 0) { + /* Use EngineID to sort instead since we want consistent sorting */ + return AircraftEngineNumberSorter(a, b); + } + + return (_internal_sort_order & 1) ? -r : r; +} + +static int CDECL AircraftEngineRunningCostSorter(const void *a, const void *b) +{ + const int va = AircraftVehInfo(*(const EngineID*)a)->running_cost; + const int vb = AircraftVehInfo(*(const EngineID*)b)->running_cost; + const int r = va - vb; + + if (r == 0) { + /* Use EngineID to sort instead since we want consistent sorting */ + return AircraftEngineNumberSorter(a, b); + } + return _internal_sort_order ? -r : r; +} + +static int CDECL AircraftEngineReliabilitySorter(const void *a, const void *b) +{ + const int va = GetEngine(*(const EngineID*)a)->reliability; + const int vb = GetEngine(*(const EngineID*)b)->reliability; + const int r = va - vb; + + if (r == 0) { + /* Use EngineID to sort instead since we want consistent sorting */ + return AircraftEngineNumberSorter(a, b); + } + return _internal_sort_order ? -r : r; +} + +static int CDECL AircraftEngineCargoSorter(const void *a, const void *b) +{ + const int va = AircraftVehInfo(*(const EngineID*)a)->passenger_capacity; + const int vb = AircraftVehInfo(*(const EngineID*)b)->passenger_capacity; + const int r = va - vb; + + if (r == 0) { + /* Use EngineID to sort instead since we want consistent sorting */ + return AircraftEngineNumberSorter(a, b); + } + return _internal_sort_order ? -r : r; +} + +static VehicleSortListingTypeFunction* const _engine_sorter[] = { + &AircraftEngineNumberSorter, + &AircraftEngineCostSorter, + &AircraftEngineSpeedSorter, + &AircraftEngineIntroDateSorter, + &AircraftEngineNameSorter, + &AircraftEngineRunningCostSorter, + &AircraftEngineReliabilitySorter, + &AircraftEngineCargoSorter, +}; + +static const StringID _engine_sort_listing[] = { + STR_ENGINE_SORT_ENGINE_ID, + STR_ENGINE_SORT_COST, + STR_SORT_BY_MAX_SPEED, + STR_ENGINE_SORT_INTRO_DATE, + STR_SORT_BY_DROPDOWN_NAME, + STR_ENGINE_SORT_RUNNING_COST, + STR_SORT_BY_RELIABILITY, + STR_ENGINE_SORT_CARGO_CAPACITY, + INVALID_STRING_ID +}; + + /** * Draw the purchase info details of an aircraft at a given location. * @param x,y location where to draw the info @@ -219,10 +365,15 @@ static inline uint16 GetEngineArrayLength(Window *w) return 0; } -static void DrawBuildAircraftWindow(Window *w) +static void SortAircraftBuildList(Window *w) { - int count = 0; + _internal_sort_order = WP(w,buildtrain_d).decenting_sort_order; + qsort((void*)GetEngineArray(w), GetEngineArrayLength(w), sizeof(GetEngineArray(w)[0]), + _engine_sorter[WP(w,buildtrain_d).sort_criteria]); +} +static void DrawBuildAircraftWindow(Window *w) +{ SetWindowWidgetLoweredState(w, BUILD_AIRCRAFT_WIDGET_PLANES, WP(w,buildtrain_d).show_engine_button == 1); SetWindowWidgetLoweredState(w, BUILD_AIRCRAFT_WIDGET_JETS, WP(w,buildtrain_d).show_engine_button == 2); SetWindowWidgetLoweredState(w, BUILD_AIRCRAFT_WIDGET_HELICOPTERS, WP(w,buildtrain_d).show_engine_button == 3); @@ -247,17 +398,9 @@ static void DrawBuildAircraftWindow(Window *w) } if (!found) WP(w,buildtrain_d).sel_engine = INVALID_ENGINE; } - - - switch (WP(w,buildtrain_d).show_engine_button) { - case 1: count = WP(w, buildtrain_d).list_a_length; break; - case 2: count = WP(w, buildtrain_d).list_b_length; break; - case 3: count = WP(w, buildtrain_d).list_c_length; break; - } - - SetVScrollCount(w, count); } + SetVScrollCount(w, GetEngineArrayLength(w)); DrawWindowWidgets(w); if (WP(w,buildtrain_d).sel_engine == INVALID_ENGINE && GetEngineArrayLength(w) != 0) { @@ -285,6 +428,8 @@ static void DrawBuildAircraftWindow(Window *w) DrawAircraftPurchaseInfo(x, w->widget[BUILD_AIRCRAFT_WIDGET_PANEL].top + 1, selected_id); } } + DrawString(85, 15, _engine_sort_listing[WP(w,buildtrain_d).sort_criteria], 0x10); + DoDrawString(WP(w,buildtrain_d).decenting_sort_order ? DOWNARROW : UPARROW, 69, 15, 0x10); } static void BuildAircraftClickEvent(Window *w, WindowEvent *e) @@ -292,6 +437,13 @@ static void BuildAircraftClickEvent(Window *w, WindowEvent *e) byte click_state = 0; switch (e->we.click.widget) { + case BUILD_AIRCRAFT_WIDGET_SORT_ASSENDING_DESENTING: + WP(w,buildtrain_d).decenting_sort_order = !WP(w,buildtrain_d).decenting_sort_order; + _last_sort_order = WP(w,buildtrain_d).decenting_sort_order; + SortAircraftBuildList(w); + SetWindowDirty(w); + break; + case BUILD_AIRCRAFT_WIDGET_LIST: { uint i = (e->we.click.pt.y - 26) / 24; if (i < w->vscroll.cap) { @@ -304,6 +456,10 @@ static void BuildAircraftClickEvent(Window *w, WindowEvent *e) } } break; + case BUILD_AIRCRAFT_WIDGET_SORT_TEXT: case BUILD_AIRCRAFT_WIDGET_SORT_DROPDOWN:/* Select sorting criteria dropdown menu */ + ShowDropDownMenu(w, _engine_sort_listing, WP(w,buildtrain_d).sort_criteria, BUILD_AIRCRAFT_WIDGET_SORT_DROPDOWN, 0, 0); + return; + case BUILD_AIRCRAFT_WIDGET_HELICOPTERS: click_state++; case BUILD_AIRCRAFT_WIDGET_JETS: click_state++; case BUILD_AIRCRAFT_WIDGET_PLANES: click_state++; @@ -313,6 +469,7 @@ static void BuildAircraftClickEvent(Window *w, WindowEvent *e) WP(w,buildtrain_d).sel_engine = INVALID_ENGINE; WP(w,buildtrain_d).show_engine_button = click_state; w->vscroll.pos = 0; + SortAircraftBuildList(w); SetWindowDirty(w); break; @@ -343,8 +500,10 @@ static void BuildAircraftWindowCreate(Window *w) WP(w, buildtrain_d).list_a = NULL; WP(w, buildtrain_d).list_b = NULL; WP(w, buildtrain_d).list_c = NULL; - WP(w, buildtrain_d).data_invalidated = false; - WP(w, buildtrain_d).sel_engine = INVALID_ENGINE; + WP(w, buildtrain_d).data_invalidated = false; + WP(w, buildtrain_d).sel_engine = INVALID_ENGINE; + WP(w, buildtrain_d).sort_criteria = _last_sort_criteria; + WP(w, buildtrain_d).decenting_sort_order = _last_sort_order; GenerateBuildList(&WP(w, buildtrain_d).list_a, &WP(w, buildtrain_d).list_a_length, &WP(w, buildtrain_d).list_b, &WP(w, buildtrain_d).list_b_length, @@ -377,6 +536,7 @@ static void BuildAircraftWindowCreate(Window *w) WP(w, buildtrain_d).show_engine_button = 1; } } + SortAircraftBuildList(w); } static void NewAircraftWndProc(Window *w, WindowEvent *e) @@ -412,6 +572,15 @@ static void NewAircraftWndProc(Window *w, WindowEvent *e) } } break; + case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */ + if (WP(w,buildtrain_d).sort_criteria != e->we.dropdown.index) { + WP(w,buildtrain_d).sort_criteria = e->we.dropdown.index; + _last_sort_criteria = e->we.dropdown.index; + SortAircraftBuildList(w); + } + SetWindowDirty(w); + break; + case WE_RESIZE: w->vscroll.cap += e->we.sizing.diff.y / 24; w->widget[BUILD_AIRCRAFT_WIDGET_LIST].data = (w->vscroll.cap << 8) + 1; diff --git a/lang/english.txt b/lang/english.txt index adfab1914..ecdb73ff4 100644 --- a/lang/english.txt +++ b/lang/english.txt @@ -387,6 +387,7 @@ STR_ENGINE_SORT_POWER :Power STR_ENGINE_SORT_INTRO_DATE :Introduction Date STR_ENGINE_SORT_RUNNING_COST :Running Cost STR_ENGINE_SORT_POWER_VS_RUNNING_COST :Power/Running Cost +STR_ENGINE_SORT_CARGO_CAPACITY :Cargo Capacity STR_NO_WAITING_CARGO :{BLACK}No cargo of any type is waiting STR_SELECT_ALL_FACILITIES :{BLACK}Select all facilities STR_SELECT_ALL_TYPES :{BLACK}Select all cargo types (including no waiting cargo) |