1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef GUIMANAGER_H
24 #define GUIMANAGER_H
25 
26 #include "common/scummsys.h"
27 #include "common/singleton.h"
28 #include "common/stack.h"
29 #include "common/str.h"
30 #include "common/list.h"
31 
32 #include "gui/ThemeEngine.h"
33 #include "gui/widget.h"
34 
35 class OSystem;
36 
37 namespace Graphics {
38 class Font;
39 }
40 
41 namespace Common {
42 	struct Event;
43 	class Keymap;
44 }
45 
46 namespace GUI {
47 
48 class Dialog;
49 class ThemeEval;
50 class GuiObject;
51 
52 #define g_gui	(GUI::GuiManager::instance())
53 
54 
55 // Height of a single text line
56 #define kLineHeight	(g_gui.getFontHeight() + 2)
57 
58 
59 
60 // Simple dialog stack class
61 // Anybody nesting dialogs deeper than 4 is mad anyway
62 typedef Common::FixedStack<Dialog *> DialogStack;
63 
64 
65 /**
66  * GUI manager singleton.
67  */
68 class GuiManager : public Common::Singleton<GuiManager> {
69 	friend class Dialog;
70 	friend class Common::Singleton<SingletonBaseType>;
71 	GuiManager();
72 	~GuiManager() override;
73 public:
74 
75 	// Main entry for the GUI: this will start an event loop that keeps running
76 	// until no dialogs are active anymore.
77 	void runLoop();
78 
79 	// If the GUI loop is running close all the dialogs causing the loop to finish.
80 	// Typically you may want to use it after setting the ConfMan active domain to
81 	// a game domain to cause the game to start.
82 	void exitLoop();
83 
84 	void processEvent(const Common::Event &event, Dialog *const activeDialog);
85 	Common::Keymap *getKeymap() const;
86 	void scheduleTopDialogRedraw();
87 
isActive()88 	bool isActive() const	{ return ! _dialogStack.empty(); }
89 
90 	bool loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx = ThemeEngine::kGfxDisabled, bool force = false);
theme()91 	ThemeEngine *theme() { return _theme; }
92 
xmlEval()93 	ThemeEval *xmlEval() { return _theme->getEvaluator(); }
94 
getGUIWidth()95 	int16 getGUIWidth() const { return _baseWidth; }
getGUIHeight()96 	int16 getGUIHeight() const { return _baseHeight; }
getScaleFactor()97 	float getScaleFactor() const { return _scaleFactor; }
98 	void computeScaleFactor();
99 
useRTL()100 	bool useRTL() const { return _useRTL; }
101 	void setLanguageRTL();
102 
103 	void setDialogPaddings(int l, int r);
getOverlayOffset()104 	int getOverlayOffset() { return _topDialogRightPadding - _topDialogLeftPadding; }
105 
106 	const Graphics::Font &getFont(ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return *(_theme->getFont(style)); }
107 	int getFontHeight(ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return _theme->getFontHeight(style); }
108 	int getStringWidth(const Common::String &str, ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return _theme->getStringWidth(str, style); }
109 	int getStringWidth(const Common::U32String &str, ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return _theme->getStringWidth(str, style); }
110 	int getCharWidth(byte c, ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return _theme->getCharWidth(c, style); }
111 	int getKerningOffset(byte left, byte right, ThemeEngine::FontStyle font = ThemeEngine::kFontStyleBold) const { return _theme->getKerningOffset(left, right, font); }
112 
113 	/**
114 	 * Tell the GuiManager to check whether the screen resolution has changed.
115 	 * If that is the case, the GuiManager will reload/refresh the active theme.
116 	 *
117 	 * @return true if the a screen change indeed occurred, false otherwise
118 	 */
119 	bool checkScreenChange();
120 
121 	/**
122 	 * Tell the GuiManager to delete the given GuiObject later. If a parent
123 	 * dialog is provided and is present in the DialogStack, the object will
124 	 * only be deleted when that dialog is the top level dialog.
125 	 */
126 	void addToTrash(GuiObject*, Dialog* parent = nullptr);
127 	void initTextToSpeech();
128 
129 	bool _launched;
130 
131 	void redrawFull();
132 
133 protected:
134 	enum RedrawStatus {
135 		kRedrawDisabled = 0,
136 		kRedrawOpenDialog,
137 		kRedrawCloseDialog,
138 		kRedrawTopDialog,
139 		kRedrawFull
140 	};
141 
142 	OSystem			*_system;
143 
144 	ThemeEngine		*_theme;
145 
146 //	bool		_needRedraw;
147 	RedrawStatus _redrawStatus;
148 	int			_lastScreenChangeID;
149 	int16		_baseWidth, _baseHeight;
150 	float		_scaleFactor;
151 	DialogStack	_dialogStack;
152 
153 	bool		_stateIsSaved;
154 
155 	bool		_useStdCursor;
156 
157 	bool		_useRTL;
158 
159 	int			_topDialogLeftPadding;
160 	int			_topDialogRightPadding;
161 
162 	// position and time of last mouse click (used to detect double clicks)
163 	struct MousePos {
MousePosMousePos164 		MousePos() : x(-1), y(-1), count(0) { time = 0; }
165 		int16 x, y;	// Position of mouse when the click occurred
166 		uint32 time;	// Time
167 		int count;	// How often was it already pressed?
168 	} _lastClick, _lastMousePosition, _globalMousePosition;
169 
170 	struct TooltipData {
TooltipDataTooltipData171 		TooltipData() : x(-1), y(-1) { time = 0; wdg = nullptr; }
172 		uint32 time; // Time
173 		Widget *wdg; // Widget that had its tooltip shown
174 		int16 x, y;  // Position of mouse before tooltip was focused
175 	} _lastTooltipShown;
176 
177 	// mouse cursor state
178 	int		_cursorAnimateCounter;
179 	int		_cursorAnimateTimer;
180 	byte	_cursor[2048];
181 
182 	// delayed deletion of GuiObject
183 	struct GuiObjectTrashItem {
184 		GuiObject* object;
185 		Dialog* parent;
186 	};
187 	Common::List<GuiObjectTrashItem> _guiObjectTrash;
188 
189 	void initKeymap();
190 	void enableKeymap(bool enabled);
191 
192 	void saveState();
193 	void restoreState();
194 
195 	void openDialog(Dialog *dialog);
196 	void closeTopDialog();
197 
198 	void redraw();
199 
200 	void setupCursor();
201 	void animateCursor();
202 
203 	Dialog *getTopDialog() const;
204 
205 	void screenChange();
206 
207 	void giveFocusToDialog(Dialog *dialog);
208 	void setLastMousePos(int16 x, int16 y);
209 };
210 
211 } // End of namespace GUI
212 
213 #endif
214