aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gui/ListWidget.cpp50
-rw-r--r--gui/ListWidget.h15
-rw-r--r--gui/ScrollBarWidget.cpp6
-rw-r--r--gui/ScrollBarWidget.h4
-rw-r--r--gui/dialog.cpp27
-rw-r--r--gui/dialog.h6
-rw-r--r--gui/widget.cpp8
-rw-r--r--gui/widget.h16
-rw-r--r--newgui.cpp40
-rw-r--r--newgui.h12
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();
diff --git a/newgui.h b/newgui.h
index 10d2861c84..ef52cf77c2 100644
--- a/newgui.h
+++ b/newgui.h
@@ -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;