1 /* 2 * The ManaPlus Client 3 * Copyright (C) 2004-2009 The Mana World Development Team 4 * Copyright (C) 2009-2010 The Mana Developers 5 * Copyright (C) 2011-2019 The ManaPlus Developers 6 * Copyright (C) 2019-2021 Andrei Karas 7 * 8 * This file is part of The ManaPlus Client. 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program. If not, see <http://www.gnu.org/licenses/>. 22 */ 23 24 /* _______ __ __ __ ______ __ __ _______ __ __ 25 * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ 26 * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / 27 * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / 28 * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / 29 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / 30 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ 31 * 32 * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson 33 * 34 * 35 * Per Larsson a.k.a finalman 36 * Olof Naessén a.k.a jansem/yakslem 37 * 38 * Visit: http://guichan.sourceforge.net 39 * 40 * License: (BSD) 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in 48 * the documentation and/or other materials provided with the 49 * distribution. 50 * 3. Neither the name of Guichan nor the names of its contributors may 51 * be used to endorse or promote products derived from this software 52 * without specific prior written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 55 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 56 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 57 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 58 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 59 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 60 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 61 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 62 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 63 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 64 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 65 */ 66 67 #ifndef GUI_GUI_H 68 #define GUI_GUI_H 69 70 #include "gui/color.h" 71 72 #include "enums/events/mousebutton.h" 73 #include "enums/events/mouseeventtype.h" 74 75 #include "enums/resources/cursor.h" 76 77 #include <deque> 78 #include <list> 79 80 #include "localconsts.h" 81 82 class Event; 83 class FocusHandler; 84 class FocusListener; 85 class Graphics; 86 class GuiConfigListener; 87 class ImageSet; 88 class KeyEvent; 89 class KeyListener; 90 class MouseEvent; 91 class MouseInput; 92 class Font; 93 class SDLInput; 94 class Widget; 95 class Window; 96 97 #ifdef USE_SDL2 98 #define MouseStateType uint32_t 99 #else // USE_SDL2 100 #define MouseStateType uint8_t 101 #endif // USE_SDL2 102 103 /** 104 * \defgroup GUI Core GUI related classes (widgets) 105 */ 106 107 /** 108 * \defgroup Interface User interface related classes (windows, dialogs) 109 */ 110 111 /** 112 * Main GUI class. 113 * 114 * \ingroup GUI 115 */ 116 class Gui final 117 { 118 public: 119 /** 120 * Constructor. 121 */ 122 Gui(); 123 124 A_DELETE_COPY(Gui) 125 126 /** 127 * Destructor. 128 */ 129 ~Gui(); 130 131 void postInit(Graphics *const graphics) A_NONNULL(2); 132 133 /** 134 * Performs logic of the GUI. Overridden to track mouse pointer 135 * activity. 136 */ 137 void logic(); 138 139 void slowLogic(); 140 141 void clearFonts(); 142 143 /** 144 * Draws the whole Gui by calling draw functions down in the 145 * Gui hierarchy. It also draws the mouse pointer. 146 */ 147 void draw(); 148 149 /** 150 * Called when the application window has been resized. 151 */ 152 void videoResized() const; 153 getFocusHandler()154 FocusHandler *getFocusHandler() const noexcept2 A_WARN_UNUSED 155 { return mFocusHandler; } 156 157 /** 158 * Return game font. 159 */ getFont()160 Font *getFont() const RETURNS_NONNULL A_WARN_UNUSED 161 { return mGuiFont; } 162 163 /** 164 * Return help font. 165 */ getHelpFont()166 Font *getHelpFont() const RETURNS_NONNULL A_WARN_UNUSED 167 { return mHelpFont; } 168 169 /** 170 * Return secure font. 171 */ getSecureFont()172 Font *getSecureFont() const RETURNS_NONNULL A_WARN_UNUSED 173 { return mSecureFont; } 174 175 /** 176 * Return npc font. 177 */ getNpcFont()178 Font *getNpcFont() const RETURNS_NONNULL A_WARN_UNUSED 179 { return mNpcFont; } 180 181 /** 182 * Return the Font used for "Info Particles", i.e. ones showing, what 183 * you picked up, etc. 184 */ getInfoParticleFont()185 Font *getInfoParticleFont() const RETURNS_NONNULL A_WARN_UNUSED 186 { return mInfoParticleFont; } 187 188 /** 189 * Sets whether a custom cursor should be rendered. 190 */ 191 void setUseCustomCursor(const bool customCursor); 192 193 /** 194 * Sets which cursor should be used. 195 */ setCursorType(const CursorT index)196 void setCursorType(const CursorT index) 197 { mCursorType = index; } 198 setDoubleClick(const bool b)199 void setDoubleClick(const bool b) 200 { mDoubleClick = b; } 201 202 void updateFonts(); 203 204 bool handleInput(); 205 206 bool handleKeyInput(); 207 208 void resetClickCount(); 209 210 MouseEvent *createMouseEvent(Window *const widget) A_WARN_UNUSED; 211 212 static void getAbsolutePosition(Widget *restrict widget, 213 int &restrict x, 214 int &restrict y); 215 216 void addGlobalFocusListener(FocusListener* focusListener); 217 218 void removeGlobalFocusListener(FocusListener* focusListener); 219 220 void distributeGlobalFocusGainedEvent(const Event &focusEvent); 221 222 void removeDragged(const Widget *const widget); 223 getLastMouseX()224 int getLastMouseX() const 225 { return mLastMouseX; } 226 getLastMouseY()227 int getLastMouseY() const 228 { return mLastMouseY; } 229 230 static MouseStateType getMouseState(int &x, int &y); 231 232 /** 233 * Sets the top widget. The top widget is the root widget 234 * of the GUI. If you want a GUI to be able to contain more 235 * than one widget the top widget should be a container. 236 * 237 * @param top The top widget. 238 * @see Container 239 */ 240 void setTop(Widget *const top); 241 242 /** 243 * Gets the top widget. The top widget is the root widget 244 * of the GUI. 245 * 246 * @return The top widget. NULL if no top widget has been set. 247 */ getTop()248 Widget* getTop() const noexcept2 A_WARN_UNUSED 249 { return mTop; } 250 251 /** 252 * Sets the graphics object to use for drawing. 253 * 254 * @param graphics The graphics object to use for drawing. 255 * @see getGraphics, AllegroGraphics, HGEGraphics, 256 * OpenLayerGraphics, OpenGLGraphics, SDLGraphics 257 */ 258 void setGraphics(Graphics *const graphics) A_NONNULL(2); 259 260 /** 261 * Gets the graphics object used for drawing. 262 * 263 * @return The graphics object used for drawing. NULL if no 264 * graphics object has been set. 265 * @see setGraphics, AllegroGraphics, HGEGraphics, 266 * OpenLayerGraphics, OpenGLGraphics, SDLGraphics 267 */ 268 Graphics* getGraphics() const RETURNS_NONNULL A_WARN_UNUSED; 269 270 /** 271 * Sets the input object to use for input handling. 272 * 273 * @param input The input object to use for input handling. 274 * @see getInput, AllegroInput, HGEInput, OpenLayerInput, 275 * SDLInput 276 */ 277 void setInput(SDLInput *const input) A_NONNULL(2); 278 279 /** 280 * Gets the input object being used for input handling. 281 * 282 * @return The input object used for handling input. NULL if no 283 * input object has been set. 284 * @see setInput, AllegroInput, HGEInput, OpenLayerInput, 285 * SDLInput 286 */ 287 SDLInput* getInput() const A_WARN_UNUSED; 288 289 /** 290 * Adds a global key listener to the Gui. A global key listener 291 * will receive all key events generated from the GUI and global 292 * key listeners will receive the events before key listeners 293 * of widgets. 294 * 295 * @param keyListener The key listener to add. 296 * @see removeGlobalKeyListener 297 */ 298 void addGlobalKeyListener(KeyListener *const keyListener); 299 300 /** 301 * Removes global key listener from the Gui. 302 * 303 * @param keyListener The key listener to remove. 304 * @throws Exception if the key listener hasn't been added. 305 * @see addGlobalKeyListener 306 */ 307 void removeGlobalKeyListener(KeyListener *const keyListener); 308 isLongPress()309 bool isLongPress() const 310 { return getMousePressLength() > 250; } 311 312 int getMousePressLength() const; 313 314 protected: 315 void handleMouseMoved(const MouseInput &mouseInput); 316 317 void handleMouseReleased(const MouseInput &mouseInput); 318 319 void handleMousePressed(const MouseInput &mouseInput); 320 321 void handleMouseInput(); 322 323 void distributeMouseEvent(Widget *const source, 324 const MouseEventTypeT type, 325 const MouseButtonT button, 326 const int x, const int y, 327 const bool force, 328 const bool toSourceOnly); 329 330 /** 331 * 332 * Handles mouse wheel moved down input. 333 * 334 * @param mouseInput The mouse input to handle. 335 */ 336 void handleMouseWheelMovedDown(const MouseInput& mouseInput); 337 338 /** 339 * Handles mouse wheel moved up input. 340 * 341 * @param mouseInput The mouse input to handle. 342 */ 343 void handleMouseWheelMovedUp(const MouseInput& mouseInput); 344 345 /** 346 * Gets the widget at a certain position. 347 * 348 * @return The widget at a certain position. 349 */ 350 Widget* getWidgetAt(const int x, const int y) const A_WARN_UNUSED; 351 352 /** 353 * Gets the source of the mouse event. 354 * 355 * @return The source widget of the mouse event. 356 */ 357 Widget* getMouseEventSource(const int x, 358 const int y) const A_WARN_UNUSED; 359 360 /** 361 * Gets the source of the key event. 362 * 363 * @return The source widget of the key event. 364 */ 365 Widget* getKeyEventSource() const A_WARN_UNUSED; 366 367 /** 368 * Distributes a key event. 369 * 370 * @param event The key event to distribute. 371 372 */ 373 void distributeKeyEvent(KeyEvent &event) const; 374 375 /** 376 * Distributes a key event to the global key listeners. 377 * 378 * @param event The key event to distribute. 379 * 380 */ 381 void distributeKeyEventToGlobalKeyListeners(KeyEvent& event); 382 383 /** 384 * Handles modal mouse input focus. Modal mouse input focus needs 385 * to be checked at each logic iteration as it might be necessary to 386 * distribute mouse entered or mouse exited events. 387 * 388 */ 389 void handleModalMouseInputFocus(); 390 391 /** 392 * Handles modal focus. Modal focus needs to be checked at 393 * each logic iteration as it might be necessary to distribute 394 * mouse entered or mouse exited events. 395 * 396 */ 397 void handleModalFocus(); 398 399 /** 400 * Handles modal focus gained. If modal focus has been gained it might 401 * be necessary to distribute mouse entered or mouse exited events. 402 * 403 */ 404 void handleModalFocusGained(); 405 406 /** 407 * Handles modal mouse input focus gained. If modal focus has been 408 * gained it might be necessary to distribute mouse entered or mouse 409 * exited events. 410 * 411 */ 412 void handleModalFocusReleased(); 413 414 private: 415 /** 416 * Holds the top widget. 417 */ 418 Widget* mTop; 419 420 /** 421 * Holds the graphics implementation used. 422 */ 423 Graphics* mGraphics A_NONNULLPOINTER; 424 425 /** 426 * Holds the input implementation used. 427 */ 428 SDLInput* mInput A_NONNULLPOINTER; 429 430 /** 431 * Holds the focus handler for the Gui. 432 */ 433 FocusHandler* mFocusHandler A_NONNULLPOINTER; 434 435 /** 436 * Typedef. 437 */ 438 typedef std::list<KeyListener*> KeyListenerList; 439 440 /** 441 * Typedef. 442 */ 443 typedef KeyListenerList::iterator KeyListenerListIterator; 444 445 /** 446 * Holds the global key listeners of the Gui. 447 */ 448 KeyListenerList mKeyListeners; 449 450 /** 451 * Holds the last mouse button pressed. 452 */ 453 MouseButtonT mLastMousePressButton; 454 455 /** 456 * Holds the last mouse press time stamp. 457 */ 458 unsigned int mLastMousePressTimeStamp; 459 460 /** 461 * Holds the last mouse x coordinate. 462 */ 463 int mLastMouseX; 464 465 /** 466 * Holds the last mouse y coordinate. 467 */ 468 int mLastMouseY; 469 470 /** 471 * Holds the current click count. Used to keep track 472 * of clicks for a the last pressed button. 473 */ 474 int mClickCount; 475 476 /** 477 * Holds the last button used when a drag of a widget 478 * was initiated. Used to be able to release a drag 479 * when the same button is released. 480 */ 481 MouseButtonT mLastMouseDragButton; 482 483 /** 484 * Holds a stack with all the widgets with the mouse. 485 * Used to properly distribute mouse events. 486 */ 487 std::deque<Widget*> mWidgetWithMouseQueue; 488 489 GuiConfigListener *mConfigListener; 490 /** The global GUI font */ 491 Font *mGuiFont A_NONNULLPOINTER; 492 /** Font for Info Particles */ 493 Font *mInfoParticleFont A_NONNULLPOINTER; 494 /** Font for Help Window */ 495 Font *mHelpFont A_NONNULLPOINTER; 496 /** Font for secure labels */ 497 Font *mSecureFont A_NONNULLPOINTER; 498 /** Font for npc text */ 499 Font *mNpcFont A_NONNULLPOINTER; 500 /** Mouse cursor images */ 501 ImageSet *mMouseCursors; 502 float mMouseCursorAlpha; 503 int mMouseInactivityTimer; 504 CursorT mCursorType; 505 #ifdef ANDROID 506 uint16_t mLastMouseRealX; 507 uint16_t mLastMouseRealY; 508 #endif // ANDROID 509 510 typedef std::list<FocusListener*> FocusListenerList; 511 typedef FocusListenerList::iterator FocusListenerIterator; 512 FocusListenerList mFocusListeners; 513 Color mForegroundColor; 514 Color mForegroundColor2; 515 time_t mTime; 516 time_t mTime10; 517 bool mCustomCursor; /**< Show custom cursor */ 518 bool mDoubleClick; 519 }; 520 521 extern Gui *gui; /**< The GUI system */ 522 523 /** 524 * Bolded text font 525 */ 526 extern Font *boldFont A_NONNULLPOINTER; 527 528 #endif // GUI_GUI_H 529