ScummVM API documentation
panel.h
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 modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (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, see <http://www.gnu.org/licenses/>.
19  *
20  *
21  * Based on the original sources
22  * Faery Tale II -- The Halls of the Dead
23  * (c) 1993-1996 The Wyrmkeep Entertainment Co.
24  */
25 
26 #ifndef SAGA2_PANEL_H
27 #define SAGA2_PANEL_H
28 
29 #include "saga2/input.h"
30 #include "saga2/vdraw.h"
31 
32 namespace Common {
33 struct Event;
34 }
35 
36 namespace Saga2 {
37 // Fix problem with DOS's encroachment on name space that should
38 // rightfully belong to the application programmer.
39 
40 #ifdef enable
41 #undef enable
42 #undef disable
43 #endif
44 
45 /* ===================================================================== *
46  Cursor Cycling Stuff
47  * ===================================================================== */
48 
49 void cycleCursor();
50 
51 /* ===================================================================== *
52  Forward declarations
53  * ===================================================================== */
54 
55 class gPanel;
56 class gPanelList;
57 class gPanelMessage;
58 class gWindow;
59 
60 /* ===================================================================== *
61  Input dispatching functions
62  * ===================================================================== */
63 
64 void HandleTimerTick(long newTick);
65 void EventLoop(bool &running, bool modal = false);
66 
67 /* ===================================================================== *
68  Constants
69  * ===================================================================== */
70 
71 enum gEventType {
72  kEventNone = 0, // no event occurred
73  kEventMouseDown, // left button pressed
74  kEventMouseUp, // left button released
75  kEventRMouseDown, // right button pressed
76  kEventRMouseUp, // right button released
77  kEventMouseMove, // mouse moved
78  kEventMouseDrag, // mouse dragged
79  kEventMouseOutside, // mouse click outside of window
80  kEventKeyDown, // keystroke
81 
82  kEventNewValue, // object had new value
83  kEventDoubleClick, // double-clicked on object
84  kEventAltValue, // for multi-function objects
85 
86  kEventLast
87 };
88 
89 /* ===================================================================== *
90  gEvent: returns input events to the user
91  * ===================================================================== */
92 
93 struct gEvent {
94  gPanel *panel; // where event came from
95  gEventType eventType; // type of event that occurred
96  Point16 mouse; // mouse position
97  int32 value; // new value of control
98  gWindow *window; // active window
99 };
100 
101 typedef void AppFunc(gEvent &);
102 
103 #ifndef __WATCOMC__
104 #define APPFUNCDECL __cdecl
105 #else
106 #define APPFUNCDECL
107 #endif
108 
109 #define APPFUNC(a) void a ( gEvent &ev )
110 #define APPFUNCV(a) void a ( gEvent & )
111 
112 // Note: panels in this system are not, in general, resizeable
113 
114 /* ===================================================================== *
115  gPanel class: The basic user interface element
116  * ===================================================================== */
117 
118 class gPanel {
119  friend class gToolBase;
120  friend class gWindow;
121 
122  AppFunc *_command; // application function
123 protected:
124  gWindow &_window; // window this belongs to
125  Rect16 _extent; // rectangular bounds of the control
126  const char *_title; // title of the panel
127  byte _enabled, // allows disabling the panel
128  _selected, // some panels have a selected state
129  _imageLabel, // button label is image, not text
130  _ghosted, // button is dimmed
131  _wantMousePoll; // send mousemoves even if mouse not moving!
132 
133  // window constructor
134  gPanel(gWindow &, const Rect16 &, AppFunc *cmd);
135 
136 public:
137  uint32 _id; // panel id number
138  void *_userData; // data for this panel
139 
140  // constructor
141  gPanel(gPanelList &, const Rect16 &, const char *, uint16, AppFunc *cmd = NULL);
142  gPanel(gPanelList &, const Rect16 &, gPixelMap &, uint16, AppFunc *cmd = NULL);
143 
144  gPanel(gPanelList &, const StaticRect &, const char *, uint16, AppFunc *cmd = NULL);
145  virtual ~gPanel(); // destructor
146 
147  virtual gPanel *hitTest(const Point16 &p);
148  virtual gPanel *keyTest(int16 key);
149 
150 protected:
151  virtual void pointerMove(gPanelMessage &msg);
152  virtual bool pointerHit(gPanelMessage &msg);
153  virtual bool pointerRHit(gPanelMessage &msg);
154  virtual void pointerDrag(gPanelMessage &msg);
155  virtual void pointerRelease(gPanelMessage &msg);
156  virtual bool keyStroke(gPanelMessage &msg);
157  virtual void timerTick(gPanelMessage &msg);
158  virtual void onMouseHintDelay();
159 
160  void notify(gEventType, int32 value);
161  void notify(gEvent &ev) {
162  if (_command) _command(ev);
163  }
164  void drawTitle(TextPositions placement);
165 
166 
167 public:
168  bool isActive(); // true if we are active panel
169  virtual bool activate(gEventType why); // activate the control
170  virtual void deactivate(); // deactivate the control
171  virtual void draw(); // redraw the panel.
172  virtual void enable(bool abled);
173  virtual void select(uint16 selected);
174  virtual void ghost(bool ghosted);
175  virtual void invalidate(Rect16 *area = nullptr);
176  virtual void setMousePoll(bool abled) {
177  _wantMousePoll = abled ? 1 : 0;
178  }
179 
180  // Redraw the panel, but only a small clipped section,
181  // and perhaps drawn onto an off-screen map.
182  virtual void drawClipped(
183  gPort &port,
184  const Point16 &offset,
185  const Rect16 &r);
186 
187 // void setCommand( AppFunc *func ) { command = func; }
188  gWindow *getWindow() {
189  return &_window;
190  }
191  void makeActive();
192  Rect16 getExtent() {
193  return _extent;
194  }
195  bool isSelected() {
196  return _selected != 0;
197  }
198  bool isGhosted() {
199  return _ghosted != 0;
200  }
201  bool getEnabled() const {
202  return (bool)_enabled;
203  }
204  void show(bool shown = true, bool inval = true) {
205  enable(shown);
206  if (inval)
207  invalidate();
208  }
209 
210  void moveToFront(gPanelList &l);
211  void moveToBack(gPanelList &l);
212 };
213 
214 /* ===================================================================== *
215  gPanelMessage class: How user input is distributes to panels
216  * ===================================================================== */
217 
219 public:
220  Point16 _pickPos, // mouse position relative to panel
221  _pickAbsPos; // mouse position relative to display
222  byte _leftButton, // left button state
223  _rightButton, // right button state
224  _inPanel, // whether mouse is currently in panel
225  _pointerEnter, // set when pointer enters panel
226  _pointerLeave, // set when pointer leaves panel
227  _doubleClick; // set when double click detected
228 
229  // For keyboard input
230 
231  uint16 _key, // keystroke from keyboard
232  _qualifier; // qualifier from keyboard
233 
234  uint32 _timeStamp; // time of message
235 
236  gPanelMessage() {
237  _leftButton = 0;
238  _rightButton = 0;
239  _inPanel = 0;
240  _pointerEnter = 0;
241  _pointerLeave = 0;
242  _doubleClick = 0;
243  _key = 0;
244  _qualifier = 0;
245  _timeStamp = 0;
246  }
247 };
248 
249 /* ===================================================================== *
250  gPanelList class: A list of panels
251  * ===================================================================== */
252 
253 class gControl;
254 
255 class gPanelList : public gPanel {
256 
257  friend class gControl;
258  friend class gToolBase;
259 
260  friend void gPanel::moveToFront(gPanelList &l);
261  friend void gPanel::moveToBack(gPanelList &l);
262 
263 protected:
264 
265  Common::List<gPanel *> _contents; // list of panels
266 
267  gPanelList(gWindow &, const Rect16 &, char *, uint16, AppFunc *cmd = NULL);
268 
269 public:
270 
272  ~gPanelList();
273 
274  gPanel *hitTest(const Point16 &p);
275  gPanel *keyTest(int16 key);
276  void removeControls();
277 
278 public:
279  void invalidate(Rect16 *area = nullptr);
280  void draw(); // redraw the controls
281  void drawClipped(
282  gPort &port,
283  const Point16 &offset,
284  const Rect16 &r);
285 
286  void enable(bool abled); // enable list and all children
287 // void setPointer( gPixelMap &map, int x, int y );
288 };
289 
290 inline void gPanel::moveToFront(gPanelList &l) {
291  l._contents.remove(this);
292  l._contents.push_front(this);
293 }
294 
295 inline void gPanel::moveToBack(gPanelList &l) {
296  l._contents.remove(this);
297  l._contents.push_back(this);
298 }
299 
300 /* ===================================================================== *
301  gWindow class: A context for holding panels.
302  * ===================================================================== */
303 
304 /*
305 enum windowFeatures {
306  windowTitleBar = (1<<0), // window has a title bar
307  windowCanDrag = (1<<1), // window is draggable
308 // windowVisible = (1<<2), // window is visible
309 // windowBackSaved = (1<<3), // backsave data under window
310 // windowCloseBox = (1<<4), // create a close box
311 // windowNoBorder = (1<<5), // window with no border
312 };
313 */
314 
315 class gWindow : public gPanelList {
316 
317  friend class gControl;
318  friend class gPanel;
319  friend class gToolBase;
320 
321 public:
322  gDisplayPort _windowPort;
323 
324  gWindow(const Rect16 &, uint16, const char saveName[], AppFunc *cmd = NULL);
325  ~gWindow();
326 
327  operator gPort() {
328  return _windowPort;
329  }
330  void postEvent(gEvent &ev) {
331  gPanel::notify(ev);
332  }
333 
334 protected:
335  bool _openFlag; // true if window open.
336 
337  //gWindowWinInfoInINIFile saver;
338 
339 private:
340  bool activate(gEventType why); // activate the control
341  void deactivate();
342 
343  void pointerMove(gPanelMessage &msg);
344  bool pointerHit(gPanelMessage &msg);
345  void pointerDrag(gPanelMessage &msg);
346  void pointerRelease(gPanelMessage &msg);
347 
348  // Dragging modes for window -- private and static!
349 
350  enum drag_modes {
351  kDragNone = 0,
352  kDragPosition
353  };
354 
355  static int _dragMode; // current dragging mode
356  static StaticRect _dragExtent; // dragging extent
357  static StaticPoint16 _dragOffset; // offset to window origin
358 
359  void shadow();
360 
361 public:
362  void setExtent(const Rect16 &); // set window position and size
363  Rect16 getExtent() {
364  return _extent; // set window position and size
365  }
366 protected:
367  void setPos(Point16 pos); // set window position
368  void insert(); // insert window into window list
369  virtual void toFront(); // re-order the windows
370 
371 public:
372  bool isOpen() {
373  return _openFlag; // true if window is visible
374  }
375  void draw(); // redraw the panel.
376  void drawClipped(
377  gPort &port,
378  const Point16 &offset,
379  const Rect16 &r);
380 
381  // Redraw the window, but only a small clipped section,
382  // and perhaps drawn onto an off-screen map.
383 // void drawClipped(
384 // gPort &port,
385 // const Point16 &offset,
386 // const Rect16 &r );
387 
388  void enable(bool abled);
389  void select(uint16 sel); // activate the window
390 
391  virtual bool open();
392  virtual void close();
393  virtual bool isModal();
394 
395  // Update a region of a window, and all floaters which
396  // might be above that window.
397  virtual void update(const Rect16 &updateRect) = 0;
398 
399 // void setPointer( gPixelMap &map, int x, int y );
400 };
401 
402 /* ===================================================================== *
403  gControl class: The basis for buttons and other controls.
404  * ===================================================================== */
405 
406 class gControl : public gPanel {
407 public:
408  uint8 _accelKey;
409  gPanelList *_list;
410 
411  gControl(gPanelList &, const Rect16 &, const char *, uint16, AppFunc *cmd = NULL);
412  gControl(gPanelList &, const Rect16 &, gPixelMap &, uint16, AppFunc *cmd = NULL);
413 
414  gControl(gPanelList &, const StaticRect &, const char *, uint16, AppFunc *cmd = NULL);
415  ~gControl(); // destructor
416 
417  gPanel *keyTest(int16 key);
418 
419  void enable(bool abled); // enable the control
420  void select(uint16 sel); // selecte the control
421  void ghost(bool ghosted);
422 // virtual void newValue( void );
423 
424  void draw(); // redraw the control.
425 };
426 
427 /* ===================================================================== *
428  gGenericControl class: A generic button that notifies everything
429  * ===================================================================== */
430 
431 class gGenericControl : public gControl {
432  bool _dblClickFlag;
433 
434 public:
435  gGenericControl(gPanelList &, const Rect16 &, uint16, AppFunc *cmd = NULL);
436 
437  // Disable double click for next mouse click
438  void disableDblClick() {
439  _dblClickFlag = true;
440  }
441 
442  enum controlValue {
443  kCVEnter = (1 << 0),
444  kCVLeave = (1 << 1)
445  };
446 
447 protected:
448  bool activate(gEventType why); // activate the control
449  void deactivate();
450 
451  void pointerMove(gPanelMessage &msg);
452  bool pointerHit(gPanelMessage &msg);
453  void pointerDrag(gPanelMessage &msg);
454  void pointerRelease(gPanelMessage &msg);
455 
456  void draw(); // redraw the control.
457 };
458 
459 
460 /* ===================================================================== *
461  gToolBase class: The primary dispatcher for user interface events
462  * ===================================================================== */
463 
464 void setMouseTextF(char *format, ...);
465 void LockUI(bool state);
466 
467 class gToolBase {
468  friend class gWindow;
469  friend class gPanel;
470  friend void EventLoop(bool &running);
471  friend int16 leftButtonState();
472  friend int16 rightButtonState();
473  friend void StageModeCleanup();
474  friend void TileModeCleanup();
475  friend void dumpGBASE(char *msg);
476 
477  // windows
478 
479  Common::List<gWindow *> _windowList; // list of windows
480  gWindow *_mouseWindow, // window mouse is in
481  *_activeWindow; // current active window
482  gPanel *_mousePanel, // panel that mouse is in
483  *_activePanel; // panel that has input focus
484  Rect16 _dragRect; // dragging rectangle for windows
485  Point16 _pickPos; // mouse pos relative to panel
486  uint8 _leftDrag, // left-button dragging
487  _rightDrag; // right button dragging
488  gPanelMessage _msg; // message that we send out
489 
490  int32 _lastMouseMoveTime; // time of last mouse move
491 
492  gMouseState _curMouseState;
493 
494 public:
495  bool _mouseHintSet; // true if mouse hint is up.
496 
497  gToolBase() {
498  _mouseWindow = nullptr;
499  _activeWindow = nullptr;
500  _mousePanel = nullptr;
501  _activePanel = nullptr;
502  _leftDrag = 0;
503  _rightDrag = 0;
504  _lastMouseMoveTime = 0;
505  }
506 
507 private:
508  void setMsgQ(gPanelMessage &msg_, gPanel *panel) {
509  if (panel == &panel->_window)
510  msg_._pickPos = _pickPos;
511  else {
512  _msg._pickPos.x = (int16)(_pickPos.x - panel->_extent.x);
513  _msg._pickPos.y = (int16)(_pickPos.y - panel->_extent.y);
514  }
515  }
516 
517  void setMsg(gPanelMessage &msg_, gPanel *panel) {
518  setMsgQ(msg_, panel);
519  _msg._inPanel = (msg_._pickPos.x >= 0
520  && msg_._pickPos.y >= 0
521  && msg_._pickPos.x < panel->_extent.width
522  && msg_._pickPos.y < panel->_extent.height);
523  // panel->extent.ptInside( pickPos );
524  }
525 
526 public:
527  void setActive(gPanel *newActive);
528  void leavePanel(); // we're changing windows
529 public:
530  void handleMouse(Common::Event &event, uint32 time);
531  void handleKeyStroke(Common::Event &event);
532  void handleTimerTick(int32 tick);
533  Common::List<gWindow *>::iterator topWindowIterator() {
534  return _windowList.end();
535  }
536  Common::List<gWindow *>::iterator bottomWindowIterator() {
537  return _windowList.reverse_begin();
538  }
539  gWindow *topWindow() {
540  return _windowList.front();
541  }
542  gWindow *bottomWindow() {
543  return _windowList.back();
544  }
545  bool isMousePanel(gPanel *p) {
546  return (_mousePanel != NULL) ? (p == _mousePanel) : (p == topWindow());
547  }
548 };
549 
550 /* ===================================================================== *
551  Application functions to call for event handling
552  * ===================================================================== */
553 
554 void EventLoop(bool &running);
555 void initPanels(gDisplayPort &port);
556 void cleanupPanels();
557 
558 //void writeHelpLine( char *msg, ... );
559 
560 int16 leftButtonState();
561 int16 rightButtonState();
562 
563 // Kludge structure to contain both a mouse event and a time stamp
565  gMouseState st;
566  int32 time;
567 };
568 
569 } // end of namespace Saga2
570 
571 #endif
Definition: panel.h:118
Definition: input.h:42
Definition: panel.h:93
Definition: actor.h:32
Definition: gdraw.h:56
Definition: gdraw.h:178
Definition: vdraw.h:33
Definition: list.h:44
Definition: panel.h:315
Definition: rect.h:282
Definition: panel.h:431
t_T & back()
Definition: list.h:167
Definition: panel.h:467
iterator end()
Definition: list.h:240
Definition: rect.h:42
Definition: panel.h:255
Definition: events.h:199
Definition: algorithm.h:29
t_T & front()
Definition: list.h:157
Definition: panel.h:218
iterator reverse_begin()
Definition: list.h:235
Definition: panel.h:564
Definition: list_intern.h:51
Definition: rect.h:33
Definition: rect.h:290
Definition: panel.h:406