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 @@
Theme | Theme to use for UI elements (see examples) | -uipalette |
Dialogs position | Position of dialogs with Stella window | -dialogpos |
HiDPI mode | Scales the UI by a factor of two when enabled | -hidpi |
- List input delay | Maximum delay between keypresses in list-widgets before a search string resets. | -listdelay |
+ List input delay | Maximum delay between keypresses in filelist-widgets before a search string resets. | -listdelay |
Mouse wheel scroll | Number of lines a mouse scroll will move in list-widgets | -mwheel |
Double-click speed | Speed of mouse double-clicks | -mdouble |
Controller repeat delay | Delay 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());