From f2547eb62c3ab6a4085f6341a66d304287f39d6f Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sat, 6 Jun 2009 17:49:59 +0000 Subject: Implement FR#2707442: "GUI: Improve Mass Add dialog" svn-id: r41263 --- gui/ListWidget.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'gui/ListWidget.cpp') diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index 06cbcdcbd9..f534c14d1e 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -133,6 +133,11 @@ void ListWidget::setList(const StringList &list) { scrollBarRecalc(); } +void ListWidget::append(const String &s) { + _list.push_back(s); + scrollBarRecalc(); +} + void ListWidget::scrollTo(int item) { int size = _list.size(); if (item >= size) @@ -445,6 +450,18 @@ void ListWidget::scrollToCurrent() { _scrollBar->recalc(); } +void ListWidget::scrollToEnd() { + if (_currentPos + _entriesPerPage < (int)_list.size()) { + _currentPos = _list.size() - _entriesPerPage; + } else { + return; + } + + _scrollBar->_currentPos = _currentPos; + _scrollBar->recalc(); + _scrollBar->draw(); +} + void ListWidget::startEditMode() { if (_editable && !_editMode && _selectedItem >= 0) { _editMode = true; -- cgit v1.2.3 From dcc90445f6ea424bd4576f04afbc790fc43a5c76 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sat, 6 Jun 2009 17:53:25 +0000 Subject: Add to launcher not yet functional search widget. Make EditableWidget CommandSender svn-id: r41267 --- gui/ListWidget.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gui/ListWidget.cpp') diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index f534c14d1e..8e5ef99f06 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -34,7 +34,7 @@ namespace GUI { ListWidget::ListWidget(GuiObject *boss, const String &name) - : EditableWidget(boss, name), CommandSender(boss) { + : EditableWidget(boss, name) { _scrollBar = NULL; _textWidth = NULL; @@ -63,7 +63,7 @@ ListWidget::ListWidget(GuiObject *boss, const String &name) } ListWidget::ListWidget(GuiObject *boss, int x, int y, int w, int h) - : EditableWidget(boss, x, y, w, h), CommandSender(boss) { + : EditableWidget(boss, x, y, w, h) { _scrollBar = NULL; _textWidth = NULL; -- cgit v1.2.3 From 5fc047dddfcad4e712bea97aadd561493f4f388c Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sat, 6 Jun 2009 17:54:08 +0000 Subject: Implement FR#1970293: "LAUNCHER: Add "quick search" input field like in iTunes" svn-id: r41268 --- gui/ListWidget.cpp | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'gui/ListWidget.cpp') diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index 8e5ef99f06..b96019af04 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -122,7 +122,12 @@ void ListWidget::setList(const StringList &list) { if (_editMode && _caretVisible) drawCaret(true); int size = list.size(); + _dataList = list; + + // Copy everything _list = list; + _filter = ""; + if (_currentPos >= size) _currentPos = size - 1; if (_currentPos < 0) @@ -134,6 +139,7 @@ void ListWidget::setList(const StringList &list) { } void ListWidget::append(const String &s) { + _dataList.push_back(s); _list.push_back(s); scrollBarRecalc(); } @@ -529,4 +535,35 @@ void ListWidget::reflowLayout() { } } +void ListWidget::setFilter(const String &filter) { + String filt; + + filt = filter; + + filt.toLowercase(); + _filter = filt; + + if (_filter == "") { + _list = _dataList; + } else { + String tmp; + + _list.clear(); + + for (StringList::iterator i = _dataList.begin(); i != _dataList.end(); ++i) { + tmp = *i; + tmp.toLowercase(); + if (tmp.contains(_filter.c_str())) { + _list.push_back(*i); + } + } + } + + _currentPos = 0; + _selectedItem = -1; + scrollBarRecalc(); + + draw(); +} + } // End of namespace GUI -- cgit v1.2.3 From f66da82f0375918c59d6edc6ad806d9530cc1387 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sat, 6 Jun 2009 17:54:28 +0000 Subject: Improvements to laucher dialog - Made quicksearch turned off in the launcher game list - Turn ListWidget into CommandSender - Turn quicksearch off in launcher game list - Connect laucher list widget with search box so search is initiated by typing svn-id: r41269 --- gui/ListWidget.cpp | 51 +++++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 24 deletions(-) (limited to 'gui/ListWidget.cpp') diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index b96019af04..10e2bc53c3 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -33,8 +33,8 @@ namespace GUI { -ListWidget::ListWidget(GuiObject *boss, const String &name) - : EditableWidget(boss, name) { +ListWidget::ListWidget(GuiObject *boss, const String &name, uint32 cmd) + : EditableWidget(boss, name), _cmd(cmd) { _scrollBar = NULL; _textWidth = NULL; @@ -60,10 +60,12 @@ ListWidget::ListWidget(GuiObject *boss, const String &name) // FIXME: This flag should come from widget definition _editable = true; + + _quickSelect = true; } -ListWidget::ListWidget(GuiObject *boss, int x, int y, int w, int h) - : EditableWidget(boss, x, y, w, h) { +ListWidget::ListWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd) + : EditableWidget(boss, x, y, w, h), _cmd(cmd) { _scrollBar = NULL; _textWidth = NULL; @@ -234,8 +236,6 @@ bool ListWidget::handleKeyDown(Common::KeyState state) { // 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 = getMillis(); if (_quickSelectTime < time) { _quickSelectStr = (char)state.ascii; @@ -244,26 +244,29 @@ bool ListWidget::handleKeyDown(Common::KeyState state) { } _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; + if (_quickSelect) { + // 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++; } - newSelectedItem++; - } - scrollToCurrent(); + scrollToCurrent(); + } else { + sendCommand(_cmd, 0); + } } else if (_editMode) { // Class EditableWidget handles all text editing related key presses for us handled = EditableWidget::handleKeyDown(state); -- cgit v1.2.3 From f6d06085d5b7e4723117147d84eec477c0b6f9db Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sat, 6 Jun 2009 17:54:59 +0000 Subject: Fix item selection on filtered out list in launcher svn-id: r41271 --- gui/ListWidget.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'gui/ListWidget.cpp') diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index 10e2bc53c3..22a9081d89 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -129,6 +129,7 @@ void ListWidget::setList(const StringList &list) { // Copy everything _list = list; _filter = ""; + setFilter(_filter, false); if (_currentPos >= size) _currentPos = size - 1; @@ -143,6 +144,9 @@ void ListWidget::setList(const StringList &list) { void ListWidget::append(const String &s) { _dataList.push_back(s); _list.push_back(s); + + setFilter(_filter, false); + scrollBarRecalc(); } @@ -538,7 +542,7 @@ void ListWidget::reflowLayout() { } } -void ListWidget::setFilter(const String &filter) { +void ListWidget::setFilter(const String &filter, bool redraw) { String filt; filt = filter; @@ -550,23 +554,30 @@ void ListWidget::setFilter(const String &filter) { _list = _dataList; } else { String tmp; + int n = 0; _list.clear(); + + _listIndex.clear(); - for (StringList::iterator i = _dataList.begin(); i != _dataList.end(); ++i) { + for (StringList::iterator i = _dataList.begin(); i != _dataList.end(); ++i, n++) { tmp = *i; tmp.toLowercase(); if (tmp.contains(_filter.c_str())) { _list.push_back(*i); + _listIndex.push_back(n); } } } _currentPos = 0; _selectedItem = -1; - scrollBarRecalc(); - draw(); + if (redraw) { + scrollBarRecalc(); + + draw(); + } } } // End of namespace GUI -- cgit v1.2.3 From 472e5906cad12161b39a8723b422221554208ce1 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sat, 6 Jun 2009 17:58:29 +0000 Subject: Do not change list content if filter was not changed svn-id: r41276 --- gui/ListWidget.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'gui/ListWidget.cpp') diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index 22a9081d89..10fa1cf243 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -548,6 +548,10 @@ void ListWidget::setFilter(const String &filter, bool redraw) { filt = filter; filt.toLowercase(); + + if (_filter == filt) // Filter was not changed + return; + _filter = filt; if (_filter == "") { -- cgit v1.2.3 From de88db5f36ff666f9ae31cd0f4287d79fd25d22d Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sun, 7 Jun 2009 13:04:16 +0000 Subject: Fix for bug #2802492 (GUI: search query causes game list scrollbar glitches) svn-id: r41334 --- gui/ListWidget.cpp | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) (limited to 'gui/ListWidget.cpp') diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index 10fa1cf243..e46d5e9b1e 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -107,11 +107,14 @@ Widget *ListWidget::findWidget(int x, int y) { void ListWidget::setSelected(int item) { assert(item >= -1 && item < (int)_list.size()); + // We only have to do something if the widget is enabled and the selection actually changes if (isEnabled() && _selectedItem != item) { if (_editMode) abortEditMode(); _selectedItem = item; + + // Notify clients that the selection changed. sendCommand(kListSelectionChangedCmd, _selectedItem); _currentPos = _selectedItem - _entriesPerPage / 2; @@ -123,14 +126,13 @@ void ListWidget::setSelected(int item) { void ListWidget::setList(const StringList &list) { if (_editMode && _caretVisible) drawCaret(true); - int size = list.size(); - _dataList = list; // Copy everything + _dataList = list; _list = list; - _filter = ""; - setFilter(_filter, false); + _filter.clear(); + int size = list.size(); if (_currentPos >= size) _currentPos = size - 1; if (_currentPos < 0) @@ -543,10 +545,11 @@ void ListWidget::reflowLayout() { } void ListWidget::setFilter(const String &filter, bool redraw) { - String filt; - - filt = filter; + // FIXME: This method does not deal correctly with edit mode! + // Until we fix that, let's make sure it isn't called while editing takes place + assert(!_editMode); + String filt = filter; filt.toLowercase(); if (_filter == filt) // Filter was not changed @@ -554,20 +557,22 @@ void ListWidget::setFilter(const String &filter, bool redraw) { _filter = filt; - if (_filter == "") { + if (_filter.empty()) { + // No filter -> display everything _list = _dataList; } else { + // Restrict the list to everything which contains _filter as a substring, + // ignoring case. String tmp; int n = 0; _list.clear(); - _listIndex.clear(); - for (StringList::iterator i = _dataList.begin(); i != _dataList.end(); ++i, n++) { + for (StringList::iterator i = _dataList.begin(); i != _dataList.end(); ++i, ++n) { tmp = *i; tmp.toLowercase(); - if (tmp.contains(_filter.c_str())) { + if (tmp.contains(_filter)) { _list.push_back(*i); _listIndex.push_back(n); } @@ -579,8 +584,18 @@ void ListWidget::setFilter(const String &filter, bool redraw) { if (redraw) { scrollBarRecalc(); - - draw(); + // Redraw the whole dialog. This is annoying, as this might be rather + // expensive when really only the list widget and its scroll bar area + // to be redrawn. However, since the scrollbar might change its + // visibility status, and the list its width, we cannot just redraw + // the two. + // TODO: A more efficient (and elegant?) way to handle this would be to + // introduce a kind of "BoxWidget" or "GroupWidget" which defines a + // rectangular region and subwidgets can be placed within it. + // Such a widget could also (optionally) draw a border (or even different + // kinds of borders) around the objects it groups; and also a 'title' + // (I am borrowing these "ideas" from the NSBox class in Cocoa :). + _boss->draw(); } } -- cgit v1.2.3 From 8aa667e342e8c8dc203fb6811f01523bacfcffab Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 2 Jul 2009 21:16:36 +0000 Subject: Enhanced the quicksearch box in the launcher to match words in the search string individually svn-id: r42038 --- gui/ListWidget.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'gui/ListWidget.cpp') diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index e46d5e9b1e..07d22973ac 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -561,8 +561,10 @@ void ListWidget::setFilter(const String &filter, bool redraw) { // No filter -> display everything _list = _dataList; } else { - // Restrict the list to everything which contains _filter as a substring, - // ignoring case. + // Restrict the list to everything which contains all words in _filter + // as substrings, ignoring case. + + Common::StringTokenizer tok(filter); String tmp; int n = 0; @@ -572,7 +574,16 @@ void ListWidget::setFilter(const String &filter, bool redraw) { for (StringList::iterator i = _dataList.begin(); i != _dataList.end(); ++i, ++n) { tmp = *i; tmp.toLowercase(); - if (tmp.contains(_filter)) { + bool matches = true; + tok.reset(); + while (!tok.empty()) { + if (!tmp.contains(tok.nextToken())) { + matches = false; + break; + } + } + + if (matches) { _list.push_back(*i); _listIndex.push_back(n); } -- cgit v1.2.3