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 GRAPHICS_MACGUI_MACWINDOWMANAGER_H
24 #define GRAPHICS_MACGUI_MACWINDOWMANAGER_H
25 
26 #include "common/hashmap.h"
27 #include "common/list.h"
28 #include "common/stack.h"
29 #include "common/events.h"
30 
31 #include "graphics/font.h"
32 #include "graphics/fontman.h"
33 #include "graphics/macgui/macwindow.h"
34 
35 #include "engines/engine.h"
36 
37 namespace Common {
38 class Archive;
39 }
40 
41 namespace Graphics {
42 
43 namespace MacGUIConstants {
44 enum {
45 	kDesktopArc = 7
46 };
47 
48 enum {
49 	kColorBlack = 0,
50 	kColorGray80 = 1,
51 	kColorGray88 = 2,
52 	kColorGrayEE = 3,
53 	kColorWhite = 4,
54 	kColorGreen = 5,
55 	kColorGreen2 = 6,
56 	kColorCount
57 };
58 
59 enum {
60 	kPatternSolid = 1,
61 	kPatternStripes = 2,
62 	kPatternCheckers = 3,
63 	kPatternCheckers2 = 4,
64 	kPatternLightGray = 5,
65 	kPatternDarkGray = 6
66 };
67 
68 enum MacCursorType {
69 	kMacCursorArrow,
70 	kMacCursorBeam,
71 	kMacCursorCrossHair,
72 	kMacCursorCrossBar,
73 	kMacCursorWatch,
74 	kMacCursorCustom,
75 	kMacCursorOff
76 };
77 
78 enum {
79 	kWMModeNone         	= 0,
80 	kWMModeNoDesktop    	= (1 << 0),
81 	kWMModeAutohideMenu 	= (1 << 1),
82 	kWMModalMenuMode 		= (1 << 2),
83 	kWMModeForceBuiltinFonts= (1 << 3),
84 	kWMModeUnicode			= (1 << 4),
85 	kWMModeManualDrawWidgets= (1 << 5),
86 	kWMModeFullscreen       = (1 << 6),
87 	kWMModeButtonDialogStyle= (1 << 7),
88 	kWMMode32bpp			= (1 << 8),
89 	kWMNoScummVMWallpaper   = (1 << 9),
90 	kWMModeWin95            = (1 << 10)
91 };
92 
93 }
94 using namespace MacGUIConstants;
95 
96 class Cursor;
97 
98 class ManagedSurface;
99 
100 class MacCursor;
101 class MacMenu;
102 class MacTextWindow;
103 class MacWidget;
104 
105 class MacFont;
106 
107 class MacFontManager;
108 
109 typedef Common::Array<byte *> MacPatterns;
110 
111 struct MacPlotData {
112 	Graphics::ManagedSurface *surface;
113 	Graphics::ManagedSurface *mask;
114 	MacPatterns *patterns;
115 	uint fillType;
116 	int fillOriginX;
117 	int fillOriginY;
118 	int thickness;
119 	uint bgColor;
120 	bool invert;
121 
122 	MacPlotData(Graphics::ManagedSurface *s, Graphics::ManagedSurface *m, MacPatterns *p, uint f, int fx, int fy, int t, uint bg, bool inv = false) :
surfaceMacPlotData123 		surface(s), mask(m), patterns(p), fillType(f), fillOriginX(fx), fillOriginY(fy), thickness(t), bgColor(bg), invert(inv) {
124 	}
125 };
126 
127 struct ZoomBox {
128 	Common::Rect start;
129 	Common::Rect end;
130 	Common::Array<Common::Rect> last;
131 	int delay;
132 	int step;
133 	uint32 startTime;
134 	uint32 nextTime;
135 };
136 
137 typedef void (* MacDrawPixPtr)(int, int, int, void *);
138 
139 /**
140  * A manager class to handle window creation, destruction,
141  * drawing, moving and event handling.
142  */
143 class MacWindowManager {
144 public:
145 	MacWindowManager(uint32 mode = 0, MacPatterns *patterns = nullptr, Common::Language language = Common::UNK_LANG);
146 	~MacWindowManager();
147 
148 	MacDrawPixPtr getDrawPixel();
149 	MacDrawPixPtr getDrawInvertPixel();
150 
151 	/**
152 	 * Mutator to indicate the surface onto which the desktop will be drawn.
153 	 * Note that this method should be called as soon as the WM is created.
154 	 * @param screen Surface on which the desktop will be drawn.
155 	 */
156 	void setScreen(ManagedSurface *screen);
157 
158 	/**
159 	 * Mutator to indicate the dimensions of the desktop, when a backing surface is not used.
160 	 * Note that this method should be called as soon as the WM is created.
161 	 * @param screen Surface on which the desktop will be drawn.
162 	 */
163 	void setScreen(int w, int h);
164 
165 	/**
166 	 * Create a window with the given parameters.
167 	 * Note that this method allocates the necessary memory for the window.
168 	 * @param scrollable True if the window has to be scrollable.
169 	 * @param resizable True if the window can be resized.
170 	 * @param editable True if the window can be edited.
171 	 * @return Pointer to the newly created window.
172 	 */
173 	MacWindow *addWindow(bool scrollable, bool resizable, bool editable);
174 	MacTextWindow *addTextWindow(const MacFont *font, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment, MacMenu *menu, bool cursorHandler = true);
175 	MacTextWindow *addTextWindow(const Font *font, int fgcolor, int bgcolor, int maxWidth, TextAlign textAlignment, MacMenu *menu, bool cursorHandler = true);
176 	void resizeScreen(int w, int h);
177 
178 	/**
179 	 * Adds a window that has already been initialized to the registry.
180 	 * Like addWindow, but this doesn't create/allocate the Window.
181 	 * @param macWindow the window to be added to the registry
182 	 */
183 	void addWindowInitialized(MacWindow *macwindow);
184 	/**
185 	 * Returns the last allocated id
186 	 * @return last allocated window id
187 	 */
getLastId()188 	int getLastId() { return _lastId; }
189 	/**
190 	 * Returns the next available id and the increments the internal counter.
191 	 * @return next (new) window id that can be used
192 	 */
getNextId()193 	int getNextId() { return _lastId++; }
194 	/**
195 	 * Add the menu to the desktop.
196 	 * Note that the returned menu is empty, and therefore must be filled
197 	 * afterwards.
198 	 * @return Pointer to a new empty menu.
199 	 */
200 	MacMenu *addMenu();
201 
202 	void removeMenu();
203 	void activateMenu();
204 
205 	void activateScreenCopy();
206 	void disableScreenCopy();
207 
208 	bool isMenuActive();
209 
210 	/**
211 	 * Set hot zone where menu appears (works only with autohide menu)
212 	 */
setMenuHotzone(const Common::Rect & rect)213 	void setMenuHotzone(const Common::Rect &rect) { _menuHotzone = rect; }
214 
215 	/**
216 	 * Set delay in milliseconds when menu appears (works only with autohide menu)
217 	 */
setMenuDelay(int delay)218 	void setMenuDelay(int delay) { _menuDelay = delay; }
219 
220 	/**
221 	 * Set the desired window state to active.
222 	 * @param id ID of the window that has to be set to active.
223 	 */
224 	void setActiveWindow(int id);
225 
226 	/**
227 	 * Mark a window for removal.
228 	 * Note that the window data will be destroyed.
229 	 * @param target Window to be removed.
230 	 */
231 	void removeWindow(MacWindow *target);
232 
233 	/**
234 	 * Mutator to indicate that the entire desktop must be refreshed.
235 	 * @param redraw Currently unused.
236 	 */
setFullRefresh(bool redraw)237 	void setFullRefresh(bool redraw) { _fullRefresh = redraw; }
238 
239 	/**
240 	 * Method to draw the desktop into the screen,
241 	 * It will take into accout the contents set as dirty.
242 	 * Note that this method does not refresh the screen,
243 	 * g_system must be called separately.
244 	 */
245 	void draw();
246 
247 	/**
248 	 * Method to process the events from the engine.
249 	 * Most often this method will be called from the engine's GUI, and
250 	 * will send the event to the relevant windows for them to process.
251 	 * @param event The event to be processed.
252 	 * @return True if the event was processed.
253 	 */
254 	bool processEvent(Common::Event &event);
255 
256 	/**
257 	 * Accessor to retrieve an arbitrary window.
258 	 * @param id The id of the desired window.
259 	 * @return Pointer to the requested window, if it exists.
260 	 */
getWindow(int id)261 	BaseMacWindow *getWindow(int id) { return _windows[id]; }
262 
263 	/**
264 	 * Retrieve the patterns used to fill surfaces.
265 	 * @return A MacPatterns object reference with the patterns.
266 	 */
getPatterns()267 	MacPatterns &getPatterns() { return _patterns; }
268 
269 	/**
270 	 * Sets an active widget, typically the one which steals the input
271 	 * It also sends deactivation message to the previous one
272 	 * @param widget Pointer to the widget to activate, nullptr for no widget
273 	 */
274 	void setActiveWidget(MacWidget *widget);
275 
getBuiltinPatterns()276 	MacPatterns  &getBuiltinPatterns() { return _builtinPatterns; }
277 
getActiveWidget()278 	MacWidget *getActiveWidget() { return _activeWidget; }
279 
getScreenBounds()280 	Common::Rect getScreenBounds() { return _screen ? _screen->getBounds() : _screenDims; }
281 
282 	void clearWidgetRefs(MacWidget *widget);
283 
284 private:
285 	void replaceCursorType(MacCursorType type);
286 
287 public:
288 	MacCursorType getCursorType() const;
289 
290 	void pushCursor(MacCursorType type, Cursor *cursor = nullptr);
291 	void replaceCursor(MacCursorType type, Cursor *cursor = nullptr);
292 
293 	void pushCustomCursor(const byte *data, int w, int h, int hx, int hy, int transcolor);
294 	void replaceCustomCursor(const byte *data, int w, int h, int hx, int hy, int transcolor);
295 	void pushCustomCursor(const Graphics::Cursor *cursor);
296 	void popCursor();
297 
298 	PauseToken pauseEngine();
299 
300 	void setMode(uint32 mode);
301 
302 	void setEngine(Engine *engine);
303 	void setEngineRedrawCallback(void *engine, void (*redrawCallback)(void *engine));
304 
305 	void passPalette(const byte *palette, uint size);
306 	uint findBestColor(byte cr, byte cg, byte cb);
307 	uint findBestColor(uint32 color);
308 	void decomposeColor(uint32 color, byte &r, byte &g, byte &b);
309 
310 	uint inverter(uint src);
311 
getPalette()312 	const byte *getPalette() { return _palette; }
getPaletteSize()313 	uint getPaletteSize() { return _paletteSize; }
314 
315 	void renderZoomBox(bool redraw = false);
316 	void addZoomBox(ZoomBox *box);
317 
318 	void removeMarked();
319 
320 	void loadDataBundle();
321 	void cleanupDataBundle();
322 	BorderOffsets getBorderOffsets(byte windowType);
323 	Common::SeekableReadStream *getBorderFile(byte windowType, uint32 flags);
324 	Common::SeekableReadStream *getFile(const Common::String &filename);
325 
326 	void setTextInClipboard(const Common::U32String &str);
327 	/**
328 	 * get text from WM clipboard or the global clipboard
329 	 * @param size will change to the length of real text in clipboard
330 	 * @return the text in clipboard, which may contained the format
331 	 */
332 	Common::U32String getTextFromClipboard(const Common::U32String &format = Common::U32String(), int *size = nullptr);
333 
334 	/**
335 	 * reset events for current widgets. i.e. we reset those variables which are used for handling events for macwidgets.
336 	 * e.g. we clear the active widget, set mouse down false, clear the hoveredWidget
337 	 * this function should be called when we are going to other level to handling events. thus wm may not handle events correctly.
338 	 */
339 	void clearHandlingWidgets();
340 
341 	void setMenuItemCheckMark(const Common::String &menuId, const Common::String &itemId, bool checkMark);
342 	void setMenuItemCheckMark(int menuId, int itemId, bool checkMark);
343 	void setMenuItemEnabled(const Common::String &menuId, const Common::String &itemId, bool enabled);
344 	void setMenuItemEnabled(int menuId, int itemId, bool enabled);
345 	void setMenuItemName(const Common::String &menuId, const Common::String &itemId, const Common::String &name);
346 	void setMenuItemName(int menuId, int itemId, const Common::String &name);
347 	void setMenuItemAction(const Common::String &menuId, const Common::String &itemId, int actionId);
348 	void setMenuItemAction(int menuId, int itemId, int actionId);
349 
350 	bool getMenuItemCheckMark(const Common::String &menuId, const Common::String &itemId);
351 	bool getMenuItemCheckMark(int menuId, int itemId);
352 	bool getMenuItemEnabled(const Common::String &menuId, const Common::String &itemId);
353 	bool getMenuItemEnabled(int menuId, int itemId);
354 	Common::String getMenuItemName(const Common::String &menuId, const Common::String &itemId);
355 	Common::String getMenuItemName(int menuId, int itemId);
356 	int getMenuItemAction(const Common::String &menuId, const Common::String &itemId);
357 	int getMenuItemAction(int menuId, int itemId);
358 
359 public:
360 	MacFontManager *_fontMan;
361 	uint32 _mode;
362 	Common::Language _language;
363 
364 	Common::Point _lastClickPos;
365 	Common::Point _lastMousePos;
366 	Common::Rect _menuHotzone;
367 
368 	bool _menuTimerActive;
369 	bool _mouseDown;
370 
371 	uint32 _colorBlack, _colorGray80, _colorGray88, _colorGrayEE, _colorWhite, _colorGreen, _colorGreen2;
372 
373 	MacWidget *_hoveredWidget;
374 
375 	// we use it to indicate whether we are clicking the hilite-able widget.
376 	// In list style button mode, we will highlight the subsequent buttons only when we've clicked the hilite-able button initially
377 	bool _hilitingWidget;
378 
379 private:
380 	void loadDesktop();
381 	void drawDesktop();
382 
383 	void removeFromStack(BaseMacWindow *target);
384 	void removeFromWindowList(BaseMacWindow *target);
385 
386 	void zoomBoxInner(Common::Rect &r, Graphics::MacPlotData &pd);
haveZoomBox()387 	bool haveZoomBox() { return !_zoomBoxes.empty(); }
388 
389 	void adjustDimensions(const Common::Rect &clip, const Common::Rect &dims, int &adjWidth, int &adjHeight);
390 
391 public:
392 	TransparentSurface *_desktopBmp;
393 	ManagedSurface *_desktop;
394 	PixelFormat _pixelformat;
395 
396 	ManagedSurface *_screen;
397 	ManagedSurface *_screenCopy;
398 	Common::Rect _screenDims;
399 
400 private:
401 	Common::List<BaseMacWindow *> _windowStack;
402 	Common::HashMap<uint, BaseMacWindow *> _windows;
403 
404 	Common::List<BaseMacWindow *> _windowsToRemove;
405 	bool _needsRemoval;
406 
407 	int _lastId;
408 	int _activeWindow;
409 
410 	bool _fullRefresh;
411 
412 	bool _inEditableArea;
413 
414 	MacPatterns _patterns;
415 	MacPatterns _builtinPatterns;
416 	byte *_palette;
417 	uint _paletteSize;
418 
419 	MacMenu *_menu;
420 	uint32 _menuDelay;
421 
422 	Engine *_engineP;
423 	void *_engineR;
424 	void (*_redrawEngineCallback)(void *engine);
425 
426 	MacCursorType _tempType;
427 	Common::Stack<MacCursorType> _cursorTypeStack;
428 	Cursor *_cursor;
429 
430 	MacWidget *_activeWidget;
431 
432 	PauseToken *_screenCopyPauseToken;
433 
434 	Common::Array<ZoomBox *> _zoomBoxes;
435 	Common::HashMap<uint, uint> _colorHash;
436 	Common::HashMap<uint, uint> _invertColorHash;
437 
438 	Common::Archive *_dataBundle;
439 
440 	Common::U32String _clipboard;
441 };
442 
443 } // End of namespace Graphics
444 
445 #endif
446