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