aboutsummaryrefslogtreecommitdiff
path: root/gui
diff options
context:
space:
mode:
authorMax Horn2004-07-21 14:28:57 +0000
committerMax Horn2004-07-21 14:28:57 +0000
commit9f91359c2ebd574ff1698ec944f6e84603e49e48 (patch)
tree421478c9fa90d3dc8645f98632065d39b964601b /gui
parentbe31329d05c77c5eee3537911567ecd1803c7ea2 (diff)
downloadscummvm-rg350-9f91359c2ebd574ff1698ec944f6e84603e49e48.tar.gz
scummvm-rg350-9f91359c2ebd574ff1698ec944f6e84603e49e48.tar.bz2
scummvm-rg350-9f91359c2ebd574ff1698ec944f6e84603e49e48.zip
Allow user to select ListWidget entries by typing them (see FR #922921)
svn-id: r14295
Diffstat (limited to 'gui')
-rw-r--r--gui/ListWidget.cpp98
-rw-r--r--gui/ListWidget.h4
2 files changed, 77 insertions, 25 deletions
diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp
index aba5abcd23..4ef2d6f56b 100644
--- a/gui/ListWidget.cpp
+++ b/gui/ListWidget.cpp
@@ -41,6 +41,8 @@ ListWidget::ListWidget(GuiObject *boss, int x, int y, int w, int h)
_caretVisible = false;
_caretTime = 0;
+
+ _quickSelectTime = 0;
// FIXME: This flag should come from widget definition
_editable = true;
@@ -125,48 +127,94 @@ void ListWidget::handleMouseWheel(int x, int y, int direction) {
_scrollBar->handleMouseWheel(x, y, direction);
}
+
+static int matchingCharsIgnoringCase(const char *x, const char *y, bool &stop) {
+ int match = 0;
+ while (*x && *y && toupper(*x) == toupper(*y)) {
+ ++x;
+ ++y;
+ ++match;
+ }
+ stop = !*y || (*x && (toupper(*x) >= toupper(*y)));
+ return match;
+}
+
bool ListWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
bool handled = true;
bool dirty = false;
int oldSelectedItem = _selectedItem;
- if (_editMode) {
+ if (!_editMode && isprint((char)ascii)) {
+ // 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 ?
+ uint32 time = g_system->get_msecs();
+ if (_quickSelectTime < time) {
+ _quickSelectStr = (char)ascii;
+ } else {
+ _quickSelectStr += (char)ascii;
+ }
+ _quickSelectTime = time + 300; // TODO: Turn this into a proper constant (kQuickSelectDelay ?)
+
+
+ // 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;
+ int bestMatch = 0;
+ bool stop;
+ for (StringList::const_iterator i = _list.begin(); i != _list.end(); ++i) {
+ const int match = matchingCharsIgnoringCase(i->c_str(), _quickSelectStr.c_str(), stop);
+ if (match > bestMatch || stop) {
+ _selectedItem = newSelectedItem;
+ bestMatch = match;
+ if (stop)
+ break;
+ }
+ newSelectedItem++;
+ }
+
+ scrollToCurrent();
+ } else if (_editMode) {
if (_caretVisible)
drawCaret(true);
switch (keycode) {
- case '\n': // enter/return
- case '\r':
- // enter, confirm edit and exit editmode
- _editMode = false;
- dirty = true;
- sendCommand(kListItemActivatedCmd, _selectedItem);
- break;
- case 27: // escape
- // ESC, abort edit and exit editmode
- _editMode = false;
- dirty = true;
- _list[_selectedItem] = _backupString;
- break;
- case 8: // backspace
- _list[_selectedItem].deleteLastChar();
+ case '\n': // enter/return
+ case '\r':
+ // confirm edit and exit editmode
+ _editMode = false;
+ dirty = true;
+ sendCommand(kListItemActivatedCmd, _selectedItem);
+ break;
+ case 27: // escape
+ // abort edit and exit editmode
+ _editMode = false;
+ dirty = true;
+ _list[_selectedItem] = _backupString;
+ break;
+ case 8: // backspace
+ _list[_selectedItem].deleteLastChar();
+ dirty = true;
+ break;
+ default:
+ if (isprint((char)ascii)) {
+ _list[_selectedItem] += (char)ascii;
dirty = true;
- break;
- default:
- if (isprint((char)ascii)) {
- _list[_selectedItem] += (char)ascii;
- dirty = true;
- } else {
- handled = false;
- }
+ } else {
+ handled = false;
+ }
}
} else {
// not editmode
switch (keycode) {
- case '\n': // enter
+ case '\n': // enter/return
case '\r':
if (_selectedItem >= 0) {
// override continuous enter keydown
diff --git a/gui/ListWidget.h b/gui/ListWidget.h
index 5a7827c57f..f2e9092660 100644
--- a/gui/ListWidget.h
+++ b/gui/ListWidget.h
@@ -56,8 +56,12 @@ protected:
ScrollBarWidget *_scrollBar;
int _currentKeyDown;
String _backupString;
+
bool _caretVisible;
uint32 _caretTime;
+
+ String _quickSelectStr;
+ uint32 _quickSelectTime;
public:
ListWidget(GuiObject *boss, int x, int y, int w, int h);
virtual ~ListWidget();