File: Window.h

package info (click to toggle)
storm-lang 0.7.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,028 kB
  • sloc: ansic: 261,471; cpp: 140,432; sh: 14,891; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (349 lines) | stat: -rw-r--r-- 12,474 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
#pragma once
#include "Message.h"
#include "Handle.h"
#include "Font.h"
#include "Key.h"
#include "Mouse.h"
#include "Core/Timing.h"
#include "Core/TObject.h"
#include "Utils/Bitmask.h"

namespace gui {
	class ContainerBase;
	class Frame;
	class Painter;
	class Timer;

	// Modifiers for the create function.
	enum CreateFlags {
		cNormal = 0x0,
		cManualVisibility = 0x1,
		cAutoPos = 0x2,
		// For use in Win32: Subclass the control.
		cWin32Subclass = 0x100,
	};

	BITMASK_OPERATORS(CreateFlags);


	/**
	 * Base class for windows and controls.
	 *
	 * The Window class itself creates a plain, empty window that can be used for drawing custom
	 * controls. The underlying window is not created directly, instead it is delayed until the
	 * window has been attached to a parent of some sort. The exception from this rule are Frames,
	 * which has no parents and therefore require special attention (see documentation for Frame).
	 *
	 * The fact that windows are not created until attached are hidden as good as possible. This
	 * means that we have to cache all properties as good as possible until the window is actually
	 * created.
	 *
	 * All windows have exactly one parent, except for frames which have none (technically their
	 * parent are the desktop, but we do not implement that here). Re-parenting of windows is not
	 * supported. The 'root' member of a Frame is set to the object itself.
	 */
	class Window : public ObjectOn<Ui> {
		STORM_CLASS;
	public:
		// Create an empty window.
		STORM_CTOR Window();

		// Destroy.
		virtual ~Window();

		// Invalid window handle.
		static const Handle invalid;

		// Get our handle. May be 'invalid'.
		Handle handle() const;

		// Set our handle, our parent is inferred from the handle itself.
		void handle(Handle handle);

		// Are we created?
		bool created() const { return handle() != invalid; }

		// Get the parent window. Null for frames.
		MAYBE(ContainerBase *) STORM_FN parent();

		// Get the frame that is in the root of the hierarchy. Returns ourself for frames, returns `null` before attached.
		MAYBE(Frame *) STORM_FN rootFrame();

		// Attach to a parent container and creation. To be called from 'container'.
		void attachParent(ContainerBase *parent);

		// Detach from our parent. This destroys the window.
		void detachParent();

		// Called when this window has been destroyed. This function is intended as a notification
		// for child classes in C++ (eg. Container). If you want to be notified when the window is
		// about to be destroyed, handle WM_CLOSE instead.
		virtual void windowDestroyed();

		// Note: 'parent' need to be set before calling this function. This initializes the creation of our window.
		virtual void parentCreated(nat id);

#ifdef GUI_WIN32
		// Called when a regular message has been received. If no result is returned, calls the
		// default window proc, or any message procedure declared by the window we're handling. Only
		// works for windows with the default window class provided by App. Otherwise, use 'beforeMessage'.
		virtual MsgResult onMessage(const Message &msg);

		// Called before a message is dispatched to the window procedure. Return a result to inhibit the regular
		// dispatch. Note: This only happens for messages that are posted from outside the process.
		virtual MsgResult beforeMessage(const Message &msg);

		// Called after messages that were marked as 'notify' from 'onMessage'.
		virtual void afterMessage(const Message &msg);

		// Called when a WM_COMMAND has been sent to (by) us. Return 'true' if it is handled. Type
		// is the notification code specified by the message (eg BN_CLICK).
		virtual bool onCommand(nat type);

		// Called when a WM_NOTIFY has been sent to (by) us. Return 'true' if it is handled. The
		// parameter is the header for notify as sent in the message. This can be casted to a
		// relevant struct to receive more information.
		virtual bool onNotify(NMHDR *data);

		// Get the current DPI for this window. Only makes sense on Windows.
		virtual Nat currentDpi();

		// Update this window to new DPI settings (i.e., "currentDpi()" has changed).
		virtual void updateDpi(Bool move);

		// Get the background color of this window as a brush. This is used to account for
		// containers that draw a different background color than the default dialog color.
		virtual void windowBackground(HBRUSH &brush, COLORREF &color);

#endif
#ifdef GUI_GTK
		// Called when we received an EXPOSE event, but before Gtk+ is informed about the
		// event. Return 'true' to inhibit the Gtk+ behaviour completely.
		bool preExpose(GtkWidget *widget);

		// Call to update the minimum size as seen by GTK. This is only relevant to do when asking
		// GTK about the preferred size of something that contains this window. Also, it is only
		// necessary for Containers with custom (manual) layout. This function calls 'minSize' to
		// ask Storm for the minimum size to use.
		virtual void updateGtkMinSize();
#endif

		// Check if the window is visible.
		Bool STORM_FN visible();

		// Set if the window is visible or not. Assignment function, so `visible` can be used as a member variable.
		void STORM_ASSIGN visible(Bool show);

		// Check if the window is enabled.
		Bool STORM_FN enabled();

		// Set if the window is enabled. Generally only interesting to do for leaf windows.
		// Assignment function, so it can be used as a member variable.
		void STORM_ASSIGN enabled(Bool enable);

		// Get the window text. How this text is used depends on the window.
		virtual Str *STORM_FN text();

		// Set the window text. Assignment function, so it can be used as a member variable.
		virtual void STORM_ASSIGN text(Str *str);

		// Get the window position. Always relative to the client area of the parent (even in Frames).
		virtual Rect STORM_FN pos();

		// Set the window position.
		virtual void STORM_ASSIGN pos(Rect r);

		// Get the minimum size for this window. Note: This does not consider the size and position
		// of any child windows in case this is a container. This function is mostly useful for
		// determining the preferred size for various windows.
		virtual Size STORM_FN minSize();

		// Get the current font.
		Font *STORM_FN font();

		// Set the current font. Assignment function, so it can be used as a member variable.
		void STORM_ASSIGN font(Font *font);

		// Set focus to this window.
		virtual void STORM_FN focus();

		// Update the window (ie repaint it) right now.
		virtual void STORM_FN update();

		// Repaint the window when we have time.
		virtual void STORM_FN repaint();

		// Called when the window is resized.
		virtual void STORM_FN resized(Size size);

		// Convenience function to trigger uptade of layouts easily.
		void STORM_FN resized();

		// Called when a key is pressed or released (depending on `pressed`). Should return `true`
		// if the keypress was recognized and should not propagate further.
		virtual Bool STORM_FN onKey(Bool pressed, key::Key keycode, mod::Modifiers modifiers);

		// Called when a key has been typed. Note that this is sometimes different from a key press
		// event. A typical example is a dead key. The dead key will produce `onKey` events as
		// usual, but will not produce a `onChar` event until the next keypress, when it might be
		// combined with the next character. Another example is when using an IME.
		virtual Bool STORM_FN onChar(Nat charCode);

		// Called when a mouse button has been pressed or released (depending on `pressed`) at the
		// location `at` in the window.
		virtual Bool STORM_FN onClick(Bool pressed, Point at, mouse::MouseButton button);

		// Called when a mouse button has been double-clicked in the window.
		virtual Bool STORM_FN onDblClick(Point at, mouse::MouseButton button);

		// Called whenever the mouse is moved in the window.
		virtual Bool STORM_FN onMouseMove(Point at);

		// Called when the mouse has been scrolled in the vertical direction.
		virtual Bool STORM_FN onMouseVScroll(Point at, Int delta);

		// Called when the mouse has been scrolled in the horizontal direction.
		virtual Bool STORM_FN onMouseHScroll(Point at, Int delta);

		// Called when the mouse entered this window. The mouse is considered to be inside the
		// window only for as long as the mouse is directly on top of the window. For example, if
		// the mouse moves over a child window, the mouse is no longer considered to be inside of
		// this window.
		virtual void STORM_FN onMouseEnter();

		// Called when the mouse has left this window.
		virtual void STORM_FN onMouseLeave();

		// Set window contents (custom drawing).
		void STORM_ASSIGN painter(MAYBE(Painter *) to);

		// Get the current painter.
		MAYBE(Painter *) STORM_FN painter();

		// Called regularly if the `setTimer` has been called to start the timer.
		virtual void STORM_FN onTimer();

		// Set the window timer. Causes `onTimer` to be called regularly.
		void STORM_FN setTimer(Duration interval);

		// Stop timer.
		void STORM_FN clearTimer();

	protected:
		// Override this to do any special window creation. The default implementation creates a
		// plain child window with no window class. Called as soon as we know our parent (not on
		// Frames). Returns 'false' on failure.
		virtual bool create(ContainerBase *parent, nat id);

		// Internal 'resized' notification.
		virtual void onResize(Size size);

		// Destroy a handle.
		virtual void destroyWindow(Handle handle);

#ifdef GUI_WIN32
		// Create a window, and handle it. Makes sure that all messages are handled correctly.
		// Equivalent to handle(CreateWindowEx(...)), but ensures that any messages sent before
		// CreateWindowEx returns are sent to this class as well.
		// If NULL is passed as the class name, the default window class will be used.
		bool createEx(LPCTSTR className, DWORD style, DWORD exStyle, HWND parent, nat id, CreateFlags flags);
		bool createEx(LPCTSTR className, DWORD style, DWORD exStyle, HWND parent, nat id);
		bool createEx(LPCTSTR className, DWORD style, DWORD exStyle, HWND parent);
#endif
#ifdef GUI_GTK
		// Called to perform initialization of the recently created widget. Performs things such as
		// setting visibility, text and position. Also calls 'handle()' on the widget.
		void initWidget(ContainerBase *parent, GtkWidget *widget);

		// Initialize any signals required by the Window class.
		virtual void initSignals(GtkWidget *widget, GtkWidget *draw);

		// Get the widget we shall set the font on.
		virtual GtkWidget *fontWidget();

	public:
		// Get the widget we shall draw on.
		virtual GtkWidget *drawWidget();
#endif
	private:
		// Handle.
		Handle myHandle;

		// Parent.
		ContainerBase *myParent;

		// Root.
		Frame *myRoot;

		// Visible?
		Bool myVisible;

		// Enabled.
		Bool myEnabled;

		// Currently drawing anything to this window?
		Bool drawing;

		// Is the mouse inside this window? (Used on Win32 to implement enter/leave notifications)
		Bool mouseInside;

		// Text.
		Str *myText;

	protected:
		// Position (Frame needs to modify this).
		Rect myPos;

	private:
		// Font.
		Font *myFont;

		// Painter.
		Painter *myPainter;

		// Last allocated width and height. Used to filter out duplicate allocate messages.
		int lastWidth;
		int lastHeight;

		// In Gtk+, widgets are usually not rendered in separate windows. When we're using OpenGL
		// rendering, we need separate windows for the widget being drawn to, and any child
		// widgets. This variable represents the created window.
		UNKNOWN(PTR_NOGC) GdkWindow *gdkWindow;

		// In Gtk+, we need to allocate a timer object separatly.
		UNKNOWN(PTR_NOGC) Timer *gTimer;

		// Timer timeout (nonzero = set).
		Duration timerInterval;

		// Prepare for a painter/prepare for no painter. Not called when we swap painter.
		void attachPainter();
		void detachPainter();

#ifdef GUI_WIN32
		// Handle on paint events.
		MsgResult onPaint();
#endif
#ifdef GUI_GTK
		// Signal landing pads.
		gboolean onKeyUp(GdkEvent *event);
		gboolean onKeyDown(GdkEvent *event);
		gboolean onButton(GdkEvent *event);
		gboolean onMotion(GdkEvent *event);
		gboolean onEnter(GdkEvent *event);
		gboolean onLeave(GdkEvent *event);
		gboolean onScroll(GdkEvent *event);
		void onSize(GdkRectangle *alloc);
		gboolean onDraw(cairo_t *ctx);
		void onRealize();
		void onUnrealize();

		// Set window mask.
		void setWindowMask(GdkWindow *window);

		// Do we need to be a separate native window? Called during realization.
		bool useNativeWindow();
#endif
	};

}