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