heaps of changes to NewGUI: mouseDown/Up events now count the clicks (so you can detect double/triple clicks); ListWidget sends a message if an item was double clicked or changed; you can abort editing in the ListWidget by pressing ESC; SaveLoadDialog will save when you double click and item, and when you finish editing an item by pressing return, will save

svn-id: r4656
This commit is contained in:
Max Horn 2002-07-27 14:16:14 +00:00
parent 403afb0514
commit 39670a73c0
10 changed files with 112 additions and 72 deletions

View file

@ -25,18 +25,6 @@
#include "newgui.h" #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 // Height of one entry
#define LINE_HEIGHT 10 #define LINE_HEIGHT 10
@ -72,7 +60,7 @@ void ListWidget::scrollBarRecalc()
_scrollBar->recalc(); _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; 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; bool dirty = false;
int oldSelectedItem = _selectedItem; int oldSelectedItem = _selectedItem;
@ -99,15 +97,19 @@ void ListWidget::handleKeyDown(char key, int modifiers)
_list[_selectedItem].deleteLastChar(); _list[_selectedItem].deleteLastChar();
if (key == '\n' || key == '\r') { if (key == '\n' || key == '\r') {
// enter, exit editmode // enter, confirm edit and exit editmode
_editMode = false; _editMode = false;
dirty = true; dirty = true;
} sendCommand(kListItemChangedCmd, _selectedItem);
else if (_editMode && key == 8) { // backspace } 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(); _list[_selectedItem].deleteLastChar();
dirty = true; dirty = true;
} else if (_editMode && } else if (// filter keystrokes
// filter keystrokes
( ( key >= 'a' && key <= 'z' ) ( ( key >= 'a' && key <= 'z' )
|| ( key >= 'A' && key <= 'Z' ) || ( key >= 'A' && key <= 'Z' )
|| ( key >= '0' && key <= '9' ) || ( key >= '0' && key <= '9' )
@ -117,7 +119,8 @@ void ListWidget::handleKeyDown(char key, int modifiers)
_list[_selectedItem] += key; _list[_selectedItem] += key;
dirty = true; dirty = true;
} } else
handled = false;
} else { } else {
// not editmode // not editmode
@ -129,6 +132,7 @@ void ListWidget::handleKeyDown(char key, int modifiers)
if ((_currentKeyDown != '\n' && _currentKeyDown != '\r')) { // override continuous enter keydown if ((_currentKeyDown != '\n' && _currentKeyDown != '\r')) { // override continuous enter keydown
_editMode = true; _editMode = true;
dirty = true; dirty = true;
_backupString = _list[_selectedItem];
} }
} }
break; break;
@ -156,6 +160,8 @@ void ListWidget::handleKeyDown(char key, int modifiers)
case 23: // end case 23: // end
_selectedItem = _list.size() - 1; _selectedItem = _list.size() - 1;
break; break;
default:
handled = false;
} }
scrollToCurrent(); scrollToCurrent();
@ -174,9 +180,11 @@ void ListWidget::handleKeyDown(char key, int modifiers)
} }
_currentKeyDown = key; _currentKeyDown = key;
return handled;
} }
void ListWidget::handleKeyUp(char key, int modifiers) bool ListWidget::handleKeyUp(char key, int modifiers)
{ {
if (key == _currentKeyDown) if (key == _currentKeyDown)
_currentKeyDown = 0; _currentKeyDown = 0;

View file

@ -32,9 +32,16 @@ enum {
kListNumberingOne = 1 kListNumberingOne = 1
}; };
// Some special commands
enum {
kListItemDoubleClickedCmd = 'LIdb', // 'data' will be item index
kListItemChangedCmd = 'LIch', // 'data' will be item index
};
/* ListWidget */ /* ListWidget */
class ListWidget : public Widget, public CommandReceiver, public CommandSender { class ListWidget : public Widget, public CommandReceiver, public CommandSender {
typedef ScummVM::StringList StringList; typedef ScummVM::StringList StringList;
typedef ScummVM::String String;
protected: protected:
StringList _list; StringList _list;
bool _editable; bool _editable;
@ -45,6 +52,7 @@ protected:
int _selectedItem; int _selectedItem;
ScrollBarWidget *_scrollBar; ScrollBarWidget *_scrollBar;
int _currentKeyDown; int _currentKeyDown;
String _backupString;
public: public:
ListWidget(Dialog *boss, int x, int y, int w, int h); ListWidget(Dialog *boss, int x, int y, int w, int h);
virtual ~ListWidget(); virtual ~ListWidget();
@ -55,9 +63,10 @@ public:
const ScummVM::String& getSelectedString() const { return _list[_selectedItem]; } const ScummVM::String& getSelectedString() const { return _list[_selectedItem]; }
void setNumberingMode(int numberingMode) { _numberingMode = numberingMode; } void setNumberingMode(int numberingMode) { _numberingMode = numberingMode; }
virtual void handleMouseDown(int x, int y, int button); virtual void handleMouseDown(int x, int y, int button, int clickCount);
virtual void handleKeyDown(char key, int modifiers); virtual void handleMouseUp(int x, int y, int button, int clickCount);
virtual void handleKeyUp(char key, int modifiers); virtual bool handleKeyDown(char key, int modifiers);
virtual bool handleKeyUp(char key, int modifiers);
virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
void scrollBarRecalc(); void scrollBarRecalc();

View file

@ -26,7 +26,7 @@
/* /*
* TODO: * 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 * brief delay, it should start to contiously scroll
* - Allow for a horizontal scrollbar, too? * - Allow for a horizontal scrollbar, too?
* - If there are less items than fit on one pages, no scrolling can be done * - 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; int old_pos = _currentPos;
@ -95,7 +95,7 @@ void ScrollBarWidget::handleMouseDown(int x, int y, int button)
checkBounds(old_pos); 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) if (_draggingPart != kNoPart)
_draggingPart = kNoPart; _draggingPart = kNoPart;

View file

@ -59,8 +59,8 @@ public:
public: public:
ScrollBarWidget(Dialog *boss, int x, int y, int w, int h); ScrollBarWidget(Dialog *boss, int x, int y, int w, int h);
void handleMouseDown(int x, int y, int button); void handleMouseDown(int x, int y, int button, int clickCount);
void handleMouseUp(int x, int y, int button); void handleMouseUp(int x, int y, int button, int clickCount);
void handleMouseMoved(int x, int y, int button); void handleMouseMoved(int x, int y, int button);
void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); } void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); }
void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); _part = kNoPart; draw(); } void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); _part = kNoPart; draw(); }

View file

@ -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; Widget *w;
w = findWidget(x, y); w = findWidget(x, y);
@ -112,10 +112,10 @@ void Dialog::handleMouseDown(int x, int y, int button)
} }
if (_focusedWidget) 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; Widget *w;
@ -133,17 +133,14 @@ void Dialog::handleMouseUp(int x, int y, int button)
} }
if (w) 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) void Dialog::handleKeyDown(char key, int modifiers)
{ {
// ESC closes all dialogs by default
if (key == 27)
close();
if (_focusedWidget) { if (_focusedWidget) {
_focusedWidget->handleKeyDown(key, modifiers); if (_focusedWidget->handleKeyDown(key, modifiers))
return;
} else { } else {
// Hotkey handling // Hotkey handling
Widget *w = _firstWidget; Widget *w = _firstWidget;
@ -152,13 +149,17 @@ void Dialog::handleKeyDown(char key, int modifiers)
if (w->_type == kButtonWidget && key == toupper(((ButtonWidget *)w)->_hotkey)) { if (w->_type == kButtonWidget && key == toupper(((ButtonWidget *)w)->_hotkey)) {
// We first send a mouseDown then a mouseUp. // We first send a mouseDown then a mouseUp.
// FIXME: insert a brief delay between both. // FIXME: insert a brief delay between both.
w->handleMouseDown(0, 0, 1); w->handleMouseDown(0, 0, 1, 1);
w->handleMouseUp(0, 0, 1); w->handleMouseUp(0, 0, 1, 1);
break; return;
} }
w = w->_next; w = w->_next;
} }
} }
// ESC closes all dialogs by default
if (key == 27)
close();
} }
void Dialog::handleKeyUp(char key, int modifiers) void Dialog::handleKeyUp(char key, int modifiers)
@ -303,6 +304,7 @@ SaveLoadDialog::SaveLoadDialog(NewGui *gui)
void SaveLoadDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) void SaveLoadDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data)
{ {
switch (cmd) { switch (cmd) {
case kListItemChangedCmd:
case kSaveCmd: case kSaveCmd:
if (_savegameList->getSelected() > 0 && !_savegameList->getSelectedString().isEmpty()) { if (_savegameList->getSelected() > 0 && !_savegameList->getSelectedString().isEmpty()) {
Scumm *s = _gui->getScumm(); Scumm *s = _gui->getScumm();
@ -313,6 +315,7 @@ void SaveLoadDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
close(); close();
} }
break; break;
case kListItemDoubleClickedCmd:
case kLoadCmd: case kLoadCmd:
if (_savegameList->getSelected() > 0 && !_savegameList->getSelectedString().isEmpty()) { if (_savegameList->getSelected() > 0 && !_savegameList->getSelectedString().isEmpty()) {
Scumm *s = _gui->getScumm(); Scumm *s = _gui->getScumm();

View file

@ -60,8 +60,8 @@ public:
virtual void draw(); virtual void draw();
virtual void handleTickle(); // Called periodically (in every guiloop() ) virtual void handleTickle(); // Called periodically (in every guiloop() )
virtual void handleMouseDown(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); virtual void handleMouseUp(int x, int y, int button, int clickCount);
virtual void handleKeyDown(char key, int modifiers); virtual void handleKeyDown(char key, int modifiers);
virtual void handleKeyUp(char key, int modifiers); virtual void handleKeyUp(char key, int modifiers);
virtual void handleMouseMoved(int x, int y, int button); virtual void handleMouseMoved(int x, int y, int button);
@ -116,7 +116,7 @@ class PauseDialog : public Dialog {
public: public:
PauseDialog(NewGui *gui); PauseDialog(NewGui *gui);
virtual void handleMouseDown(int x, int y, int button) virtual void handleMouseDown(int x, int y, int button, int clickCount)
{ close(); } { close(); }
virtual void handleKeyDown(char key, int modifiers) virtual void handleKeyDown(char key, int modifiers)
{ {

View file

@ -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) if (_flags & WIDGET_ENABLED && x >= 0 && x < _w && y >= 0 && y < _h)
sendCommand(_cmd, 0); sendCommand(_cmd, 0);
@ -168,7 +168,7 @@ CheckboxWidget::CheckboxWidget(Dialog *boss, int x, int y, int w, int h, const c
_type = kCheckboxWidget; _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) { if (_flags & WIDGET_ENABLED) {
_state = !_state; _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) { if (_flags & WIDGET_ENABLED) {
int barx; 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) { if ((_flags & WIDGET_ENABLED) && _isDragging) {
sendCommand(_cmd, _value); sendCommand(_cmd, _value);

View file

@ -90,13 +90,13 @@ public:
Widget(Dialog *boss, int x, int y, int w, int h); Widget(Dialog *boss, int x, int y, int w, int h);
virtual ~Widget() {} virtual ~Widget() {}
virtual void handleMouseDown(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) {} virtual void handleMouseUp(int x, int y, int button, int clickCount) {}
virtual void handleMouseEntered(int button) {} virtual void handleMouseEntered(int button) {}
virtual void handleMouseLeft(int button) {} virtual void handleMouseLeft(int button) {}
virtual void handleMouseMoved(int x, int y, int button) {} virtual void handleMouseMoved(int x, int y, int button) {}
virtual void handleKeyDown(char key, int modifiers) {} virtual bool handleKeyDown(char key, int modifiers) { return false; } // Return true if the event was handled
virtual void handleKeyUp(char key, int modifiers) {} virtual bool handleKeyUp(char key, int modifiers) { return false; } // Return true if the event was handled
virtual void handleTickle() {} virtual void handleTickle() {}
void draw(); void draw();
void receivedFocus() { _hasFocus = true; receivedFocusWidget(); } void receivedFocus() { _hasFocus = true; receivedFocusWidget(); }
@ -146,7 +146,7 @@ public:
void setCmd(uint32 cmd) { _cmd = cmd; } void setCmd(uint32 cmd) { _cmd = cmd; }
uint32 getCmd() const { return _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 handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); }
void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); } void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); }
}; };
@ -160,7 +160,7 @@ public:
void setState(bool state) { _state = state; } void setState(bool state) { _state = state; }
bool getState() const { return _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 handleMouseEntered(int button) {}
virtual void handleMouseLeft(int button) {} virtual void handleMouseLeft(int button) {}
@ -185,8 +185,8 @@ public:
int getMaxValue() const { return _valueMax; } int getMaxValue() const { return _valueMax; }
void handleMouseMoved(int x, int y, int button); void handleMouseMoved(int x, int y, int button);
void handleMouseDown(int x, int y, int button); void handleMouseDown(int x, int y, int button, int clickCount);
void handleMouseUp(int x, int y, int button); void handleMouseUp(int x, int y, int button, int clickCount);
protected: protected:
void drawWidget(bool hilite); void drawWidget(bool hilite);

View file

@ -36,6 +36,8 @@
* - ... * - ...
*/ */
#define ABS(x) ((x) < 0 ? -(x) : (x))
NewGui::NewGui(Scumm *s) : _s(s), _use_alpha_blending(true), NewGui::NewGui(Scumm *s) : _s(s), _use_alpha_blending(true),
_need_redraw(false),_prepare_for_gui(true), _need_redraw(false),_prepare_for_gui(true),
_pauseDialog(0), _saveLoadDialog(0), _aboutDialog(0), _optionsDialog(0), _pauseDialog(0), _saveLoadDialog(0), _aboutDialog(0), _optionsDialog(0),
@ -102,6 +104,10 @@ void NewGui::loop()
_eventList.clear(); _eventList.clear();
_currentKeyDown = 0; _currentKeyDown = 0;
_lastClick.x = _lastClick.y = 0;
_lastClick.time = 0;
_lastClick.count = 0;
_prepare_for_gui = false; _prepare_for_gui = false;
} }
@ -130,8 +136,8 @@ void NewGui::loop()
// init continuous event stream // init continuous event stream
_currentKeyDown = t.kbd.ascii; _currentKeyDown = t.kbd.ascii;
_currentKeyDownFlags = t.kbd.flags; _currentKeyDownFlags = t.kbd.flags;
_eventFiredCount = 1; _keyRepeatEvenCount = 1;
_loopCount = 0; _keyRepeatLoopCount = 0;
break; break;
case OSystem::EVENT_KEYUP: case OSystem::EVENT_KEYUP:
activeDialog->handleKeyUp(t.kbd.ascii, t.kbd.flags); activeDialog->handleKeyUp(t.kbd.ascii, t.kbd.flags);
@ -144,12 +150,24 @@ void NewGui::loop()
break; break;
// We don't distinguish between mousebuttons (for now at least) // We don't distinguish between mousebuttons (for now at least)
case OSystem::EVENT_LBUTTONDOWN: case OSystem::EVENT_LBUTTONDOWN:
case OSystem::EVENT_RBUTTONDOWN: case OSystem::EVENT_RBUTTONDOWN: {
activeDialog->handleMouseDown(t.mouse.x - activeDialog->_x, t.mouse.y - activeDialog->_y, 1); 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; break;
case OSystem::EVENT_LBUTTONUP: case OSystem::EVENT_LBUTTONUP:
case OSystem::EVENT_RBUTTONUP: 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; break;
} }
} }
@ -161,16 +179,16 @@ void NewGui::loop()
if (_currentKeyDown != 0) if (_currentKeyDown != 0)
{ {
// if only fired once, wait longer // if only fired once, wait longer
if ( _loopCount >= ((_eventFiredCount > 1) ? 2 : 4) ) if ( _keyRepeatLoopCount >= ((_keyRepeatEvenCount > 1) ? 2 : 4) )
// ^ loops to wait first event // ^ loops to wait first event
// ^ loops to wait after first event // ^ loops to wait after first event
{ {
// fire event // fire event
activeDialog->handleKeyDown(_currentKeyDown, _currentKeyDownFlags); activeDialog->handleKeyDown(_currentKeyDown, _currentKeyDownFlags);
_eventFiredCount++; _keyRepeatEvenCount++;
_loopCount = 0; _keyRepeatLoopCount = 0;
} }
_loopCount++; _keyRepeatLoopCount++;
} }
_s->drawDirtyScreenParts(); _s->drawDirtyScreenParts();

View file

@ -94,8 +94,8 @@ protected:
// for continuous events (keyDown) // for continuous events (keyDown)
int _currentKeyDown, _currentKeyDownFlags; int _currentKeyDown, _currentKeyDownFlags;
int _loopCount; int _keyRepeatLoopCount;
int _eventFiredCount; int _keyRepeatEvenCount;
// sound state // sound state
bool _old_soundsPaused; bool _old_soundsPaused;
@ -105,10 +105,12 @@ protected:
int _old_cursorHotspotX, _old_cursorHotspotY, _old_cursorWidth, _old_cursorHeight; int _old_cursorHotspotX, _old_cursorHotspotY, _old_cursorWidth, _old_cursorHeight;
byte _old_grabbedCursor[2048]; byte _old_grabbedCursor[2048];
// mouse pos // position and time of last mouse click (used to detect double clicks)
struct { struct {
int16 x,y; int16 x, y; // Position of mouse when the click occured
} _old_mouse; uint32 time; // Time
int count; // How often was it already pressed?
} _lastClick;
// List of events to be handled // List of events to be handled
EventList _eventList; EventList _eventList;