diff options
-rw-r--r-- | gui/ListWidget.cpp | 129 | ||||
-rw-r--r-- | gui/ListWidget.h | 3 | ||||
-rw-r--r-- | gui/dialog.cpp | 23 | ||||
-rw-r--r-- | gui/util.cpp | 8 | ||||
-rw-r--r-- | gui/util.h | 1 | ||||
-rw-r--r-- | gui/widget.cpp | 3 | ||||
-rw-r--r-- | gui/widget.h | 6 |
7 files changed, 164 insertions, 9 deletions
diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index f435663bc5..9781ed4912 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -27,8 +27,6 @@ /* * TODO: - * - Implement scrolling using arrow keys, pageup/pagedown, home/end keys etc. - * - Implement editing of the selected string in a generic fashion */ @@ -39,7 +37,7 @@ ListWidget::ListWidget(Dialog *boss, int x, int y, int w, int h) : Widget(boss, x, y, w - kScrollBarWidth, h) { - _flags = WIDGET_ENABLED | WIDGET_CLEARBG; + _flags = WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_WANT_TICKLE; _type = kListWidget; _numberingMode = kListNumberingOne; _entriesPerPage = (_h - 4) / LINE_HEIGHT; @@ -48,6 +46,11 @@ ListWidget::ListWidget(Dialog *boss, int x, int y, int w, int h) _scrollBar = new ScrollBarWidget(boss, _x + _w, _y, kScrollBarWidth, _h); _scrollBar->setTarget(this); + // FIXME: This flag should come from widget definition + _editable = true; + + _editMode = false; + // FIXME - fill in dummy data for now _list.push_back("A simple game?"); _list.push_back("This space for rent!"); @@ -81,14 +84,114 @@ ListWidget::~ListWidget() void ListWidget::handleMouseDown(int x, int y, int button) { + int oldSelectedItem = _selectedItem; + if (_flags & WIDGET_ENABLED) { _selectedItem = (y - 2) / LINE_HEIGHT + _currentPos; + + if (_editMode && oldSelectedItem != _selectedItem) { + // loose caret + _list[_selectedItem].deleteLastChar(); + _editMode = false; + } draw(); } } void ListWidget::handleKeyDown(char key, int modifiers) { + bool dirty = false; + int oldSelectedItem = _selectedItem; + + if (_editMode) { + + // get rid of caret + _list[_selectedItem].deleteLastChar(); + + if (key == '\n' || key == '\r') { + // enter, exit editmode + _editMode = false; + dirty = true; + } + else if (_editMode && key == 8) { // backspace + _list[_selectedItem].deleteLastChar(); + dirty = true; + } else if (_editMode && + // filter keystrokes + ( ( key >= 'a' && key <= 'z' ) + || ( key >= 'A' && key <= 'Z' ) + || ( key >= '0' && key <= '9' ) + || ( key == ' ') + ) ) + { + + _list[_selectedItem] += key; + dirty = true; + } + + } else { + // not editmode + + switch (key) { + case '\n': // enter + case '\r': + if (_selectedItem >= 0) { + _editMode = true; + dirty = true; + } + break; + case 17: // up arrow + if (_selectedItem > 0) + _selectedItem--; + break; + case 18: // down arrow + if (_selectedItem < _list.size() - 1) + _selectedItem++; + break; + case 24: // pageup + _selectedItem -= _entriesPerPage - 1; + if (_selectedItem < 0) + _selectedItem = 0; + break; + case 25: // pagedown + _selectedItem += _entriesPerPage - 1; + if (_selectedItem >= _list.size() ) + _selectedItem = _list.size() - 1; + break; + case 22: // home + _selectedItem = 0; + break; + case 23: // end + _selectedItem = _list.size() - 1; + break; + } + + scrollToCurrent(); + } + + if (_editMode) + // re-add caret + _list[_selectedItem] += '_'; + + if (dirty || _selectedItem != oldSelectedItem) + draw(); + + if (_selectedItem != oldSelectedItem) { + // also draw scrollbar + _scrollBar->draw(); + } + +} + +void ListWidget::lostFocusWidget() +{ + if (_editMode) { + // loose caret + _list[_selectedItem].deleteLastChar(); + _editMode = false; + } + + draw(); } void ListWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) @@ -119,7 +222,25 @@ void ListWidget::drawWidget(bool hilite) } else buffer = ""; buffer += _list[pos]; + gui->drawString(buffer, _x+5, _y+2 + LINE_HEIGHT * i, _w - 10, - (_selectedItem == pos) ? gui->_textcolorhi : gui->_textcolor); + (_selectedItem == pos && _hasFocus) ? gui->_textcolorhi : gui->_textcolor); + } +} + +void ListWidget::scrollToCurrent() { + + // Only do something if the current item is not in our view port + if (_selectedItem < _currentPos) { + // it's above our view + _currentPos = _selectedItem; + } else if (_selectedItem >= _currentPos + _entriesPerPage ) { + // it's below our view + _currentPos = _selectedItem - _entriesPerPage + 1; + if (_currentPos < 0) + _currentPos = 0; } + + _scrollBar->_currentPos = _currentPos; + _scrollBar->recalc(); } diff --git a/gui/ListWidget.h b/gui/ListWidget.h index d3f7b7760d..5927d44492 100644 --- a/gui/ListWidget.h +++ b/gui/ListWidget.h @@ -37,6 +37,7 @@ class ListWidget : public Widget, public CommandReceiver { protected: StringList _list; bool _editable; + bool _editMode; int _numberingMode; int _currentPos; int _entriesPerPage; @@ -57,6 +58,8 @@ public: protected: void drawWidget(bool hilite); + void lostFocusWidget(); + void scrollToCurrent(); }; #endif diff --git a/gui/dialog.cpp b/gui/dialog.cpp index f17cf4bf65..ddeb45dc2b 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -73,11 +73,24 @@ void Dialog::draw() void Dialog::handleMouseDown(int x, int y, int button) { - _focusedWidget = findWidget(x, y); + Widget *w; + w = findWidget(x, y); - if (_focusedWidget) { - _focusedWidget->handleMouseDown(x - _focusedWidget->_x, y - _focusedWidget->_y, button); + if (w != _focusedWidget) { + // The focus will change. Tell the old focused widget (if any) + // that it lost the focus. + if (_focusedWidget) + _focusedWidget->lostFocus(); + + // Tell the new focused widget (if any) that it just gained the focus. + if (w) + w->recievedFocus(); + + _focusedWidget = w; } + + if (_focusedWidget) + _focusedWidget->handleMouseDown(x - _focusedWidget->_x, y - _focusedWidget->_y, button); } void Dialog::handleMouseUp(int x, int y, int button) @@ -88,8 +101,10 @@ void Dialog::handleMouseUp(int x, int y, int button) w = _focusedWidget; // Lose focus on mouseup unless the widget requested to retain the focus - if (! (_focusedWidget->getFlags() & WIDGET_RETAIN_FOCUS )) + if (! (_focusedWidget->getFlags() & WIDGET_RETAIN_FOCUS )) { + _focusedWidget->lostFocus(); _focusedWidget = 0; + } } else { w = findWidget(x, y); diff --git a/gui/util.cpp b/gui/util.cpp index 26475a8392..11f3aa4716 100644 --- a/gui/util.cpp +++ b/gui/util.cpp @@ -163,6 +163,13 @@ String& String::operator +=(char c) return *this; } +void String::deleteLastChar() { + if (_len > 0) { + _len--; + _str[_len]=0; + } +} + void String::clear() { if (_str) @@ -187,3 +194,4 @@ void String::ensureCapacity(int new_len, bool keep_old) free(old_str); } } + diff --git a/gui/util.h b/gui/util.h index c1bd9bbc77..4509a0bcb3 100644 --- a/gui/util.h +++ b/gui/util.h @@ -114,6 +114,7 @@ public: const char *c_str() const { return _str; } int size() const { return _len; } + void deleteLastChar(); void clear(); protected: diff --git a/gui/widget.cpp b/gui/widget.cpp index 4b8219cc08..fa31e2f6d2 100644 --- a/gui/widget.cpp +++ b/gui/widget.cpp @@ -25,7 +25,8 @@ Widget::Widget (Dialog *boss, int x, int y, int w, int h) - : _type(0), _boss(boss), _x(x), _y(y), _w(w), _h(h), _id(0), _flags(0) + : _type(0), _boss(boss), _x(x), _y(y), _w(w), _h(h), + _id(0), _flags(0), _hasFocus(false) { // Insert into the widget list of the boss _next = _boss->_firstWidget; diff --git a/gui/widget.h b/gui/widget.h index 4b72df1b42..e29936dd49 100644 --- a/gui/widget.h +++ b/gui/widget.h @@ -84,6 +84,7 @@ protected: uint16 _w, _h; uint16 _id; uint16 _flags; + bool _hasFocus; public: Widget(Dialog *boss, int x, int y, int w, int h); @@ -98,6 +99,8 @@ public: virtual void handleKeyUp(char key, int modifiers) {} virtual void handleTickle() {} void draw(); + void recievedFocus() { _hasFocus = true; recievedFocusWidget(); } + void lostFocus() { _hasFocus = false; lostFocusWidget(); } void setFlags(int flags) { _flags |= flags; } void clearFlags(int flags) { _flags &= ~flags; } @@ -105,6 +108,9 @@ public: protected: virtual void drawWidget(bool hilite) {} + + virtual void recievedFocusWidget() {} + virtual void lostFocusWidget() {} }; |