1 #pragma once
2 
3 #ifndef SCREENBOARD_H
4 #define SCREENBOARD_H
5 
6 #include "tcommon.h"
7 
8 #include <QWidget>
9 #include <QList>
10 
11 #undef DVAPI
12 #undef DVVAR
13 #ifdef TOONZQT_EXPORTS
14 #define DVAPI DV_EXPORT_API
15 #define DVVAR DV_EXPORT_VAR
16 #else
17 #define DVAPI DV_IMPORT_API
18 #define DVVAR DV_IMPORT_VAR
19 #endif
20 
21 namespace DVGui {
22 
23 //****************************************************************************
24 //    ScreenBoard class
25 //****************************************************************************
26 
27 //! The ScreenBoard is a singleton class that allows self-drawing objects to
28 //! be rendered on the whole desktop surface.
29 
30 /*! The Qt Framework does not provide a standard way to draw directly on the
31     desktop.
32 \n\n
33     Typically, users have to allocate a QWidget to host any drawing command
34     to be rendered - but the rendering surface only covers the entirety of the
35     widget geometry, and nothing more.
36 
37     Plus, the maximal drawing geometry should be known in advance when using a
38     host widget, or else heavy flickering will result from attempts to move
39     \a and resize the widget to cover new portions of the desktop.
40 \n\n
41     Another important use for the ScreenBoard is that of allowing dektop-wide
42 mouse
43     grabbing through the grabMouse() and releaseMouse() functions.
44 \n\n
45     The ScreenBoard stores a private collection of static, inert and transparent
46     <I> screen widgets <\I>, each overlapping a desktop screen, to be used as
47     drawable surfaces for self-drawing objects (ScreenBoard::Drawing instances)
48     that are added to the board.
49 \n\n
50     Drawings can be added to the board by direct manipulation of the drawings()
51     container list.
52 
53     Use the update() method to refresh the screen after drawing insertions or
54     removals.
55 \n\n
56     Screen widgets redirect any event they receive to drawings that accept
57 redirection
58     through the Drawings::accpetScreenEvents() method.
59 
60     The drawings() list sorting affects the order in which events from screen
61 widgets
62     are delivered to drawings.
63 
64     In particular, drawings' <I> stacking order <\I> is \b inverse to the their
65 list
66     ordering - so, paint events are received in \b reverse with respect to other
67     events. Event acceptance is ignored to determine event delivery to drawings.
68 \n\n
69     Observe that upon every update() invocation, the screen widgets pool will
70     be refreshed to keep it to a minimum.
71 */
72 
73 class DVAPI ScreenBoard final : public QObject {
74   Q_OBJECT
75 
76 public:
77   class Drawing;
78 
79 private:
80   class ScreenWidget;
81 
82   QVector<ScreenWidget *> m_screenWidgets;
83   QList<Drawing *> m_drawings;
84 
85   QCursor m_cursor;
86 
87   bool m_grabbing;
88   bool m_mouseOnAScreen;
89   bool m_updated;
90 
91 public:
92   static ScreenBoard *instance();
93 
drawings()94   const QList<Drawing *> &drawings() const { return m_drawings; }
drawings()95   QList<Drawing *> &drawings() { return m_drawings; }
96 
97   void grabMouse(
98       const QCursor &cursor);  //!< Grabs mouse inputs across the whole desktop.
99   void releaseMouse();         //!< Releases the mouse grab after grabMouse().
100 
grabbingMouse()101   bool grabbingMouse() const {
102     return m_grabbing;
103   }  //!< Whether mouse grabbing is on.
104 
105 private:
106   ScreenBoard();
107 
108   void reallocScreenWidgets();
109   void ensureMouseOnAScreen();
110 
111 public slots:
112 
113   void update();  //!< Refreshes the screen widgets pool and updates them.
114 
115 private slots:
116 
117   friend class ScreenWidget;
118 
119   void trackCursor();
120   void doUpdate();
121 };
122 
123 //****************************************************************************
124 //    ScreenBoard::Drawing class
125 //****************************************************************************
126 
127 //! ScreenDrawing is the base class for objects that can be painted directly
128 //! in screen coordinates through the ScreenBoard.
129 class ScreenBoard::Drawing {
130 public:
131   //! Generic event handler for drawings.
132   /*! Reimplement it to receive events from screen widgets other than paint
133 events.
134 Paint events are \b not received in this handler, since they must be delivered
135 in reverse order.
136 */
event(QWidget * widget,QEvent * e)137   virtual void event(QWidget *widget, QEvent *e) {}
138 
139   //! Paints the drawing on the specified screen widget. Use the widget's
140   //! mapFromGlobal() function to match desktop coordinates to screen
141   //! coordinates.
142   virtual void paintEvent(QWidget *widget, QPaintEvent *pe) = 0;
143 
144   //! Returns whether the drawing is interested in events from the passed screen
145   //! geometry.
146   //! Accepting a screen causes a screen widget to be allocated in order to
147   //! receive events.
148   virtual bool acceptScreenEvents(const QRect &screenRect) const = 0;
149 };
150 
151 }  // namespace DVGui
152 
153 #endif  // SCREENBOARD_H
154