From a520c88cabf03973ddf27435eb5a970f9c214d30 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Mon, 17 Feb 2014 21:31:57 +0300 Subject: combine focushandler into one file. --- src/CMakeLists.txt | 2 - src/Makefile.am | 6 +- src/gui/base/basiccontainer.cpp | 3 +- src/gui/base/focushandler.cpp | 569 ---------------------------------------- src/gui/base/focushandler.hpp | 417 ----------------------------- src/gui/base/gui.cpp | 2 +- src/gui/base/gui.hpp | 2 +- src/gui/base/widget.cpp | 3 +- src/gui/base/widget.hpp | 2 +- src/gui/focushandler.cpp | 518 +++++++++++++++++++++++++++++++++++- src/gui/focushandler.h | 379 ++++++++++++++++++++++++-- src/gui/gui.h | 2 +- src/gui/widgets/guitable.cpp | 2 +- src/gui/widgets/guitable.h | 2 +- src/gui/widgets/listbox.cpp | 2 +- src/gui/widgets/window.cpp | 3 +- src/gui/windows/chatwindow.cpp | 3 +- src/input/inputmanager.cpp | 2 +- 18 files changed, 879 insertions(+), 1040 deletions(-) delete mode 100644 src/gui/base/focushandler.cpp delete mode 100644 src/gui/base/focushandler.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3fca244eb..711d9e47b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -770,7 +770,6 @@ SET(SRCS gui/base/color.hpp listeners/deathlistener.h events/event.h - gui/base/focushandler.hpp listeners/focuslistener.h gui/base/gui.hpp events/inputguievent.h @@ -800,7 +799,6 @@ SET(SRCS gui/base/basiccontainer.cpp gui/base/cliprectangle.cpp gui/base/color.cpp - gui/base/focushandler.cpp gui/base/gui.cpp input/key.cpp gui/base/rectangle.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 1b3710b60..f20376feb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,13 +29,11 @@ dyecmd_CXXFLAGS = dyecmd_SOURCES = gui/base/cliprectangle.cpp \ gui/base/color.cpp \ gui/base/rectangle.cpp \ - gui/base/widget.cpp \ events/actionevent.h \ gui/base/cliprectangle.hpp \ gui/base/color.hpp \ events/event.h \ - gui/base/rectangle.hpp \ - gui/base/widget.hpp + gui/base/rectangle.hpp dyecmd_SOURCES += dyetool/dyemain.cpp \ animatedsprite.cpp \ @@ -157,7 +155,6 @@ manaplus_SOURCES += events/actionevent.h \ gui/base/color.hpp \ listeners/deathlistener.h \ events/event.h \ - gui/base/focushandler.hpp \ listeners/focuslistener.h \ render/graphics.h \ gui/base/gui.hpp \ @@ -188,7 +185,6 @@ manaplus_SOURCES += events/actionevent.h \ gui/base/basiccontainer.cpp \ gui/base/cliprectangle.cpp \ gui/base/color.cpp \ - gui/base/focushandler.cpp \ gui/base/gui.cpp \ input/key.cpp \ gui/base/rectangle.cpp \ diff --git a/src/gui/base/basiccontainer.cpp b/src/gui/base/basiccontainer.cpp index 82ef1c025..05d89f172 100644 --- a/src/gui/base/basiccontainer.cpp +++ b/src/gui/base/basiccontainer.cpp @@ -69,7 +69,8 @@ #include -#include "gui/base/focushandler.hpp" +#include "gui/focushandler.h" + #include "input/mouseinput.h" #include "render/graphics.h" diff --git a/src/gui/base/focushandler.cpp b/src/gui/base/focushandler.cpp deleted file mode 100644 index 3c6978e70..000000000 --- a/src/gui/base/focushandler.cpp +++ /dev/null @@ -1,569 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2011-2014 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* _______ __ __ __ ______ __ __ _______ __ __ - * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ - * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / - * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / - * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / - * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / - * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ - * - * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson - * - * - * Per Larsson a.k.a finalman - * Olof Naessén a.k.a jansem/yakslem - * - * Visit: http://guichan.sourceforge.net - * - * License: (BSD) - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of Guichan nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * For comments regarding functions please see the header file. - */ - -#include "gui/base/focushandler.hpp" - -#include "gui/base/widget.hpp" - -#include "listeners/focuslistener.h" - -#include "debug.h" - -namespace gcn -{ - FocusHandler::FocusHandler() : - mWidgets(), - mFocusedWidget(nullptr), - mModalFocusedWidget(nullptr), - mModalMouseInputFocusedWidget(nullptr), - mDraggedWidget(nullptr), - mLastWidgetWithMouse(nullptr), - mLastWidgetWithModalFocus(nullptr), - mLastWidgetWithModalMouseInputFocus(nullptr), - mLastWidgetPressed(nullptr) - { - } - - void FocusHandler::requestFocus(Widget* widget) - { - if (!widget || widget == mFocusedWidget) - return; - - int toBeFocusedIndex = -1; - for (unsigned int i = 0, sz = static_cast( - mWidgets.size()); i < sz; ++i) - { - if (mWidgets[i] == widget) - { - toBeFocusedIndex = i; - break; - } - } - - if (toBeFocusedIndex < 0) - return; - - Widget *const oldFocused = mFocusedWidget; - - if (oldFocused != widget) - { - mFocusedWidget = mWidgets.at(toBeFocusedIndex); - - if (oldFocused) - { - Event focusEvent(oldFocused); - distributeFocusLostEvent(focusEvent); - } - - Event focusEvent(mWidgets.at(toBeFocusedIndex)); - distributeFocusGainedEvent(focusEvent); - } - } - - void FocusHandler::requestModalFocus(Widget* widget) - { - if (mModalFocusedWidget && mModalFocusedWidget != widget) - return; - - mModalFocusedWidget = widget; - if (mFocusedWidget && !mFocusedWidget->isModalFocused()) - focusNone(); - } - - void FocusHandler::requestModalMouseInputFocus(Widget* widget) - { - if (mModalMouseInputFocusedWidget - && mModalMouseInputFocusedWidget != widget) - { - return; - } - - mModalMouseInputFocusedWidget = widget; - } - - void FocusHandler::releaseModalFocus(Widget* widget) - { - if (mModalFocusedWidget == widget) - mModalFocusedWidget = nullptr; - } - - void FocusHandler::releaseModalMouseInputFocus(Widget* widget) - { - if (mModalMouseInputFocusedWidget == widget) - mModalMouseInputFocusedWidget = nullptr; - } - - Widget* FocusHandler::getFocused() const - { - return mFocusedWidget; - } - - Widget* FocusHandler::getModalFocused() const - { - return mModalFocusedWidget; - } - - Widget* FocusHandler::getModalMouseInputFocused() const - { - return mModalMouseInputFocusedWidget; - } - - void FocusHandler::focusNext() - { - int i; - int focusedWidget = -1; - const int sz = static_cast(mWidgets.size()); - for (i = 0; i < sz; ++i) - { - if (mWidgets[i] == mFocusedWidget) - focusedWidget = i; - } - const int focused = focusedWidget; - - // i is a counter that ensures that the following loop - // won't get stuck in an infinite loop - i = sz; - do - { - ++ focusedWidget; - - if (i == 0) - { - focusedWidget = -1; - break; - } - - -- i; - - if (focusedWidget >= sz) - focusedWidget = 0; - - if (focusedWidget == focused) - return; - } - while (!mWidgets.at(focusedWidget)->isFocusable()); - - if (focusedWidget >= 0) - { - mFocusedWidget = mWidgets.at(focusedWidget); - - Event focusEvent(mFocusedWidget); - distributeFocusGainedEvent(focusEvent); - } - - if (focused >= 0) - { - Event focusEvent(mWidgets.at(focused)); - distributeFocusLostEvent(focusEvent); - } - } - - void FocusHandler::focusPrevious() - { - if (mWidgets.empty()) - { - mFocusedWidget = nullptr; - return; - } - - int i; - int focusedWidget = -1; - const int sz = static_cast(mWidgets.size()); - for (i = 0; i < sz; ++ i) - { - if (mWidgets[i] == mFocusedWidget) - focusedWidget = i; - } - const int focused = focusedWidget; - - // i is a counter that ensures that the following loop - // won't get stuck in an infinite loop - i = sz; - do - { - -- focusedWidget; - - if (i == 0) - { - focusedWidget = -1; - break; - } - - -- i; - - if (focusedWidget <= 0) - focusedWidget = sz - 1; - - if (focusedWidget == focused) - return; - } - while (!mWidgets.at(focusedWidget)->isFocusable()); - - if (focusedWidget >= 0) - { - mFocusedWidget = mWidgets.at(focusedWidget); - Event focusEvent(mFocusedWidget); - distributeFocusGainedEvent(focusEvent); - } - - if (focused >= 0) - { - Event focusEvent(mWidgets.at(focused)); - distributeFocusLostEvent(focusEvent); - } - } - - bool FocusHandler::isFocused(const Widget* widget) const - { - return mFocusedWidget == widget; - } - - void FocusHandler::add(Widget* widget) - { - mWidgets.push_back(widget); - } - - void FocusHandler::remove(Widget* widget) - { - if (isFocused(widget)) - mFocusedWidget = nullptr; - - for (WidgetIterator iter = mWidgets.begin(); - iter != mWidgets.end(); ++iter) - { - if ((*iter) == widget) - { - mWidgets.erase(iter); - break; - } - } - - if (mDraggedWidget == widget) - { - mDraggedWidget = nullptr; - return; - } - - if (mLastWidgetWithMouse == widget) - { - mLastWidgetWithMouse = nullptr; - return; - } - - if (mLastWidgetWithModalFocus == widget) - { - mLastWidgetWithModalFocus = nullptr; - return; - } - - if (mLastWidgetWithModalMouseInputFocus == widget) - { - mLastWidgetWithModalMouseInputFocus = nullptr; - return; - } - - if (mLastWidgetPressed == widget) - { - mLastWidgetPressed = nullptr; - return; - } - } - - void FocusHandler::focusNone() - { - if (mFocusedWidget) - { - Widget *const focused = mFocusedWidget; - mFocusedWidget = nullptr; - - Event focusEvent(focused); - distributeFocusLostEvent(focusEvent); - } - } - - void FocusHandler::tabNext() - { - if (mFocusedWidget) - { - if (!mFocusedWidget->isTabOutEnabled()) - return; - } - - if (mWidgets.empty()) - { - mFocusedWidget = nullptr; - return; - } - - int i; - int focusedWidget = -1; - const int sz = static_cast(mWidgets.size()); - for (i = 0; i < sz; ++ i) - { - if (mWidgets[i] == mFocusedWidget) - focusedWidget = i; - } - const int focused = focusedWidget; - bool done = false; - - // i is a counter that ensures that the following loop - // won't get stuck in an infinite loop - i = sz; - do - { - ++ focusedWidget; - - if (i == 0) - { - focusedWidget = -1; - break; - } - - -- i; - - if (focusedWidget >= sz) - focusedWidget = 0; - - if (focusedWidget == focused) - return; - - const Widget *const widget = mWidgets.at(focusedWidget); - if (widget->isFocusable() && widget->isTabInEnabled() && - (!mModalFocusedWidget || widget->isModalFocused())) - { - done = true; - } - } - while (!done); - - if (focusedWidget >= 0) - { - mFocusedWidget = mWidgets.at(focusedWidget); - Event focusEvent(mFocusedWidget); - distributeFocusGainedEvent(focusEvent); - } - - if (focused >= 0) - { - Event focusEvent(mWidgets.at(focused)); - distributeFocusLostEvent(focusEvent); - } - } - - void FocusHandler::tabPrevious() - { - if (mFocusedWidget) - { - if (!mFocusedWidget->isTabOutEnabled()) - return; - } - - if (mWidgets.empty()) - { - mFocusedWidget = nullptr; - return; - } - - int i; - int focusedWidget = -1; - const int sz = static_cast(mWidgets.size()); - for (i = 0; i < sz; ++ i) - { - if (mWidgets[i] == mFocusedWidget) - focusedWidget = i; - } - const int focused = focusedWidget; - bool done = false; - - // i is a counter that ensures that the following loop - // won't get stuck in an infinite loop - i = sz; - do - { - -- focusedWidget; - - if (i == 0) - { - focusedWidget = -1; - break; - } - - -- i; - - if (focusedWidget <= 0) - focusedWidget = sz - 1; - - if (focusedWidget == focused) - return; - - const Widget *const widget = mWidgets.at(focusedWidget); - if (widget->isFocusable() && widget->isTabInEnabled() && - (!mModalFocusedWidget || widget->isModalFocused())) - { - done = true; - } - } - while (!done); - - if (focusedWidget >= 0) - { - mFocusedWidget = mWidgets.at(focusedWidget); - Event focusEvent(mFocusedWidget); - distributeFocusGainedEvent(focusEvent); - } - - if (focused >= 0) - { - Event focusEvent(mWidgets.at(focused)); - distributeFocusLostEvent(focusEvent); - } - } - - void FocusHandler::distributeFocusLostEvent(const Event& focusEvent) - { - Widget *const sourceWidget = focusEvent.getSource(); - - std::list focusListeners - = sourceWidget->_getFocusListeners(); - - // Send the event to all focus listeners of the widget. - for (std::list::const_iterator - it = focusListeners.begin(); - it != focusListeners.end(); - ++ it) - { - (*it)->focusLost(focusEvent); - } - } - - void FocusHandler::distributeFocusGainedEvent(const Event& focusEvent) - { - Widget *const sourceWidget = focusEvent.getSource(); - - std::list focusListeners - = sourceWidget->_getFocusListeners(); - - // Send the event to all focus listeners of the widget. - for (std::list::const_iterator - it = focusListeners.begin(); - it != focusListeners.end(); - ++ it) - { - (*it)->focusGained(focusEvent); - } - } - - Widget* FocusHandler::getDraggedWidget() - { - return mDraggedWidget; - } - - void FocusHandler::setDraggedWidget(Widget* draggedWidget) - { - mDraggedWidget = draggedWidget; - } - - Widget* FocusHandler::getLastWidgetWithMouse() - { - return mLastWidgetWithMouse; - } - - void FocusHandler::setLastWidgetWithMouse(Widget* lastWidgetWithMouse) - { - mLastWidgetWithMouse = lastWidgetWithMouse; - } - - Widget* FocusHandler::getLastWidgetWithModalFocus() - { - return mLastWidgetWithModalFocus; - } - - void FocusHandler::setLastWidgetWithModalFocus(Widget* widget) - { - mLastWidgetWithModalFocus = widget; - } - - Widget* FocusHandler::getLastWidgetWithModalMouseInputFocus() - { - return mLastWidgetWithModalMouseInputFocus; - } - - void FocusHandler::setLastWidgetWithModalMouseInputFocus(Widget* widget) - { - mLastWidgetWithModalMouseInputFocus = widget; - } - - Widget* FocusHandler::getLastWidgetPressed() - { - return mLastWidgetPressed; - } - - void FocusHandler::setLastWidgetPressed(Widget* lastWidgetPressed) - { - mLastWidgetPressed = lastWidgetPressed; - } -} // namespace gcn diff --git a/src/gui/base/focushandler.hpp b/src/gui/base/focushandler.hpp deleted file mode 100644 index a5c1b14a1..000000000 --- a/src/gui/base/focushandler.hpp +++ /dev/null @@ -1,417 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2011-2014 The ManaPlus Developers - * - * This file is part of The ManaPlus Client. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* _______ __ __ __ ______ __ __ _______ __ __ - * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ - * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / - * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / - * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / - * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / - * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ - * - * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson - * - * - * Per Larsson a.k.a finalman - * Olof Naessén a.k.a jansem/yakslem - * - * Visit: http://guichan.sourceforge.net - * - * License: (BSD) - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of Guichan nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GCN_FOCUSHANDLER_HPP -#define GCN_FOCUSHANDLER_HPP - -#include - -#include "events/event.h" - -namespace gcn -{ - class Widget; - - /** - * Handles focus for widgets in a Gui. Each Gui has at least one - * focus handler. - * You will probably not use the focus handler directly as Widget - * has functions that automatically uses the active focus handler. - * - * @see Widget::isFocus, Widget::isModalFocused, - * Widget::isModalMouseInputFocused, Widget::requestFocus, - * Widget::requestModalFocus, Widget::requestModalMouseInputFocus, - * Widget::releaseModalFocus, Widget::relaseModalMouseInputFocus, - * Widget::setFocusable, Widget::isFocusable, FocusListener - * - * @since 0.1.0 - */ - class FocusHandler - { - public: - /** - * Constructor. - */ - FocusHandler(); - - A_DELETE_COPY(FocusHandler) - - /** - * Destructor. - */ - virtual ~FocusHandler() - { } - - /** - * Requests focus for a widget. Focus will only be granted to a widget - * if it's focusable and if no other widget has modal focus. - * If a widget receives focus a focus event will be sent to the - * focus listeners of the widget. - * - * @param widget The widget to request focus for. - * @see isFocused, Widget::requestFocus - */ - virtual void requestFocus(Widget* widget); - - /** - * Requests modal focus for a widget. Focus will only be granted - * to a widget if it's focusable and if no other widget has modal - * focus. - * - * @param widget The widget to request modal focus for. - * @throws Exception when another widget already has modal focus. - * @see releaseModalFocus, Widget::requestModalFocus - */ - virtual void requestModalFocus(Widget* widget); - - /** - * Requests modal mouse input focus for a widget. Focus will only - * be granted to a widget if it's focusable and if no other widget - * has modal mouse input focus. - * - * Modal mouse input focus means no other widget then the widget with - * modal mouse input focus will receive mouse input. The widget with - * modal mouse input focus will also receive mouse input no matter what - * the mouse input is or where the mouse input occurs. - * - * @param widget The widget to focus for modal mouse input focus. - * @throws Exception when another widget already has modal mouse input - * focus. - * @see releaseModalMouseInputFocus, Widget::requestModalMouseInputFocus - */ - virtual void requestModalMouseInputFocus(Widget* widget); - - /** - * Releases modal focus if the widget has modal focus. - * If the widget doesn't have modal focus no relase will occur. - * - * @param widget The widget to release modal focus for. - * @see reuqestModalFocus, Widget::releaseModalFocus - */ - virtual void releaseModalFocus(Widget* widget); - - /** - * Releases modal mouse input focus if the widget has modal mouse input - * focus. If the widget doesn't have modal mouse input focus no relase - * will occur. - * - * @param widget the widget to release modal mouse input focus for. - * @see requestModalMouseInputFocus, Widget::releaseModalMouseInputFocus - */ - virtual void releaseModalMouseInputFocus(Widget* widget); - - /** - * Checks if a widget is focused. - * - * @param widget The widget to check. - * @return True if the widget is focused, false otherwise. - * @see Widget::isFocused - */ - virtual bool isFocused(const Widget* widget) const; - - /** - * Gets the widget with focus. - * - * @return The widget with focus. NULL if no widget has focus. - */ - virtual Widget* getFocused() const A_WARN_UNUSED; - - /** - * Gets the widget with modal focus. - * - * @return The widget with modal focus. NULL if no widget has - * modal focus. - */ - virtual Widget* getModalFocused() const A_WARN_UNUSED; - - /** - * Gets the widget with modal mouse input focus. - * - * @return The widget with modal mouse input focus. NULL if - * no widget has modal mouse input focus. - */ - virtual Widget* getModalMouseInputFocused() const A_WARN_UNUSED; - - /** - * Focuses the next widget added to a conainer. - * If no widget has focus the first widget gets focus. The order - * in which the widgets are focused is determined by the order - * they were added to a container. - * - * @see focusPrevious - */ - virtual void focusNext(); - - /** - * Focuses the previous widget added to a contaienr. - * If no widget has focus the first widget gets focus. The order - * in which the widgets are focused is determined by the order - * they were added to a container. - * - * @see focusNext - */ - virtual void focusPrevious(); - - /** - * Adds a widget to by handles by the focus handler. - * - * @param widget The widget to add. - * @see remove - */ - virtual void add(Widget* widget); - - /** - * Removes a widget from the focus handler. - * - * @param widget The widget to remove. - * @see add - */ - virtual void remove(Widget* widget); - - /** - * Focuses nothing. A focus event will also be sent to the - * focused widget's focus listeners if a widget has focus. - */ - virtual void focusNone(); - - /** - * Focuses the next widget which allows tabbing in unless - * the current focused Widget disallows tabbing out. - * - * @see tabPrevious - */ - virtual void tabNext(); - - /** - * Focuses the previous widget which allows tabbing in unless - * current focused widget disallows tabbing out. - * - * @see tabNext - */ - virtual void tabPrevious(); - - /** - * Gets the widget being dragged. Used by the Gui class to - * keep track of the dragged widget. - * - * @return the widget being dragged. - * @see setDraggedWidget - */ - virtual Widget* getDraggedWidget() A_WARN_UNUSED; - - /** - * Sets the widget being dragged. Used by the Gui class to - * keep track of the dragged widget. - * - * @param draggedWidget The widget being dragged. - * @see getDraggedWidget - */ - virtual void setDraggedWidget(Widget* draggedWidget); - - /** - * Gets the last widget with the mouse. Used by the Gui class - * to keep track the last widget with the mouse. - * - * @return The last widget with the mouse. - * @see setLastWidgetWithMouse - */ - virtual Widget* getLastWidgetWithMouse() A_WARN_UNUSED; - - /** - * Sets the last widget with the mouse. Used by the Gui class - * to keep track the last widget with the mouse. - * - * @param lastWidgetWithMouse The last widget with the mouse. - * @see getLastWidgetWithMouse - */ - virtual void setLastWidgetWithMouse(Widget* lastWidgetWithMouse); - - /** - * Gets the last widget with modal focus. - * - * @return The last widget with modal focus. - * @see setLastWidgetWithModalFocus - */ - virtual Widget* getLastWidgetWithModalFocus() A_WARN_UNUSED; - - /** - * Sets the last widget with modal focus. - * - * @param widget The last widget with modal focus. - * @see getLastWidgetWithModalFocus - */ - virtual void setLastWidgetWithModalFocus(Widget* widget); - - /** - * Gets the last widget with modal mouse input focus. - * - * @return The last widget with modal mouse input focus. - * @see setLastWidgetWithModalMouseInputFocus - */ - virtual Widget* getLastWidgetWithModalMouseInputFocus() A_WARN_UNUSED; - - /** - * Sets the last widget with modal mouse input focus. - * - * @param widget The last widget with modal mouse input focus. - * @see getLastWidgetWithModalMouseInputFocus - */ - virtual void setLastWidgetWithModalMouseInputFocus(Widget* widget); - - /** - * Gets the last widget pressed. Used by the Gui class to keep track - * of pressed widgets. - * - * @return The last widget pressed. - * @see setLastWidgetPressed - */ - virtual Widget* getLastWidgetPressed() A_WARN_UNUSED; - - /** - * Sets the last widget pressed. Used by the Gui class to keep track - * of pressed widgets. - * - * @param lastWidgetPressed The last widget pressed. - * @see getLastWidgetPressed - */ - virtual void setLastWidgetPressed(Widget* lastWidgetPressed); - - protected: - /** - * Distributes a focus lost event. - * - * @param focusEvent the event to distribute. - * @since 0.7.0 - */ - virtual void distributeFocusLostEvent(const Event& focusEvent); - - /** - * Distributes a focus gained event. - * - * @param focusEvent the event to distribute. - * @since 0.7.0 - */ - virtual void distributeFocusGainedEvent(const Event& focusEvent); - - /** - * Typedef. - */ - typedef std::vector WidgetVector; - - /** - * Typedef. - */ - typedef WidgetVector::iterator WidgetIterator; - - /** - * Holds the widgets currently being handled by the - * focus handler. - */ - WidgetVector mWidgets; - - /** - * Holds the focused widget. NULL if no widget has focus. - */ - Widget* mFocusedWidget; - - /** - * Holds the modal focused widget. NULL if no widget has - * modal focused. - */ - Widget* mModalFocusedWidget; - - /** - * Holds the modal mouse input focused widget. NULL if no widget - * is being dragged. - */ - Widget* mModalMouseInputFocusedWidget; - - /** - * Holds the dragged widget. NULL if no widget is - * being dragged. - */ - Widget* mDraggedWidget; - - /** - * Holds the last widget with the mouse. - */ - Widget* mLastWidgetWithMouse; - - /** - * Holds the last widget with modal focus. - */ - Widget* mLastWidgetWithModalFocus; - - /** - * Holds the last widget with modal mouse input focus. - */ - Widget* mLastWidgetWithModalMouseInputFocus; - - /** - * Holds the last widget pressed. - */ - Widget* mLastWidgetPressed; - }; -} // namespace gcn - -#endif // end GCN_FOCUSHANDLER_HPP diff --git a/src/gui/base/gui.cpp b/src/gui/base/gui.cpp index 02c6e6674..f62e24260 100644 --- a/src/gui/base/gui.cpp +++ b/src/gui/base/gui.cpp @@ -68,9 +68,9 @@ #include "gui/base/gui.hpp" #include "gui/base/basiccontainer.hpp" -#include "gui/base/focushandler.hpp" #include "gui/base/widget.hpp" +#include "gui/focushandler.h" #include "gui/sdlinput.h" #include "input/keyinput.h" diff --git a/src/gui/base/gui.hpp b/src/gui/base/gui.hpp index 6e6a3867d..f614c00fd 100644 --- a/src/gui/base/gui.hpp +++ b/src/gui/base/gui.hpp @@ -72,13 +72,13 @@ #include "input/mouseinput.h" +class FocusHandler; class Graphics; class KeyListener; class SDLInput; namespace gcn { - class FocusHandler; class Widget; // The following comment will appear in the doxygen main page. diff --git a/src/gui/base/widget.cpp b/src/gui/base/widget.cpp index 5b4ada76e..9e2912d39 100644 --- a/src/gui/base/widget.cpp +++ b/src/gui/base/widget.cpp @@ -72,7 +72,8 @@ #include "events/event.h" #include "gui/base/basiccontainer.hpp" -#include "gui/base/focushandler.hpp" + +#include "gui/focushandler.h" #include "input/keyinput.h" #include "input/mouseinput.h" diff --git a/src/gui/base/widget.hpp b/src/gui/base/widget.hpp index f2718697e..1c1c0ae14 100644 --- a/src/gui/base/widget.hpp +++ b/src/gui/base/widget.hpp @@ -75,6 +75,7 @@ class ActionListener; class DeathListener; +class FocusHandler; class FocusListener; class Font; class Graphics; @@ -87,7 +88,6 @@ class WidgetListener; namespace gcn { class BasicContainer; - class FocusHandler; /** * Abstract class for widgets of Guichan. It contains basic functions diff --git a/src/gui/focushandler.cpp b/src/gui/focushandler.cpp index 04cb3f555..22153c91f 100644 --- a/src/gui/focushandler.cpp +++ b/src/gui/focushandler.cpp @@ -20,6 +20,49 @@ * along with this program. If not, see . */ +/* _______ __ __ __ ______ __ __ _______ __ __ + * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ + * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / + * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / + * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / + * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / + * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ + * + * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson + * + * + * Per Larsson a.k.a finalman + * Olof Naessén a.k.a jansem/yakslem + * + * Visit: http://guichan.sourceforge.net + * + * License: (BSD) + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Guichan nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include "gui/focushandler.h" #include "gui/gui.h" @@ -28,6 +71,20 @@ #include "debug.h" +FocusHandler::FocusHandler() : + mWidgets(), + mFocusedWidget(nullptr), + mModalFocusedWidget(nullptr), + mModalMouseInputFocusedWidget(nullptr), + mDraggedWidget(nullptr), + mLastWidgetWithMouse(nullptr), + mLastWidgetWithModalFocus(nullptr), + mLastWidgetWithModalMouseInputFocus(nullptr), + mLastWidgetPressed(nullptr), + mModalStack() +{ +} + void FocusHandler::requestModalFocus(gcn::Widget *widget) { /* If there is another widget with modal focus, remove its modal focus @@ -39,7 +96,9 @@ void FocusHandler::requestModalFocus(gcn::Widget *widget) mModalFocusedWidget = nullptr; } - gcn::FocusHandler::requestModalFocus(widget); + mModalFocusedWidget = widget; + if (mFocusedWidget && !mFocusedWidget->isModalFocused()) + focusNone(); } void FocusHandler::releaseModalFocus(gcn::Widget *widget) @@ -48,14 +107,15 @@ void FocusHandler::releaseModalFocus(gcn::Widget *widget) if (mModalFocusedWidget == widget) { - gcn::FocusHandler::releaseModalFocus(widget); + if (mModalFocusedWidget == widget) + mModalFocusedWidget = nullptr; /* Check if there were any previously modal widgets that'd still like * to regain their modal focus. */ if (!mModalStack.empty()) { - gcn::FocusHandler::requestModalFocus(mModalStack.front()); + requestModalFocus(mModalStack.front()); mModalStack.pop_front(); } } @@ -65,19 +125,188 @@ void FocusHandler::remove(gcn::Widget *widget) { releaseModalFocus(widget); - gcn::FocusHandler::remove(widget); + if (isFocused(widget)) + mFocusedWidget = nullptr; + + for (WidgetIterator iter = mWidgets.begin(); + iter != mWidgets.end(); ++iter) + { + if ((*iter) == widget) + { + mWidgets.erase(iter); + break; + } + } + + if (mDraggedWidget == widget) + { + mDraggedWidget = nullptr; + return; + } + + if (mLastWidgetWithMouse == widget) + { + mLastWidgetWithMouse = nullptr; + return; + } + + if (mLastWidgetWithModalFocus == widget) + { + mLastWidgetWithModalFocus = nullptr; + return; + } + + if (mLastWidgetWithModalMouseInputFocus == widget) + { + mLastWidgetWithModalMouseInputFocus = nullptr; + return; + } + + if (mLastWidgetPressed == widget) + { + mLastWidgetPressed = nullptr; + return; + } } void FocusHandler::tabNext() { - gcn::FocusHandler::tabNext(); + if (mFocusedWidget) + { + if (!mFocusedWidget->isTabOutEnabled()) + return; + } + + if (mWidgets.empty()) + { + mFocusedWidget = nullptr; + return; + } + + int i; + int focusedWidget = -1; + const int sz = static_cast(mWidgets.size()); + for (i = 0; i < sz; ++ i) + { + if (mWidgets[i] == mFocusedWidget) + focusedWidget = i; + } + const int focused = focusedWidget; + bool done = false; + + // i is a counter that ensures that the following loop + // won't get stuck in an infinite loop + i = sz; + do + { + ++ focusedWidget; + + if (i == 0) + { + focusedWidget = -1; + break; + } + + -- i; + + if (focusedWidget >= sz) + focusedWidget = 0; + + if (focusedWidget == focused) + return; + + const gcn::Widget *const widget = mWidgets.at(focusedWidget); + if (widget->isFocusable() && widget->isTabInEnabled() && + (!mModalFocusedWidget || widget->isModalFocused())) + { + done = true; + } + } + while (!done); + + if (focusedWidget >= 0) + { + mFocusedWidget = mWidgets.at(focusedWidget); + Event focusEvent(mFocusedWidget); + distributeFocusGainedEvent(focusEvent); + } + + if (focused >= 0) + { + Event focusEvent(mWidgets.at(focused)); + distributeFocusLostEvent(focusEvent); + } checkForWindow(); } void FocusHandler::tabPrevious() { - gcn::FocusHandler::tabPrevious(); + if (mFocusedWidget) + { + if (!mFocusedWidget->isTabOutEnabled()) + return; + } + + if (mWidgets.empty()) + { + mFocusedWidget = nullptr; + return; + } + + int i; + int focusedWidget = -1; + const int sz = static_cast(mWidgets.size()); + for (i = 0; i < sz; ++ i) + { + if (mWidgets[i] == mFocusedWidget) + focusedWidget = i; + } + const int focused = focusedWidget; + bool done = false; + + // i is a counter that ensures that the following loop + // won't get stuck in an infinite loop + i = sz; + do + { + -- focusedWidget; + + if (i == 0) + { + focusedWidget = -1; + break; + } + + -- i; + + if (focusedWidget <= 0) + focusedWidget = sz - 1; + + if (focusedWidget == focused) + return; + + const gcn::Widget *const widget = mWidgets.at(focusedWidget); + if (widget->isFocusable() && widget->isTabInEnabled() && + (!mModalFocusedWidget || widget->isModalFocused())) + { + done = true; + } + } + while (!done); + + if (focusedWidget >= 0) + { + mFocusedWidget = mWidgets.at(focusedWidget); + Event focusEvent(mFocusedWidget); + distributeFocusGainedEvent(focusEvent); + } + + if (focused >= 0) + { + Event focusEvent(mWidgets.at(focused)); + distributeFocusLostEvent(focusEvent); + } checkForWindow(); } @@ -107,5 +336,280 @@ void FocusHandler::distributeFocusGainedEvent(const Event &focusEvent) { if (gui) gui->distributeGlobalFocusGainedEvent(focusEvent); - gcn::FocusHandler::distributeFocusGainedEvent(focusEvent); + + gcn::Widget *const sourceWidget = focusEvent.getSource(); + + std::list focusListeners + = sourceWidget->_getFocusListeners(); + + // Send the event to all focus listeners of the widget. + for (std::list::const_iterator + it = focusListeners.begin(); + it != focusListeners.end(); + ++ it) + { + (*it)->focusGained(focusEvent); + } +} + +void FocusHandler::requestFocus(gcn::Widget* widget) +{ + if (!widget || widget == mFocusedWidget) + return; + + int toBeFocusedIndex = -1; + for (unsigned int i = 0, sz = static_cast( + mWidgets.size()); i < sz; ++i) + { + if (mWidgets[i] == widget) + { + toBeFocusedIndex = i; + break; + } + } + + if (toBeFocusedIndex < 0) + return; + + gcn::Widget *const oldFocused = mFocusedWidget; + + if (oldFocused != widget) + { + mFocusedWidget = mWidgets.at(toBeFocusedIndex); + + if (oldFocused) + { + Event focusEvent(oldFocused); + distributeFocusLostEvent(focusEvent); + } + + Event focusEvent(mWidgets.at(toBeFocusedIndex)); + distributeFocusGainedEvent(focusEvent); + } +} + +void FocusHandler::requestModalMouseInputFocus(gcn::Widget* widget) +{ + if (mModalMouseInputFocusedWidget + && mModalMouseInputFocusedWidget != widget) + { + return; + } + + mModalMouseInputFocusedWidget = widget; +} + +void FocusHandler::releaseModalMouseInputFocus(gcn::Widget* widget) +{ + if (mModalMouseInputFocusedWidget == widget) + mModalMouseInputFocusedWidget = nullptr; +} + +gcn::Widget* FocusHandler::getFocused() const +{ + return mFocusedWidget; +} + +gcn::Widget* FocusHandler::getModalFocused() const +{ + return mModalFocusedWidget; +} + +gcn::Widget* FocusHandler::getModalMouseInputFocused() const +{ + return mModalMouseInputFocusedWidget; +} + +void FocusHandler::focusNext() +{ + int i; + int focusedWidget = -1; + const int sz = static_cast(mWidgets.size()); + for (i = 0; i < sz; ++i) + { + if (mWidgets[i] == mFocusedWidget) + focusedWidget = i; + } + const int focused = focusedWidget; + + // i is a counter that ensures that the following loop + // won't get stuck in an infinite loop + i = sz; + do + { + ++ focusedWidget; + + if (i == 0) + { + focusedWidget = -1; + break; + } + + -- i; + + if (focusedWidget >= sz) + focusedWidget = 0; + + if (focusedWidget == focused) + return; + } + while (!mWidgets.at(focusedWidget)->isFocusable()); + + if (focusedWidget >= 0) + { + mFocusedWidget = mWidgets.at(focusedWidget); + + Event focusEvent(mFocusedWidget); + distributeFocusGainedEvent(focusEvent); + } + + if (focused >= 0) + { + Event focusEvent(mWidgets.at(focused)); + distributeFocusLostEvent(focusEvent); + } +} + +void FocusHandler::focusPrevious() +{ + if (mWidgets.empty()) + { + mFocusedWidget = nullptr; + return; + } + + int i; + int focusedWidget = -1; + const int sz = static_cast(mWidgets.size()); + for (i = 0; i < sz; ++ i) + { + if (mWidgets[i] == mFocusedWidget) + focusedWidget = i; + } + const int focused = focusedWidget; + + // i is a counter that ensures that the following loop + // won't get stuck in an infinite loop + i = sz; + do + { + -- focusedWidget; + + if (i == 0) + { + focusedWidget = -1; + break; + } + + -- i; + + if (focusedWidget <= 0) + focusedWidget = sz - 1; + + if (focusedWidget == focused) + return; + } + while (!mWidgets.at(focusedWidget)->isFocusable()); + + if (focusedWidget >= 0) + { + mFocusedWidget = mWidgets.at(focusedWidget); + Event focusEvent(mFocusedWidget); + distributeFocusGainedEvent(focusEvent); + } + + if (focused >= 0) + { + Event focusEvent(mWidgets.at(focused)); + distributeFocusLostEvent(focusEvent); + } +} + +bool FocusHandler::isFocused(const gcn::Widget* widget) const +{ + return mFocusedWidget == widget; +} + +void FocusHandler::add(gcn::Widget* widget) +{ + mWidgets.push_back(widget); +} + +void FocusHandler::focusNone() +{ + if (mFocusedWidget) + { + gcn::Widget *const focused = mFocusedWidget; + mFocusedWidget = nullptr; + + Event focusEvent(focused); + distributeFocusLostEvent(focusEvent); + } +} + +void FocusHandler::distributeFocusLostEvent(const Event& focusEvent) +{ + gcn::Widget *const sourceWidget = focusEvent.getSource(); + + std::list focusListeners + = sourceWidget->_getFocusListeners(); + + // Send the event to all focus listeners of the widget. + for (std::list::const_iterator + it = focusListeners.begin(); + it != focusListeners.end(); + ++ it) + { + (*it)->focusLost(focusEvent); + } +} + +gcn::Widget* FocusHandler::getDraggedWidget() +{ + return mDraggedWidget; +} + +void FocusHandler::setDraggedWidget(gcn::Widget* draggedWidget) +{ + mDraggedWidget = draggedWidget; +} + +gcn::Widget* FocusHandler::getLastWidgetWithMouse() +{ + return mLastWidgetWithMouse; +} + +void FocusHandler::setLastWidgetWithMouse(gcn::Widget* lastWidgetWithMouse) +{ + mLastWidgetWithMouse = lastWidgetWithMouse; +} + +gcn::Widget* FocusHandler::getLastWidgetWithModalFocus() +{ + return mLastWidgetWithModalFocus; +} + +void FocusHandler::setLastWidgetWithModalFocus(gcn::Widget* widget) +{ + mLastWidgetWithModalFocus = widget; +} + +gcn::Widget* FocusHandler::getLastWidgetWithModalMouseInputFocus() +{ + return mLastWidgetWithModalMouseInputFocus; +} + +void FocusHandler::setLastWidgetWithModalMouseInputFocus(gcn::Widget* widget) +{ + mLastWidgetWithModalMouseInputFocus = widget; +} + +gcn::Widget* FocusHandler::getLastWidgetPressed() +{ + return mLastWidgetPressed; +} + +void FocusHandler::setLastWidgetPressed(gcn::Widget* lastWidgetPressed) +{ + mLastWidgetPressed = lastWidgetPressed; } diff --git a/src/gui/focushandler.h b/src/gui/focushandler.h index 0e07625b7..0131a4c29 100644 --- a/src/gui/focushandler.h +++ b/src/gui/focushandler.h @@ -20,59 +20,311 @@ * along with this program. If not, see . */ +/* _______ __ __ __ ______ __ __ _______ __ __ + * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ + * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / + * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / + * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / + * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / + * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ + * + * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson + * + * + * Per Larsson a.k.a finalman + * Olof Naessén a.k.a jansem/yakslem + * + * Visit: http://guichan.sourceforge.net + * + * License: (BSD) + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Guichan nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #ifndef GUI_FOCUSHANDLER_H #define GUI_FOCUSHANDLER_H -#include "gui/base/focushandler.hpp" +#include "gui/focushandler.h" + +#include "events/event.h" #include +#include #include "localconsts.h" +namespace gcn +{ + class Widget; +} + /** * The focus handler. This focus handler does exactly the same as the Guichan * focus handler, but keeps a stack of modal widgets to be able to handle * multiple modal focus requests. */ -class FocusHandler final : public gcn::FocusHandler +class FocusHandler final { public: - FocusHandler() : - mModalStack() - { } + FocusHandler(); A_DELETE_COPY(FocusHandler) /** - * Sets modal focus to a widget. When there is already a modal widget - * then that widget loses modal focus and will regain it after this - * widget releases his modal focus. - */ - void requestModalFocus(gcn::Widget *widget) override final; + * Requests focus for a widget. Focus will only be granted to a widget + * if it's focusable and if no other widget has modal focus. + * If a widget receives focus a focus event will be sent to the + * focus listeners of the widget. + * + * @param widget The widget to request focus for. + * @see isFocused, Widget::requestFocus + */ + void requestFocus(gcn::Widget* widget); /** - * Releases modal focus of a widget. When this widget had modal focus - * and there are other widgets that had also requested modal focus, - * then modal focus will be transfered to the last of those. - */ - void releaseModalFocus(gcn::Widget *widget) override final; + * Requests modal focus for a widget. Focus will only be granted + * to a widget if it's focusable and if no other widget has modal + * focus. + * + * @param widget The widget to request modal focus for. + * @throws Exception when another widget already has modal focus. + * @see releaseModalFocus, Widget::requestModalFocus + */ + void requestModalFocus(gcn::Widget* widget); /** - * Removes a widget from the focus handler. Also makes sure no dangling - * pointers remain in modal focus stack. - */ - void remove(gcn::Widget *widget) override final; + * Requests modal mouse input focus for a widget. Focus will only + * be granted to a widget if it's focusable and if no other widget + * has modal mouse input focus. + * + * Modal mouse input focus means no other widget then the widget with + * modal mouse input focus will receive mouse input. The widget with + * modal mouse input focus will also receive mouse input no matter what + * the mouse input is or where the mouse input occurs. + * + * @param widget The widget to focus for modal mouse input focus. + * @throws Exception when another widget already has modal mouse input + * focus. + * @see releaseModalMouseInputFocus, Widget::requestModalMouseInputFocus + */ + void requestModalMouseInputFocus(gcn::Widget* widget); /** - * Overloaded to allow windows to move to the top when one of their - * widgets is tabbed to when tabbing through focusable elements. - */ - void tabNext() override final; + * Releases modal focus if the widget has modal focus. + * If the widget doesn't have modal focus no relase will occur. + * + * @param widget The widget to release modal focus for. + * @see reuqestModalFocus, Widget::releaseModalFocus + */ + void releaseModalFocus(gcn::Widget* widget); + + /** + * Releases modal mouse input focus if the widget has modal mouse input + * focus. If the widget doesn't have modal mouse input focus no relase + * will occur. + * + * @param widget the widget to release modal mouse input focus for. + * @see requestModalMouseInputFocus, Widget::releaseModalMouseInputFocus + */ + void releaseModalMouseInputFocus(gcn::Widget* widget); + + /** + * Checks if a widget is focused. + * + * @param widget The widget to check. + * @return True if the widget is focused, false otherwise. + * @see Widget::isFocused + */ + bool isFocused(const gcn::Widget* widget) const; + + /** + * Gets the widget with focus. + * + * @return The widget with focus. NULL if no widget has focus. + */ + gcn::Widget* getFocused() const A_WARN_UNUSED; + + /** + * Gets the widget with modal focus. + * + * @return The widget with modal focus. NULL if no widget has + * modal focus. + */ + gcn::Widget* getModalFocused() const A_WARN_UNUSED; + + /** + * Gets the widget with modal mouse input focus. + * + * @return The widget with modal mouse input focus. NULL if + * no widget has modal mouse input focus. + */ + gcn::Widget* getModalMouseInputFocused() const A_WARN_UNUSED; + + /** + * Focuses the next widget added to a conainer. + * If no widget has focus the first widget gets focus. The order + * in which the widgets are focused is determined by the order + * they were added to a container. + * + * @see focusPrevious + */ + void focusNext(); + + /** + * Focuses the previous widget added to a contaienr. + * If no widget has focus the first widget gets focus. The order + * in which the widgets are focused is determined by the order + * they were added to a container. + * + * @see focusNext + */ + void focusPrevious(); + + /** + * Adds a widget to by handles by the focus handler. + * + * @param widget The widget to add. + * @see remove + */ + void add(gcn::Widget* widget); + + /** + * Removes a widget from the focus handler. + * + * @param widget The widget to remove. + * @see add + */ + void remove(gcn::Widget* widget); + + /** + * Focuses nothing. A focus event will also be sent to the + * focused widget's focus listeners if a widget has focus. + */ + void focusNone(); + + /** + * Focuses the next widget which allows tabbing in unless + * the current focused Widget disallows tabbing out. + * + * @see tabPrevious + */ + void tabNext(); + + /** + * Focuses the previous widget which allows tabbing in unless + * current focused widget disallows tabbing out. + * + * @see tabNext + */ + void tabPrevious(); + + /** + * Gets the widget being dragged. Used by the Gui class to + * keep track of the dragged widget. + * + * @return the widget being dragged. + * @see setDraggedWidget + */ + gcn::Widget* getDraggedWidget() A_WARN_UNUSED; + + /** + * Sets the widget being dragged. Used by the Gui class to + * keep track of the dragged widget. + * + * @param draggedWidget The widget being dragged. + * @see getDraggedWidget + */ + void setDraggedWidget(gcn::Widget* draggedWidget); + + /** + * Gets the last widget with the mouse. Used by the Gui class + * to keep track the last widget with the mouse. + * + * @return The last widget with the mouse. + * @see setLastWidgetWithMouse + */ + gcn::Widget* getLastWidgetWithMouse() A_WARN_UNUSED; + + /** + * Sets the last widget with the mouse. Used by the Gui class + * to keep track the last widget with the mouse. + * + * @param lastWidgetWithMouse The last widget with the mouse. + * @see getLastWidgetWithMouse + */ + void setLastWidgetWithMouse(gcn::Widget* lastWidgetWithMouse); + + /** + * Gets the last widget with modal focus. + * + * @return The last widget with modal focus. + * @see setLastWidgetWithModalFocus + */ + gcn::Widget* getLastWidgetWithModalFocus() A_WARN_UNUSED; + + /** + * Sets the last widget with modal focus. + * + * @param widget The last widget with modal focus. + * @see getLastWidgetWithModalFocus + */ + void setLastWidgetWithModalFocus(gcn::Widget* widget); + + /** + * Gets the last widget with modal mouse input focus. + * + * @return The last widget with modal mouse input focus. + * @see setLastWidgetWithModalMouseInputFocus + */ + gcn::Widget* getLastWidgetWithModalMouseInputFocus() A_WARN_UNUSED; + + /** + * Sets the last widget with modal mouse input focus. + * + * @param widget The last widget with modal mouse input focus. + * @see getLastWidgetWithModalMouseInputFocus + */ + void setLastWidgetWithModalMouseInputFocus(gcn::Widget* widget); - void tabPrevious() override final; + /** + * Gets the last widget pressed. Used by the Gui class to keep track + * of pressed widgets. + * + * @return The last widget pressed. + * @see setLastWidgetPressed + */ + gcn::Widget* getLastWidgetPressed() A_WARN_UNUSED; - void distributeFocusGainedEvent(const Event &focusEvent) - override final; + /** + * Sets the last widget pressed. Used by the Gui class to keep track + * of pressed widgets. + * + * @param lastWidgetPressed The last widget pressed. + * @see getLastWidgetPressed + */ + void setLastWidgetPressed(gcn::Widget* lastWidgetPressed); private: /** @@ -81,6 +333,81 @@ class FocusHandler final : public gcn::FocusHandler */ void checkForWindow() const; + /** + * Distributes a focus lost event. + * + * @param focusEvent the event to distribute. + * @since 0.7.0 + */ + void distributeFocusLostEvent(const Event& focusEvent); + + /** + * Distributes a focus gained event. + * + * @param focusEvent the event to distribute. + * @since 0.7.0 + */ + void distributeFocusGainedEvent(const Event& focusEvent); + + /** + * Typedef. + */ + typedef std::vector WidgetVector; + + /** + * Typedef. + */ + typedef WidgetVector::iterator WidgetIterator; + + /** + * Holds the widgets currently being handled by the + * focus handler. + */ + WidgetVector mWidgets; + + /** + * Holds the focused widget. NULL if no widget has focus. + */ + gcn::Widget* mFocusedWidget; + + /** + * Holds the modal focused widget. NULL if no widget has + * modal focused. + */ + gcn::Widget* mModalFocusedWidget; + + /** + * Holds the modal mouse input focused widget. NULL if no widget + * is being dragged. + */ + gcn::Widget* mModalMouseInputFocusedWidget; + + /** + * Holds the dragged widget. NULL if no widget is + * being dragged. + */ + gcn::Widget* mDraggedWidget; + + /** + * Holds the last widget with the mouse. + */ + gcn::Widget* mLastWidgetWithMouse; + + /** + * Holds the last widget with modal focus. + */ + gcn::Widget* mLastWidgetWithModalFocus; + + /** + * Holds the last widget with modal mouse input focus. + */ + gcn::Widget* mLastWidgetWithModalMouseInputFocus; + + /** + * Holds the last widget pressed. + */ + gcn::Widget* mLastWidgetPressed; + /** * Stack of widgets that have requested modal forcus. */ diff --git a/src/gui/gui.h b/src/gui/gui.h index b790d4d2c..aacd33946 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -90,7 +90,7 @@ class Gui final : public gcn::Gui */ void videoResized() const; - gcn::FocusHandler *getFocusHandler() const A_WARN_UNUSED + FocusHandler *getFocusHandler() const A_WARN_UNUSED { return mFocusHandler; } /** diff --git a/src/gui/widgets/guitable.cpp b/src/gui/widgets/guitable.cpp index f87ca2fe7..1b1124cff 100644 --- a/src/gui/widgets/guitable.cpp +++ b/src/gui/widgets/guitable.cpp @@ -588,7 +588,7 @@ int GuiTable::getColumnForX(int x) const return column; } -void GuiTable::_setFocusHandler(gcn::FocusHandler* focusHandler) +void GuiTable::_setFocusHandler(FocusHandler* focusHandler) { // add check for focusHandler. may be need remove it? diff --git a/src/gui/widgets/guitable.h b/src/gui/widgets/guitable.h index da367dd94..ab7dc1a66 100644 --- a/src/gui/widgets/guitable.h +++ b/src/gui/widgets/guitable.h @@ -122,7 +122,7 @@ public: void moveToBottom(gcn::Widget *child) override final; - void _setFocusHandler(gcn::FocusHandler* focusHandler) override final; + void _setFocusHandler(FocusHandler* focusHandler) override final; // Inherited from KeyListener void keyPressed(KeyEvent& keyEvent) override final; diff --git a/src/gui/widgets/listbox.cpp b/src/gui/widgets/listbox.cpp index 537c7283c..c2fa1a686 100644 --- a/src/gui/widgets/listbox.cpp +++ b/src/gui/widgets/listbox.cpp @@ -28,10 +28,10 @@ #include "input/keydata.h" +#include "gui/focushandler.h" #include "gui/font.h" #include "gui/gui.h" -#include "gui/base/focushandler.hpp" #include "gui/base/listmodel.hpp" #include "render/graphics.h" diff --git a/src/gui/widgets/window.cpp b/src/gui/widgets/window.cpp index e2f24a0f2..2ea86f9df 100644 --- a/src/gui/widgets/window.cpp +++ b/src/gui/widgets/window.cpp @@ -29,6 +29,7 @@ #include "soundconsts.h" #include "soundmanager.h" +#include "gui/focushandler.h" #include "gui/font.h" #include "gui/gui.h" #include "gui/viewport.h" @@ -38,8 +39,6 @@ #include "resources/cursor.h" #include "resources/image.h" -#include "gui/base/focushandler.hpp" - #include "debug.h" const int resizeMask = 8 + 4 + 2 + 1; diff --git a/src/gui/windows/chatwindow.cpp b/src/gui/windows/chatwindow.cpp index e49c78803..45a76495b 100644 --- a/src/gui/windows/chatwindow.cpp +++ b/src/gui/windows/chatwindow.cpp @@ -39,6 +39,7 @@ #include "input/inputmanager.h" +#include "gui/focushandler.h" #include "gui/font.h" #include "gui/sdlinput.h" #include "gui/viewport.h" @@ -69,8 +70,6 @@ #include "resources/resourcemanager.h" -#include "gui/base/focushandler.hpp" - #include #include diff --git a/src/input/inputmanager.cpp b/src/input/inputmanager.cpp index 46494532a..d19130e7c 100644 --- a/src/input/inputmanager.cpp +++ b/src/input/inputmanager.cpp @@ -51,7 +51,7 @@ #include "utils/timer.h" -#include "gui/base/focushandler.hpp" +#include "gui/focushandler.h" #include -- cgit v1.2.3-70-g09d2