diff options
-rw-r--r-- | gui/ListWidget.cpp | 50 | ||||
-rw-r--r-- | gui/ListWidget.h | 15 | ||||
-rw-r--r-- | gui/ScrollBarWidget.cpp | 6 | ||||
-rw-r--r-- | gui/ScrollBarWidget.h | 4 | ||||
-rw-r--r-- | gui/dialog.cpp | 27 | ||||
-rw-r--r-- | gui/dialog.h | 6 | ||||
-rw-r--r-- | gui/widget.cpp | 8 | ||||
-rw-r--r-- | gui/widget.h | 16 | ||||
-rw-r--r-- | newgui.cpp | 40 | ||||
-rw-r--r-- | newgui.h | 12 |
10 files changed, 112 insertions, 72 deletions
diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index 2f697acbaa..2b438f2153 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -25,18 +25,6 @@ #include "newgui.h" -/* - * TODO: - * - Abort changes when ESC is pressed or the selection changes - * - When the editing of a string is ended by return, we might consider sending - * a message. Return means that the edit was confirmed. Hence the SaveDialog - * could immediatly do the save in a trivial fashion. - * - Handle double clicks: either start editing of the selected item, or - * send a cmd to our target (i.e. as specified via setCmd or setDoubleCmd) - * This will allow a double click in the load dialog to immediatly load the game - */ - - // Height of one entry #define LINE_HEIGHT 10 @@ -72,7 +60,7 @@ void ListWidget::scrollBarRecalc() _scrollBar->recalc(); } -void ListWidget::handleMouseDown(int x, int y, int button) +void ListWidget::handleMouseDown(int x, int y, int button, int clickCount) { int oldSelectedItem = _selectedItem; @@ -88,8 +76,18 @@ void ListWidget::handleMouseDown(int x, int y, int button) } } -void ListWidget::handleKeyDown(char key, int modifiers) +void ListWidget::handleMouseUp(int x, int y, int button, int clickCount) +{ + // If this was a double click and the mouse is still over the selected item, + // send the double click command + if (clickCount > 1 && (_selectedItem == (y - 2) / LINE_HEIGHT + _currentPos)) { + sendCommand(kListItemDoubleClickedCmd, _selectedItem); + } +} + +bool ListWidget::handleKeyDown(char key, int modifiers) { + bool handled = true; bool dirty = false; int oldSelectedItem = _selectedItem; @@ -99,15 +97,19 @@ void ListWidget::handleKeyDown(char key, int modifiers) _list[_selectedItem].deleteLastChar(); if (key == '\n' || key == '\r') { - // enter, exit editmode + // enter, confirm edit and exit editmode _editMode = false; dirty = true; - } - else if (_editMode && key == 8) { // backspace + sendCommand(kListItemChangedCmd, _selectedItem); + } else if (key == 27) { + // ESC, abort edit and exit editmode + _editMode = false; + dirty = true; + _list[_selectedItem] = _backupString; + } else if (key == 8) { // backspace _list[_selectedItem].deleteLastChar(); dirty = true; - } else if (_editMode && - // filter keystrokes + } else if (// filter keystrokes ( ( key >= 'a' && key <= 'z' ) || ( key >= 'A' && key <= 'Z' ) || ( key >= '0' && key <= '9' ) @@ -117,7 +119,8 @@ void ListWidget::handleKeyDown(char key, int modifiers) _list[_selectedItem] += key; dirty = true; - } + } else + handled = false; } else { // not editmode @@ -129,6 +132,7 @@ void ListWidget::handleKeyDown(char key, int modifiers) if ((_currentKeyDown != '\n' && _currentKeyDown != '\r')) { // override continuous enter keydown _editMode = true; dirty = true; + _backupString = _list[_selectedItem]; } } break; @@ -156,6 +160,8 @@ void ListWidget::handleKeyDown(char key, int modifiers) case 23: // end _selectedItem = _list.size() - 1; break; + default: + handled = false; } scrollToCurrent(); @@ -174,9 +180,11 @@ void ListWidget::handleKeyDown(char key, int modifiers) } _currentKeyDown = key; + + return handled; } -void ListWidget::handleKeyUp(char key, int modifiers) +bool ListWidget::handleKeyUp(char key, int modifiers) { if (key == _currentKeyDown) _currentKeyDown = 0; diff --git a/gui/ListWidget.h b/gui/ListWidget.h index bdb00fd7be..688d86e151 100644 --- a/gui/ListWidget.h +++ b/gui/ListWidget.h @@ -32,9 +32,16 @@ enum { kListNumberingOne = 1 }; +// Some special commands +enum { + kListItemDoubleClickedCmd = 'LIdb', // 'data' will be item index + kListItemChangedCmd = 'LIch', // 'data' will be item index +}; + /* ListWidget */ class ListWidget : public Widget, public CommandReceiver, public CommandSender { typedef ScummVM::StringList StringList; + typedef ScummVM::String String; protected: StringList _list; bool _editable; @@ -45,6 +52,7 @@ protected: int _selectedItem; ScrollBarWidget *_scrollBar; int _currentKeyDown; + String _backupString; public: ListWidget(Dialog *boss, int x, int y, int w, int h); virtual ~ListWidget(); @@ -55,9 +63,10 @@ public: const ScummVM::String& getSelectedString() const { return _list[_selectedItem]; } void setNumberingMode(int numberingMode) { _numberingMode = numberingMode; } - virtual void handleMouseDown(int x, int y, int button); - virtual void handleKeyDown(char key, int modifiers); - virtual void handleKeyUp(char key, int modifiers); + virtual void handleMouseDown(int x, int y, int button, int clickCount); + virtual void handleMouseUp(int x, int y, int button, int clickCount); + virtual bool handleKeyDown(char key, int modifiers); + virtual bool handleKeyUp(char key, int modifiers); virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); void scrollBarRecalc(); diff --git a/gui/ScrollBarWidget.cpp b/gui/ScrollBarWidget.cpp index 02503c97db..a9af686215 100644 --- a/gui/ScrollBarWidget.cpp +++ b/gui/ScrollBarWidget.cpp @@ -26,7 +26,7 @@ /* * TODO: - * - Auto-repeat: if one clicks & holds on one of the arrows, then after a + * - Auto-repeat: if user clicks & holds on one of the arrows, then after a * brief delay, it should start to contiously scroll * - Allow for a horizontal scrollbar, too? * - If there are less items than fit on one pages, no scrolling can be done @@ -70,7 +70,7 @@ ScrollBarWidget::ScrollBarWidget(Dialog *boss, int x, int y, int w, int h) } -void ScrollBarWidget::handleMouseDown(int x, int y, int button) +void ScrollBarWidget::handleMouseDown(int x, int y, int button, int clickCount) { int old_pos = _currentPos; @@ -95,7 +95,7 @@ void ScrollBarWidget::handleMouseDown(int x, int y, int button) checkBounds(old_pos); } -void ScrollBarWidget::handleMouseUp(int x, int y, int button) +void ScrollBarWidget::handleMouseUp(int x, int y, int button, int clickCount) { if (_draggingPart != kNoPart) _draggingPart = kNoPart; diff --git a/gui/ScrollBarWidget.h b/gui/ScrollBarWidget.h index e25f6bf171..e4b5752746 100644 --- a/gui/ScrollBarWidget.h +++ b/gui/ScrollBarWidget.h @@ -59,8 +59,8 @@ public: public: ScrollBarWidget(Dialog *boss, int x, int y, int w, int h); - void handleMouseDown(int x, int y, int button); - void handleMouseUp(int x, int y, int button); + void handleMouseDown(int x, int y, int button, int clickCount); + void handleMouseUp(int x, int y, int button, int clickCount); void handleMouseMoved(int x, int y, int button); void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); } void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); _part = kNoPart; draw(); } diff --git a/gui/dialog.cpp b/gui/dialog.cpp index c4f53892c7..a6bb965f98 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -93,7 +93,7 @@ void Dialog::draw() } } -void Dialog::handleMouseDown(int x, int y, int button) +void Dialog::handleMouseDown(int x, int y, int button, int clickCount) { Widget *w; w = findWidget(x, y); @@ -112,10 +112,10 @@ void Dialog::handleMouseDown(int x, int y, int button) } if (_focusedWidget) - _focusedWidget->handleMouseDown(x - _focusedWidget->_x, y - _focusedWidget->_y, button); + _focusedWidget->handleMouseDown(x - _focusedWidget->_x, y - _focusedWidget->_y, button, clickCount); } -void Dialog::handleMouseUp(int x, int y, int button) +void Dialog::handleMouseUp(int x, int y, int button, int clickCount) { Widget *w; @@ -133,17 +133,14 @@ void Dialog::handleMouseUp(int x, int y, int button) } if (w) - w->handleMouseUp(x - w->_x, y - w->_y, button); + w->handleMouseUp(x - w->_x, y - w->_y, button, clickCount); } void Dialog::handleKeyDown(char key, int modifiers) { - // ESC closes all dialogs by default - if (key == 27) - close(); - if (_focusedWidget) { - _focusedWidget->handleKeyDown(key, modifiers); + if (_focusedWidget->handleKeyDown(key, modifiers)) + return; } else { // Hotkey handling Widget *w = _firstWidget; @@ -152,13 +149,17 @@ void Dialog::handleKeyDown(char key, int modifiers) if (w->_type == kButtonWidget && key == toupper(((ButtonWidget *)w)->_hotkey)) { // We first send a mouseDown then a mouseUp. // FIXME: insert a brief delay between both. - w->handleMouseDown(0, 0, 1); - w->handleMouseUp(0, 0, 1); - break; + w->handleMouseDown(0, 0, 1, 1); + w->handleMouseUp(0, 0, 1, 1); + return; } w = w->_next; } } + + // ESC closes all dialogs by default + if (key == 27) + close(); } void Dialog::handleKeyUp(char key, int modifiers) @@ -303,6 +304,7 @@ SaveLoadDialog::SaveLoadDialog(NewGui *gui) void SaveLoadDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { switch (cmd) { + case kListItemChangedCmd: case kSaveCmd: if (_savegameList->getSelected() > 0 && !_savegameList->getSelectedString().isEmpty()) { Scumm *s = _gui->getScumm(); @@ -313,6 +315,7 @@ void SaveLoadDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat close(); } break; + case kListItemDoubleClickedCmd: case kLoadCmd: if (_savegameList->getSelected() > 0 && !_savegameList->getSelectedString().isEmpty()) { Scumm *s = _gui->getScumm(); diff --git a/gui/dialog.h b/gui/dialog.h index df93c22f21..0e9b46222a 100644 --- a/gui/dialog.h +++ b/gui/dialog.h @@ -60,8 +60,8 @@ public: virtual void draw(); virtual void handleTickle(); // Called periodically (in every guiloop() ) - virtual void handleMouseDown(int x, int y, int button); - virtual void handleMouseUp(int x, int y, int button); + virtual void handleMouseDown(int x, int y, int button, int clickCount); + virtual void handleMouseUp(int x, int y, int button, int clickCount); virtual void handleKeyDown(char key, int modifiers); virtual void handleKeyUp(char key, int modifiers); virtual void handleMouseMoved(int x, int y, int button); @@ -116,7 +116,7 @@ class PauseDialog : public Dialog { public: PauseDialog(NewGui *gui); - virtual void handleMouseDown(int x, int y, int button) + virtual void handleMouseDown(int x, int y, int button, int clickCount) { close(); } virtual void handleKeyDown(char key, int modifiers) { diff --git a/gui/widget.cpp b/gui/widget.cpp index 79354de515..b407d8200c 100644 --- a/gui/widget.cpp +++ b/gui/widget.cpp @@ -140,7 +140,7 @@ ButtonWidget::~ButtonWidget() } } -void ButtonWidget::handleMouseUp(int x, int y, int button) +void ButtonWidget::handleMouseUp(int x, int y, int button, int clickCount) { if (_flags & WIDGET_ENABLED && x >= 0 && x < _w && y >= 0 && y < _h) sendCommand(_cmd, 0); @@ -168,7 +168,7 @@ CheckboxWidget::CheckboxWidget(Dialog *boss, int x, int y, int w, int h, const c _type = kCheckboxWidget; } -void CheckboxWidget::handleMouseDown(int x, int y, int button) +void CheckboxWidget::handleMouseDown(int x, int y, int button, int clickCount) { if (_flags & WIDGET_ENABLED) { _state = !_state; @@ -221,7 +221,7 @@ void SliderWidget::handleMouseMoved(int x, int y, int button) { } } -void SliderWidget::handleMouseDown(int x, int y, int button) { +void SliderWidget::handleMouseDown(int x, int y, int button, int clickCount) { if (_flags & WIDGET_ENABLED) { int barx; @@ -234,7 +234,7 @@ void SliderWidget::handleMouseDown(int x, int y, int button) { } } -void SliderWidget::handleMouseUp(int x, int y, int button) { +void SliderWidget::handleMouseUp(int x, int y, int button, int clickCount) { if ((_flags & WIDGET_ENABLED) && _isDragging) { sendCommand(_cmd, _value); diff --git a/gui/widget.h b/gui/widget.h index 83df0e6735..ef3ca50356 100644 --- a/gui/widget.h +++ b/gui/widget.h @@ -90,13 +90,13 @@ public: Widget(Dialog *boss, int x, int y, int w, int h); virtual ~Widget() {} - virtual void handleMouseDown(int x, int y, int button) {} - virtual void handleMouseUp(int x, int y, int button) {} + virtual void handleMouseDown(int x, int y, int button, int clickCount) {} + virtual void handleMouseUp(int x, int y, int button, int clickCount) {} virtual void handleMouseEntered(int button) {} virtual void handleMouseLeft(int button) {} virtual void handleMouseMoved(int x, int y, int button) {} - virtual void handleKeyDown(char key, int modifiers) {} - virtual void handleKeyUp(char key, int modifiers) {} + virtual bool handleKeyDown(char key, int modifiers) { return false; } // Return true if the event was handled + virtual bool handleKeyUp(char key, int modifiers) { return false; } // Return true if the event was handled virtual void handleTickle() {} void draw(); void receivedFocus() { _hasFocus = true; receivedFocusWidget(); } @@ -146,7 +146,7 @@ public: void setCmd(uint32 cmd) { _cmd = cmd; } uint32 getCmd() const { return _cmd; } - void handleMouseUp(int x, int y, int button); + void handleMouseUp(int x, int y, int button, int clickCount); void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); } void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); } }; @@ -160,7 +160,7 @@ public: void setState(bool state) { _state = state; } bool getState() const { return _state; } - void handleMouseDown(int x, int y, int button); + void handleMouseDown(int x, int y, int button, int clickCount); virtual void handleMouseEntered(int button) {} virtual void handleMouseLeft(int button) {} @@ -185,8 +185,8 @@ public: int getMaxValue() const { return _valueMax; } void handleMouseMoved(int x, int y, int button); - void handleMouseDown(int x, int y, int button); - void handleMouseUp(int x, int y, int button); + void handleMouseDown(int x, int y, int button, int clickCount); + void handleMouseUp(int x, int y, int button, int clickCount); protected: void drawWidget(bool hilite); diff --git a/newgui.cpp b/newgui.cpp index f301d8677e..d4db25f85a 100644 --- a/newgui.cpp +++ b/newgui.cpp @@ -36,6 +36,8 @@ * - ... */ +#define ABS(x) ((x) < 0 ? -(x) : (x)) + NewGui::NewGui(Scumm *s) : _s(s), _use_alpha_blending(true), _need_redraw(false),_prepare_for_gui(true), _pauseDialog(0), _saveLoadDialog(0), _aboutDialog(0), _optionsDialog(0), @@ -102,6 +104,10 @@ void NewGui::loop() _eventList.clear(); _currentKeyDown = 0; + + _lastClick.x = _lastClick.y = 0; + _lastClick.time = 0; + _lastClick.count = 0; _prepare_for_gui = false; } @@ -130,8 +136,8 @@ void NewGui::loop() // init continuous event stream _currentKeyDown = t.kbd.ascii; _currentKeyDownFlags = t.kbd.flags; - _eventFiredCount = 1; - _loopCount = 0; + _keyRepeatEvenCount = 1; + _keyRepeatLoopCount = 0; break; case OSystem::EVENT_KEYUP: activeDialog->handleKeyUp(t.kbd.ascii, t.kbd.flags); @@ -144,12 +150,24 @@ void NewGui::loop() break; // We don't distinguish between mousebuttons (for now at least) case OSystem::EVENT_LBUTTONDOWN: - case OSystem::EVENT_RBUTTONDOWN: - activeDialog->handleMouseDown(t.mouse.x - activeDialog->_x, t.mouse.y - activeDialog->_y, 1); + case OSystem::EVENT_RBUTTONDOWN: { + uint32 time = _s->_system->get_msecs(); + if (_lastClick.count && (time < _lastClick.time + 1000) + && ABS(_lastClick.x - t.mouse.x) < 3 + && ABS(_lastClick.y - t.mouse.y) < 3) { + _lastClick.count++; + } else { + _lastClick.x = t.mouse.x; + _lastClick.y = t.mouse.y; + _lastClick.count = 1; + } + _lastClick.time = time; + } + activeDialog->handleMouseDown(t.mouse.x - activeDialog->_x, t.mouse.y - activeDialog->_y, 1, _lastClick.count); break; case OSystem::EVENT_LBUTTONUP: case OSystem::EVENT_RBUTTONUP: - activeDialog->handleMouseUp(t.mouse.x - activeDialog->_x, t.mouse.y - activeDialog->_y, 1); + activeDialog->handleMouseUp(t.mouse.x - activeDialog->_x, t.mouse.y - activeDialog->_y, 1, _lastClick.count); break; } } @@ -161,16 +179,16 @@ void NewGui::loop() if (_currentKeyDown != 0) { // if only fired once, wait longer - if ( _loopCount >= ((_eventFiredCount > 1) ? 2 : 4) ) - // ^ loops to wait first event - // ^ loops to wait after first event + if ( _keyRepeatLoopCount >= ((_keyRepeatEvenCount > 1) ? 2 : 4) ) + // ^ loops to wait first event + // ^ loops to wait after first event { // fire event activeDialog->handleKeyDown(_currentKeyDown, _currentKeyDownFlags); - _eventFiredCount++; - _loopCount = 0; + _keyRepeatEvenCount++; + _keyRepeatLoopCount = 0; } - _loopCount++; + _keyRepeatLoopCount++; } _s->drawDirtyScreenParts(); @@ -94,8 +94,8 @@ protected: // for continuous events (keyDown) int _currentKeyDown, _currentKeyDownFlags; - int _loopCount; - int _eventFiredCount; + int _keyRepeatLoopCount; + int _keyRepeatEvenCount; // sound state bool _old_soundsPaused; @@ -105,10 +105,12 @@ protected: int _old_cursorHotspotX, _old_cursorHotspotY, _old_cursorWidth, _old_cursorHeight; byte _old_grabbedCursor[2048]; - // mouse pos + // position and time of last mouse click (used to detect double clicks) struct { - int16 x,y; - } _old_mouse; + int16 x, y; // Position of mouse when the click occured + uint32 time; // Time + int count; // How often was it already pressed? + } _lastClick; // List of events to be handled EventList _eventList; |