diff options
Diffstat (limited to 'src/gui/gui.cpp')
-rw-r--r-- | src/gui/gui.cpp | 1515 |
1 files changed, 0 insertions, 1515 deletions
diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp deleted file mode 100644 index 3fab73d0a..000000000 --- a/src/gui/gui.cpp +++ /dev/null @@ -1,1515 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2004-2009 The Mana World Development Team - * Copyright (C) 2009-2010 The Mana Developers - * Copyright (C) 2011-2017 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 <http://www.gnu.org/licenses/>. - */ - -/* _______ __ __ __ ______ __ __ _______ __ __ - * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ - * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / - * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / - * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / - * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / - * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ - * - * 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/gui.h" - -#include "gui/focushandler.h" -#include "gui/sdlinput.h" -#include "gui/viewport.h" - -#include "gui/fonts/font.h" - -#include "gui/widgets/label.h" -#include "gui/widgets/window.h" - -#include "gui/widgets/tabs/tab.h" - -#ifndef DYECMD -#include "dragdrop.h" -#else // DYECMD -#include "resources/image/image.h" -#endif // DYECMD -#include "settings.h" - -#include "listeners/focuslistener.h" -#include "listeners/guiconfiglistener.h" -#include "listeners/keylistener.h" - -#include "input/inputmanager.h" - -#include "input/touch/touchmanager.h" - -#include "render/renderers.h" - -#include "resources/imageset.h" - -#include "resources/resourcemanager/resourcemanager.h" - -#include "utils/delete2.h" -#include "utils/foreach.h" -#include "utils/langs.h" -#include "utils/sdlsharedhelper.h" -#include "utils/timer.h" - -#include "net/ipc.h" - -#include "debug.h" - -Gui *gui = nullptr; -Font *boldFont = nullptr; - -Gui::Gui() : - mTop(nullptr), - mGraphics(nullptr), - mInput(nullptr), - mFocusHandler(new FocusHandler), - mKeyListeners(), - mLastMousePressButton(MouseButton::EMPTY), - mLastMousePressTimeStamp(0U), - mLastMouseX(0), - mLastMouseY(0), - mClickCount(1), - mLastMouseDragButton(MouseButton::EMPTY), - mWidgetWithMouseQueue(), - mConfigListener(new GuiConfigListener(this)), - mGuiFont(nullptr), - mInfoParticleFont(nullptr), - mHelpFont(nullptr), - mSecureFont(nullptr), - mNpcFont(nullptr), - mMouseCursors(nullptr), - mMouseCursorAlpha(1.0F), - mMouseInactivityTimer(0), - mCursorType(Cursor::CURSOR_POINTER), -#ifdef ANDROID - mLastMouseRealX(0), - mLastMouseRealY(0), -#endif // ANDROID - mFocusListeners(), - mForegroundColor(theme->getColor(ThemeColorId::TEXT, 255)), - mForegroundColor2(theme->getColor(ThemeColorId::TEXT_OUTLINE, 255)), - mTime(0), - mTime10(0), - mCustomCursor(false), - mDoubleClick(true) -{ -} - -void Gui::postInit(Graphics *const graphics) -{ - logger->log1("Initializing GUI..."); - // Set graphics - setGraphics(graphics); - - // Set input - guiInput = new SDLInput; - setInput(guiInput); - - // Set focus handler - delete mFocusHandler; - mFocusHandler = new FocusHandler; - - // Initialize top GUI widget - WindowContainer *const guiTop = new WindowContainer(nullptr); - guiTop->setFocusable(true); - guiTop->setSize(graphics->mWidth, graphics->mHeight); - guiTop->setOpaque(Opaque_false); - Window::setWindowContainer(guiTop); - setTop(guiTop); - - const StringVect langs = getLang(); - const bool isJapan = (!langs.empty() && langs[0].size() > 3 - && langs[0].substr(0, 3) == "ja_"); - const bool isChinese = (!langs.empty() && langs[0].size() > 3 - && langs[0].substr(0, 3) == "zh_"); - - // Set global font - const int fontSize = config.getIntValue("fontSize"); - std::string fontFile = config.getValue("font", ""); - if (isJapan) - { - fontFile = config.getValue("japanFont", ""); - if (fontFile.empty()) - fontFile = branding.getStringValue("japanFont"); - } - else if (isChinese) - { - fontFile = config.getValue("chinaFont", ""); - if (fontFile.empty()) - fontFile = branding.getStringValue("chinaFont"); - } - if (fontFile.empty()) - fontFile = branding.getStringValue("font"); - - mGuiFont = new Font(fontFile, fontSize, TTF_STYLE_NORMAL); - - // Set particle font - fontFile = config.getValue("particleFont", ""); - if (isJapan) - { - fontFile = config.getValue("japanFont", ""); - if (fontFile.empty()) - fontFile = branding.getStringValue("japanFont"); - } - else if (isChinese) - { - fontFile = config.getValue("chinaFont", ""); - if (fontFile.empty()) - fontFile = branding.getStringValue("chinaFont"); - } - if (fontFile.empty()) - fontFile = branding.getStringValue("particleFont"); - - mInfoParticleFont = new Font(fontFile, fontSize, TTF_STYLE_BOLD); - - // Set bold font - fontFile = config.getValue("boldFont", ""); - if (fontFile.empty()) - fontFile = branding.getStringValue("boldFont"); - - boldFont = new Font(fontFile, fontSize, TTF_STYLE_NORMAL); - - // Set help font - fontFile = config.getValue("helpFont", ""); - if (fontFile.empty()) - fontFile = branding.getStringValue("helpFont"); - - mHelpFont = new Font(fontFile, fontSize, TTF_STYLE_NORMAL); - - // Set secure font - fontFile = config.getValue("secureFont", ""); - if (fontFile.empty()) - fontFile = branding.getStringValue("secureFont"); - - mSecureFont = new Font(fontFile, fontSize, TTF_STYLE_NORMAL); - - // Set npc font - const int npcFontSize = config.getIntValue("npcfontSize"); - fontFile = config.getValue("npcFont", ""); - if (isJapan) - { - fontFile = config.getValue("japanFont", ""); - if (fontFile.empty()) - fontFile = branding.getStringValue("japanFont"); - } - else if (isChinese) - { - fontFile = config.getValue("chinaFont", ""); - if (fontFile.empty()) - fontFile = branding.getStringValue("chinaFont"); - } - if (fontFile.empty()) - fontFile = branding.getStringValue("npcFont"); - - mNpcFont = new Font(fontFile, npcFontSize, TTF_STYLE_NORMAL); - - Widget::setGlobalFont(mGuiFont); - - // Initialize mouse cursor and listen for changes to the option - setUseCustomCursor(config.getBoolValue("customcursor")); - setDoubleClick(config.getBoolValue("doubleClick")); - config.addListener("customcursor", mConfigListener); - config.addListener("doubleClick", mConfigListener); -} - -Gui::~Gui() -{ - config.removeListeners(mConfigListener); - delete2(mConfigListener); - - if (mMouseCursors != nullptr) - { - mMouseCursors->decRef(); - mMouseCursors = nullptr; - } - - if (windowContainer != nullptr) - windowContainer->slowLogic(); - Widget *top = mTop; - if (Widget::widgetExists(mTop)) - setTop(nullptr); - Window::setWindowContainer(nullptr); - delete top; - - delete2(mGuiFont); - delete2(boldFont); - delete2(mHelpFont); - delete2(mSecureFont); - delete2(mInfoParticleFont); - delete2(mNpcFont); - delete2(guiInput); - delete2(theme); - - delete2(mFocusHandler); - Label::finalCleanup(); - Tab::finalCleanup(); - Widget::cleanGlobalFont(); -} - -void Gui::logic() -{ - BLOCK_START("Gui::logic") - ResourceManager::clearScheduled(); - - if (mTop == nullptr) - { - BLOCK_END("Gui::logic") - return; - } - - handleModalFocus(); - handleModalMouseInputFocus(); - - if (guiInput != nullptr) - handleMouseInput(); - - mTop->logic(); - BLOCK_END("Gui::logic") -} - -void Gui::slowLogic() -{ - BLOCK_START("Gui::slowLogic") - Palette::advanceGradients(); - - // Fade out mouse cursor after extended inactivity - if (mMouseInactivityTimer < 100 * 15) - { - ++mMouseInactivityTimer; - mMouseCursorAlpha = std::min(1.0F, mMouseCursorAlpha + 0.05F); - } - else - { - mMouseCursorAlpha = std::max(0.0F, mMouseCursorAlpha - 0.005F); - } - if (mGuiFont != nullptr) - mGuiFont->slowLogic(0); - if (mInfoParticleFont != nullptr) - mInfoParticleFont->slowLogic(1); - if (mHelpFont != nullptr) - mHelpFont->slowLogic(2); - if (mSecureFont != nullptr) - mSecureFont->slowLogic(3); - if (boldFont != nullptr) - boldFont->slowLogic(4); - if (mNpcFont != nullptr) - mNpcFont->slowLogic(5); - if (windowContainer != nullptr) - windowContainer->slowLogic(); - - const time_t time = cur_time; - if (mTime != time) - { - logger->flush(); - if (ipc != nullptr) - ipc->flush(); - mTime = time; - - if (time > mTime10 || mTime10 - time > 10) - { - mTime10 = time + 10; - ResourceManager::cleanOrphans(); - guiInput->simulateMouseMove(); - } - } - - BLOCK_END("Gui::slowLogic") -} - -void Gui::clearFonts() -{ - if (mGuiFont != nullptr) - mGuiFont->clear(); - if (mInfoParticleFont != nullptr) - mInfoParticleFont->clear(); - if (mHelpFont != nullptr) - mHelpFont->clear(); - if (mSecureFont != nullptr) - mSecureFont->clear(); - if (boldFont != nullptr) - boldFont->clear(); - if (mNpcFont != nullptr) - mNpcFont->clear(); -} - -bool Gui::handleInput() -{ - if (mInput != nullptr) - return handleKeyInput(); - return false; -} - -bool Gui::handleKeyInput() -{ - if (guiInput == nullptr) - return false; - - BLOCK_START("Gui::handleKeyInput") - bool consumed(false); - - while (!mInput->isKeyQueueEmpty()) - { - const KeyInput keyInput = guiInput->dequeueKeyInput(); - - KeyEvent eventToGlobalKeyListeners(nullptr, - keyInput.getType(), - keyInput.getActionId(), keyInput.getKey()); - -#ifdef USE_SDL2 - if (!keyInput.getText().empty()) - eventToGlobalKeyListeners.setText(keyInput.getText()); -#endif // USE_SDL2 - - distributeKeyEventToGlobalKeyListeners( - eventToGlobalKeyListeners); - - // If a global key listener consumes the event it will not be - // sent further to the source of the event. - if (eventToGlobalKeyListeners.isConsumed()) - { - consumed = true; - continue; - } - - if (mFocusHandler != nullptr) - { - bool eventConsumed = false; - - // Send key inputs to the focused widgets - if (mFocusHandler->getFocused() != nullptr) - { - KeyEvent event(getKeyEventSource(), - keyInput.getType(), - keyInput.getActionId(), keyInput.getKey()); -#ifdef USE_SDL2 - if (!keyInput.getText().empty()) - event.setText(keyInput.getText()); -#endif // USE_SDL2 - - if (!mFocusHandler->getFocused()->isFocusable()) - mFocusHandler->focusNone(); - else - distributeKeyEvent(event); - - eventConsumed = event.isConsumed(); - if (eventConsumed) - consumed = true; - } - - // If the key event hasn't been consumed and - // tabbing is enable check for tab press and - // change focus. - if (!eventConsumed && keyInput.getActionId() - == InputAction::GUI_TAB && - keyInput.getType() == KeyEventType::PRESSED) - { - if (inputManager.isActionActive(InputAction::GUI_MOD)) - mFocusHandler->tabPrevious(); - else - mFocusHandler->tabNext(); - } - } - } // end while - BLOCK_END("Gui::handleKeyInput") - return consumed; -} - -void Gui::draw() -{ - BLOCK_START("Gui::draw 1") - Widget *const top = getTop(); - if (top == nullptr) - return; - mGraphics->pushClipArea(top->getDimension()); - - if (isBatchDrawRenders(openGLMode)) - { - top->draw(mGraphics); - touchManager.draw(); - } - else - { - top->safeDraw(mGraphics); - touchManager.safeDraw(); - } - - int mouseX; - int mouseY; - const MouseStateType button = getMouseState(mouseX, mouseY); - - if ((settings.mouseFocused || - ((button & SDL_BUTTON(1)) != 0)) && - mMouseCursors != nullptr && - mCustomCursor && - mMouseCursorAlpha > 0.0F) - { -#ifndef DYECMD - const Image *const image = dragDrop.getItemImage(); - if (mGuiFont != nullptr) - { - const std::string &str = dragDrop.getText(); - if (!str.empty()) - { - const int posX = mouseX - mGuiFont->getWidth(str) / 2; - const int posY = mouseY + - (image != nullptr ? image->mBounds.h / 2 : 0); - mGuiFont->drawString(mGraphics, - mForegroundColor, mForegroundColor2, - str, - posX, posY); - } - } - if (image != nullptr) - { - const int posX = mouseX - (image->mBounds.w / 2); - const int posY = mouseY - (image->mBounds.h / 2); - mGraphics->drawImage(image, posX, posY); - } -#endif // DYECMD - - Image *const mouseCursor = mMouseCursors->get( - CAST_SIZE(mCursorType)); - if (mouseCursor != nullptr) - { - mouseCursor->setAlpha(mMouseCursorAlpha); - mGraphics->drawImage(mouseCursor, mouseX - 15, mouseY - 17); - } - } - - mGraphics->popClipArea(); - BLOCK_END("Gui::draw 1") -} - -void Gui::videoResized() const -{ - WindowContainer *const top = static_cast<WindowContainer *>(getTop()); - - if (top != nullptr) - { - const int oldWidth = top->getWidth(); - const int oldHeight = top->getHeight(); - - top->setSize(mainGraphics->mWidth, mainGraphics->mHeight); - top->adjustAfterResize(oldWidth, oldHeight); - } - - if (viewport != nullptr) - viewport->videoResized(); - Widget::distributeWindowResizeEvent(); -} - -void Gui::setUseCustomCursor(const bool customCursor) -{ - if (settings.options.hideCursor) - { - SDL::showCursor(false); - return; - } - if (customCursor != mCustomCursor) - { - mCustomCursor = customCursor; - - if (mCustomCursor) - { - // Hide the SDL mouse cursor - SDL::showCursor(false); - - // Load the mouse cursor - if (mMouseCursors != nullptr) - mMouseCursors->decRef(); - mMouseCursors = Theme::getImageSetFromTheme("mouse.png", 40, 40); - - if (mMouseCursors == nullptr) - logger->log("Error: Unable to load mouse cursors."); - } - else - { - // Show the SDL mouse cursor - SDL::showCursor(true); - - // Unload the mouse cursor - if (mMouseCursors != nullptr) - { - mMouseCursors->decRef(); - mMouseCursors = nullptr; - } - } - } -} - -void Gui::handleMouseMoved(const MouseInput &mouseInput) -{ - // Check if the mouse leaves the application window. - if (mTop != nullptr && - !mWidgetWithMouseQueue.empty() && - (mouseInput.getX() < 0 || - mouseInput.getY() < 0 || - !mTop->getDimension().isPointInRect(mouseInput.getX(), - mouseInput.getY()))) - { - // Distribute an event to all widgets in the - // "widget with mouse" queue. - while (!mWidgetWithMouseQueue.empty()) - { - Widget *const widget = mWidgetWithMouseQueue.front(); - - if (Widget::widgetExists(widget)) - { - distributeMouseEvent(widget, - MouseEventType::EXITED, - mouseInput.getButton(), - mouseInput.getX(), - mouseInput.getY(), - true, - true); - } - - mWidgetWithMouseQueue.pop_front(); - } - - mMouseInactivityTimer = 0; - return; - } - - const int mouseX = mouseInput.getX(); - const int mouseY = mouseInput.getY(); - const MouseButtonT button = mouseInput.getButton(); - - // Check if there is a need to send mouse exited events by - // traversing the "widget with mouse" queue. - bool widgetWithMouseQueueCheckDone = mWidgetWithMouseQueue.empty(); - while (!widgetWithMouseQueueCheckDone) - { - unsigned int iterations = 0; - for (std::deque<Widget*>::iterator - iter = mWidgetWithMouseQueue.begin(); - iter != mWidgetWithMouseQueue.end(); - ++ iter) - { - Widget *const widget = *iter; - - // If a widget in the "widget with mouse queue" doesn't - // exists anymore it should be removed from the queue. - if (!Widget::widgetExists(widget)) - { - mWidgetWithMouseQueue.erase(iter); - break; - } - else - { - int x; - int y; - widget->getAbsolutePosition(x, y); - - if (x > mouseX - || y > mouseY - || x + widget->getWidth() <= mouseX - || y + widget->getHeight() <= mouseY - || !widget->isVisible()) - { - distributeMouseEvent(widget, - MouseEventType::EXITED, - button, - mouseX, - mouseY, - true, - true); - mClickCount = 1; - mLastMousePressTimeStamp = 0U; - mWidgetWithMouseQueue.erase(iter); - break; - } - } - - iterations++; - } - - widgetWithMouseQueueCheckDone = - (CAST_SIZE(iterations) == mWidgetWithMouseQueue.size()); - } - - // Check all widgets below the mouse to see if they are - // present in the "widget with mouse" queue. If a widget - // is not then it should be added and an entered event should - // be sent to it. - Widget* parent = getMouseEventSource(mouseX, mouseY); - Widget* widget = parent; - - // If a widget has modal mouse input focus then it will - // always be returned from getMouseEventSource, but we only wan't to - // send mouse entered events if the mouse has actually entered the - // widget with modal mouse input focus, hence we need to check if - // that's the case. If it's not we should simply ignore to send any - // mouse entered events. - if ((mFocusHandler->getModalMouseInputFocused() != nullptr) - && widget == mFocusHandler->getModalMouseInputFocused() - && Widget::widgetExists(widget) && - (widget != nullptr)) - { - int x, y; - widget->getAbsolutePosition(x, y); - - if (x > mouseX || y > mouseY - || x + widget->getWidth() <= mouseX - || y + widget->getHeight() <= mouseY) - { - parent = nullptr; - } - } - - while (parent != nullptr) - { - parent = widget->getParent(); - - // Check if the widget is present in the "widget with mouse" queue. - bool widgetIsPresentInQueue = false; - FOR_EACH (std::deque<Widget*>::const_iterator, - iter, mWidgetWithMouseQueue) - { - if (*iter == widget) - { - widgetIsPresentInQueue = true; - break; - } - } - - // Widget is not present, send an entered event and add - // it to the "widget with mouse" queue. - if (!widgetIsPresentInQueue - && Widget::widgetExists(widget)) - { - distributeMouseEvent(widget, - MouseEventType::ENTERED, - button, - mouseX, - mouseY, - true, - true); - mWidgetWithMouseQueue.push_front(widget); - } - - const Widget *const swap = widget; - widget = parent; - parent = swap->getParent(); - } - - if (mFocusHandler->getDraggedWidget() != nullptr) - { - distributeMouseEvent(mFocusHandler->getDraggedWidget(), - MouseEventType::DRAGGED, - mLastMouseDragButton, - mouseX, - mouseY); - } - else - { - Widget *const sourceWidget = getMouseEventSource(mouseX, mouseY); - distributeMouseEvent(sourceWidget, - MouseEventType::MOVED, - button, - mouseX, - mouseY); - } - mMouseInactivityTimer = 0; -} - -void Gui::handleMousePressed(const MouseInput &mouseInput) -{ - const int x = mouseInput.getX(); - const int y = mouseInput.getY(); - const MouseButtonT button = mouseInput.getButton(); - const unsigned int timeStamp = mouseInput.getTimeStamp(); - - Widget *sourceWidget = getMouseEventSource(x, y); - - if (mFocusHandler->getDraggedWidget() != nullptr) - sourceWidget = mFocusHandler->getDraggedWidget(); - - if (sourceWidget == nullptr) - return; - int sourceWidgetX; - int sourceWidgetY; - sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY); - - if (((mFocusHandler->getModalFocused() != nullptr) - && sourceWidget->isModalFocused()) - || (mFocusHandler->getModalFocused() == nullptr)) - { - sourceWidget->requestFocus(); - } - - if (mDoubleClick && - timeStamp - mLastMousePressTimeStamp < 250U && - mLastMousePressButton == button) - { - mClickCount ++; - } - else - { - mClickCount = 1; - } - - distributeMouseEvent(sourceWidget, MouseEventType::PRESSED, button, x, y); - mFocusHandler->setLastWidgetPressed(sourceWidget); - mFocusHandler->setDraggedWidget(sourceWidget); - mLastMouseDragButton = button; - mLastMousePressButton = button; - mLastMousePressTimeStamp = timeStamp; -} - -void Gui::updateFonts() -{ - const int fontSize = config.getIntValue("fontSize"); - std::string fontFile = config.getValue("font", ""); - if (fontFile.empty()) - fontFile = branding.getStringValue("font"); - - mGuiFont->loadFont(fontFile, fontSize, TTF_STYLE_NORMAL); - - fontFile = config.getValue("particleFont", ""); - if (fontFile.empty()) - fontFile = branding.getStringValue("particleFont"); - - mInfoParticleFont->loadFont(fontFile, fontSize, TTF_STYLE_BOLD); - - fontFile = config.getValue("boldFont", ""); - if (fontFile.empty()) - fontFile = branding.getStringValue("boldFont"); - - boldFont->loadFont(fontFile, fontSize, TTF_STYLE_NORMAL); - - const int npcFontSize = config.getIntValue("npcfontSize"); - - fontFile = config.getValue("npcFont", ""); - if (fontFile.empty()) - fontFile = branding.getStringValue("npcFont"); - - mNpcFont->loadFont(fontFile, npcFontSize, TTF_STYLE_NORMAL); -} - -void Gui::distributeMouseEvent(Widget *const source, - const MouseEventTypeT type, - const MouseButtonT button, - const int x, const int y, - const bool force, - const bool toSourceOnly) -{ - if ((source == nullptr) || (mFocusHandler == nullptr)) - return; - - Widget *widget = source; - - if (!force) - { - if (mFocusHandler->getModalFocused() != nullptr - && !widget->isModalFocused()) - { - return; - } - if (mFocusHandler->getModalMouseInputFocused() != nullptr - && !widget->isModalMouseInputFocused()) - { - return; - } - } - - MouseEvent event(source, - type, button, - x, y, mClickCount); - - Widget* parent = source; - while (parent != nullptr) - { - // If the widget has been removed due to input - // cancel the distribution. - if (!Widget::widgetExists(widget)) - break; - - parent = widget->getParent(); - - if (widget->isEnabled() || force) - { - int widgetX; - int widgetY; - widget->getAbsolutePosition(widgetX, widgetY); - - event.setX(x - widgetX); - event.setY(y - widgetY); - - std::list<MouseListener*> mouseListeners - = widget->getMouseListeners(); - - const MouseEventTypeT mouseType = event.getType(); - // Send the event to all mouse listeners of the widget. - FOR_EACH (std::list<MouseListener*>::const_iterator, - it, mouseListeners) - { - switch (mouseType) - { - case MouseEventType::ENTERED: - (*it)->mouseEntered(event); - break; - case MouseEventType::EXITED: - (*it)->mouseExited(event); - break; - case MouseEventType::MOVED: - (*it)->mouseMoved(event); - break; - case MouseEventType::PRESSED: - (*it)->mousePressed(event); - break; - case MouseEventType::RELEASED: - case MouseEventType::RELEASED2: - (*it)->mouseReleased(event); - break; - case MouseEventType::WHEEL_MOVED_UP: - (*it)->mouseWheelMovedUp(event); - break; - case MouseEventType::WHEEL_MOVED_DOWN: - (*it)->mouseWheelMovedDown(event); - break; - case MouseEventType::DRAGGED: - (*it)->mouseDragged(event); - break; - case MouseEventType::CLICKED: - (*it)->mouseClicked(event); - break; - default: - break; - } - } - - if (toSourceOnly) - break; - } - - const Widget *const swap = widget; - widget = parent; - parent = swap->getParent(); - -#ifndef DYECMD - if (type == MouseEventType::RELEASED) - dragDrop.clear(); -#endif // DYECMD - - if ((widget == nullptr) || event.isConsumed()) - break; - - // If a non modal focused widget has been reach - // and we have modal focus cancel the distribution. - if ((mFocusHandler->getModalFocused() != nullptr) - && !widget->isModalFocused()) - { - 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() != nullptr) - && !widget->isModalMouseInputFocused()) - { - break; - } - } -} - -void Gui::resetClickCount() -{ - mClickCount = 1; - mLastMousePressTimeStamp = 0; -} - -MouseEvent *Gui::createMouseEvent(Window *const widget) -{ - if ((viewport == nullptr) || (widget == nullptr)) - return nullptr; - - int x = 0; - int y = 0; - int mouseX = 0; - int mouseY = 0; - - getAbsolutePosition(widget, x, y); - getMouseState(mouseX, mouseY); - - return new MouseEvent(widget, - MouseEventType::MOVED, - MouseButton::EMPTY, - mouseX - x, - mouseY - y, - mClickCount); -} - -void Gui::getAbsolutePosition(Widget *restrict widget, - int &restrict x, - int &restrict y) -{ - if (widget == nullptr) - return; - x = 0; - y = 0; - while (widget->getParent() != nullptr) - { - x += widget->getX(); - y += widget->getY(); - widget = widget->getParent(); - } -} - -void Gui::handleMouseInput() -{ - BLOCK_START("Gui::handleMouseInput") - while (!mInput->isMouseQueueEmpty()) - { - const MouseInput mouseInput = guiInput->dequeueMouseInput(); - - if (touchManager.processEvent(mouseInput)) - { -#ifdef ANDROID -#ifndef USE_SDL2 - SDL_WarpMouse(mLastMouseX, mLastMouseY, - mLastMouseRealX, mLastMouseRealY); -#endif // USE_SDL2 -#endif // ANDROID - - mMouseInactivityTimer = 0; - continue; - } - - // 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(); -#ifdef ANDROID - mLastMouseRealX = mouseInput.getRealX(); - mLastMouseRealY = mouseInput.getRealY(); -#endif // ANDROID - - switch (mouseInput.getType()) - { - case MouseEventType::PRESSED: - handleMousePressed(mouseInput); - break; - case MouseEventType::RELEASED: - handleMouseReleased(mouseInput); - break; - case MouseEventType::MOVED: - handleMouseMoved(mouseInput); - break; - case MouseEventType::WHEEL_MOVED_DOWN: - handleMouseWheelMovedDown(mouseInput); - break; - case MouseEventType::WHEEL_MOVED_UP: - handleMouseWheelMovedUp(mouseInput); - break; - case MouseEventType::CLICKED: - case MouseEventType::ENTERED: - case MouseEventType::EXITED: - case MouseEventType::DRAGGED: - case MouseEventType::RELEASED2: - default: - break; - } - } - BLOCK_END("Gui::handleMouseInput") -} - -void Gui::handleMouseReleased(const MouseInput &mouseInput) -{ - Widget *sourceWidget = getMouseEventSource( - mouseInput.getX(), mouseInput.getY()); - - int sourceWidgetX; - int sourceWidgetY; - if (mFocusHandler->getDraggedWidget() != nullptr) - { - if (sourceWidget != mFocusHandler->getLastWidgetPressed()) - mFocusHandler->setLastWidgetPressed(nullptr); - - Widget *const oldWidget = sourceWidget; - sourceWidget = mFocusHandler->getDraggedWidget(); - if ((oldWidget != nullptr) && oldWidget != sourceWidget) - { - oldWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY); - distributeMouseEvent(oldWidget, - MouseEventType::RELEASED2, - mouseInput.getButton(), - mouseInput.getX(), - mouseInput.getY()); - } - } - - if (sourceWidget == nullptr) - return; - sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY); - distributeMouseEvent(sourceWidget, - MouseEventType::RELEASED, - mouseInput.getButton(), - mouseInput.getX(), - mouseInput.getY()); - - if (mouseInput.getButton() == mLastMousePressButton - && mFocusHandler->getLastWidgetPressed() == sourceWidget) - { - distributeMouseEvent(sourceWidget, - MouseEventType::CLICKED, - mouseInput.getButton(), - mouseInput.getX(), - mouseInput.getY()); - - mFocusHandler->setLastWidgetPressed(nullptr); - } - else - { - mLastMousePressButton = MouseButton::EMPTY; - mClickCount = 0; - } - - if (mFocusHandler->getDraggedWidget() != nullptr) - mFocusHandler->setDraggedWidget(nullptr); -} - -void Gui::addGlobalFocusListener(FocusListener* focusListener) -{ - mFocusListeners.push_back(focusListener); -} - -void Gui::removeGlobalFocusListener(FocusListener* focusListener) -{ - mFocusListeners.remove(focusListener); -} - -void Gui::distributeGlobalFocusGainedEvent(const Event &focusEvent) -{ - for (FocusListenerIterator iter = mFocusListeners.begin(); - iter != mFocusListeners.end(); - ++ iter) - { - (*iter)->focusGained(focusEvent); - } -} - -void Gui::removeDragged(const Widget *const widget) -{ - if (mFocusHandler == nullptr) - return; - - if (mFocusHandler->getDraggedWidget() == widget) - mFocusHandler->setDraggedWidget(nullptr); -} - -MouseStateType Gui::getMouseState(int &x, int &y) -{ - const MouseStateType res = SDL_GetMouseState(&x, &y); - const int scale = mainGraphics->getScale(); - x /= scale; - y /= scale; - return res; -} - -void Gui::setTop(Widget *const top) -{ - if (mTop != nullptr) - mTop->setFocusHandler(nullptr); - if (top != nullptr) - top->setFocusHandler(mFocusHandler); - - mTop = top; -} - -void Gui::setGraphics(Graphics *const graphics) -{ - mGraphics = graphics; -} - -Graphics* Gui::getGraphics() const -{ - return mGraphics; -} - -void Gui::setInput(SDLInput *const input) -{ - mInput = input; -} - -SDLInput* Gui::getInput() const -{ - return mInput; -} - -void Gui::addGlobalKeyListener(KeyListener *const keyListener) -{ - mKeyListeners.push_back(keyListener); -} - -void Gui::removeGlobalKeyListener(KeyListener *const keyListener) -{ - mKeyListeners.remove(keyListener); -} - -void Gui::handleMouseWheelMovedDown(const MouseInput& mouseInput) -{ - Widget* sourceWidget = getMouseEventSource( - mouseInput.getX(), mouseInput.getY()); - - if (mFocusHandler->getDraggedWidget() != nullptr) - sourceWidget = mFocusHandler->getDraggedWidget(); - - if (sourceWidget != nullptr) - { - int sourceWidgetX = 0; - int sourceWidgetY = 0; - - sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY); - distributeMouseEvent(sourceWidget, - MouseEventType::WHEEL_MOVED_DOWN, - mouseInput.getButton(), - mouseInput.getX(), - mouseInput.getY()); - } -} - -void Gui::handleMouseWheelMovedUp(const MouseInput& mouseInput) -{ - Widget* sourceWidget = getMouseEventSource( - mouseInput.getX(), mouseInput.getY()); - - if (mFocusHandler->getDraggedWidget() != nullptr) - sourceWidget = mFocusHandler->getDraggedWidget(); - - if (sourceWidget != nullptr) - { - int sourceWidgetX; - int sourceWidgetY; - - sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY); - distributeMouseEvent(sourceWidget, - MouseEventType::WHEEL_MOVED_UP, - mouseInput.getButton(), - mouseInput.getX(), - mouseInput.getY()); - } -} - -Widget* Gui::getWidgetAt(const int x, const int y) const -{ - // If the widget's parent has no child then we have found the widget.. - Widget* parent = mTop; - Widget* child = mTop; - Widget* selectable = mTop; - - while (child != nullptr) - { - Widget *const swap = child; - int parentX, parentY; - parent->getAbsolutePosition(parentX, parentY); - child = parent->getWidgetAt(x - parentX, y - parentY); - parent = swap; - if (parent->isSelectable()) - selectable = parent; - } - - return selectable; -} - -Widget* Gui::getMouseEventSource(const int x, const int y) const -{ - Widget *const widget = getWidgetAt(x, y); - if (widget == nullptr) - return nullptr; - - if (mFocusHandler != nullptr && - mFocusHandler->getModalMouseInputFocused() != nullptr && - !widget->isModalMouseInputFocused()) - { - return mFocusHandler->getModalMouseInputFocused(); - } - - return widget; -} - -Widget* Gui::getKeyEventSource() const -{ - Widget* widget = mFocusHandler->getFocused(); - - while (widget != nullptr && - widget->getInternalFocusHandler() != nullptr && - widget->getInternalFocusHandler()->getFocused() != nullptr) - { - widget = widget->getInternalFocusHandler()->getFocused(); - } - - return widget; -} - -void Gui::distributeKeyEvent(KeyEvent &event) const -{ - Widget* parent = event.getSource(); - Widget* widget = parent; - - if (parent == nullptr) - return; - if (mFocusHandler->getModalFocused() != nullptr && - !widget->isModalFocused()) - { - return; - } - if (mFocusHandler->getModalMouseInputFocused() != nullptr && - !widget->isModalMouseInputFocused()) - { - return; - } - - while (parent != nullptr) - { - // If the widget has been removed due to input - // cancel the distribution. - if (!Widget::widgetExists(widget)) - break; - - parent = widget->getParent(); - - if (widget->isEnabled()) - { - std::list<KeyListener*> keyListeners - = widget->getKeyListeners(); - - const KeyEventTypeT eventType = event.getType(); - // Send the event to all key listeners of the source widget. - FOR_EACH (std::list<KeyListener*>::const_iterator, - it, keyListeners) - { - switch (eventType) - { - case KeyEventType::PRESSED: - (*it)->keyPressed(event); - break; - case KeyEventType::RELEASED: - (*it)->keyReleased(event); - break; - default: - break; - } - } - } - - const Widget *const swap = widget; - widget = parent; - parent = swap->getParent(); - - // If a non modal focused widget has been reach - // and we have modal focus cancel the distribution. - if ((widget != nullptr) && - (mFocusHandler->getModalFocused() != nullptr) && - !widget->isModalFocused()) - { - break; - } - } -} - -void Gui::distributeKeyEventToGlobalKeyListeners(KeyEvent& event) -{ - BLOCK_START("Gui::distributeKeyEventToGlobalKeyListeners") - const KeyEventTypeT eventType = event.getType(); - FOR_EACH (KeyListenerListIterator, it, mKeyListeners) - { - switch (eventType) - { - case KeyEventType::PRESSED: - (*it)->keyPressed(event); - break; - case KeyEventType::RELEASED: - (*it)->keyReleased(event); - break; - default: - break; - } - - if (event.isConsumed()) - break; - } - BLOCK_END("Gui::distributeKeyEventToGlobalKeyListeners") -} - -void Gui::handleModalMouseInputFocus() -{ - BLOCK_START("Gui::handleModalMouseInputFocus") - Widget *const lastModalWidget - = mFocusHandler->getLastWidgetWithModalMouseInputFocus(); - Widget *const modalWidget = mFocusHandler->getModalMouseInputFocused(); - if (lastModalWidget != modalWidget) - { - // Check if modal mouse input focus has been gained by a widget. - if (lastModalWidget == nullptr) - { - handleModalFocusGained(); - mFocusHandler->setLastWidgetWithModalMouseInputFocus(modalWidget); - } - // Check if modal mouse input focus has been released. - else - { - handleModalFocusReleased(); - mFocusHandler->setLastWidgetWithModalMouseInputFocus(nullptr); - } - } - BLOCK_END("Gui::handleModalMouseInputFocus") -} - -void Gui::handleModalFocus() -{ - BLOCK_START("Gui::handleModalFocus") - Widget *const lastModalWidget - = mFocusHandler->getLastWidgetWithModalFocus(); - Widget *const modalWidget = mFocusHandler->getModalFocused(); - - if (lastModalWidget != modalWidget) - { - // Check if modal focus has been gained by a widget. - if (lastModalWidget == nullptr) - { - handleModalFocusGained(); - mFocusHandler->setLastWidgetWithModalFocus(modalWidget); - } - // Check if modal focus has been released. - else - { - handleModalFocusReleased(); - mFocusHandler->setLastWidgetWithModalFocus(nullptr); - } - } - BLOCK_END("Gui::handleModalFocus") -} - -void Gui::handleModalFocusGained() -{ - // Distribute an event to all widgets in the "widget with mouse" queue. - while (!mWidgetWithMouseQueue.empty()) - { - Widget *const widget = mWidgetWithMouseQueue.front(); - - if (Widget::widgetExists(widget)) - { - distributeMouseEvent(widget, - MouseEventType::EXITED, - mLastMousePressButton, - mLastMouseX, - mLastMouseY, - true, - true); - } - - mWidgetWithMouseQueue.pop_front(); - } - - mFocusHandler->setLastWidgetWithModalMouseInputFocus( - mFocusHandler->getModalMouseInputFocused()); -} - -void Gui::handleModalFocusReleased() -{ - // Check all widgets below the mouse to see if they are - // present in the "widget with mouse" queue. If a widget - // is not then it should be added and an entered event should - // be sent to it. - Widget* widget = getMouseEventSource(mLastMouseX, mLastMouseY); - Widget* parent = widget; - - while (parent != nullptr && - widget != nullptr) - { - parent = widget->getParent(); - - // Check if the widget is present in the "widget with mouse" queue. - bool widgetIsPresentInQueue = false; - FOR_EACH (std::deque<Widget*>::const_iterator, - iter, mWidgetWithMouseQueue) - { - if (*iter == widget) - { - widgetIsPresentInQueue = true; - break; - } - } - - // Widget is not present, send an entered event and add - // it to the "widget with mouse" queue. - if (!widgetIsPresentInQueue && Widget::widgetExists(widget)) - { - distributeMouseEvent(widget, - MouseEventType::ENTERED, - mLastMousePressButton, - mLastMouseX, - mLastMouseY, - false, - true); - mWidgetWithMouseQueue.push_front(widget); - } - - const Widget *const swap = widget; - widget = parent; - parent = swap->getParent(); - } -} - -int Gui::getMousePressLength() const -{ - if (mLastMousePressTimeStamp == 0u) - return 0; - unsigned int ticks = SDL_GetTicks(); - if (ticks > mLastMousePressTimeStamp) - return ticks - mLastMousePressTimeStamp; - return mLastMousePressTimeStamp - ticks; -} |