Graphviz 13.1.3~dev.20250905.1412
Loading...
Searching...
No Matches
gltemplate.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include <stdbool.h>
12#include <stdlib.h>
13#include <math.h>
14#include "gui/gui.h"
15#include "viewport.h"
16#include "gltemplate.h"
17#include <glcomp/glutils.h>
18#include <util/exit.h>
19#include <util/list.h>
20#include "glexpose.h"
21#include "glmotion.h"
22
23#include <glcomp/glcompset.h>
24#include "viewportcamera.h"
25#include "gui/menucallbacks.h"
26#include "arcball.h"
27#include "gui/appmouse.h"
28static float begin_x = 0.0;
29static float begin_y = 0.0;
30
31/*mouse mode mapping funvtion from gtk to glcomp*/
33{
34 switch (n) {
35 case 1:
36 return glMouseLeftButton;
37 case 2:
39 case 3:
40 return glMouseRightButton;
41
42 default:
43 return glMouseLeftButton;
44 }
45}
46
47/*
48 initialize the gl , run only once!!
49 params:gtk opgn gl canvas and optional data pointer
50 return value:none
51*/
52static void realize(GtkWidget *widget, void *data) {
53 (void)data;
54
55 GdkGLContext *glcontext = gtk_widget_get_gl_context(widget);
56 GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget);
57
58 /*smyrna does not use any ligthting affects but can be turned on for more effects in the future */
59 float ambient[] = {0.0f, 0.0f, 0.0f, 1.0f};
60 float diffuse[] = {0.5f, 0.5f, 0.5f, 1.0f};
61 float position[] = {0.0f, 3.0f, 3.0f, 0.0f};
62
63 float lmodel_ambient[] = {0.2f, 0.2f, 0.2f, 1.0f};
64 float local_view[] = {0.0f};
65
66 /*** OpenGL BEGIN ***/
67 if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
68 return;
69
70 glClearColor((float)view->bgColor.R, (float)view->bgColor.G,
71 (float)view->bgColor.B, (float)view->bgColor.A); // background color
72 glClearDepth(1.0);
73 glClear(GL_COLOR_BUFFER_BIT);
74
75
76 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
77 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
78 glLightfv(GL_LIGHT0, GL_POSITION, position);
79 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
80 glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);
81
82 glFrontFace(GL_CW);
83 glEnable(GL_BLEND);
84 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
85 gdk_gl_drawable_gl_end(gldrawable);
86 /*** OpenGL END ***/
87}
88
89/*
90 set up GL for window size changes, run this when necesary (when window size or monitor resolution is changed)
91 params:gtk opgn gl canvas , GdkEventConfigure object to retrieve window dimensions and custom data
92 return value:true or false, fails (false) if cannot init gl
93*/
94static gboolean configure_event(GtkWidget *widget, GdkEventConfigure *event,
95 void *data) {
96 (void)event;
97 (void)data;
98
99 int vPort[4];
100 float aspect;
101 GdkGLContext *glcontext = gtk_widget_get_gl_context(widget);
102 GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget);
103 view->w = widget->allocation.width;
104 view->h = widget->allocation.height;
105 if (view->widgets)
107
108
109 /*** OpenGL BEGIN ***/
110 if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
111 return FALSE;
112 glViewport(0, 0, view->w, view->h);
113 /* get current viewport */
114 glGetIntegerv(GL_VIEWPORT, vPort);
115 /* setup various opengl things that we need */
116 glMatrixMode(GL_PROJECTION);
117 glLoadIdentity();
118 if (widget->allocation.width > 1)
120
121 if (view->w > view->h) {
122 aspect = (float) view->w / (float) view->h;
123 glOrtho(-aspect * GL_VIEWPORT_FACTOR, aspect * GL_VIEWPORT_FACTOR,
124 GL_VIEWPORT_FACTOR * -1, GL_VIEWPORT_FACTOR, -1500, 1500);
125 } else {
126 aspect = (float) view->h / (float) view->w;
128 -aspect * GL_VIEWPORT_FACTOR, aspect * GL_VIEWPORT_FACTOR,
129 -1500, 1500);
130 }
131
132 glMatrixMode(GL_MODELVIEW);
133 gdk_gl_drawable_gl_end(gldrawable);
134 /*** OpenGL END ***/
135
136
137 return TRUE;
138}
139
140/*
141 expose function.real drawing takes place here,
142 params:gtk opgn gl canvas , GdkEventExpose object and custom data
143 return value:true or false, fails (false) if cannot init gl
144*/
145gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, void *data) {
146 (void)event;
147 (void)data;
148
149 GdkGLContext *glcontext = gtk_widget_get_gl_context(widget);
150 GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget);
151
152 /*** OpenGL BEGIN ***/
153 if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
154 return FALSE;
155 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
156 glLoadIdentity();
157 glexpose_main(view); //draw all stuff
158 /* Swap buffers */
159 if (gdk_gl_drawable_is_double_buffered(gldrawable))
160 gdk_gl_drawable_swap_buffers(gldrawable);
161 else
162 glFlush();
163 gdk_gl_drawable_gl_end(gldrawable);
164 /*** OpenGL END ***/
165 if (view->initFile) {
166 view->initFile = 0;
167 if (view->activeGraph == 0)
170 }
171 return TRUE;
172}
173
174/*
175 when a mouse button is clicked this function is called
176 params:gtk opgn gl canvas , GdkEventButton object and custom data
177 return value:true or false, fails (false) if cannot init gl
178*/
179static gboolean button_press_event(GtkWidget *widget, GdkEventButton *event, void *data) {
180 (void)widget;
181 (void)data;
182
183 if (view->g == 0) return FALSE;
184
185 begin_x = (float) event->x;
186 begin_y = (float) event->y;
188 (float)event->x,
189 (float)event->y,
190 getGlCompMouseType(event->button));
191 if (event->button == 1) //left click
192 appmouse_left_click_down(view,(int) event->x,(int) event->y);
193
194 if (event->button == 3) //right click
195 appmouse_right_click_down(view,(int) event->x,(int) event->y);
196 if (event->button == 2) //middle click
197 appmouse_middle_click_down(view,(int) event->x,(int) event->y);
198
200
201 return FALSE;
202}
203
204/*
205 when a mouse button is released(always after click) this function is called
206 params:gtk opgn gl canvas , GdkEventButton object and custom data
207 return value:true or false, fails (false) if cannot init gl
208*/
209static gboolean button_release_event(GtkWidget *widget, GdkEventButton *event,
210 void *data) {
211 (void)widget;
212 (void)data;
213
214 if (view->widgets == 0) return FALSE;
215 view->arcball->isDragging = 0;
217 (float)event->x,
218 (float)event->y,
219 getGlCompMouseType(event->button));
220
221 // left/middle/right click release
222 if (event->button == 1 || event->button == 2 || event->button == 3)
223 appmouse_up(view, (int)event->x, (int)event->y);
224
226
227 return FALSE;
228}
229
230static gboolean key_press_event(GtkWidget *widget, GdkEventKey *event,
231 void *data) {
232 (void)widget;
233 (void)data;
234
235 appmouse_key_press(view,event->keyval);
236 return FALSE;
237}
238
239static gboolean key_release_event(GtkWidget *widget, GdkEventKey *event,
240 void *data) {
241 (void)widget;
242 (void)event;
243 (void)data;
244
246 return FALSE;
247}
248
249static gboolean scroll_event(GtkWidget *widget, GdkEventScroll *event,
250 void *data) {
251 (void)widget;
252 (void)data;
253
254 gdouble seconds;
255
256 seconds = g_timer_elapsed(view->timer2, NULL);
257 if (seconds > 0.005) {
258 g_timer_stop(view->timer2);
259 if (event->direction == 0)
260 view->mouse.dragX = -30;
261 if (event->direction == 1)
262 view->mouse.dragX = +30;
264 glexpose();
265 g_timer_start(view->timer2);
266
267 }
268 return TRUE;
269}
270
271/*
272 when mouse is moved over glcanvas this function is called
273 params:gtk opgn gl canvas , GdkEventMotion object and custom data
274 return value:always TRUE !!!
275*/
276static gboolean motion_notify_event(GtkWidget *widget, GdkEventMotion *event,
277 void *data) {
278 (void)data;
279
280 float x = (float) event->x;
281 float y = (float) event->y;
282
283 bool redraw = false;
284 if (view->widgets)
286
287 view->mouse.dragX = x - begin_x;
288 view->mouse.dragY = y - begin_y;
289 appmouse_move(view,(int)event->x,(int)event->y);
290
291 if (view->mouse.down) {
292 appmouse_drag(view,(int)event->x,(int)event->y);
293 redraw = true;
294 }
296 redraw = true;
297
298 begin_x = x;
299 begin_y = y;
300
301
302 if (redraw)
303 gdk_window_invalidate_rect(widget->window, &widget->allocation,FALSE);
304 return TRUE;
305}
306
307/*
308 configures various opengl settings
309 params:none
310 return value:GdkGLConfig object
311*/
312GdkGLConfig *configure_gl(void)
313{
314 GdkGLConfig *glconfig;
315 /* Try double-buffered visual */
316 glconfig = gdk_gl_config_new_by_mode(GDK_GL_MODE_RGB |
317 GDK_GL_MODE_DEPTH |
318 GDK_GL_MODE_DOUBLE);
319 if (glconfig == NULL) {
320 g_print("\n*** Cannot find the double-buffered visual.\n");
321 g_print("\n*** Trying single-buffered visual.\n");
322
323 /* Try single-buffered visual */
324 glconfig = gdk_gl_config_new_by_mode(GDK_GL_MODE_RGB |
325 GDK_GL_MODE_DEPTH);
326 if (glconfig == NULL) {
327 g_print("*** No appropriate OpenGL-capable visual found.\n");
328 graphviz_exit(1);
329 }
330 }
331
332 return glconfig;
333}
334
335/*
336 run this function only once to create and customize gtk based opengl canvas
337 all signal, socket connections are done here for opengl interractions
338 params:gl config object, gtk container widget for opengl canvas
339 return value:none
340*/
341void create_window(GdkGLConfig * glconfig, GtkWidget * vbox)
342{
343 /* Try double-buffered visual */
344
345 /* Drawing area for drawing OpenGL scene. */
346 view->drawing_area = gtk_drawing_area_new();
347 gtk_widget_set_size_request(view->drawing_area, 300, 300);
348 /* Set OpenGL-capability to the widget. */
349 gtk_widget_set_gl_capability(view->drawing_area,
350 glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE);
351
352 gtk_widget_add_events(view->drawing_area,
353 GDK_BUTTON_MOTION_MASK |
354 GDK_POINTER_MOTION_MASK |
355 GDK_BUTTON_PRESS_MASK | GDK_KEY_PRESS |
356 GDK_BUTTON_RELEASE_MASK |
357 GDK_SCROLL | GDK_VISIBILITY_NOTIFY_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK );
358
359 g_signal_connect_after(G_OBJECT(view->drawing_area), "realize",
360 G_CALLBACK(realize), NULL);
361 g_signal_connect(G_OBJECT(view->drawing_area), "configure_event",
362 G_CALLBACK(configure_event), NULL);
363 g_signal_connect(G_OBJECT(view->drawing_area), "expose_event",
364 G_CALLBACK(expose_event), NULL);
365
366 g_signal_connect(G_OBJECT(view->drawing_area), "button_press_event",
367 G_CALLBACK(button_press_event), NULL);
368
369 g_signal_connect(G_OBJECT(view->drawing_area), "button_release_event",G_CALLBACK(button_release_event), NULL);
370 g_signal_connect(G_OBJECT(view->drawing_area), "key_release_event", G_CALLBACK(key_release_event), NULL);
371 g_signal_connect(G_OBJECT(view->drawing_area), "key_press_event", G_CALLBACK(key_press_event), NULL);
372 g_signal_connect(G_OBJECT(view->drawing_area), "scroll_event",
373 G_CALLBACK(scroll_event), NULL);
374
375 g_signal_connect(G_OBJECT(view->drawing_area), "motion_notify_event",
376 G_CALLBACK(motion_notify_event), NULL);
377
378 gtk_box_pack_start(GTK_BOX(vbox), view->drawing_area, TRUE, TRUE, 0);
379
380 gtk_widget_show(view->drawing_area);
381
382
383
384 gtk_widget_add_events(glade_xml_get_widget(xml, "frmMain"),
385 GDK_BUTTON_MOTION_MASK |
386 GDK_POINTER_MOTION_MASK |
387 GDK_BUTTON_PRESS_MASK | GDK_KEY_PRESS |
388 GDK_BUTTON_RELEASE_MASK |
389 GDK_SCROLL | GDK_VISIBILITY_NOTIFY_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK );
390
391
392 g_signal_connect(G_OBJECT(glade_xml_get_widget(xml, "frmMain")), "key_release_event", G_CALLBACK(key_release_event), NULL);
393 g_signal_connect(G_OBJECT(glade_xml_get_widget(xml, "frmMain")), "key_press_event", G_CALLBACK(key_press_event), NULL);
394}
void appmouse_drag(ViewInfo *v, int x, int y)
Definition appmouse.c:99
void appmouse_key_release(ViewInfo *v)
Definition appmouse.c:134
void appmouse_move(ViewInfo *v, int x, int y)
Definition appmouse.c:130
void appmouse_key_press(ViewInfo *v, int key)
Definition appmouse.c:143
void appmouse_middle_click_down(ViewInfo *v, int x, int y)
Definition appmouse.c:122
void appmouse_left_click_down(ViewInfo *v, int x, int y)
Definition appmouse.c:106
void appmouse_right_click_down(ViewInfo *v, int x, int y)
Definition appmouse.c:114
void appmouse_up(ViewInfo *v, int x, int y)
Definition appmouse.c:88
void init_arcBall(ArcBall_t *a, float NewWidth, float NewHeight)
Definition arcball.c:88
static NORETURN void graphviz_exit(int status)
Definition exit.h:23
glMouseButtonType
Definition glcompdefs.h:67
@ glMouseRightButton
Definition glcompdefs.h:67
@ glMouseMiddleButton
Definition glcompdefs.h:68
@ glMouseLeftButton
Definition glcompdefs.h:67
void glcompsetUpdateBorder(glCompSet *s, int w, int h)
Definition glcompset.c:236
int glexpose_main(ViewInfo *vi)
Definition glexpose.c:144
void glmotion_zoom(void)
Definition glmotion.c:53
static gboolean button_press_event(GtkWidget *widget, GdkEventButton *event, void *data)
Definition gltemplate.c:179
static gboolean configure_event(GtkWidget *widget, GdkEventConfigure *event, void *data)
Definition gltemplate.c:94
static float begin_x
Definition gltemplate.c:28
static void realize(GtkWidget *widget, void *data)
Definition gltemplate.c:52
static gboolean button_release_event(GtkWidget *widget, GdkEventButton *event, void *data)
Definition gltemplate.c:209
static gboolean motion_notify_event(GtkWidget *widget, GdkEventMotion *event, void *data)
Definition gltemplate.c:276
static float begin_y
Definition gltemplate.c:29
static gboolean scroll_event(GtkWidget *widget, GdkEventScroll *event, void *data)
Definition gltemplate.c:249
gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, void *data)
Definition gltemplate.c:145
static gboolean key_press_event(GtkWidget *widget, GdkEventKey *event, void *data)
Definition gltemplate.c:230
static glMouseButtonType getGlCompMouseType(int n)
Definition gltemplate.c:32
static gboolean key_release_event(GtkWidget *widget, GdkEventKey *event, void *data)
Definition gltemplate.c:239
GdkGLConfig * configure_gl(void)
Definition gltemplate.c:312
void create_window(GdkGLConfig *glconfig, GtkWidget *vbox)
Definition gltemplate.c:341
node NULL
Definition grammar.y:181
GladeXML * xml
Definition gui.c:22
type-generic dynamically expanding list
#define LIST_IS_EMPTY(list)
Definition list.h:90
ViewInfo * view
Definition viewport.c:37
#define GL_VIEWPORT_FACTOR
Definition smyrnadefs.h:37
void glexpose(void)
Definition viewport.c:520
int isDragging
Definition arcball.h:553
ArcBall_t * arcball
Definition smyrnadefs.h:333
topview * Topview
Definition smyrnadefs.h:307
Agraph_t ** g
Definition smyrnadefs.h:290
glCompSet * widgets
Definition smyrnadefs.h:326
char * initFileName
Definition smyrnadefs.h:327
GTimer * timer2
Definition smyrnadefs.h:311
int activeGraph
Definition smyrnadefs.h:294
glCompColor bgColor
Definition smyrnadefs.h:258
GtkWidget * drawing_area
open gl canvas
Definition smyrnadefs.h:304
glCompMouse mouse
Definition smyrnadefs.h:297
glCompPoly_t selPoly
Definition smyrnadefs.h:208
Definition legal.c:50
glcompmouseupfunc_t mouseup
Definition glcompdefs.h:154
glcompmousedownfunc_t mousedown
Definition glcompdefs.h:153
glcompmouseoverfunc_t mouseover
Definition glcompdefs.h:152
glCompCallBacks functions
Definition glcompdefs.h:179
glCompCommon common
Definition glcompdefs.h:185
glCompObj base
Definition glcompdefs.h:240
selection sel
Definition smyrnadefs.h:237
void close_graph(ViewInfo *vi)
Definition viewport.c:71
int add_graph_to_viewport_from_file(char *fileName)
Definition viewport.c:344