2
* animation.c - Demonstrates the use of the plplot canvas widget with gtk.
4
* Copyright (C) 2004, 2005 Thomas J. Duck
7
* Thomas J. Duck <tom.duck@dal.ca>
8
* Department of Physics and Atmospheric Science,
9
* Dalhousie University, Halifax, Nova Scotia, Canada, B3H 3J5
13
* $Date: 2005/05/16 17:05:35 $
14
* $Name: cvs-tarball_2006-05-29-23-03-54 $
19
* This program is free software; you can redistribute it and/or modify
20
* it under the terms of the GNU General Public License as published by
21
* the Free Software Foundation; either version 2 of the License, or
22
* (at your option) any later version.
24
* This program is distributed in the hope that it will be useful,
25
* but WITHOUT ANY WARRANTY; without even the implied warranty of
26
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27
* GNU General Public License for more details.
29
* You should have received a copy of the GNU General Public License
30
* along with this program; if not, write to the Free Software
31
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
37
* This program demonstrates the use of the plplot canvas widget with gtk.
38
* Two graphs are draw in a window. When the Execute button is pressed,
39
* two different waves progress through the graph in real time. Plotting
40
* to the two graphs is handled in two different threads.
47
#include <plplotcanvas.h>
52
/* The number of time steps */
55
/* The number of points and period for the first wave */
59
/* The width and height for each plot widget */
63
/* Run the plots in different threads */
64
GThread* thread0=NULL;
65
GThread* thread1=NULL;
70
ThreadData data0,data1;
71
gint Nthreads = 0; /* Count the number of threads */
73
/* Create two different canvases */
74
PlplotCanvas *canvas0=NULL;
75
PlplotCanvas *canvas1=NULL;
77
/* Create the x and y array */
78
static PLFLT x[NPTS], y[NPTS];
80
/* Lock on the gtkstate so that we don't try to plot after gtk_main_quit */
81
#define GTKSTATE_CONTINUE (TRUE)
82
#define GTKSTATE_QUIT (FALSE)
83
G_LOCK_DEFINE_STATIC(gtkstate);
84
static volatile int gtkstate = GTKSTATE_CONTINUE;
86
/* setup_plot - preparation for plotting an animation to a canvas */
87
void setup_plot(PlplotCanvas *canvas, char* title)
89
/* Set up the viewport and window */
90
plplot_canvas_vsta(canvas);
91
plplot_canvas_wind(canvas,x[0],x[NPTS-1],-2.,2.);
93
/* Set the pen width */
94
plplot_canvas_wid(canvas,2);
96
/* The axes should be persistent, so that they don't have to be
97
* replotted every time (which would slow down the animation)
99
plplot_canvas_use_persistence(canvas,TRUE);
102
plplot_canvas_col0(canvas,15);
103
plplot_canvas_box(canvas,"bcnst",0.,0,"bcnstv",0.,0);
104
plplot_canvas_lab(canvas,"(x)","(y)",title);
106
/* Prepare for plotting */
107
plplot_canvas_col0(canvas,plplot_canvas_get_stream_number(canvas)+8);
109
/* The animated data should not be persistent */
110
plplot_canvas_use_persistence(canvas,FALSE);
113
/* plot - draws a plot on a canvas */
114
void plot(PlplotCanvas *canvas,gdouble offset,char* title)
118
gdouble xmin,xmax,ymin,ymax;
120
/* Get the stream number */
121
Nstream = plplot_canvas_get_stream_number(canvas);
123
/* Generate the sinusoid */
124
for (i = 0; i < NPTS; i++)
125
y[i] = sin(2.*3.14*(x[i]+offset*(Nstream+1))/PERIOD/(float)(Nstream+1));
128
plplot_canvas_line(canvas,NPTS, x, y);
130
/* Advance the page to finalize the plot */
131
plplot_canvas_adv(canvas,0);
134
/* Delete event callback */
135
gint delete_event( GtkWidget *widget,GdkEvent *event,gpointer data ) {
139
/* Destroy event calback */
140
void destroy(GtkWidget *widget,gpointer data) {
142
gtkstate=GTKSTATE_QUIT;
148
GThreadFunc plot_thread(ThreadData* data) {
153
/* Draw STEPS plots in succession */
154
for(i=0;i<STEPS;i++) {
157
/* Lock the current gtk state */
160
/* Check to make sure gtk hasn't quit */
161
if(gtkstate == GTKSTATE_QUIT){
168
plot(data->canvas,i,data->title);
170
/* Release the lock */
179
/* Start threads callback from execute button */
180
void start_threads(GtkWidget *widget,gpointer data)
184
/* Ignore call if threads are currently active */
187
/* Create the two plotting threads */
188
data0.canvas = canvas0;
189
data0.title = "A phase-progressing wave";
190
if((thread0=g_thread_create((GThreadFunc)plot_thread,&data0,TRUE,gerror))\
192
fprintf(stderr,"Could not create thread");
196
data1.canvas = canvas1;
197
data1.title = "Another phase-progressing wave";
198
if((thread1=g_thread_create((GThreadFunc)plot_thread,&data1,TRUE,gerror))\
200
fprintf(stderr,"Could not create thread");
205
int main(int argc,char *argv[] )
212
GtkFrame *canvas0frame;
213
GtkFrame *canvas1frame;
220
/* Parse the options */
221
plparseopts(&argc, argv, PL_PARSE_FULL);
226
gtk_init(&argc, &argv);
229
/* Initialize the x array */
230
for(i=0;i<NPTS;i++) x[i] = (PLFLT)i;
232
/* Create the first canvas, set its size, draw some axes on it, and
233
* place it in a frame
235
canvas0 = plplot_canvas_new(TRUE);
236
plplot_canvas_set_size(canvas0,WIDTH,HEIGHT);
237
plplot_canvas_adv(canvas0,0);
238
setup_plot(canvas0,"A phase-progressing wave");
239
plplot_canvas_adv(canvas0,0); /* Advance the page to finalize the plot */
240
canvas0frame = GTK_FRAME(gtk_frame_new(NULL));
241
gtk_frame_set_shadow_type(canvas0frame,GTK_SHADOW_ETCHED_OUT);
242
gtk_container_add(GTK_CONTAINER(canvas0frame),GTK_WIDGET(canvas0));
244
/* Create the second canvas, set its size, draw some axes on it, and
245
* place it in a frame
247
canvas1 = plplot_canvas_new(TRUE);
248
plplot_canvas_set_size(canvas1,WIDTH,HEIGHT);
249
plplot_canvas_adv(canvas1,0);
250
setup_plot(canvas1,"Another phase-progressing wave");
251
plplot_canvas_adv(canvas1,0); /* Advance the page to finalize the plot */
252
canvas1frame = GTK_FRAME(gtk_frame_new(NULL));
253
gtk_frame_set_shadow_type(canvas1frame,GTK_SHADOW_ETCHED_OUT);
254
gtk_container_add(GTK_CONTAINER(canvas1frame),GTK_WIDGET(canvas1));
256
/* Create a button and put it in a box */
257
button = GTK_BUTTON(gtk_button_new_from_stock(GTK_STOCK_EXECUTE));
258
g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(start_threads),
260
gtk_container_set_border_width(GTK_CONTAINER(button),10);
261
buttonbox = GTK_BOX(gtk_hbox_new(FALSE,0));
262
gtk_box_pack_start(buttonbox,GTK_WIDGET(button),TRUE,FALSE,0);
264
/* Create and fill the vbox with the widgets */
265
vbox = GTK_BOX(gtk_vbox_new(FALSE,0));
266
gtk_box_pack_start(vbox,GTK_WIDGET(canvas0frame),TRUE,FALSE,0);
267
gtk_box_pack_start(vbox,GTK_WIDGET(canvas1frame),TRUE,FALSE,10);
268
gtk_box_pack_start(vbox,GTK_WIDGET(buttonbox),TRUE,FALSE,0);
270
/* Create a new window */
271
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
273
/* Set the border width of the window */
274
gtk_container_set_border_width(GTK_CONTAINER(window),10);
276
/* Connect the signal handlers to the window decorations */
277
g_signal_connect(G_OBJECT(window),"delete_event",
278
G_CALLBACK(delete_event),NULL);
279
g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(destroy),NULL);
281
/* Put the vbox into the window */
282
gtk_container_add(GTK_CONTAINER(window),GTK_WIDGET(vbox));
284
/* Display everything */
285
gtk_widget_show_all(window);
287
/* Start the gtk main loop */