PLplot: gcw-lib.c Source File

PLplot 5.10.0

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
gcw-lib.c
Go to the documentation of this file.
1 // gcw-lib - Library routines for the Gnome Canvas Widget device driver.
2 //
3 // Copyright (C) 2005 Thomas J. Duck
4 // All rights reserved.
5 //
6 //
7 // NOTICE
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
22 // USA
23 //
24 // DESCRIPTION
25 //
26 // The gcw-lib API allows users to interact with the GCW driver. The
27 // library routines are also invoked by the driver itself when needed.
28 //
29 //
30
31 #include "gcw.h"
32
33 extern PLStream *pls[];
34
35 void gcw_debug( char* msg )
36 {
37 fputs( msg, stderr );
38 fflush( stderr );
39 }
40
41
42 //--------------------------------------------------------------------------
43 // gcw_set_gdk_color()
44 //
45 // Sets the gdk foreground color for drawing in the current device
46 // according to the current drawing color.
47 //
48 //--------------------------------------------------------------------------
49
50 void gcw_set_gdk_color()
51 {
52 #ifdef DEBUG_GCW_1
53 gcw_debug( "<gcw_set_gdk_color>\n" );
54 #endif
55
56 GcwPLdev * dev = plsc->dev;
57 GdkColor color;
58
59 color.red = (guint16) ( plsc->curcolor.r / 255. * 65535 );
60 color.green = (guint16) ( plsc->curcolor.g / 255. * 65535 );
61 color.blue = (guint16) ( plsc->curcolor.b / 255. * 65535 );
62
63 if ( !gdk_colormap_alloc_color( dev->colormap, &color, FALSE, TRUE ) )
64 plwarn( "GCW driver <set_gdk_color>: Could not allocate color." );
65
66 gdk_gc_set_foreground( dev->gc, &color );
67
68 #ifdef DEBUG_GCW_1
69 gcw_debug( "</gcw_set_gdk_color>\n" );
70 #endif
71 }
72
73
74 //--------------------------------------------------------------------------
75 // gcw_clear_background()
76 //
77 // Clears the background pixmap for the current gcw device with the
78 // background color.
79 //
80 //--------------------------------------------------------------------------
81
82 void gcw_clear_background()
83 {
84 GcwPLdev* dev = plsc->dev;
85
86 PLINT width, height;
87
88 #ifdef DEBUG_GCW_1
89 gcw_debug( "<clear_background>\n" );
90 #endif
91
92 // Retrieve the device width and height
93 width = *(PLINT *) g_object_get_data( G_OBJECT( dev->canvas ), "canvas-width" );
94 height = *(PLINT *) g_object_get_data( G_OBJECT( dev->canvas ), "canvas-height" );
95
96 // Allocate the background color
97 gdk_colormap_alloc_color( dev->colormap, &( dev->bgcolor ), FALSE, TRUE );
98
99 // Clear the background pixmap with the background color. Note that
100 // we are going to reset the current gdk drawing color below, so we
101 // can reuse the gc.
102 gdk_gc_set_foreground( dev->gc, &( dev->bgcolor ) );
103 gdk_draw_rectangle( dev->background, dev->gc, TRUE, 0, 0, width, height );
104
105 // Note that our pixmap is currently clear
106 dev->pixmap_has_data = FALSE;
107
108 // Reset the current gdk drawing color
109 gcw_set_gdk_color();
110
111 #ifdef DEBUG_GCW_1
112 gcw_debug( "</clear_background>\n" );
113 #endif
114 }
115
116
117 //--------------------------------------------------------------------------
118 // gcw_init_canvas()
119 //
120 // Initializes a canvas for use with this driver, and installs it into
121 // the current gcw device.
122 //
123 //--------------------------------------------------------------------------
124
125 void gcw_init_canvas( GnomeCanvas* canvas )
126 {
127 GcwPLdev* dev = plsc->dev;
128
129 #ifdef DEBUG_GCW_1
130 gcw_debug( "<gcw_init_canvas>\n" );
131 #endif
132
133 if ( !GNOME_IS_CANVAS( canvas ) )
134 plexit( "GCW driver: Canvas not found" );
135
136 // Add the canvas to the device
137 dev->canvas = canvas;
138
139 // Get the colormap
140 dev->colormap = gtk_widget_get_colormap( GTK_WIDGET( dev->canvas ) );
141
142 // Size the canvas
143 gcw_set_canvas_size( canvas, dev->width, dev->height );
144
145 // Create the persistent group, which is always visible
146 if ( !GNOME_IS_CANVAS_ITEM(
147 dev->group_persistent = GNOME_CANVAS_GROUP( gnome_canvas_item_new(
148 gnome_canvas_root( canvas ),
149 gnome_canvas_clipgroup_get_type(),
150 "x", 0.,
151 "y", 0.,
152 NULL ) )
153 ) )
154 {
155 plexit( "GCW driver <gcw_init_canvas>: Canvas group cannot be created" );
156 }
157
158 // Set the clip to NULL
159 g_object_set( G_OBJECT( dev->group_persistent ), "path", NULL, NULL );
160
161 #ifdef DEBUG_GCW1
162 gcw_debug( "</gcw_init_canvas>\n" );
163 #endif
164 }
165
166
167 //--------------------------------------------------------------------------
168 // gcw_install_canvas()
169 //
170 // Installs a canvas into the current gcw device's window. The canvas is
171 // created if necessary. A variety of callbacks are defined for actions
172 // in the window.
173 //
174 //--------------------------------------------------------------------------
175
176 //******************************
177 // Main window event callbacks *
178 //*****************************
179
180 // Delete event callback
181 gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data )
182 {
183 return FALSE; // FALSE follows with the destroy signal
184 }
185
186 // Destroy event calback
187 void destroy( GtkWidget *widget, gpointer data )
188 {
189 gtk_main_quit();
190 }
191
192 //*****************
193 // Zoom callbacks *
194 //****************
195
196 // All-purpose zoom callback. Referred to by specific zoom callbacks given
197 // below.
198 //
199 void zoom( gpointer data, gint flag )
200 {
201 gint n;
202
203 GnomeCanvas *canvas;
204 GtkWidget *scrolled_window;
205 GList *list;
206
207 GcwPLdev * dev = data;
208
209 gdouble curmag, dum;
210
211 // Get the current canvas
212 n = gtk_notebook_get_current_page( GTK_NOTEBOOK( dev->notebook ) );
213 scrolled_window = gtk_notebook_get_nth_page( GTK_NOTEBOOK( dev->notebook ), n );
214 canvas = GNOME_CANVAS( gtk_container_get_children(
215 GTK_CONTAINER( gtk_container_get_children(
216 GTK_CONTAINER( scrolled_window ) )->data ) )->data );
217
218 // Determine the new magnification
219 if ( flag == 2 ) // Zoom in
220 gcw_set_canvas_zoom( canvas, ZOOMSTEP );
221 else if ( flag == 0 ) // Zoom out
222
223 { // Don't zoom smaller than the original size: this causes GDK pixmap
224 // errors.
225 //
226 gnome_canvas_c2w( canvas, 1, 0, &curmag, &dum );
227 curmag = 1. / curmag;
228 if ( curmag / ZOOMSTEP > 1. )
229 {
230 gcw_set_canvas_zoom( canvas, 1. / ZOOMSTEP );
231 }
232 else
233 {
234 gcw_set_canvas_zoom( canvas, (PLFLT) ( ZOOM100 / curmag ) );
235 }
236 }
237 else // Zoom 100
238 {
239 // Get current magnification
240 gnome_canvas_c2w( canvas, 1, 0, &curmag, &dum );
241 curmag = 1. / curmag;
242 gcw_set_canvas_zoom( canvas, (PLFLT) ( ZOOM100 / curmag ) );
243 }
244
245 // Set the focus on the notebook
246 gtk_window_set_focus( GTK_WINDOW( dev->window ), dev->notebook );
247 }
248
249
250 // Callback when zoom in button is pressed
251 void zoom_in( GtkWidget *widget, gpointer data )
252 {
253 zoom( data, 2 );
254 }
255
256 // Callback when zoom 100 button is pressed
257 void zoom_100( GtkWidget *widget, gpointer data )
258 {
259 zoom( data, 1 );
260 }
261
262 // Callback when zoom out button is pressed
263 void zoom_out( GtkWidget *widget, gpointer data )
264 {
265 zoom( data, 0 );
266 }
267
268 //****************************
269 // File selection callbacks. *
270 //***************************
271
272 // Callback to OK file selection. Retrieves the selected filename and
273 // replays the plot buffer to it through the associated driver.
274 //
275 void file_ok_sel( GtkWidget *w, gpointer data )
276 {
277 GcwPLdev * dev = data;
278
279 GtkWidget *scrolled_window;
280 GnomeCanvas *canvas;
281
282 gchar *fname;
283 guint n;
284 char devname[10], str[100];
285
286 void *save_state;
287 void *new_state;
288
289 PLINT cur_strm, new_strm;
290 PLStream *plsr;
291
292 GtkWidget *fs;
293
294 gdouble curmag, dum;
295
296 gboolean errflag = FALSE;
297
298 struct stat buf;
299
300 GtkDialog *dialog;
301 GtkWidget *hbox, *message, *icon;
302 gint result;
303
304 guint context;
305
306 FILE *f;
307
308 // Get the file name
309 if ( ( fname =
310 strdup( gtk_file_selection_get_filename( GTK_FILE_SELECTION( dev->filew ) ) ) )
311 == NULL )
312 plabort( "GCW driver <file_ok_sel>: Cannot obtain filename" );
313
314 // Check to see if the file already exists, and respond appropriately
315 if ( stat( fname, &buf ) == 0 )
316 {
317 // Confirm the user wants to overwrite the existing file
318
319 dialog = GTK_DIALOG( gtk_dialog_new_with_buttons( "",
320 GTK_WINDOW( dev->filew ),
321 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
322 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
323 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL ) );
324
325 message = gtk_label_new( "" );
326 gtk_label_set_markup( GTK_LABEL( message ),
327 "<span size=\"large\"><b>File exists. "
328 "Overwrite?</b></span>" );
329
330 icon = gtk_image_new_from_stock( GTK_STOCK_DIALOG_QUESTION,
331 GTK_ICON_SIZE_DIALOG );
332
333 hbox = gtk_hbox_new( FALSE, 0 );
334 gtk_box_pack_start( GTK_BOX( hbox ), icon, TRUE, TRUE, 10 );
335 gtk_box_pack_start( GTK_BOX( hbox ), message, TRUE, TRUE, 10 );
336 gtk_container_add( GTK_CONTAINER( dialog->vbox ), hbox );
337
338 gtk_widget_show_all( GTK_WIDGET( dialog ) );
339
340 result = gtk_dialog_run( dialog );
341 gtk_widget_destroy( GTK_WIDGET( dialog ) );
342 if ( result == GTK_RESPONSE_REJECT )
343 return;
344 }
345
346 // Hide the file selection widget
347 gtk_widget_hide( dev->filew );
348
349 // Put the focus back on the notebook
350 gtk_window_set_focus( GTK_WINDOW( dev->window ), dev->notebook );
351
352 // Test that we can open and write to the file
353 if ( ( f = fopen( fname, "w" ) ) == NULL )
354 plabort( "GCW driver <file_ok_sel>: Cannot open output file" );
355 fclose( f );
356 remove( fname ); // Otherwise, we may leave behind a zero-length file
357
358 // Get the file extension and make sure we recognize it. Allow names
359 // of display devices as well.
360 //
361 // Note that we can't replot to xwin or tk devices, which can't open a
362 // display for some reason.
363 //
364 //
365 n = strlen( fname );
366 if ( strcasecmp( &fname[n - 3], "png" ) == 0 )
367 sprintf( devname, "png" );
368 else if ( strcasecmp( &fname[n - 3], "gif" ) == 0 )
369 sprintf( devname, "gif" );
370 else if ( strcasecmp( &fname[n - 3], "jpg" ) == 0 )
371 sprintf( devname, "jpg" );
372 else if ( strcasecmp( &fname[n - 4], "jpeg" ) == 0 )
373 sprintf( devname, "jpeg" );
374 else if ( strcasecmp( &fname[n - 2], "ps" ) == 0 )
375 sprintf( devname, "ps" );
376 else if ( strcasecmp( &fname[n - 3], "psc" ) == 0 )
377 sprintf( devname, "psc" );
378 else if ( strcasecmp( &fname[n - 4], "xwin" ) == 0 )
379 sprintf( devname, "xwin" );
380 else if ( strcasecmp( &fname[n - 3], "gcw" ) == 0 )
381 sprintf( devname, "gcw" );
382 else if ( strcasecmp( &fname[n - 2], "tk" ) == 0 )
383 sprintf( devname, "tk" );
384 else
385 {
386 if ( dev->statusbar != NULL )
387 {
388 context = gtk_statusbar_get_context_id( GTK_STATUSBAR( dev->statusbar ),
389 "PLplot" );
390 gtk_statusbar_push( GTK_STATUSBAR( dev->statusbar ), context,
391 " WARNING: File type not recognized (unknown "
392 "extension). Use one of ps, psc, png, jpg, or "
393 "gif."
394 );
395 return;
396 }
397 else
398 plabort( "GCW driver <file_ok_sel>: File type not recognized" );
399 }
400
401 // Check that we are set up appropriately for device
402 if ( strcmp( devname, "ps" ) == 0 || strcmp( devname, "psc" ) == 0 )
403 {
404 if ( plsc->dev_hrshsym != 1 )
405 if ( dev->statusbar != NULL )
406 {
407 context = gtk_statusbar_get_context_id( GTK_STATUSBAR( dev->statusbar ),
408 "PLplot" );
409
410 gtk_statusbar_push( GTK_STATUSBAR( dev->statusbar ), context,
411 " NOTE: Use '-drvopt hrshsym' on command-line "
412 "for complete symbol set in PostScript files."
413 );
414 }
415 else
416 plwarn( "GCW driver: Use '-drvopt hrshsym' if symbols are missing in "
417 "saved PostScript files." );
418 }
419 if ( strcmp( devname, "xwin" ) == 0 || strcmp( devname, "tk" ) == 0 )
420 {
421 if ( plsc->dev_text != 0 )
422 plwarn( "GCW driver: Use '-drvopt text=0'" );
423 }
424
425 // Get the current canvas
426 n = gtk_notebook_get_current_page( GTK_NOTEBOOK( dev->notebook ) );
427 scrolled_window = gtk_notebook_get_nth_page( GTK_NOTEBOOK( dev->notebook ), n );
428 canvas = GNOME_CANVAS( gtk_container_get_children(
429 GTK_CONTAINER( gtk_container_get_children(
430 GTK_CONTAINER( scrolled_window ) )->data ) )->data );
431
432 // Switch in the previously saved plot state
433 new_state = g_object_get_data( G_OBJECT( canvas ), "plotbuf" );
434
435 if ( new_state != NULL )
436 {
437 save_state = (void *) plbuf_switch( plsc, new_state );
438
439 plsetopt( "drvopt", "text" ); // Blank out the drvopts (not needed here)
440
441 // Get the current stream and make a new one
442 plgstrm( &cur_strm );
443 plsr = plsc; // Save a pointer to the current stream
444
445 plmkstrm( &new_strm );
446 plsfnam( fname ); // Set the file name
447 plsdev( devname ); // Set the device
448
449 // Copy the current stream to the new stream.
450 plcpstrm( cur_strm, 0 );
451
452 plreplot(); // do the save by replaying the plot buffer
453
454 plend1(); // finish the device
455
456 plsstrm( cur_strm ); // return to previous stream
457
458 plbuf_restore( plsc, save_state );
459 free( save_state );
460 }
461 else
462 {
463 plwarn( "GCW driver <file_ok_sel>: Cannot set up output stream." );
464 }
465 }
466
467 // Callback to cancel file selection
468 void file_cancel_sel( GtkWidget *w, gpointer data )
469 {
470 GcwPLdev* dev = data;
471
472 // Hide the file selection widget
473 gtk_widget_hide( dev->filew );
474
475 // Put the focus back on the notebook
476 gtk_window_set_focus( GTK_WINDOW( dev->window ), dev->notebook );
477 }
478
479 // Callback to create file selection dialog
480 void filesel( GtkWidget *widget, gpointer data )
481 {
482 GtkWidget *scrolled_window;
483 GnomeCanvas *canvas;
484
485 GcwPLdev * dev = data;
486
487 guint n;
488
489 // Get the current canvas
490 n = gtk_notebook_get_current_page( GTK_NOTEBOOK( dev->notebook ) );
491 scrolled_window = gtk_notebook_get_nth_page( GTK_NOTEBOOK( dev->notebook ), n );
492 canvas = GNOME_CANVAS( gtk_container_get_children(
493 GTK_CONTAINER( gtk_container_get_children(
494 GTK_CONTAINER( scrolled_window ) )->data ) )->data );
495
496 // Create a new file dialog if it doesn't already exist
497 if ( dev->filew == NULL )
498 {
499 // Create a new file selection widget
500 dev->filew = gtk_file_selection_new( "File selection" );
501
502 // Connect the ok_button to file_ok_sel function
503 g_signal_connect( G_OBJECT( GTK_FILE_SELECTION( dev->filew )->ok_button ),
504 "clicked", G_CALLBACK( file_ok_sel ), (gpointer) dev );
505
506 // Connect the cancel_button to destroy the widget
507 g_signal_connect( G_OBJECT( GTK_FILE_SELECTION( dev->filew )->cancel_button ),
508 "clicked", G_CALLBACK( file_cancel_sel ), (gpointer) dev );
509
510 // Lets set the filename, as if this were a save dialog, and we are giving
511 // a default filename
512 gtk_file_selection_set_filename( GTK_FILE_SELECTION( dev->filew ),
513 "plot.psc" );
514 }
515
516 gtk_widget_show( dev->filew );
517 }
518
519 //*************************
520 // Key release callbacks. *
521 //************************
522
523 void key_release( GtkWidget *widget, GdkEventKey *event, gpointer data )
524 {
525 if ( event->keyval == '+' )
526 zoom( data, 2 );
527 if ( event->keyval == '=' )
528 zoom( data, 1 );
529 if ( event->keyval == '-' )
530 zoom( data, 0 );
531 if ( event->keyval == 'q' )
532 destroy( widget, data );
533 }
534
535 //*********************
536 // gcw_install_canvas *
537 //********************
538
539 void gcw_install_canvas( GnomeCanvas *canvas )
540 {
541 GcwPLdev * dev = plsc->dev;
542 GtkWidget *vbox, *hbox, *button, *image, *scrolled_window;
543
544 gboolean flag = FALSE;
545
546 PLINT width, height;
547
548 #ifdef DEBUG_GCW_1
549 gcw_debug( "<gcw_install_canvas>\n" );
550 #endif
551
552 // Create a new canvas if needed
553 if ( !GNOME_IS_CANVAS( canvas ) )
554 {
555 if ( !GNOME_IS_CANVAS( canvas = GNOME_CANVAS( gnome_canvas_new_aa() ) ) )
556 plexit( "GCW driver <gcw_install_canvas>: Could not create Canvas" );
557 }
558
559 // Initialize canvas
560 gcw_init_canvas( canvas );
561
562 if ( dev->window == NULL ) // Create a new window and install a notebook
563
564 {
565 flag = TRUE;
566
567 // Create a new window
568 dev->window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
569 gtk_window_set_title( GTK_WINDOW( dev->window ), "PLplot" );
570
571 // Connect the signal handlers to the window decorations
572 g_signal_connect( G_OBJECT( dev->window ), "delete_event",
573 G_CALLBACK( delete_event ), NULL );
574 g_signal_connect( G_OBJECT( dev->window ), "destroy", G_CALLBACK( destroy ), NULL );
575
576
577 // Create a vbox and put it into the window
578 vbox = gtk_vbox_new( FALSE, 2 );
579 gtk_container_add( GTK_CONTAINER( dev->window ), vbox );
580
581 // Create a hbox and put it into the vbox
582 hbox = gtk_hbox_new( FALSE, 0 );
583 gtk_box_pack_start( GTK_BOX( vbox ), hbox, TRUE, TRUE, 0 );
584
585 // Create a statusbar and put it into the vbox
586 dev->statusbar = gtk_statusbar_new();
587 gtk_box_pack_start( GTK_BOX( vbox ), dev->statusbar, FALSE, FALSE, 0 );
588
589 // Add an vbox to the hbox
590 vbox = gtk_vbox_new( FALSE, 5 );
591 gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 );
592 gtk_box_pack_start( GTK_BOX( hbox ), vbox, FALSE, FALSE, 0 );
593
594 // Create the new notebook and add it to the hbox
595 dev->notebook = gtk_notebook_new();
596 gtk_notebook_set_scrollable( GTK_NOTEBOOK( dev->notebook ), TRUE );
597 gtk_box_pack_start( GTK_BOX( hbox ), dev->notebook, TRUE, TRUE, 0 );
598 g_signal_connect( G_OBJECT( dev->notebook ), "key_release_event",
599 G_CALLBACK( key_release ), G_OBJECT( dev->notebook ) );
600
601 // Use a few labels as spacers
602 gtk_box_pack_start( GTK_BOX( vbox ), gtk_label_new( " " ), FALSE, FALSE, 0 );
603 gtk_box_pack_start( GTK_BOX( vbox ), gtk_label_new( " " ), FALSE, FALSE, 0 );
604
605 // Add buttons to the vbox
606
607 // Add zoom in button and create callbacks
608 image = gtk_image_new_from_stock( GTK_STOCK_ZOOM_IN,
609 GTK_ICON_SIZE_SMALL_TOOLBAR );
610 button = gtk_button_new();
611 gtk_container_add( GTK_CONTAINER( button ), image );
612 gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
613 g_signal_connect( G_OBJECT( button ), "clicked",
614 G_CALLBACK( zoom_in ), (gpointer) dev );
615 g_signal_connect( G_OBJECT( button ), "key_release_event",
616 G_CALLBACK( key_release ), (gpointer) dev );
617
618 // Add zoom100 button and create callbacks
619 image = gtk_image_new_from_stock( GTK_STOCK_ZOOM_100,
620 GTK_ICON_SIZE_SMALL_TOOLBAR );
621 button = gtk_button_new();
622 gtk_container_add( GTK_CONTAINER( button ), image );
623 gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
624 g_signal_connect( G_OBJECT( button ), "clicked",
625 G_CALLBACK( zoom_100 ), (gpointer) dev );
626
627 // Add zoom out button and create callbacks
628 image = gtk_image_new_from_stock( GTK_STOCK_ZOOM_OUT,
629 GTK_ICON_SIZE_SMALL_TOOLBAR );
630 button = gtk_button_new();
631 gtk_container_add( GTK_CONTAINER( button ), image );
632 gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
633 g_signal_connect( G_OBJECT( button ), "clicked",
634 G_CALLBACK( zoom_out ), (gpointer) dev );
635 g_signal_connect( G_OBJECT( button ), "key_release_event",
636 G_CALLBACK( key_release ), (gpointer) dev );
637
638 // Add save button and create callbacks
639 if ( plsc->plbuf_write )
640 {
641 image = gtk_image_new_from_stock( GTK_STOCK_SAVE,
642 GTK_ICON_SIZE_SMALL_TOOLBAR );
643 button = gtk_button_new();
644 gtk_container_add( GTK_CONTAINER( button ), image );
645 gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
646 g_signal_connect( G_OBJECT( button ), "clicked",
647 G_CALLBACK( filesel ), (gpointer) dev );
648 }
649 } // if(dev->window==NULL)
650
651 // Put the canvas in a scrolled window
652 scrolled_window = gtk_scrolled_window_new( NULL, NULL );
653 gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scrolled_window ),
654 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
655 gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( scrolled_window ),
656 GTK_WIDGET( canvas ) );
657
658 // Install the scrolled window in the notebook
659 gtk_notebook_append_page( GTK_NOTEBOOK( dev->notebook ), scrolled_window, NULL );
660
661 if ( flag )
662 {
663 // Set the focus on the notebook
664 gtk_window_set_focus( GTK_WINDOW( dev->window ), dev->notebook );
665
666 // Retrieve the canvas width and height
667 width = *(PLINT *) g_object_get_data( G_OBJECT( canvas ), "canvas-width" );
668 height = *(PLINT *) g_object_get_data( G_OBJECT( canvas ), "canvas-height" );
669
670 // Size the window
671 gtk_window_resize( GTK_WINDOW( dev->window ), width * ZOOM100 + 65,
672 height * ZOOM100 + 75 );
673 }
674
675 // Display everything
676 gtk_widget_show_all( dev->window );
677
678 #ifdef DEBUG_GCW_1
679 gcw_debug( "</gcw_install_canvas>\n" );
680 #endif
681 }
682
683
684 //--------------------------------------------------------------------------
685 // gcw_set_device_size()
686 //
687 // Sets the page size for this device.
688 //
689 // Width and height are both measured in device coordinate units.
690 //
691 // Note that coordinates in driver-space are measured in device units,
692 // which correspond to the pixel size on a typical screen. The coordinates
693 // reported and received from the PLplot core, however, are in virtual
694 // coordinates, which is just a scaled version of the device coordinates.
695 // This strategy is used so that the calculations in the PLplot
696 // core are performed at reasonably high resolution.
697 //
698 //--------------------------------------------------------------------------
699
700 void gcw_set_device_size( PLINT width, PLINT height )
701 {
702 GcwPLdev* dev = plsc->dev;
703 PLINT w, h;
704
705 // Set the number of virtual coordinate units per mm
706 plP_setpxl( (PLFLT) VIRTUAL_PIXELS_PER_MM, (PLFLT) VIRTUAL_PIXELS_PER_MM );
707
708 // Set up physical limits of plotting device, in virtual coord units
709 w = (PLINT) ( width * VSCALE );
710 h = (PLINT) ( height * VSCALE );
711 plP_setphy( (PLINT) 0, w, (PLINT) 0, h );
712
713 // Save the width and height for the device, in device units
714 dev->width = width;
715 dev->height = height;
716 }
717
718 //--------------------------------------------------------------------------
719 // gcw_set_canvas_size()
720 //
721 // Sets the canvas size. If resizing is not allowed, this function
722 // ensures that the canvas size matches the physical page size.
723 //
724 //--------------------------------------------------------------------------
725
726 gint count = 0;
727
728 void gcw_set_canvas_size( GnomeCanvas* canvas, PLINT width, PLINT height )
729 {
730 GcwPLdev * dev = plsc->dev;
731 PLINT tmp;
732
733 PLINT *w, *h;
734
735 GdkGC *gc_new;
736 GdkGCValues values;
737
738 PLINT strm;
739
740 GdkPixmap *background;
741
742 #ifdef DEBUG_GCW_1
743 gcw_debug( "<gcw_set_canvas_size>\n" );
744 #endif
745
746 // Set the device size, if resizing is allowed.
747 if ( dev->allow_resize )
748 gcw_set_device_size( width, height );
749
750 width = dev->width;
751 height = dev->height;
752 if ( plsc->portrait ) // Swap width and height of display
753 {
754 tmp = width;
755 width = height;
756 height = tmp;
757 }
758
759 // The width and height need to be enlarged by 1 pixel for the canvas
760 width += 1;
761 height += 1;
762
763 // Attach the width and height to the canvas
764 if ( ( w = (PLINT *) malloc( sizeof ( gint ) ) ) == NULL )
765 plwarn( "GCW driver <gcw_set_canvas_size>: Insufficient memory." );
766 if ( ( h = (PLINT *) malloc( sizeof ( gint ) ) ) == NULL )
767 plwarn( "GCW driver <gcw_set_canvas_size>: Insufficient memory." );
768 *w = width;
769 *h = height;
770 g_object_set_data( G_OBJECT( canvas ), "canvas-width", (gpointer) w );
771 g_object_set_data( G_OBJECT( canvas ), "canvas-height", (gpointer) h );
772
773 // Size the canvas appropriately
774 gtk_widget_set_size_request( GTK_WIDGET( canvas ), (gint) ( width ),
775 (gint) ( height ) );
776
777 // Position the canvas appropriately
778 gnome_canvas_set_scroll_region( canvas, 0., (gdouble) ( -height ),
779 (gdouble) ( width ), 1. );
780
781 // Set up the background pixmap
782 if ( dev->background == NULL || dev->allow_resize )
783 {
784 if ( GDK_IS_PIXMAP( dev->background ) )
785 g_object_unref( dev->background );
786
787 // Why does this next *useless* command speed up the animation demo?
788 // If we unref the allocated pixmaps, the benefit goes away!!
789 // if(count<2) {
790 // gdk_pixmap_new(NULL,width,height,gdk_visual_get_best_depth());
791 // printf("Count %d\n",count);
792 // count++;
793 // }
794 // else { printf("Count %d\n",count); count ++; }
795
796 dev->background = gdk_pixmap_new( NULL, width, height,
797 gtk_widget_get_visual( GTK_WIDGET( canvas ) )->depth );
798 }
799
800 // Set up the drawing context for the background pixmap
801 if ( dev->gc == NULL || dev->allow_resize )
802 {
803 // Maintain the old values for pen width, color, etc
804 if ( GDK_IS_GC( dev->gc ) )
805 {
806 gdk_gc_get_values( dev->gc, &values );
807 gdk_gc_unref( dev->gc );
808 dev->gc = gdk_gc_new_with_values( dev->background, &values,
809 GDK_GC_FOREGROUND | GDK_GC_LINE_WIDTH |
810 GDK_GC_LINE_STYLE | GDK_GC_CAP_STYLE |
811 GDK_GC_JOIN_STYLE );
812 }
813 else
814 dev->gc = gdk_gc_new( dev->background );
815 }
816
817 // Clear the background pixmap
818 gcw_clear_background( dev );
819
820 // Advance the page if we are allowing resizing. This ensures that
821 // the physical coordinate system is set up correctly.
822 //
823 if ( dev->allow_resize )
824 pladv( 0 );
825
826 #ifdef DEBUG_GCW_1
827 gcw_debug( "</gcw_set_canvas_size>\n" );
828 #endif
829 }
830
831
832 //--------------------------------------------------------------------------
833 // gcw_set_canvas_zoom()
834 //
835 // Sets the zoom magnification on the canvas and resizes the widget
836 // appropriately.
837 //--------------------------------------------------------------------------
838
839 void gcw_set_canvas_zoom( GnomeCanvas* canvas, PLFLT magnification )
840 {
841 gdouble curmag = 1., dum;
842
843 PLINT width, height;
844
845 #ifdef DEBUG_GCW_1
846 gcw_debug( "<gcw_set_canvas_zoom>\n" );
847 #endif
848
849 // Retrieve the device width and height
850 width = *(PLINT *) g_object_get_data( G_OBJECT( canvas ), "canvas-width" );
851 height = *(PLINT *) g_object_get_data( G_OBJECT( canvas ), "canvas-height" );
852
853 // Get the current magnification
854 gnome_canvas_c2w( canvas, 1, 0, &curmag, &dum );
855 curmag = 1. / curmag;
856
857 // Apply the new magnification
858 gnome_canvas_set_pixels_per_unit( canvas, magnification * curmag );
859
860 // Size the canvas appropriately
861 gtk_widget_set_size_request( GTK_WIDGET( canvas ),
862 (gint) ( ( width ) * magnification * curmag ),
863 (gint) ( ( height ) * magnification * curmag ) );
864
865 // Position the canvas appropriately
866 gnome_canvas_set_scroll_region( canvas, 0., (gdouble) ( -height ),
867 (gdouble) ( width ), 1. );
868
869 #ifdef DEBUG_GCW_1
870 gcw_debug( "</gcw_set_canvas_zoom>\n" );
871 #endif
872 }
873
874
875 //--------------------------------------------------------------------------
876 // gcw_use_text()
877 //
878 // Used to turn text usage on and off for the current device.
879 //--------------------------------------------------------------------------
880
881 void gcw_use_text( PLINT use_text )
882 {
883 GcwPLdev* dev = plsc->dev;
884
885 #ifdef DEBUG_GCW_1
886 gcw_debug( "<gcw_use_text>\n" );
887 #endif
888
889 #ifdef PL_HAVE_FREETYPE
890
891 if ( use_text )
892 plsc->dev_text = 1; // Allow text handling
893 else
894 plsc->dev_text = 0; // Disallow text handling
895
896 #endif
897
898 #ifdef DEBUG_GCW_1
899 gcw_debug( "</gcw_use_text>\n" );
900 #endif
901 }
902
903
904 //--------------------------------------------------------------------------
905 // gcw_use_pixmap()
906 //
907 // Used to turn pixmap usage on and off for the current device.
908 // This is relevant for polygon fills (used during shading calls).
909 //--------------------------------------------------------------------------
910
911 void gcw_use_pixmap( PLINT use_pixmap )
912 {
913 GcwPLdev* dev = plsc->dev;
914
915 #ifdef DEBUG_GCW_1
916 gcw_debug( "<gcw_use_pixmap>\n" );
917 #endif
918
919 dev->use_pixmap = (gboolean) use_pixmap;
920
921 #ifdef DEBUG_GCW_1
922 gcw_debug( "</gcw_use_pixmap>\n" );
923 #endif
924 }
925
926
927 //--------------------------------------------------------------------------
928 // gcw_use_hrshsym()
929 //
930 // Used to turn hershey symbol usage on and off for the current device.
931 //--------------------------------------------------------------------------
932
933 void gcw_use_hrshsym( PLINT use_hrshsym )
934 {
935 GcwPLdev* dev = plsc->dev;
936
937 #ifdef DEBUG_GCW_1
938 gcw_debug( "<gcw_use_hrshsym>\n" );
939 #endif
940
941 plsc->dev_hrshsym = use_hrshsym;
942
943 #ifdef DEBUG_GCW_1
944 gcw_debug( "</gcw_use_hrshsym>\n" );
945 #endif
946 }
947
948
949 //--------------------------------------------------------------------------
950 // gcw_use_persistence
951 //
952 // Directs the GCW driver whether or not the subsequent drawing operations
953 // should be persistent.
954 //--------------------------------------------------------------------------
955
956 void gcw_use_persistence( PLINT use_persistence )
957 {
958 GcwPLdev* dev = plsc->dev;
959
960 #ifdef DEBUG_GCW_1
961 gcw_debug( "<gcw_use_persistence>\n" );
962 #endif
963
964 dev->use_persistence = (gboolean) use_persistence;
965
966 #ifdef DEBUG_GCW_1
967 gcw_debug( "</gcw_use_persistence>\n" );
968 #endif
969 }