From 2540d0d8034e9bd686f47e894880c5f1dd4324e9 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Fri, 23 Aug 2019 22:08:06 -0230 Subject: [PATCH] Entering an uppercase char (ie, hold Shift) on the first character in file listings now selects among directories; use lowercase to select among files (fixes #160). Refactored relevant code from ListWidget to FileListWidget, where it more properly belongs. Updates to docs (new info, typo's, etc). --- Changes.txt | 30 ++++++++--------- docs/index.html | 14 +++++--- src/emucore/EventHandler.cxx | 6 ++-- src/gui/CheckListWidget.cxx | 2 +- src/gui/FileListWidget.cxx | 45 +++++++++++++++++++++++++- src/gui/FileListWidget.hxx | 7 ++++ src/gui/ListWidget.cxx | 62 +++--------------------------------- src/gui/ListWidget.hxx | 11 +------ src/gui/StringListWidget.cxx | 3 +- src/gui/UIDialog.cxx | 4 +-- 10 files changed, 87 insertions(+), 97 deletions(-) diff --git a/Changes.txt b/Changes.txt index ec3a2550c..147e95751 100644 --- a/Changes.txt +++ b/Changes.txt @@ -26,8 +26,8 @@ * Added automatic controller detection. - * Controllers can be changed during emulation (no ROM reload required - anymore) + * Controllers can be changed during emulation (no ROM reload required + anymore). * Removed superfluous controller option 'PADDLES_IDIR'. @@ -47,9 +47,9 @@ down the mouse button (Time Machine, debugger step/trace/frame advance, etc.) - * Added option to configure mouse double click speed + * Added option to configure mouse double click speed. - * Added option to configure controller input repeat speed + * Added option to configure controller input repeat speed. * Added 'HiDPI' mode, which scales the UI by 2x when enabled. This is meant for 4k and above monitors, but can actually be used at any @@ -76,11 +76,15 @@ * Enhanced 'Command' menu to display current state and more commands. - * Added option to save and load all TimeMachine states at once + * Added option to save and load all TimeMachine states at once. - * Added option to change pitch of Pitfall II music + * Added option to change pitch of Pitfall II music. - * Fixed bug when starting ROMs via MacOS finder + * In file listings, you can now select directories by holding 'Shift' on + the first character entered. Entering characters in lowercase still + selects files, as before. + + * Fixed bug when starting ROMs via MacOS finder. * Added various developer options for oddball TIAs: - stuffed player, missiles and ball move @@ -89,9 +93,9 @@ * Disabled some developer options for 'Player settings'. - * Improved breakpoints to now consider the banks + * Improved breakpoints to now consider the banks. - * Improved debugger's TIA display and zoom windows + * Improved debugger's TIA display and zoom windows. * Improved hotkeys, now many emulation keys work in debugger too. @@ -100,7 +104,7 @@ * Reworked ROM properties database, making it load faster in certain cases. Related to this, completely removed 'Display_Height' stuff. - (TODO: Stella.pro cleanup, doc) + (TODO: Stella.pro cleanup, doc). * Updated internal ROM properties database to ROM-Hunter version 15 (thanks go to RomHunter for his tireless research in this area). @@ -114,12 +118,6 @@ * Fixed not working 7800 pause key. - * Added support for CDFJ bankswitching type. - - * Allow the DPC+ scheme to not enable playfield 'jitter' effect for - certain older DPC+ driver versions; this allows 'Epic Adventure' ROM - to finally work in Stella. - * Enhanced UA bankswitching to support certain Brazilian carts. * Auto-detection of bankswitch scheme by file extension now includes diff --git a/docs/index.html b/docs/index.html index f37185281..d2ab1ecf5 100644 --- a/docs/index.html +++ b/docs/index.html @@ -576,7 +576,7 @@ These settings are optional, and can be left at the defaults if you won't be using snapshots in the ROM launcher.

-

you can start emulation by selecting a ROM and pressing 'Enter' or clicking 'Select', +

You can start emulation by selecting a ROM and pressing 'Enter' or clicking 'Select', or double-clicking a ROM. Note that some games require you to 'Reset' the console before you start playing. In this case, you need to hit the virtual reset switch, which by default is the F2 key. Also, some games may require that you press the @@ -590,6 +590,12 @@ listing can be narrowed down, showing only the ROMs that match the pattern you enter.

+

While the file listing is in focus, you can type some characters, and the listing + will 'jump' to the file that matches what you typed. This is case-insensitive. Hold + down the Shift key on the first character to select directories instead. The delay + between successive keypresses being treated as part of one word is controlled by the + 'listdelay' option; see User Interface Settings to change this setting.

+

Command Menu

@@ -2313,8 +2319,8 @@
-listdelay <delay>
Set the amount of time to wait between treating successive - keypresses as a single word in list widgets (value can range - from 300-1000). Use '0' to disable list-skipping completely, + keypresses as a single word in file listings (value can range + from 300-1000). Use '0' to disable list-skipping completely. @@ -2817,7 +2823,7 @@ ThemeTheme to use for UI elements (see examples)-uipalette Dialogs positionPosition of dialogs with Stella window-dialogpos HiDPI modeScales the UI by a factor of two when enabled-hidpi - List input delayMaximum delay between keypresses in list-widgets before a search string resets. -listdelay + List input delayMaximum delay between keypresses in filelist-widgets before a search string resets. -listdelay Mouse wheel scrollNumber of lines a mouse scroll will move in list-widgets-mwheel Double-click speedSpeed of mouse double-clicks-mdouble Controller repeat delayDelay before controller input repeats-ctrldelay diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index df9a41edb..e4f4f9472 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -55,7 +55,7 @@ #include "DialogContainer.hxx" #include "Launcher.hxx" #include "TimeMachine.hxx" - #include "ListWidget.hxx" + #include "FileListWidget.hxx" #include "ScrollBarWidget.hxx" #endif @@ -104,7 +104,7 @@ void EventHandler::initialize() #ifdef GUI_SUPPORT // Set quick select delay when typing characters in listwidgets - ListWidget::setQuickSelectDelay(myOSystem.settings().getInt("listdelay")); + FileListWidget::setQuickSelectDelay(myOSystem.settings().getInt("listdelay")); // Set number of lines a mousewheel will scroll ScrollBarWidget::setWheelLines(myOSystem.settings().getInt("mwheel")); @@ -1446,7 +1446,7 @@ int EventHandler::getActionListIndex(int idx, Event::Group group) const default: return -1; - }; + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/CheckListWidget.cxx b/src/gui/CheckListWidget.cxx index 80958d90c..e8a4faf16 100644 --- a/src/gui/CheckListWidget.cxx +++ b/src/gui/CheckListWidget.cxx @@ -23,7 +23,7 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CheckListWidget::CheckListWidget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h) - : ListWidget(boss, font, x, y, w, h, false) // disable quick select + : ListWidget(boss, font, x, y, w, h) { int ypos = _y + 2; diff --git a/src/gui/FileListWidget.cxx b/src/gui/FileListWidget.cxx index c9db28035..34a6f2e05 100644 --- a/src/gui/FileListWidget.cxx +++ b/src/gui/FileListWidget.cxx @@ -15,8 +15,11 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include + #include "ScrollBarWidget.hxx" #include "FileListWidget.hxx" +#include "TimerManager.hxx" #include "bspf.hxx" @@ -25,7 +28,8 @@ FileListWidget::FileListWidget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h) : StringListWidget(boss, font, x, y, w, h), _fsmode(FilesystemNode::ListMode::All), - _selected(0) + _selected(0), + _quickSelectTime(0) { // This widget is special, in that it catches signals and redirects them setTarget(this); @@ -108,6 +112,42 @@ void FileListWidget::reload() setLocation(_node, selected().getName()); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FileListWidget::handleText(char text) +{ + // Quick selection mode: Go to first list item starting with this key + // (or a substring accumulated from the last couple key presses). + // Only works in a useful fashion if the list entries are sorted. + uInt64 time = TimerManager::getTicks() / 1000; + if(_quickSelectTime < time) + { + if(std::isupper(text)) + { + // Select directories when the first character is uppercase + _quickSelectStr = " ["; + _quickSelectStr.push_back(text); + } + else + _quickSelectStr = text; + } + else + _quickSelectStr += text; + _quickSelectTime = time + _QUICK_SELECT_DELAY; + + int selectedItem = 0; + for(const auto& i: _list) + { + if(BSPF::startsWithIgnoreCase(i, _quickSelectStr)) + break; + selectedItem++; + } + + if(selectedItem > 0) + setSelected(selectedItem); + + return true; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FileListWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) { @@ -149,3 +189,6 @@ void FileListWidget::handleCommand(CommandSender* sender, int cmd, int data, int sendCommand(cmd, data, id); setTarget(this); } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt64 FileListWidget::_QUICK_SELECT_DELAY = 300; diff --git a/src/gui/FileListWidget.hxx b/src/gui/FileListWidget.hxx index 04fce87d0..c209a13a1 100644 --- a/src/gui/FileListWidget.hxx +++ b/src/gui/FileListWidget.hxx @@ -79,6 +79,8 @@ class FileListWidget : public StringListWidget } const FilesystemNode& currentDir() const { return _node; } + static void setQuickSelectDelay(uInt64 time) { _QUICK_SELECT_DELAY = time; } + private: /** Very similar to setDirectory(), but also updates the history */ void setLocation(const FilesystemNode& node, string select = EmptyString); @@ -86,6 +88,7 @@ class FileListWidget : public StringListWidget /** Descend into currently selected directory */ void selectDirectory(); + bool handleText(char text) override; void handleCommand(CommandSender* sender, int cmd, int data, int id) override; private: @@ -97,6 +100,10 @@ class FileListWidget : public StringListWidget Common::FixedStack _history; uInt32 _selected; + string _quickSelectStr; + uInt64 _quickSelectTime; + static uInt64 _QUICK_SELECT_DELAY; + private: // Following constructors and assignment operators not supported FileListWidget() = delete; diff --git a/src/gui/ListWidget.cxx b/src/gui/ListWidget.cxx index 067864a7a..b35171eaf 100644 --- a/src/gui/ListWidget.cxx +++ b/src/gui/ListWidget.cxx @@ -15,31 +15,25 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include -#include - #include "OSystem.hxx" #include "Widget.hxx" #include "ScrollBarWidget.hxx" #include "Dialog.hxx" #include "FrameBuffer.hxx" #include "StellaKeys.hxx" -#include "TimerManager.hxx" #include "EventHandler.hxx" #include "ListWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ListWidget::ListWidget(GuiObject* boss, const GUI::Font& font, - int x, int y, int w, int h, bool quickSelect) + int x, int y, int w, int h) : EditableWidget(boss, font, x, y, 16, 16), _rows(0), _cols(0), _currentPos(0), _selectedItem(-1), _highlightedItem(-1), - _editMode(false), - _quickSelect(quickSelect), - _quickSelectTime(0) + _editMode(false) { _flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS; _bgcolor = kWidColor; @@ -253,53 +247,8 @@ int ListWidget::findItem(int x, int y) const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool ListWidget::handleText(char text) { - bool handled = true; - int oldSelectedItem = _selectedItem; - - if (!_editMode && _quickSelect) - { - // Quick selection mode: Go to first list item starting with this key - // (or a substring accumulated from the last couple key presses). - // Only works in a useful fashion if the list entries are sorted. - // TODO: Maybe this should be off by default, and instead we add a - // method "enableQuickSelect()" or so ? - uInt64 time = TimerManager::getTicks() / 1000; - if (_quickSelectTime < time) - _quickSelectStr = text; - else - _quickSelectStr += text; - _quickSelectTime = time + _QUICK_SELECT_DELAY; - - // FIXME: This is bad slow code (it scans the list linearly each time a - // key is pressed); it could be much faster. Only of importance if we have - // quite big lists to deal with -- so for now we can live with this lazy - // implementation :-) - int newSelectedItem = 0; - for(const auto& i: _list) - { - if(BSPF::startsWithIgnoreCase(i, _quickSelectStr)) - { - _selectedItem = newSelectedItem; - break; - } - newSelectedItem++; - } - } - else if (_editMode) - { - // Class EditableWidget handles all text editing related key presses for us - handled = EditableWidget::handleText(text); - } - - if (_selectedItem != oldSelectedItem) - { - _scrollBar->draw(); - scrollToSelected(); - - sendCommand(ListWidget::kSelectionChangedCmd, _selectedItem, _id); - } - - return handled; + // Class EditableWidget handles all text editing related key presses for us + return _editMode ? EditableWidget::handleText(text) : true; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -521,6 +470,3 @@ void ListWidget::abortEditMode() // Reset to normal data entry EditableWidget::abortEditMode(); } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt64 ListWidget::_QUICK_SELECT_DELAY = 300; diff --git a/src/gui/ListWidget.hxx b/src/gui/ListWidget.hxx index cda1dc4da..88ce7f646 100644 --- a/src/gui/ListWidget.hxx +++ b/src/gui/ListWidget.hxx @@ -42,7 +42,7 @@ class ListWidget : public EditableWidget public: ListWidget(GuiObject* boss, const GUI::Font& font, - int x, int y, int w, int h, bool quickSelect); + int x, int y, int w, int h); virtual ~ListWidget() = default; int rows() const { return _rows; } @@ -64,8 +64,6 @@ class ListWidget : public EditableWidget // Account for the extra width of embedded scrollbar int getWidth() const override; - static void setQuickSelectDelay(uInt64 time) { _QUICK_SELECT_DELAY = time; } - protected: void handleMouseDown(int x, int y, MouseButton b, int clickCount) override; void handleMouseUp(int x, int y, MouseButton b, int clickCount) override; @@ -106,13 +104,6 @@ class ListWidget : public EditableWidget ScrollBarWidget* _scrollBar; StringList _list; - string _backupString; - bool _quickSelect; - string _quickSelectStr; - uInt64 _quickSelectTime; - - private: - static uInt64 _QUICK_SELECT_DELAY; private: // Following constructors and assignment operators not supported diff --git a/src/gui/StringListWidget.cxx b/src/gui/StringListWidget.cxx index 7bce81953..cc8338825 100644 --- a/src/gui/StringListWidget.cxx +++ b/src/gui/StringListWidget.cxx @@ -25,8 +25,7 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - StringListWidget::StringListWidget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h, bool hilite) - : ListWidget(boss, font, x, y, w, h, - boss->instance().settings().getInt("listdelay") >= 300), + : ListWidget(boss, font, x, y, w, h), _hilite(hilite) { _bgcolorlo = kDlgColor; diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx index 4ca332f1d..7e432969c 100644 --- a/src/gui/UIDialog.cxx +++ b/src/gui/UIDialog.cxx @@ -21,7 +21,7 @@ #include "OSystem.hxx" #include "FrameBuffer.hxx" #include "FBSurface.hxx" -#include "ListWidget.hxx" +#include "FileListWidget.hxx" #include "PopUpWidget.hxx" #include "ScrollBarWidget.hxx" #include "EditTextWidget.hxx" @@ -396,7 +396,7 @@ void UIDialog::saveConfig() // Listwidget quick delay settings.setValue("listdelay", myListDelaySlider->getValue()); - ListWidget::setQuickSelectDelay(myListDelaySlider->getValue()); + FileListWidget::setQuickSelectDelay(myListDelaySlider->getValue()); // Mouse wheel lines settings.setValue("mwheel", myWheelLinesSlider->getValue());