| 1 | //============================================================================ |
| 2 | // |
| 3 | // SSSS tt lll lll |
| 4 | // SS SS tt ll ll |
| 5 | // SS tttttt eeee ll ll aaaa |
| 6 | // SSSS tt ee ee ll ll aa |
| 7 | // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" |
| 8 | // SS SS tt ee ll ll aa aa |
| 9 | // SSSS ttt eeeee llll llll aaaaa |
| 10 | // |
| 11 | // Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony |
| 12 | // and the Stella Team |
| 13 | // |
| 14 | // See the file "License.txt" for information on usage and redistribution of |
| 15 | // this file, and for a DISCLAIMER OF ALL WARRANTIES. |
| 16 | //============================================================================ |
| 17 | |
| 18 | #ifndef DIALOG_CONTAINER_HXX |
| 19 | #define DIALOG_CONTAINER_HXX |
| 20 | |
| 21 | class Dialog; |
| 22 | class OSystem; |
| 23 | class EventHandler; |
| 24 | |
| 25 | #include "EventHandlerConstants.hxx" |
| 26 | #include "StellaKeys.hxx" |
| 27 | #include "Stack.hxx" |
| 28 | #include "bspf.hxx" |
| 29 | |
| 30 | /** |
| 31 | The base class for groups of dialog boxes. Each dialog box has a |
| 32 | parent. In most cases, the parent is itself a dialog box, but in the |
| 33 | case of the lower-most dialog box, this class is its parent. |
| 34 | |
| 35 | This class keeps track of its children (dialog boxes), organizes them into |
| 36 | a stack, and handles their events. |
| 37 | |
| 38 | @author Stephen Anthony |
| 39 | */ |
| 40 | class DialogContainer |
| 41 | { |
| 42 | friend class EventHandler; |
| 43 | friend class Dialog; |
| 44 | |
| 45 | public: |
| 46 | /** |
| 47 | Create a new DialogContainer stack |
| 48 | */ |
| 49 | explicit DialogContainer(OSystem& osystem); |
| 50 | virtual ~DialogContainer() = default; |
| 51 | |
| 52 | public: |
| 53 | /** |
| 54 | Update the dialog container with the current time. |
| 55 | This is useful if we want to trigger events at some specified time. |
| 56 | |
| 57 | @param time The current time in microseconds |
| 58 | */ |
| 59 | void updateTime(uInt64 time); |
| 60 | |
| 61 | /** |
| 62 | Handle a keyboard Unicode text event. |
| 63 | |
| 64 | @param text Unicode character string |
| 65 | */ |
| 66 | void handleTextEvent(char text); |
| 67 | |
| 68 | /** |
| 69 | Handle a keyboard single-key event. |
| 70 | |
| 71 | @param key Actual key symbol |
| 72 | @param mod Modifiers |
| 73 | @param pressed Pressed (true) or released (false) |
| 74 | */ |
| 75 | void handleKeyEvent(StellaKey key, StellaMod mod, bool pressed, bool repeat); |
| 76 | |
| 77 | /** |
| 78 | Handle a mouse motion event. |
| 79 | |
| 80 | @param x The x location |
| 81 | @param y The y location |
| 82 | */ |
| 83 | void handleMouseMotionEvent(int x, int y); |
| 84 | |
| 85 | /** |
| 86 | Handle a mouse button event. |
| 87 | |
| 88 | @param b The mouse button |
| 89 | @param pressed Whether the button was pressed (true) or released (false) |
| 90 | @param x The x location |
| 91 | @param y The y location |
| 92 | */ |
| 93 | void handleMouseButtonEvent(MouseButton b, bool pressed, int x, int y); |
| 94 | |
| 95 | /** |
| 96 | Handle a joystick button event. |
| 97 | |
| 98 | @param stick The joystick number |
| 99 | @param button The joystick button |
| 100 | @param pressed Pressed (true) or released (false) |
| 101 | */ |
| 102 | void handleJoyBtnEvent(int stick, int button, bool pressed); |
| 103 | |
| 104 | /** |
| 105 | Handle a joystick axis event. |
| 106 | |
| 107 | @param stick The joystick number |
| 108 | @param axis The joystick axis |
| 109 | @param adir Value associated with given axis |
| 110 | */ |
| 111 | void handleJoyAxisEvent(int stick, JoyAxis axis, JoyDir adir, int button); |
| 112 | |
| 113 | /** |
| 114 | Handle a joystick hat event. |
| 115 | |
| 116 | @param stick The joystick number |
| 117 | @param hat The joystick hat |
| 118 | @param hdir Direction of the given hat |
| 119 | */ |
| 120 | void handleJoyHatEvent(int stick, int hat, JoyHatDir hdir, int button); |
| 121 | |
| 122 | /** |
| 123 | Draw the stack of menus (full indicates to redraw all items). |
| 124 | |
| 125 | @return Answers whether any drawing actually occurred. |
| 126 | */ |
| 127 | bool draw(bool full = false); |
| 128 | |
| 129 | /** |
| 130 | Answers whether a full redraw is required. |
| 131 | */ |
| 132 | bool needsRedraw() const; |
| 133 | |
| 134 | /** |
| 135 | Answers whether the base dialog is currently active |
| 136 | (ie, there are no overlaid dialogs other than the bottom one) |
| 137 | */ |
| 138 | bool baseDialogIsActive() const; |
| 139 | |
| 140 | /** |
| 141 | Reset dialog stack to the main configuration menu. |
| 142 | */ |
| 143 | void reStack(); |
| 144 | |
| 145 | /** |
| 146 | Inform the container that it should resize according to the current |
| 147 | screen dimensions. We make this virtual, since the container may or |
| 148 | may not choose to do a resize, and even if it does, *how* it does it |
| 149 | is determined by the specific container. |
| 150 | */ |
| 151 | virtual void requestResize() { } |
| 152 | |
| 153 | /** |
| 154 | Return (and possibly create) the bottom-most dialog of this container. |
| 155 | */ |
| 156 | virtual Dialog* baseDialog() = 0; |
| 157 | |
| 158 | /** |
| 159 | Set input speeds |
| 160 | */ |
| 161 | static void setDoubleClickDelay(int delay) { _DOUBLE_CLICK_DELAY = delay; } |
| 162 | static void setControllerDelay(int delay) { _REPEAT_INITIAL_DELAY = delay; } |
| 163 | static void setControllerRate(int rate) { _REPEAT_SUSTAIN_DELAY = 1000 / rate; } |
| 164 | |
| 165 | private: |
| 166 | void reset(); |
| 167 | |
| 168 | /** |
| 169 | Add a dialog box to the stack. |
| 170 | */ |
| 171 | int addDialog(Dialog* d); |
| 172 | |
| 173 | /** |
| 174 | Remove the topmost dialog box from the stack. |
| 175 | */ |
| 176 | void removeDialog(); |
| 177 | |
| 178 | protected: |
| 179 | OSystem& myOSystem; |
| 180 | Common::FixedStack<Dialog*> myDialogStack; |
| 181 | |
| 182 | private: |
| 183 | // Indicates the most current time (in milliseconds) as set by updateTime() |
| 184 | uInt64 myTime; |
| 185 | |
| 186 | static uInt64 _DOUBLE_CLICK_DELAY; |
| 187 | static uInt64 _REPEAT_INITIAL_DELAY; |
| 188 | static uInt64 _REPEAT_SUSTAIN_DELAY; |
| 189 | static constexpr uInt64 _REPEAT_NONE = 1 << 24; // loooong |
| 190 | static constexpr uInt64 _LONG_PRESS_DELAY = 1000; // 1 second |
| 191 | |
| 192 | // For continuous 'mouse down' events |
| 193 | struct { |
| 194 | int x; |
| 195 | int y; |
| 196 | MouseButton b; |
| 197 | } myCurrentMouseDown; |
| 198 | uInt64 myClickRepeatTime; |
| 199 | |
| 200 | // For continuous 'joy button down' events |
| 201 | struct { |
| 202 | int stick; |
| 203 | int button; |
| 204 | } myCurrentButtonDown; |
| 205 | uInt64 myButtonRepeatTime; |
| 206 | uInt64 myButtonLongPressTime; |
| 207 | |
| 208 | // For continuous 'joy axis down' events |
| 209 | struct { |
| 210 | int stick; |
| 211 | JoyAxis axis; |
| 212 | JoyDir adir; |
| 213 | } myCurrentAxisDown; |
| 214 | uInt64 myAxisRepeatTime; |
| 215 | |
| 216 | // For continuous 'joy hat' events |
| 217 | struct { |
| 218 | int stick; |
| 219 | int hat; |
| 220 | JoyHatDir hdir; |
| 221 | } myCurrentHatDown; |
| 222 | uInt64 myHatRepeatTime; |
| 223 | |
| 224 | // Position and time of last mouse click (used to detect double clicks) |
| 225 | struct { |
| 226 | int x, y; // Position of mouse when the click occurred |
| 227 | int count; // How often was it already pressed? |
| 228 | uInt64 time; // Time |
| 229 | } myLastClick; |
| 230 | |
| 231 | private: |
| 232 | // Following constructors and assignment operators not supported |
| 233 | DialogContainer() = delete; |
| 234 | DialogContainer(const DialogContainer&) = delete; |
| 235 | DialogContainer(DialogContainer&&) = delete; |
| 236 | DialogContainer& operator=(const DialogContainer&) = delete; |
| 237 | DialogContainer& operator=(DialogContainer&&) = delete; |
| 238 | }; |
| 239 | |
| 240 | #endif |
| 241 | |