diff options
author | Max Horn | 2002-07-13 22:41:29 +0000 |
---|---|---|
committer | Max Horn | 2002-07-13 22:41:29 +0000 |
commit | c3c11b79cb1fb41646265db458081eeedbd9ac1c (patch) | |
tree | f4c9b9a080e2d231a2ddc848313ca3599b31f233 /gui | |
parent | 1238d7422705e88097d21a3d0e34683262be4331 (diff) | |
download | scummvm-rg350-c3c11b79cb1fb41646265db458081eeedbd9ac1c.tar.gz scummvm-rg350-c3c11b79cb1fb41646265db458081eeedbd9ac1c.tar.bz2 scummvm-rg350-c3c11b79cb1fb41646265db458081eeedbd9ac1c.zip |
added latest of painelf's patches which makes NewGui handle system events directly (code becomes much cleaner and more powerful this way); he also implemented a 'focus' item in NewGui; atop of this several changes of my own that further improve the GUI behaviour
svn-id: r4541
Diffstat (limited to 'gui')
-rw-r--r-- | gui/ListWidget.cpp | 6 | ||||
-rw-r--r-- | gui/ScrollBarWidget.cpp | 61 | ||||
-rw-r--r-- | gui/ScrollBarWidget.h | 19 | ||||
-rw-r--r-- | gui/dialog.cpp | 128 | ||||
-rw-r--r-- | gui/dialog.h | 13 | ||||
-rw-r--r-- | gui/widget.cpp | 6 | ||||
-rw-r--r-- | gui/widget.h | 12 |
7 files changed, 152 insertions, 93 deletions
diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index 096c8cd1d5..f435663bc5 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -27,11 +27,7 @@ /* * TODO: - * - The handleKey method of widgets is currently never called, code for that has - * to be added to dialog.cpp - * - Once the above item is done, implement scrolling using arrow keys, - * pageup/pagedown, home/end keys etc. - * - Allow user to select an entry w/ the mouse + * - Implement scrolling using arrow keys, pageup/pagedown, home/end keys etc. * - Implement editing of the selected string in a generic fashion */ diff --git a/gui/ScrollBarWidget.cpp b/gui/ScrollBarWidget.cpp index 79db84ca30..c83c6f224c 100644 --- a/gui/ScrollBarWidget.cpp +++ b/gui/ScrollBarWidget.cpp @@ -60,11 +60,11 @@ static uint32 down_arrow[8] = { ScrollBarWidget::ScrollBarWidget(Dialog *boss, int x, int y, int w, int h) : Widget (boss, x, y, w, h), CommandSender(boss) { - _flags = WIDGET_ENABLED | WIDGET_TRACK_MOUSE | WIDGET_CLEARBG; + _flags = WIDGET_ENABLED | WIDGET_TRACK_MOUSE | WIDGET_CLEARBG | WIDGET_WANT_TICKLE; _type = kScrollBarWidget; _part = kNoPart; - _isDraggingSlider = false; + _draggingPart = kNoPart; } @@ -75,37 +75,33 @@ void ScrollBarWidget::handleMouseDown(int x, int y, int button) if (y <= UP_DOWN_BOX_HEIGHT) { // Up arrow _currentPos--; + _draggingPart = kUpArrowPart; } else if (y >= _h - UP_DOWN_BOX_HEIGHT) { // Down arrow _currentPos++; + _draggingPart = kDownArrowPart; } else if (y < _sliderPos) { _currentPos -= _entriesPerPage; } else if (y >= _sliderPos + _sliderHeight) { _currentPos += _entriesPerPage; } else { - _isDraggingSlider = true; + _draggingPart = kSliderPart; _sliderDeltaMouseDownPos = y - _sliderPos; } // Make sure that _currentPos is still inside the bounds - checkbounds(); - - if (old_pos != _currentPos) { - recalc(); - draw(); - sendCommand(kSetPositionCmd, _currentPos); - } + checkBounds(old_pos); } void ScrollBarWidget::handleMouseUp(int x, int y, int button) { - if (_isDraggingSlider) - _isDraggingSlider = false; + if (_draggingPart != kNoPart) + _draggingPart = kNoPart; } void ScrollBarWidget::handleMouseMoved(int x, int y, int button) { - if (_isDraggingSlider) { + if (_draggingPart == kSliderPart) { int old_pos = _currentPos; _sliderPos = y - _sliderDeltaMouseDownPos; @@ -118,12 +114,7 @@ void ScrollBarWidget::handleMouseMoved(int x, int y, int button) _currentPos = (_sliderPos - UP_DOWN_BOX_HEIGHT) * (_numEntries - _entriesPerPage) / (_h - _sliderHeight - 2 * UP_DOWN_BOX_HEIGHT); - checkbounds(); - - if (_currentPos != old_pos) { - draw(); - sendCommand(kSetPositionCmd, _currentPos); - } + checkBounds(old_pos); } else { int old_part = _part; @@ -143,12 +134,39 @@ void ScrollBarWidget::handleMouseMoved(int x, int y, int button) } } -void ScrollBarWidget::checkbounds() +void ScrollBarWidget::handleTickle() +{ +/* + // FIXME - this code is supposed to allow for "click-repeat" (like key repeat), + // i.e. if you click on one of the arrows and keep clicked, it will scroll + // continously. However, just like key repeat, this requires two delays: + // First an "initial" delay that has to pass before repeating starts (otherwise + // it is near to impossible to achieve single clicks). Secondly, a repeat delay + // that determines how often per second a click is simulated. + int old_pos = _currentPos; + + if (_draggingPart == kUpArrowPart) + _currentPos--; + else if (_draggingPart == kDownArrowPart) + _currentPos++; + + // Make sure that _currentPos is still inside the bounds + checkBounds(old_pos); +*/ +} + +void ScrollBarWidget::checkBounds(int old_pos) { if (_currentPos > _numEntries - _entriesPerPage) _currentPos = _numEntries - _entriesPerPage; else if (_currentPos < 0) _currentPos = 0; + + if (old_pos != _currentPos) { + recalc(); + draw(); + sendCommand(kSetPositionCmd, _currentPos); + } } void ScrollBarWidget::recalc() @@ -172,6 +190,9 @@ void ScrollBarWidget::drawWidget(bool hilite) gui->frameRect(_x, _y, _w, _h, gui->_shadowcolor); + if (_draggingPart != kNoPart) + _part = _draggingPart; + // Up arrow gui->frameRect(_x, _y, _w, UP_DOWN_BOX_HEIGHT, gui->_color); gui->drawBitmap(up_arrow, _x, _y, diff --git a/gui/ScrollBarWidget.h b/gui/ScrollBarWidget.h index c4b54b446c..e25f6bf171 100644 --- a/gui/ScrollBarWidget.h +++ b/gui/ScrollBarWidget.h @@ -27,6 +27,7 @@ enum { kScrollBarWidth = 9 }; + enum { kSetPositionCmd = 'SETP' }; @@ -34,24 +35,27 @@ enum { class ScrollBarWidget : public Widget, public CommandSender { protected: - enum { + typedef enum { kNoPart, kUpArrowPart, kDownArrowPart, kSliderPart, kPageUpPart, kPageDownPart - } _part; + } Part; + + Part _part; int _sliderHeight; int _sliderPos; - bool _isDraggingSlider; + Part _draggingPart; int _sliderDeltaMouseDownPos; public: int _numEntries; int _entriesPerPage; int _currentPos; + public: ScrollBarWidget(Dialog *boss, int x, int y, int w, int h); @@ -60,13 +64,16 @@ public: 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(); } - - // FIXME: Shouldn't these be private? + void handleTickle(); + + // FIXME - this should be private, but then we also have to add accessors + // for _numEntries, _entriesPerPage and _currentPos. This again leads to the question: + // should these accessors force a redraw? void recalc(); protected: void drawWidget(bool hilite); - void checkbounds(); + void checkBounds(int old_pos); }; diff --git a/gui/dialog.cpp b/gui/dialog.cpp index 52556d5fcf..f17cf4bf65 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -40,15 +40,6 @@ void Dialog::setupScreenBuf() // Draw the fixed parts of the dialog: background and border. _gui->blendRect(_x, _y, _w, _h, _gui->_bgcolor); _gui->box(_x, _y, _w, _h); - - // Draw a bgcolor rectangle for all widgets which have WIDGET_CLEARBG set. - Widget *w = _firstWidget; - while (w) { - if (w->_flags & WIDGET_CLEARBG) - _gui->fillRect(_x + w->_x, _y + w->_y, w->_w, w->_h, _gui->_bgcolor); - // FIXME - should we also draw borders here if WIDGET_BORDER is set? - w = w->_next; - } // Finally blit this to _screenBuf _gui->blitTo(_screenBuf, _x, _y, _w, _h); @@ -82,18 +73,30 @@ void Dialog::draw() void Dialog::handleMouseDown(int x, int y, int button) { - // FIXME: If outside focused widget, widget loses focus + _focusedWidget = findWidget(x, y); - Widget *w = findWidget(x - _x, y - _y); - if (w) - w->handleMouseDown(x - _x - w->_x, y - _y - w->_y, button); + if (_focusedWidget) { + _focusedWidget->handleMouseDown(x - _focusedWidget->_x, y - _focusedWidget->_y, button); + } } void Dialog::handleMouseUp(int x, int y, int button) { - Widget *w = findWidget(x - _x, y - _y); + Widget *w; + + if (_focusedWidget) { + w = _focusedWidget; + + // Lose focus on mouseup unless the widget requested to retain the focus + if (! (_focusedWidget->getFlags() & WIDGET_RETAIN_FOCUS )) + _focusedWidget = 0; + + } else { + w = findWidget(x, y); + } + if (w) - w->handleMouseUp(x - _x - w->_x, y - _y - w->_y, button); + w->handleMouseUp(x - w->_x, y - w->_y, button); } void Dialog::handleKeyDown(char key, int modifiers) @@ -102,53 +105,76 @@ void Dialog::handleKeyDown(char key, int modifiers) if (key == 27) close(); - // FIXME: Only if not focused widget - - // Hotkey handling - Widget *w = _firstWidget; - key = toupper(key); - while (w) { - if (w->_type == kButtonWidget && key == toupper(((ButtonWidget *)w)->_hotkey)) { - // FIXME: Calling both handlers is bad style, but we don't really know which one we're supposed to call - w->handleMouseDown(0, 0, 1); - w->handleMouseUp(0, 0, 1); - break; + if (_focusedWidget) { + _focusedWidget->handleKeyDown(key, modifiers); + } else { + // Hotkey handling + Widget *w = _firstWidget; + key = toupper(key); + while (w) { + 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 = w->_next; } - w = w->_next; } - - // TODO - introduce the notion of a "focused" widget which receives - // key events (by calling its handleKey method). Required for editfields - // and also for an editable list widget. } void Dialog::handleKeyUp(char key, int modifiers) { - // FIXME: Focused widget recieves keyup + // Focused widget recieves keyup events + if (_focusedWidget) + _focusedWidget->handleKeyUp(key, modifiers); } void Dialog::handleMouseMoved(int x, int y, int button) { - Widget *w = findWidget(x - _x, y - _y); - - if (_mouseWidget != w) { - if (_mouseWidget) - _mouseWidget->handleMouseLeft(button); - if (w) - w->handleMouseEntered(button); - _mouseWidget = w; - } - - if (!w) - return; + Widget *w; - if (w->getFlags() & WIDGET_TRACK_MOUSE) { - w->handleMouseMoved(x - _x - w->_x, y - _y - w->_y, button); + if (_focusedWidget) { + w = _focusedWidget; + + // We still send mouseEntered/Left messages to the focused item + // (but to no other items). + bool mouseInFocusedWidget = (x >= w->_x && x < w->_x + w->_w && y >= w->_y && y < w->_y + w->_h); + if (mouseInFocusedWidget && _mouseWidget != w) { + _mouseWidget = w; + w->handleMouseEntered(button); + } else if (!mouseInFocusedWidget && _mouseWidget == w) { + _mouseWidget = 0; + w->handleMouseLeft(button); + } + + } else { + w = findWidget(x, y); + + if (_mouseWidget != w) { + if (_mouseWidget) + _mouseWidget->handleMouseLeft(button); + if (w) + w->handleMouseEntered(button); + _mouseWidget = w; + } + + if (!w || !(w->getFlags() & WIDGET_TRACK_MOUSE)) { + return; + } } - - //FIXME: Focused widget recieves mouseup + + w->handleMouseMoved(x - w->_x, y - w->_y, button); } +void Dialog::handleTickle() +{ + // Focused widget recieves tickle notifications + if (_focusedWidget && _focusedWidget->getFlags() & WIDGET_WANT_TICKLE) { + _focusedWidget->handleTickle(); + } +} void Dialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { @@ -167,8 +193,8 @@ Widget *Dialog::findWidget(int x, int y) { Widget *w = _firstWidget; while (w) { - // Stop as soon as we find a fidget that contains (x,y) - if (x >= w->_x && x <= w->_x + w->_w && y >= w->_y && y <= w->_y + w->_h) + // Stop as soon as we find a widget that contains the point (x,y) + if (x >= w->_x && x < w->_x + w->_w && y >= w->_y && y < w->_y + w->_h) break; w = w->_next; } @@ -177,6 +203,8 @@ Widget *Dialog::findWidget(int x, int y) void Dialog::close() { + _mouseWidget = 0; + _focusedWidget = 0; _gui->closeTopDialog(); } diff --git a/gui/dialog.h b/gui/dialog.h index 460fa6e0bf..ee92f34e37 100644 --- a/gui/dialog.h +++ b/gui/dialog.h @@ -36,27 +36,30 @@ enum { class Dialog : public CommandReceiver { friend class Widget; + friend class NewGui; protected: NewGui *_gui; - Widget *_firstWidget; int16 _x, _y; uint16 _w, _h; + Widget *_firstWidget; Widget *_mouseWidget; + Widget *_focusedWidget; byte *_screenBuf; public: Dialog(NewGui *gui, int x, int y, int w, int h) - : _gui(gui), _firstWidget(0), _x(x), _y(y), _w(w), _h(h), _mouseWidget(0), _screenBuf(0) + : _gui(gui), _x(x), _y(y), _w(w), _h(h), _firstWidget(0), + _mouseWidget(0), _focusedWidget(0), _screenBuf(0) {} virtual ~Dialog(); virtual void draw(); - //virtual void handleIdle(); // Called periodically + 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 handleKeyDown(char key, int modifiers); // modifiers = alt/shift/ctrl etc. - virtual void handleKeyUp(char key, int modifiers); // modifiers = alt/shift/ctrl etc. + virtual void handleKeyDown(char key, int modifiers); + virtual void handleKeyUp(char key, int modifiers); virtual void handleMouseMoved(int x, int y, int button); virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); diff --git a/gui/widget.cpp b/gui/widget.cpp index 22bf54096c..c72d44647c 100644 --- a/gui/widget.cpp +++ b/gui/widget.cpp @@ -34,7 +34,7 @@ Widget::Widget (Dialog *boss, int x, int y, int w, int h) void Widget::draw() { - NewGui *gui = _boss->_gui; + NewGui *gui = _boss->getGui(); if (_flags & WIDGET_INVISIBLE) return; @@ -127,9 +127,9 @@ ButtonWidget::~ButtonWidget() } } -void ButtonWidget::handleMouseDown(int x, int y, int button) +void ButtonWidget::handleMouseUp(int x, int y, int button) { - if (_flags & WIDGET_ENABLED) + if (_flags & WIDGET_ENABLED && x >= 0 && x < _w && y >= 0 && y < _h) sendCommand(_cmd, 0); } diff --git a/gui/widget.h b/gui/widget.h index e237e24824..8d2f49e164 100644 --- a/gui/widget.h +++ b/gui/widget.h @@ -32,7 +32,9 @@ enum { WIDGET_BORDER = 1 << 3, WIDGET_CLEARBG = 1 << 4, WIDGET_WANT_TICKLE = 1 << 5, - WIDGET_TRACK_MOUSE = 1 << 6 + WIDGET_TRACK_MOUSE = 1 << 6, + WIDGET_RETAIN_FOCUS = 1 << 7 // Retain focus on mouse up. By default widgets lose focus on mouseup, but some widgets might want to retain it - widgets where you enter text, for instance + }; enum { @@ -75,13 +77,14 @@ public: class Widget { friend class Dialog; protected: - int _type; + uint32 _type; Dialog *_boss; Widget *_next; int16 _x, _y; uint16 _w, _h; uint16 _id; - int _flags; + uint16 _flags; + public: Widget(Dialog *boss, int x, int y, int w, int h); virtual ~Widget() {} @@ -93,6 +96,7 @@ public: virtual void handleMouseMoved(int x, int y, int button) {} virtual void handleKeyDown(char key, int modifiers) {} virtual void handleKeyUp(char key, int modifiers) {} + virtual void handleTickle() {} void draw(); void setFlags(int flags) { _flags |= flags; } @@ -132,7 +136,7 @@ public: void setCmd(uint32 cmd) { _cmd = cmd; } uint32 getCmd() const { return _cmd; } - void handleMouseDown(int x, int y, int button); + void handleMouseUp(int x, int y, int button); void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); } void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); } }; |