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
This commit is contained in:
Max Horn 2002-07-13 22:41:29 +00:00
parent 1238d74227
commit c3c11b79cb
10 changed files with 159 additions and 100 deletions

View file

@ -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);
//FIXME: Focused widget recieves mouseup
if (_mouseWidget != w) {
if (_mouseWidget)
_mouseWidget->handleMouseLeft(button);
if (w)
w->handleMouseEntered(button);
_mouseWidget = w;
}
if (!w || !(w->getFlags() & WIDGET_TRACK_MOUSE)) {
return;
}
}
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();
}