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