1 /* GemRB - Infinity Engine Emulator
2  * Copyright (C) 2015 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 #ifndef __GemRB__WindowManager__
20 #define __GemRB__WindowManager__
21 
22 #include "Audio.h"
23 #include "EventMgr.h"
24 #include "Resource.h"
25 #include "Sprite2D.h"
26 #include "Tooltip.h"
27 #include "Video.h"
28 
29 #include <deque>
30 
31 namespace GemRB {
32 
33 class Sprite2D;
34 class Window;
35 
36 using WindowList = std::deque<Window*>;
37 
38 struct ToolTipData
39 {
40 	Tooltip tt;
41 	unsigned long time = 0;
42 	Holder<SoundHandle> tooltip_sound;
43 	bool reset = false;
44 
ToolTipDataToolTipData45 	ToolTipData(Tooltip tt)
46 	: tt(std::move(tt)) {}
47 };
48 
49 class WindowManager {
50 public:
51 	// Colors of modal window shadow
52 	// !!! Keep these synchronized with GUIDefines.py !!!
53 	enum ModalShadow {
54 		ShadowNone = 0,
55 		ShadowGray,
56 		ShadowBlack
57 	};
58 
59 	enum CursorFeedback {
60 		MOUSE_ALL			= 0,
61 		MOUSE_NO_CURSOR		= 1,
62 		MOUSE_NO_TOOLTIPS	= 2,
63 		MOUSE_NONE			= MOUSE_NO_CURSOR|MOUSE_NO_TOOLTIPS
64 	} cursorFeedback;
65 
66 	static Holder<Sprite2D> CursorMouseUp;
67 	static Holder<Sprite2D> CursorMouseDown;
68 
69 	Color FadeColor;
70 
71 	struct HUDLock {
72 		const WindowManager& wm;
73 
HUDLockHUDLock74 		HUDLock(WindowManager& wm)
75 		: wm(wm) {
76 			wm.video->PushDrawingBuffer(wm.HUDBuf);
77 		}
78 
~HUDLockHUDLock79 		~HUDLock() {
80 			wm.video->PopDrawingBuffer();
81 		}
82 	};
83 
84 private:
85 	WindowList windows;
86 	WindowList closedWindows; // windows that have been closed. kept around temporarily in case they get reopened
87 
88 	Region screen; // only a Region for convinience. we dont use x,y
89 	Window* modalWin;
90 	Window* gameWin;
91 	Window* hoverWin;
92 	Window* trackingWin;
93 
94 	EventMgr eventMgr;
95 
96 	Holder<Video> video;
97 	VideoBufferPtr HUDBuf = nullptr; // heads up display layer. Contains cursors/tooltips/borders and whatever gets drawn via DrawHUD()
98 	ModalShadow modalShadow = ShadowNone;
99 
100 	// these are mutable instead of statice because Sprite2Ds must be released before the video driver is unloaded
101 	mutable ToolTipData tooltip;
102 	mutable std::map<ResRef, Holder<Sprite2D>> winframes;
103 
104 	static int ToolTipDelay;
105 	static unsigned long TooltipTime;
106 
107 private:
108 	bool IsOpenWindow(Window* win) const;
109 	Holder<Sprite2D> WinFrameEdge(int edge) const;
110 
111 	inline void DrawWindowFrame(BlitFlags flags) const;
112 	inline void DrawMouse() const;
113 	// DrawMouse simply calls the following with some position calculations and buffer context changes
114 	inline void DrawCursor(const Point& pos) const;
115 	inline void DrawTooltip(Point pos) const;
116 
117 	Window* NextEventWindow(const Event& event, WindowList::const_iterator& current);
118 	bool DispatchEvent(const Event&);
119 	bool HotKey(const Event&);
120 
121 	inline void DestroyWindows(WindowList& list);
122 
123 public:
124 	WindowManager(Video* vid);
125 	~WindowManager();
126 
127 	WindowManager(const WindowManager&) = delete;
128 
129 	Window* MakeWindow(const Region& rgn);
130 	void CloseWindow(Window* win);
131 	void DestroyAllWindows();
132 
133 	bool OrderFront(Window* win);
134 	bool OrderBack(Window* win);
135 	bool OrderRelativeTo(Window* win, Window* win2, bool front);
136 
137 	bool FocusWindow(Window* win);
138 	bool IsPresentingModalWindow() const;
139 	bool PresentModalWindow(Window* win, ModalShadow Shadow = ShadowNone);
140 
141 	CursorFeedback SetCursorFeedback(CursorFeedback feedback);
142 
143 	// all drawing will be done directly on the screen until DrawingLock is destoryed
144 	HUDLock DrawHUD();
145 
146 	/*
147 	 Drawing is done in layers:
148 	 1. Game Window is drawn
149 	 2. Normal Windows are drawn (in order)
150 	 3. the window frame and modalShield is drawn (if applicable)
151 	 4. modalWindow is drawn (if applicable)
152 	 5. cursor and tooltip are drawn (if applicable)
153 	*/
154 	void DrawWindows() const;
155 
ScreenSize()156 	Size ScreenSize() const { return screen.Dimensions(); }
157 
158 	Holder<Sprite2D> GetScreenshot(Window* win);
GetGameWindow()159 	Window* GetGameWindow() const { return gameWin; }
160 	Window* GetFocusWindow() const;
161 
162 	GEM_EXPORT static void SetTooltipDelay(int);
163 };
164 
165 
166 }
167 
168 #endif /* defined(__GemRB__WindowManager__) */
169