From a69e1854ebab158fbc22ef2cf5bbdce269b6d73f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=ADdac=20P=C3=A9rez=20Parera?= Date: Sat, 10 Apr 2021 22:45:30 -0700 Subject: [PATCH] Feature: make NewGRF active list react on key presses --- src/newgrf_gui.cpp | 94 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 80 insertions(+), 14 deletions(-) diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index ad37b35425a9c..fab5046e6c5d9 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -716,6 +716,21 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { } } + /** Given a position */ + void SelectActive(int position) + { + GRFConfig *c; + for (c = this->actives; c != nullptr && position > 0; c = c->next, position--) {} + + if (this->active_sel != c) { + DeleteWindowByClass(WC_GRF_PARAMETERS); + DeleteWindowByClass(WC_TEXTFILE); + } + this->active_sel = c; + this->avail_sel = nullptr; + this->avail_pos = -1; + } + void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override { switch (widget) { @@ -997,20 +1012,11 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { case WID_NS_FILE_LIST: { // Select an active GRF. ResetObjectToPlace(); - uint i = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_NS_FILE_LIST); + int pos = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_NS_FILE_LIST); + this->SelectActive(pos); - GRFConfig *c; - for (c = this->actives; c != nullptr && i > 0; c = c->next, i--) {} + this->InvalidateData(0); - if (this->active_sel != c) { - DeleteWindowByClass(WC_GRF_PARAMETERS); - DeleteWindowByClass(WC_TEXTFILE); - } - this->active_sel = c; - this->avail_sel = nullptr; - this->avail_pos = -1; - - this->InvalidateData(); if (click_count == 1) { if (this->editable && this->active_sel != nullptr) SetObjectToPlaceWnd(SPR_CURSOR_MOUSE, PAL_NONE, HT_DRAG, this); break; @@ -1314,10 +1320,59 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { this->SetWidgetDisabledState(WID_NS_PRESET_SAVE, has_missing); } - EventState OnKeyPress(WChar key, uint16 keycode) override + EventState OnKeyPressForActiveList(uint16 keycode) { - if (!this->editable) return ES_NOT_HANDLED; + /* Get total actives and index of current selection. */ + int active_pos = 0; + int active_count = 0; + for (GRFConfig *c = this->actives; c != nullptr; c = c->next, active_count++) {} + for (GRFConfig *c = this->actives; c != nullptr && c != this->active_sel; c = c->next, active_pos++) {} + switch (keycode) { + case WKC_UP: + /* scroll up by one */ + if (active_pos > 0) active_pos--; + break; + + case WKC_DOWN: + /* scroll down by one */ + if (active_pos < active_count - 1) active_pos++; + break; + + case WKC_PAGEUP: + /* scroll up a page */ + active_pos = (active_pos < this->vscroll->GetCapacity()) ? 0 : active_pos - this->vscroll->GetCapacity(); + break; + + case WKC_PAGEDOWN: + /* scroll down a page */ + active_pos = std::min(active_pos + this->vscroll->GetCapacity(), active_count - 1); + break; + + case WKC_HOME: + /* jump to beginning */ + active_pos = 0; + break; + + case WKC_END: + /* jump to end */ + active_pos = active_count - 1; + break; + + default: + return ES_NOT_HANDLED; + } + + if (this->actives != nullptr) { + this->SelectActive(active_pos); + this->vscroll->ScrollTowards(active_pos == active_count - 1 ? active_pos + 1 : active_pos); + this->InvalidateData(0); + } + + return ES_HANDLED; + } + + EventState OnKeyPressForAvailList(uint16 keycode) { switch (keycode) { case WKC_UP: /* scroll up by one */ @@ -1366,6 +1421,17 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { return ES_HANDLED; } + EventState OnKeyPress(WChar key, uint16 keycode) override + { + if (!this->editable) return ES_NOT_HANDLED; + + if (this->IsWidgetFocused(WID_NS_FILE_LIST)) { + return OnKeyPressForActiveList(keycode); + } else { + return OnKeyPressForAvailList(keycode); + } + } + void OnEditboxChanged(int wid) override { if (!this->editable) return;