1 /* GemRB - Infinity Engine Emulator 2 * Copyright (C) 2003 The GemRB Project 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 * 18 * 19 */ 20 21 /** 22 * @file Control.h 23 * Declares Control, root class for all widgets except of windows 24 */ 25 26 #ifndef CONTROL_H 27 #define CONTROL_H 28 29 #define IE_GUI_BUTTON 0 30 #define IE_GUI_PROGRESSBAR 1 //gemrb extension 31 #define IE_GUI_SLIDER 2 32 #define IE_GUI_EDIT 3 33 #define IE_GUI_TEXTAREA 5 34 #define IE_GUI_LABEL 6 35 #define IE_GUI_SCROLLBAR 7 36 #define IE_GUI_WORLDMAP 8 // gemrb extension 37 #define IE_GUI_MAP 9 // gemrb extension 38 #define IE_GUI_CONSOLE 10 // gemrb extension 39 #define IE_GUI_VIEW 254 // gemrb extension 40 #define IE_GUI_INVALID 255 41 42 #include "RGBAColor.h" 43 #include "exports.h" 44 #include "globals.h" 45 46 #include "Callback.h" 47 #include "GUI/View.h" 48 #include "Timer.h" 49 50 #include <limits> 51 #include <map> 52 53 namespace GemRB { 54 55 class ControlAnimation; 56 class Control; 57 class Sprite2D; 58 59 #define ACTION_CAST(a) \ 60 static_cast<Control::Action>(a) 61 62 #define ACTION_IS_SCREEN(a) \ 63 (a <= Control::HoverEnd) 64 65 #define ACTION_DEFAULT ControlActionKey(Control::Click, 0, GEM_MB_ACTION, 1) 66 #define ACTION_CUSTOM(x) ACTION_CAST(Control::CustomAction + int(x)) 67 68 #define CTL_INVALID_VALUE ieDword(-1) 69 70 /** 71 * @class Control 72 * Basic Control Object, also called widget or GUI element. Parent class for Labels, Buttons, etc. 73 */ 74 75 using ControlActionResponder = View::ActionResponder<Control*>; 76 using ControlEventHandler = ControlActionResponder::Responder; 77 78 class GEM_EXPORT Control : public View, public ControlActionResponder { 79 private: 80 void ClearActionTimer(); 81 Timer* StartActionTimer(const ControlEventHandler& action, unsigned int delay = 0); 82 ViewScriptingRef* CreateScriptingRef(ScriptingId id, ResRef group) override; 83 84 void HandleTouchActionTimer(const Control*); 85 86 public: // Public attributes 87 enum Action : ControlActionResponder::Action { 88 // !!! Keep these synchronized with GUIDefines.py !!! 89 // screen events, send coords to callback 90 Click, 91 // avoid Drag and Hover if you can (will fire frequently). or throttle using SetActionInterval 92 Drag, 93 // "mouse" over, enter, leave 94 Hover, 95 HoverBegin, 96 HoverEnd, 97 98 // other events 99 ValueChange, // many times we only care that the value has changed, not about the event that changed it 100 101 DragDropCreate, 102 DragDropSource, // a DragOp was succesfully taken from here 103 DragDropDest, // a DragOp was successfully dropped here 104 105 CustomAction // entry value for defining custom actions in subclasses. Must be last in enum. 106 }; 107 108 struct ControlDragOp : public DragOp { ControlDragOpControlDragOp109 ControlDragOp(Control* c) 110 : DragOp(c, c->DragCursor()){} 111 SourceControlDragOp112 Control* Source() const { 113 return static_cast<Control*>(dragView); 114 } 115 DestinationControlDragOp116 Control* Destination() const { 117 return static_cast<Control*>(dropView); 118 } 119 ~ControlDragOpControlDragOp120 ~ControlDragOp() override { 121 Control* src = Source(); 122 ActionKey srckey(Action::DragDropSource); 123 124 Control* dst = Destination(); 125 ActionKey dstkey(Action::DragDropDest); 126 127 if (dst) { // only send actions for successful drags 128 if (src->SupportsAction(srckey)) { 129 src->PerformAction(srckey); 130 } 131 132 if (dst->SupportsAction(dstkey)) { 133 dst->PerformAction(dstkey); 134 } 135 } 136 } 137 }; 138 139 /** Variable length is 40-1 (zero terminator) */ 140 char VarName[MAX_VARIABLE_LENGTH]; 141 142 ControlAnimation* animation; 143 Holder<Sprite2D> AnimPicture; 144 145 /** Defines the Control ID Number used for GUI Scripting */ 146 ieDword ControlID; 147 /** Type of control */ 148 ieByte ControlType; 149 150 static unsigned int ActionRepeatDelay; 151 152 public: 153 explicit Control(const Region& frame); 154 ~Control() override; 155 IsAnimated()156 bool IsAnimated() const override { return animation && AnimPicture; } 157 bool IsOpaque() const override; 158 159 /** Sets the Text of the current control */ 160 void SetText(const String*); SetText(const String &)161 virtual void SetText(const String&) {}; 162 163 /** Update the control if it's tied to a GUI variable */ 164 void UpdateState(const char*, unsigned int); UpdateState(unsigned int)165 virtual void UpdateState(unsigned int) {} 166 167 /** Returns the Owner */ 168 virtual void SetFocus(); 169 bool IsFocused(); 170 TracksMouseDown()171 bool TracksMouseDown() const override { return bool(actionTimer); } 172 173 UniqueDragOp DragOperation() override; 174 bool AcceptsDragOperation(const DragOp&) const override; 175 virtual Holder<Sprite2D> DragCursor() const; 176 177 //Events 178 void SetAction(Responder handler, Action type, EventButton button = 0, 179 Event::EventMods mod = 0, short count = 0); 180 void SetAction(Responder handler, const ActionKey& key = ACTION_DEFAULT) override; 181 void SetActionInterval(unsigned int interval=ActionRepeatDelay); 182 183 bool PerformAction(); // perform default action (left mouse button up) 184 bool PerformAction(const ActionKey&) override; 185 bool SupportsAction(const ActionKey&) override; 186 QueryText()187 virtual String QueryText() const { return String(); } 188 /** Sets the animation picture ref */ 189 virtual void SetAnimPicture(Holder<Sprite2D> Picture); 190 191 typedef std::pair<ieDword, ieDword> ValueRange; 192 const static ValueRange MaxValueRange; 193 GetValue()194 ieDword GetValue() const { return Value; } GetValueRange()195 ValueRange GetValueRange() const { return range; } 196 197 void SetValue(ieDword val); 198 void SetValueRange(ValueRange range = MaxValueRange); 199 void SetValueRange(ieDword min, ieDword max = std::numeric_limits<ieDword>::max()); 200 201 bool HitTest(const Point& p) const override; 202 203 protected: 204 using ActionKey = ControlActionResponder::ActionKey; 205 struct ControlActionKey : public ActionKey { 206 static uint32_t BuildKeyValue(Control::Action type, Event::EventMods mod = 0, EventButton button = 0, short count = 0) { 207 // pack the parameters into the 32 bit key... 208 // we will only support the lower 8 bits for each, however. (more than enough for our purposes) 209 uint32_t key = 0; 210 uint32_t mask = 0x000000FF; 211 key |= type & mask; 212 key |= (mod & mask) << 8; 213 key |= (button & mask) << 16; 214 key |= (count & mask) << 24; 215 return key; 216 } 217 218 ControlActionKey(Control::Action type, Event::EventMods mod = 0, EventButton button = 0, short count = 0) ActionKeyControlActionKey219 : ActionKey(BuildKeyValue(type, mod, button, count) ) {} 220 }; 221 222 void FlagsChanged(unsigned int /*oldflags*/) override; 223 224 bool OnMouseUp(const MouseEvent& /*me*/, unsigned short /*Mod*/) override; 225 bool OnMouseDown(const MouseEvent& /*me*/, unsigned short /*Mod*/) override; 226 void OnMouseEnter(const MouseEvent& /*me*/, const DragOp*) override; 227 void OnMouseLeave(const MouseEvent& /*me*/, const DragOp*) override; 228 229 bool OnTouchDown(const TouchEvent& /*te*/, unsigned short /*Mod*/) override; 230 bool OnTouchUp(const TouchEvent& /*te*/, unsigned short /*Mod*/) override; 231 232 bool OnKeyPress(const KeyboardEvent& /*Key*/, unsigned short /*Mod*/) override; 233 234 private: 235 // if the input is held: fires the action at the interval specified by ActionRepeatDelay 236 // otherwise action fires on input release up only 237 unsigned int repeatDelay; 238 typedef std::map<ActionKey, ControlEventHandler>::iterator ActionIterator; 239 std::map<ActionKey, ControlEventHandler> actions; 240 Timer* actionTimer; 241 242 /** the value of the control to add to the variable */ 243 ieDword Value = CTL_INVALID_VALUE; 244 ValueRange range; 245 246 }; 247 248 249 } 250 251 #endif 252