1 /*
2  * This file is part of gtkD.
3  *
4  * gtkD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 3
7  * of the License, or (at your option) any later version, with
8  * some exceptions, please read the COPYING file.
9  *
10  * gtkD is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with gtkD; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
18  */
19 
20 // generated automatically - do not change
21 // find conversion definition on APILookup.txt
22 // implement new conversion functionalities on the wrap.utils pakage
23 
24 
25 module gtk.GLArea;
26 
27 private import gdk.GLContext;
28 private import glib.ConstructionException;
29 private import glib.ErrorG;
30 private import gobject.ObjectG;
31 private import gobject.Signals;
32 private import gtk.Widget;
33 public  import gtkc.gdktypes;
34 private import gtkc.gtk;
35 public  import gtkc.gtktypes;
36 
37 
38 /**
39  * #GtkGLArea is a widget that allows drawing with OpenGL.
40  * 
41  * #GtkGLArea sets up its own #GdkGLContext for the window it creates, and
42  * creates a custom GL framebuffer that the widget will do GL rendering onto.
43  * It also ensures that this framebuffer is the default GL rendering target
44  * when rendering.
45  * 
46  * In order to draw, you have to connect to the #GtkGLArea::render signal,
47  * or subclass #GtkGLArea and override the @GtkGLAreaClass.render() virtual
48  * function.
49  * 
50  * The #GtkGLArea widget ensures that the #GdkGLContext is associated with
51  * the widget's drawing area, and it is kept updated when the size and
52  * position of the drawing area changes.
53  * 
54  * ## Drawing with GtkGLArea ##
55  * 
56  * The simplest way to draw using OpenGL commands in a #GtkGLArea is to
57  * create a widget instance and connect to the #GtkGLArea::render signal:
58  * 
59  * |[<!-- language="C" -->
60  * // create a GtkGLArea instance
61  * GtkWidget *gl_area = gtk_gl_area_new ();
62  * 
63  * // connect to the "render" signal
64  * g_signal_connect (gl_area, "render", G_CALLBACK (render), NULL);
65  * ]|
66  * 
67  * The `render()` function will be called when the #GtkGLArea is ready
68  * for you to draw its content:
69  * 
70  * |[<!-- language="C" -->
71  * static gboolean
72  * render (GtkGLArea *area, GdkGLContext *context)
73  * {
74  * // inside this function it's safe to use GL; the given
75  * // #GdkGLContext has been made current to the drawable
76  * // surface used by the #GtkGLArea and the viewport has
77  * // already been set to be the size of the allocation
78  * 
79  * // we can start by clearing the buffer
80  * glClearColor (0, 0, 0, 0);
81  * glClear (GL_COLOR_BUFFER_BIT);
82  * 
83  * // draw your object
84  * draw_an_object ();
85  * 
86  * // we completed our drawing; the draw commands will be
87  * // flushed at the end of the signal emission chain, and
88  * // the buffers will be drawn on the window
89  * return TRUE;
90  * }
91  * ]|
92  * 
93  * If you need to initialize OpenGL state, e.g. buffer objects or
94  * shaders, you should use the #GtkWidget::realize signal; you
95  * can use the #GtkWidget::unrealize signal to clean up.
96  * 
97  * If you need to change the options for creating the #GdkGLContext
98  * you should use the #GtkGLArea::create-context signal.
99  *
100  * Since: 3.16
101  */
102 public class GLArea : Widget
103 {
104 	/** the main Gtk struct */
105 	protected GtkGLArea* gtkGLArea;
106 
107 	/** Get the main Gtk struct */
108 	public GtkGLArea* getGLAreaStruct()
109 	{
110 		return gtkGLArea;
111 	}
112 
113 	/** the main Gtk struct as a void* */
114 	protected override void* getStruct()
115 	{
116 		return cast(void*)gtkGLArea;
117 	}
118 
119 	protected override void setStruct(GObject* obj)
120 	{
121 		gtkGLArea = cast(GtkGLArea*)obj;
122 		super.setStruct(obj);
123 	}
124 
125 	/**
126 	 * Sets our main struct and passes it to the parent class.
127 	 */
128 	public this (GtkGLArea* gtkGLArea, bool ownedRef = false)
129 	{
130 		this.gtkGLArea = gtkGLArea;
131 		super(cast(GtkWidget*)gtkGLArea, ownedRef);
132 	}
133 
134 	/**
135 	 */
136 
137 	public static GType getType()
138 	{
139 		return gtk_gl_area_get_type();
140 	}
141 
142 	/**
143 	 * Creates a new #GtkGLArea widget.
144 	 *
145 	 * Return: the newly created #GtkGLArea
146 	 *
147 	 * Since: 3.16
148 	 *
149 	 * Throws: ConstructionException GTK+ fails to create the object.
150 	 */
151 	public this()
152 	{
153 		auto p = gtk_gl_area_new();
154 		
155 		if(p is null)
156 		{
157 			throw new ConstructionException("null returned by new");
158 		}
159 		
160 		this(cast(GtkGLArea*) p, true);
161 	}
162 
163 	/**
164 	 * Ensures that the @area framebuffer object is made the current draw
165 	 * and read target, and that all the required buffers for the @area
166 	 * are created and bound to the frambuffer.
167 	 *
168 	 * This function is automatically called before emitting the
169 	 * #GtkGLArea::render signal, and doesn't normally need to be called
170 	 * by application code.
171 	 *
172 	 * Since: 3.16
173 	 */
174 	public void attachBuffers()
175 	{
176 		gtk_gl_area_attach_buffers(gtkGLArea);
177 	}
178 
179 	/**
180 	 * Returns whether the area is in auto render mode or not.
181 	 *
182 	 * Return: %TRUE if the @area is auto rendering, %FALSE otherwise
183 	 *
184 	 * Since: 3.16
185 	 */
186 	public bool getAutoRender()
187 	{
188 		return gtk_gl_area_get_auto_render(gtkGLArea) != 0;
189 	}
190 
191 	/**
192 	 * Retrieves the #GdkGLContext used by @area.
193 	 *
194 	 * Return: the #GdkGLContext
195 	 *
196 	 * Since: 3.16
197 	 */
198 	public GLContext getContext()
199 	{
200 		auto p = gtk_gl_area_get_context(gtkGLArea);
201 		
202 		if(p is null)
203 		{
204 			return null;
205 		}
206 		
207 		return ObjectG.getDObject!(GLContext)(cast(GdkGLContext*) p);
208 	}
209 
210 	/**
211 	 * Gets the current error set on the @area.
212 	 *
213 	 * Return: the #GError or %NULL
214 	 *
215 	 * Since: 3.16
216 	 */
217 	public ErrorG getError()
218 	{
219 		auto p = gtk_gl_area_get_error(gtkGLArea);
220 		
221 		if(p is null)
222 		{
223 			return null;
224 		}
225 		
226 		return new ErrorG(cast(GError*) p);
227 	}
228 
229 	/**
230 	 * Returns whether the area has an alpha component.
231 	 *
232 	 * Return: %TRUE if the @area has an alpha component, %FALSE otherwise
233 	 *
234 	 * Since: 3.16
235 	 */
236 	public bool getHasAlpha()
237 	{
238 		return gtk_gl_area_get_has_alpha(gtkGLArea) != 0;
239 	}
240 
241 	/**
242 	 * Returns whether the area has a depth buffer.
243 	 *
244 	 * Return: %TRUE if the @area has a depth buffer, %FALSE otherwise
245 	 *
246 	 * Since: 3.16
247 	 */
248 	public bool getHasDepthBuffer()
249 	{
250 		return gtk_gl_area_get_has_depth_buffer(gtkGLArea) != 0;
251 	}
252 
253 	/**
254 	 * Returns whether the area has a stencil buffer.
255 	 *
256 	 * Return: %TRUE if the @area has a stencil buffer, %FALSE otherwise
257 	 *
258 	 * Since: 3.16
259 	 */
260 	public bool getHasStencilBuffer()
261 	{
262 		return gtk_gl_area_get_has_stencil_buffer(gtkGLArea) != 0;
263 	}
264 
265 	/**
266 	 * Retrieves the required version of OpenGL set
267 	 * using gtk_gl_area_set_required_version().
268 	 *
269 	 * Params:
270 	 *     major = return location for the required major version
271 	 *     minor = return location for the required minor version
272 	 *
273 	 * Since: 3.16
274 	 */
275 	public void getRequiredVersion(out int major, out int minor)
276 	{
277 		gtk_gl_area_get_required_version(gtkGLArea, &major, &minor);
278 	}
279 
280 	/**
281 	 * Ensures that the #GdkGLContext used by @area is associated with
282 	 * the #GtkGLArea.
283 	 *
284 	 * This function is automatically called before emitting the
285 	 * #GtkGLArea::render signal, and doesn't normally need to be called
286 	 * by application code.
287 	 *
288 	 * Since: 3.16
289 	 */
290 	public void makeCurrent()
291 	{
292 		gtk_gl_area_make_current(gtkGLArea);
293 	}
294 
295 	/**
296 	 * Marks the currently rendered data (if any) as invalid, and queues
297 	 * a redraw of the widget, ensuring that the #GtkGLArea::render signal
298 	 * is emitted during the draw.
299 	 *
300 	 * This is only needed when the gtk_gl_area_set_auto_render() has
301 	 * been called with a %FALSE value. The default behaviour is to
302 	 * emit #GtkGLArea::render on each draw.
303 	 *
304 	 * Since: 3.16
305 	 */
306 	public void queueRender()
307 	{
308 		gtk_gl_area_queue_render(gtkGLArea);
309 	}
310 
311 	/**
312 	 * If @auto_render is %TRUE the #GtkGLArea::render signal will be
313 	 * emitted every time the widget draws. This is the default and is
314 	 * useful if drawing the widget is faster.
315 	 *
316 	 * If @auto_render is %FALSE the data from previous rendering is kept
317 	 * around and will be used for drawing the widget the next time,
318 	 * unless the window is resized. In order to force a rendering
319 	 * gtk_gl_area_queue_render() must be called. This mode is useful when
320 	 * the scene changes seldomly, but takes a long time to redraw.
321 	 *
322 	 * Params:
323 	 *     autoRender = a boolean
324 	 *
325 	 * Since: 3.16
326 	 */
327 	public void setAutoRender(bool autoRender)
328 	{
329 		gtk_gl_area_set_auto_render(gtkGLArea, autoRender);
330 	}
331 
332 	/**
333 	 * Sets an error on the area which will be shown instead of the
334 	 * GL rendering. This is useful in the #GtkGLArea::create-context
335 	 * signal if GL context creation fails.
336 	 *
337 	 * Params:
338 	 *     error = a new #GError, or %NULL to unset the error
339 	 *
340 	 * Since: 3.16
341 	 */
342 	public void setError(ErrorG error)
343 	{
344 		gtk_gl_area_set_error(gtkGLArea, (error is null) ? null : error.getErrorGStruct());
345 	}
346 
347 	/**
348 	 * If @has_alpha is %TRUE the buffer allocated by the widget will have
349 	 * an alpha channel component, and when rendering to the window the
350 	 * result will be composited over whatever is below the widget.
351 	 *
352 	 * If @has_alpha is %FALSE there will be no alpha channel, and the
353 	 * buffer will fully replace anything below the widget.
354 	 *
355 	 * Params:
356 	 *     hasAlpha = %TRUE to add an alpha component
357 	 *
358 	 * Since: 3.16
359 	 */
360 	public void setHasAlpha(bool hasAlpha)
361 	{
362 		gtk_gl_area_set_has_alpha(gtkGLArea, hasAlpha);
363 	}
364 
365 	/**
366 	 * If @has_depth_buffer is %TRUE the widget will allocate and
367 	 * enable a depth buffer for the target framebuffer. Otherwise
368 	 * there will be none.
369 	 *
370 	 * Params:
371 	 *     hasDepthBuffer = %TRUE to add a depth buffer
372 	 *
373 	 * Since: 3.16
374 	 */
375 	public void setHasDepthBuffer(bool hasDepthBuffer)
376 	{
377 		gtk_gl_area_set_has_depth_buffer(gtkGLArea, hasDepthBuffer);
378 	}
379 
380 	/**
381 	 * If @has_stencil_buffer is %TRUE the widget will allocate and
382 	 * enable a stencil buffer for the target framebuffer. Otherwise
383 	 * there will be none.
384 	 *
385 	 * Params:
386 	 *     hasStencilBuffer = %TRUE to add a stencil buffer
387 	 *
388 	 * Since: 3.16
389 	 */
390 	public void setHasStencilBuffer(bool hasStencilBuffer)
391 	{
392 		gtk_gl_area_set_has_stencil_buffer(gtkGLArea, hasStencilBuffer);
393 	}
394 
395 	/**
396 	 * Sets the required version of OpenGL to be used when creating the context
397 	 * for the widget.
398 	 *
399 	 * This function must be called before the area has been realized.
400 	 *
401 	 * Params:
402 	 *     major = the major version
403 	 *     minor = the minor version
404 	 *
405 	 * Since: 3.16
406 	 */
407 	public void setRequiredVersion(int major, int minor)
408 	{
409 		gtk_gl_area_set_required_version(gtkGLArea, major, minor);
410 	}
411 
412 	int[string] connectedSignals;
413 
414 	GLContext delegate(GLArea)[] onCreateContextListeners;
415 	/**
416 	 * The ::create-context signal is emitted when the widget is being
417 	 * realized, and allows you to override how the GL context is
418 	 * created. This is useful when you want to reuse an existing GL
419 	 * context, or if you want to try creating different kinds of GL
420 	 * options.
421 	 *
422 	 * If context creation fails then the signal handler can use
423 	 * gtk_gl_area_set_error() to register a more detailed error
424 	 * of how the construction failed.
425 	 *
426 	 * Return: a newly created #GdkGLContext;
427 	 *     the #GtkGLArea widget will take ownership of the returned value.
428 	 *
429 	 * Since: 3.16
430 	 */
431 	void addOnCreateContext(GLContext delegate(GLArea) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
432 	{
433 		if ( "create-context" !in connectedSignals )
434 		{
435 			Signals.connectData(
436 				this,
437 				"create-context",
438 				cast(GCallback)&callBackCreateContext,
439 				cast(void*)this,
440 				null,
441 				connectFlags);
442 			connectedSignals["create-context"] = 1;
443 		}
444 		onCreateContextListeners ~= dlg;
445 	}
446 	extern(C) static GdkGLContext* callBackCreateContext(GtkGLArea* glareaStruct, GLArea _glarea)
447 	{
448 		foreach ( GLContext delegate(GLArea) dlg; _glarea.onCreateContextListeners )
449 		{
450 			if ( auto r = dlg(_glarea) )
451 				return r.getGLContextStruct();
452 		}
453 		
454 		return null;
455 	}
456 
457 	bool delegate(GLContext, GLArea)[] onRenderListeners;
458 	/**
459 	 * The ::render signal is emitted every time the contents
460 	 * of the #GtkGLArea should be redrawn.
461 	 *
462 	 * The @context is bound to the @area prior to emitting this function,
463 	 * and the buffers are painted to the window once the emission terminates.
464 	 *
465 	 * Params:
466 	 *     context = the #GdkGLContext used by @area
467 	 *
468 	 * Return: %TRUE to stop other handlers from being invoked for the event.
469 	 *     %FALSE to propagate the event further.
470 	 *
471 	 * Since: 3.16
472 	 */
473 	void addOnRender(bool delegate(GLContext, GLArea) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
474 	{
475 		if ( "render" !in connectedSignals )
476 		{
477 			Signals.connectData(
478 				this,
479 				"render",
480 				cast(GCallback)&callBackRender,
481 				cast(void*)this,
482 				null,
483 				connectFlags);
484 			connectedSignals["render"] = 1;
485 		}
486 		onRenderListeners ~= dlg;
487 	}
488 	extern(C) static int callBackRender(GtkGLArea* glareaStruct, GdkGLContext* context, GLArea _glarea)
489 	{
490 		foreach ( bool delegate(GLContext, GLArea) dlg; _glarea.onRenderListeners )
491 		{
492 			if ( dlg(ObjectG.getDObject!(GLContext)(context), _glarea) )
493 			{
494 				return 1;
495 			}
496 		}
497 		
498 		return 0;
499 	}
500 
501 	void delegate(int, int, GLArea)[] onResizeListeners;
502 	void addOnResize(void delegate(int, int, GLArea) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
503 	{
504 		if ( "resize" !in connectedSignals )
505 		{
506 			Signals.connectData(
507 				this,
508 				"resize",
509 				cast(GCallback)&callBackResize,
510 				cast(void*)this,
511 				null,
512 				connectFlags);
513 			connectedSignals["resize"] = 1;
514 		}
515 		onResizeListeners ~= dlg;
516 	}
517 	extern(C) static void callBackResize(GtkGLArea* glareaStruct, int object, int p0, GLArea _glarea)
518 	{
519 		foreach ( void delegate(int, int, GLArea) dlg; _glarea.onResizeListeners )
520 		{
521 			dlg(object, p0, _glarea);
522 		}
523 	}
524 }