/* _______ __ __ __ ______ __ __ _______ __ __ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ * * Copyright (c) 2004, 2005, 2006, 2007 Olof Naessén and Per Larsson * * Js_./ * Per Larsson a.k.a finalman _RqZ{a<^_aa * Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a// * _Qhm`] _f "'c 1!5m * Visit: http://guichan.darkbits.org )Qk

ws?a-?' ._/L #' * binary forms, with or without )4d[#7r, . ' )d`)[ * modification, are permitted provided _Q-5'5W..j/?' -?!\)cam' * that the following conditions are met: j<. a J@\ * this list of conditions and the j(]1u_setFocusHandler(NULL); } if (top != NULL) { top->_setFocusHandler(mFocusHandler); } mTop = top; } Widget* Gui::getTop() const { return mTop; } void Gui::setGraphics(Graphics* graphics) { mGraphics = graphics; } Graphics* Gui::getGraphics() const { return mGraphics; } void Gui::setInput(Input* input) { mInput = input; } Input* Gui::getInput() const { return mInput; } void Gui::logic() { if (mTop == NULL) { throw GCN_EXCEPTION("No top widget set"); } mFocusHandler->applyChanges(); // Release of modal focus or modal mouse input focus might make it // necessary to distribute mouse events. handleModalFocusRelease(); handleModalMouseInputFocusRelease(); if (mInput != NULL) { mInput->_pollInput(); handleKeyInput(); handleMouseInput(); // Apply changes even if no input has been processed. // A widget might has asked for focus. mFocusHandler->applyChanges(); } // end if mTop->logic(); } void Gui::draw() { if (mTop == NULL) { throw GCN_EXCEPTION("No top widget set"); } if (mGraphics == NULL) { throw GCN_EXCEPTION("No graphics set"); } if (!mTop->isVisible()) { return; } mGraphics->_beginDraw(); // If top has a border, // draw it before drawing top if (mTop->getBorderSize() > 0) { Rectangle rec = mTop->getDimension(); rec.x -= mTop->getBorderSize(); rec.y -= mTop->getBorderSize(); rec.width += 2 * mTop->getBorderSize(); rec.height += 2 * mTop->getBorderSize(); mGraphics->pushClipArea(rec); mTop->drawBorder(mGraphics); mGraphics->popClipArea(); } mGraphics->pushClipArea(mTop->getDimension()); mTop->draw(mGraphics); mGraphics->popClipArea(); mGraphics->_endDraw(); } void Gui::focusNone() { mFocusHandler->focusNone(); } void Gui::setTabbingEnabled(bool tabbing) { mTabbing = tabbing; } bool Gui::isTabbingEnabled() { return mTabbing; } void Gui::addGlobalKeyListener(KeyListener* keyListener) { mKeyListeners.push_back(keyListener); } void Gui::removeGlobalKeyListener(KeyListener* keyListener) { mKeyListeners.remove(keyListener); } void Gui::handleMouseInput() { while (!mInput->isMouseQueueEmpty()) { MouseInput mouseInput = mInput->dequeueMouseInput(); // Save the current mouse state. It will be needed if modal focus // changes or modal mouse input focus changes. mLastMouseX = mouseInput.getX(); mLastMouseY = mouseInput.getY(); switch (mouseInput.getType()) { case MouseInput::PRESSED: handleMousePressed(mouseInput); break; case MouseInput::RELEASED: handleMouseReleased(mouseInput); break; case MouseInput::MOVED: handleMouseMoved(mouseInput); break; case MouseInput::WHEEL_MOVED_DOWN: handleMouseWheelMovedDown(mouseInput); break; case MouseInput::WHEEL_MOVED_UP: handleMouseWheelMovedUp(mouseInput); break; default: throw GCN_EXCEPTION("Unknown mouse input type."); break; } } } void Gui::handleKeyInput() { while (!mInput->isKeyQueueEmpty()) { KeyInput keyInput = mInput->dequeueKeyInput(); // Save modifiers state mShiftPressed = keyInput.isShiftPressed(); mMetaPressed = keyInput.isMetaPressed(); mControlPressed = keyInput.isControlPressed(); mAltPressed = keyInput.isAltPressed(); KeyEvent keyEventToGlobalKeyListeners(NULL, mShiftPressed, mControlPressed, mAltPressed, mMetaPressed, keyInput.getType(), keyInput.isNumericPad(), keyInput.getKey()); distributeKeyEventToGlobalKeyListeners(keyEventToGlobalKeyListeners); // If a global key listener consumes the event it will not be // sent further to the source of the event. if (keyEventToGlobalKeyListeners.isConsumed()) { continue; } bool keyEventConsumed = false; // Send key inputs to the focused widgets if (mFocusHandler->getFocused() != NULL) { KeyEvent keyEvent(getKeyEventSource(), mShiftPressed, mControlPressed, mAltPressed, mMetaPressed, keyInput.getType(), keyInput.isNumericPad(), keyInput.getKey()); if (!mFocusHandler->getFocused()->isFocusable()) { mFocusHandler->focusNone(); } else { distributeKeyEvent(keyEvent); } keyEventConsumed = keyEvent.isConsumed(); } // If the key event hasn't been consumed and // tabbing is enable check for tab press and // change focus. if (!keyEventConsumed && mTabbing && keyInput.getKey().getValue() == Key::TAB && keyInput.getType() == KeyInput::PRESSED) { if (keyInput.isShiftPressed()) { mFocusHandler->tabPrevious(); } else { mFocusHandler->tabNext(); } } mFocusHandler->applyChanges(); } // end while } void Gui::handleMouseMoved(const MouseInput& mouseInput) { // Check if the mouse leaves the application window. if (mLastWidgetWithMouse != NULL && Widget::widgetExists(mLastWidgetWithMouse) && (mouseInput.getX() < 0 || mouseInput.getY() < 0 || !mTop->getDimension().isPointInRect(mouseInput.getX(), mouseInput.getY())) ) { int lastWidgetWithMouseX, lastWidgetWithMouseY; mLastWidgetWithMouse->getAbsolutePosition(lastWidgetWithMouseX, lastWidgetWithMouseY); MouseEvent mouseEvent(mLastWidgetWithMouse, mShiftPressed, mControlPressed, mAltPressed, mMetaPressed, MouseEvent::EXITED, mouseInput.getButton(), mouseInput.getX() - lastWidgetWithMouseX, mouseInput.getY() - lastWidgetWithMouseY, mClickCount); distributeMouseEvent(mouseEvent, true, true); mLastWidgetWithMouse = NULL; return; } Widget* sourceWidget = getMouseEventSource(mouseInput.getX(), mouseInput.getY()); if (sourceWidget != mLastWidgetWithMouse) { if (mLastWidgetWithMouse != NULL && Widget::widgetExists(mLastWidgetWithMouse)) { int lastWidgetWithMouseX, lastWidgetWithMouseY; mLastWidgetWithMouse->getAbsolutePosition(lastWidgetWithMouseX, lastWidgetWithMouseY); MouseEvent mouseEvent(mLastWidgetWithMouse, mShiftPressed, mControlPressed, mAltPressed, mMetaPressed, MouseEvent::EXITED, mouseInput.getButton(), mouseInput.getX() - lastWidgetWithMouseX, mouseInput.getY() - lastWidgetWithMouseY, mClickCount); distributeMouseEvent(mouseEvent, true, true); mClickCount = 0; mLastMousePressTimeStamp = 0; } int sourceWidgetX, sourceWidgetY; sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY); MouseEvent mouseEvent(sourceWidget, mShiftPressed, mControlPressed, mAltPressed, mMetaPressed, MouseEvent::ENTERED, mouseInput.getButton(), mouseInput.getX() - sourceWidgetX, mouseInput.getY() - sourceWidgetY, mClickCount); distributeMouseEvent(mouseEvent, true, true); mLastWidgetWithMouse = sourceWidget; } if (mDraggedWidget != NULL && Widget::widgetExists(mDraggedWidget)) { int draggedWidgetX, draggedWidgetY; mDraggedWidget->getAbsolutePosition(draggedWidgetX, draggedWidgetY); MouseEvent mouseEvent(mDraggedWidget, mShiftPressed, mControlPressed, mAltPressed, mMetaPressed, MouseEvent::DRAGGED, mouseInput.getButton(), mouseInput.getX() - draggedWidgetX, mouseInput.getY() - draggedWidgetY, mClickCount); distributeMouseEvent(mouseEvent); } else { int sourceWidgetX, sourceWidgetY; sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY); MouseEvent mouseEvent(sourceWidget, mShiftPressed, mControlPressed, mAltPressed, mMetaPressed, MouseEvent::MOVED, mouseInput.getButton(), mouseInput.getX() - sourceWidgetX, mouseInput.getY() - sourceWidgetY, mClickCount); distributeMouseEvent(mouseEvent); } } void Gui::handleMousePressed(const MouseInput& mouseInput) { Widget* sourceWidget = getMouseEventSource(mouseInput.getX(), mouseInput.getY()); if (mDraggedWidget != NULL) { sourceWidget = mDraggedWidget; } int sourceWidgetX, sourceWidgetY; sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY); MouseEvent mouseEvent(sourceWidget, mShiftPressed, mControlPressed, mAltPressed, mMetaPressed, MouseEvent::PRESSED, mouseInput.getButton(), mouseInput.getX() - sourceWidgetX, mouseInput.getY() - sourceWidgetY, mClickCount); distributeMouseEvent(mouseEvent); mLastWidgetPressed = sourceWidget; if (mFocusHandler->getModalFocused() != NULL && sourceWidget->hasModalFocus() || mFocusHandler->getModalFocused() == NULL) { sourceWidget->requestFocus(); } mDraggedWidget = sourceWidget; if (mLastMousePressTimeStamp < 300 && mLastMousePressButton == mouseInput.getButton()) { mClickCount++; } else { mClickCount = 0; } mLastMousePressButton = mouseInput.getButton(); mLastMousePressTimeStamp = mouseInput.getTimeStamp(); } void Gui::handleMouseWheelMovedDown(const MouseInput& mouseInput) { Widget* sourceWidget = getMouseEventSource(mouseInput.getX(), mouseInput.getY()); if (mDraggedWidget != NULL) { sourceWidget = mDraggedWidget; } int sourceWidgetX, sourceWidgetY; sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY); MouseEvent mouseEvent(sourceWidget, mShiftPressed, mControlPressed, mAltPressed, mMetaPressed, MouseEvent::WHEEL_MOVED_DOWN, mouseInput.getButton(), mouseInput.getX() - sourceWidgetX, mouseInput.getY() - sourceWidgetY, mClickCount); distributeMouseEvent(mouseEvent); } void Gui::handleMouseWheelMovedUp(const MouseInput& mouseInput) { Widget* sourceWidget = getMouseEventSource(mouseInput.getX(), mouseInput.getY()); if (mDraggedWidget != NULL) { sourceWidget = mDraggedWidget; } int sourceWidgetX, sourceWidgetY; sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY); MouseEvent mouseEvent(sourceWidget, mShiftPressed, mControlPressed, mAltPressed, mMetaPressed, MouseEvent::WHEEL_MOVED_UP, mouseInput.getButton(), mouseInput.getX() - sourceWidgetX, mouseInput.getY() - sourceWidgetY, mClickCount); distributeMouseEvent(mouseEvent); } void Gui::handleMouseReleased(const MouseInput& mouseInput) { Widget* sourceWidget = getMouseEventSource(mouseInput.getX(), mouseInput.getY()); if (mDraggedWidget != NULL) { if (sourceWidget != mLastWidgetPressed) { mLastWidgetPressed = NULL; } sourceWidget = mDraggedWidget; } int sourceWidgetX, sourceWidgetY; sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY); MouseEvent mouseEvent(sourceWidget, mShiftPressed, mControlPressed, mAltPressed, mMetaPressed, MouseEvent::RELEASED, mouseInput.getButton(), mouseInput.getX() - sourceWidgetX, mouseInput.getY() - sourceWidgetY, mClickCount); distributeMouseEvent(mouseEvent); if (mouseInput.getButton() == mLastMousePressButton && mLastWidgetPressed == sourceWidget) { MouseEvent mouseEvent(sourceWidget, mShiftPressed, mControlPressed, mAltPressed, mMetaPressed, MouseEvent::CLICKED, mouseInput.getButton(), mouseInput.getX() - sourceWidgetX, mouseInput.getY() - sourceWidgetY, mClickCount); distributeMouseEvent(mouseEvent); mLastWidgetPressed = NULL; } else { mLastMousePressButton = 0; mClickCount = 0; } if (mDraggedWidget != NULL) { mDraggedWidget = NULL; } } void Gui::handleModalFocusRelease() { if (mLastWidgetWithModalFocus != mFocusHandler->getModalFocused()) { Widget* sourceWidget = getWidgetAt(mLastMouseX, mLastMouseY); if (sourceWidget != mLastWidgetWithModalFocus && mLastWidgetWithModalFocus != NULL) { int sourceWidgetX, sourceWidgetY; sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY); MouseEvent mouseEvent(sourceWidget, mShiftPressed, mControlPressed, mAltPressed, mMetaPressed, MouseEvent::ENTERED, mLastMousePressButton, mLastMouseX, mLastMouseY, mClickCount); distributeMouseEvent(mouseEvent); } mLastWidgetWithModalFocus = mFocusHandler->getModalFocused(); } } void Gui::handleModalMouseInputFocusRelease() { if (mLastWidgetWithModalMouseInputFocus != mFocusHandler->getModalMouseInputFocused()) { Widget* sourceWidget = getWidgetAt(mLastMouseX, mLastMouseY); if (sourceWidget != mLastWidgetWithModalMouseInputFocus && mLastWidgetWithModalMouseInputFocus != NULL) { int sourceWidgetX, sourceWidgetY; sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY); MouseEvent mouseEvent(sourceWidget, mShiftPressed, mControlPressed, mAltPressed, mMetaPressed, MouseEvent::ENTERED, mLastMousePressButton, mLastMouseX, mLastMouseY, mClickCount); distributeMouseEvent(mouseEvent); } mLastWidgetWithModalMouseInputFocus = mFocusHandler->getModalMouseInputFocused(); } } Widget* Gui::getWidgetAt(int x, int y) { // If the widget's parent has no child then we have found the widget.. Widget* parent = mTop; Widget* child = mTop; while (child != NULL) { Widget* swap = child; int parentX, parentY; parent->getAbsolutePosition(parentX, parentY); child = parent->getWidgetAt(x - parentX, y - parentY); parent = swap; } return parent; } Widget* Gui::getMouseEventSource(int x, int y) { Widget* widget = getWidgetAt(x, y); if (mFocusHandler->getModalMouseInputFocused() != NULL && !widget->hasModalMouseInputFocus()) { return mFocusHandler->getModalMouseInputFocused(); } return widget; } Widget* Gui::getKeyEventSource() { Widget* widget = mFocusHandler->getFocused(); while (widget->_getInternalFocusHandler() != NULL && widget->_getInternalFocusHandler()->getFocused() != NULL) { widget = widget->_getInternalFocusHandler()->getFocused(); } return widget; } void Gui::distributeMouseEvent(MouseEvent& mouseEvent, bool force, bool toSourceOnly) { Widget* parent = mouseEvent.getSource(); Widget* widget = mouseEvent.getSource(); if (mFocusHandler->getModalFocused() != NULL && !widget->hasModalFocus()) { return; } if (mFocusHandler->getModalMouseInputFocused() != NULL && !widget->hasModalMouseInputFocus()) { return; } while (parent != NULL) { // If the widget has been removed due to input // cancel the distribution. if (!Widget::widgetExists(widget)) { break; } parent = (Widget*)widget->getParent(); if (widget->isEnabled() || force) { std::list mouseListeners = widget->_getMouseListeners(); // Send the event to all mouse listeners of the widget. for (std::list::iterator it = mouseListeners.begin(); it != mouseListeners.end(); ++it) { switch (mouseEvent.getType()) { case MouseEvent::ENTERED: (*it)->mouseEntered(mouseEvent); break; case MouseEvent::EXITED: (*it)->mouseExited(mouseEvent); break; case MouseEvent::MOVED: (*it)->mouseMoved(mouseEvent); break; case MouseEvent::PRESSED: (*it)->mousePressed(mouseEvent); break; case MouseEvent::RELEASED: (*it)->mouseReleased(mouseEvent); break; case MouseEvent::WHEEL_MOVED_UP: (*it)->mouseWheelMovedUp(mouseEvent); break; case MouseEvent::WHEEL_MOVED_DOWN: (*it)->mouseWheelMovedDown(mouseEvent); break; case MouseEvent::DRAGGED: (*it)->mouseDragged(mouseEvent); break; case MouseEvent::CLICKED: (*it)->mouseClicked(mouseEvent); break; default: throw GCN_EXCEPTION("Unknown mouse event type."); } } if (toSourceOnly) { break; } } Widget* swap = widget; widget = parent; parent = (Widget*)swap->getParent(); // If a non modal focused widget has been reach // and we have modal focus cancel the distribution. if (mFocusHandler->getModalFocused() != NULL && !widget->hasModalFocus()) { break; } // If a non modal mouse input focused widget has been reach // and we have modal mouse input focus cancel the distribution. if (mFocusHandler->getModalMouseInputFocused() != NULL && !widget->hasModalMouseInputFocus()) { break; } } } void Gui::distributeKeyEvent(KeyEvent& keyEvent) { Widget* sourceWidget = keyEvent.getSource(); if (mFocusHandler->getModalFocused() != NULL && !sourceWidget->hasModalFocus()) { return; } // If the widget has been removed due to input // cancel the distribution. if (!Widget::widgetExists(sourceWidget)) { return; } if (sourceWidget->isEnabled()) { std::list keyListeners = sourceWidget->_getKeyListeners(); // Send the event to all key listeners of the source widget. for (std::list::iterator it = keyListeners.begin(); it != keyListeners.end(); ++it) { switch (keyEvent.getType()) { case KeyEvent::PRESSED: (*it)->keyPressed(keyEvent); break; case KeyEvent::RELEASED: (*it)->keyReleased(keyEvent); break; default: throw GCN_EXCEPTION("Unknown key event type."); } } } } void Gui::distributeKeyEventToGlobalKeyListeners(KeyEvent& keyEvent) { KeyListenerListIterator it; for (it = mKeyListeners.begin(); it != mKeyListeners.end(); it++) { switch (keyEvent.getType()) { case KeyEvent::PRESSED: (*it)->keyPressed(keyEvent); break; case KeyEvent::RELEASED: (*it)->keyReleased(keyEvent); break; default: throw GCN_EXCEPTION("Unknown key event type."); } if (keyEvent.isConsumed()) { break; } } } }