PLplot
5.10.0
|
00001 // gcw-lib - Library routines for the Gnome Canvas Widget device driver. 00002 // 00003 // Copyright (C) 2005 Thomas J. Duck 00004 // All rights reserved. 00005 // 00006 // 00007 // NOTICE 00008 // 00009 // This library is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU Lesser General Public 00011 // License as published by the Free Software Foundation; either 00012 // version 2.1 of the License, or (at your option) any later version. 00013 // 00014 // This library is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 // Lesser General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU Lesser General Public 00020 // License along with this library; if not, write to the Free Software 00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 00022 // USA 00023 // 00024 // DESCRIPTION 00025 // 00026 // The gcw-lib API allows users to interact with the GCW driver. The 00027 // library routines are also invoked by the driver itself when needed. 00028 // 00029 // 00030 00031 #include "gcw.h" 00032 00033 extern PLStream *pls[]; 00034 00035 void gcw_debug( char* msg ) 00036 { 00037 fputs( msg, stderr ); 00038 fflush( stderr ); 00039 } 00040 00041 00042 //-------------------------------------------------------------------------- 00043 // gcw_set_gdk_color() 00044 // 00045 // Sets the gdk foreground color for drawing in the current device 00046 // according to the current drawing color. 00047 // 00048 //-------------------------------------------------------------------------- 00049 00050 void gcw_set_gdk_color() 00051 { 00052 #ifdef DEBUG_GCW_1 00053 gcw_debug( "<gcw_set_gdk_color>\n" ); 00054 #endif 00055 00056 GcwPLdev * dev = plsc->dev; 00057 GdkColor color; 00058 00059 color.red = (guint16) ( plsc->curcolor.r / 255. * 65535 ); 00060 color.green = (guint16) ( plsc->curcolor.g / 255. * 65535 ); 00061 color.blue = (guint16) ( plsc->curcolor.b / 255. * 65535 ); 00062 00063 if ( !gdk_colormap_alloc_color( dev->colormap, &color, FALSE, TRUE ) ) 00064 plwarn( "GCW driver <set_gdk_color>: Could not allocate color." ); 00065 00066 gdk_gc_set_foreground( dev->gc, &color ); 00067 00068 #ifdef DEBUG_GCW_1 00069 gcw_debug( "</gcw_set_gdk_color>\n" ); 00070 #endif 00071 } 00072 00073 00074 //-------------------------------------------------------------------------- 00075 // gcw_clear_background() 00076 // 00077 // Clears the background pixmap for the current gcw device with the 00078 // background color. 00079 // 00080 //-------------------------------------------------------------------------- 00081 00082 void gcw_clear_background() 00083 { 00084 GcwPLdev* dev = plsc->dev; 00085 00086 PLINT width, height; 00087 00088 #ifdef DEBUG_GCW_1 00089 gcw_debug( "<clear_background>\n" ); 00090 #endif 00091 00092 // Retrieve the device width and height 00093 width = *(PLINT *) g_object_get_data( G_OBJECT( dev->canvas ), "canvas-width" ); 00094 height = *(PLINT *) g_object_get_data( G_OBJECT( dev->canvas ), "canvas-height" ); 00095 00096 // Allocate the background color 00097 gdk_colormap_alloc_color( dev->colormap, &( dev->bgcolor ), FALSE, TRUE ); 00098 00099 // Clear the background pixmap with the background color. Note that 00100 // we are going to reset the current gdk drawing color below, so we 00101 // can reuse the gc. 00102 gdk_gc_set_foreground( dev->gc, &( dev->bgcolor ) ); 00103 gdk_draw_rectangle( dev->background, dev->gc, TRUE, 0, 0, width, height ); 00104 00105 // Note that our pixmap is currently clear 00106 dev->pixmap_has_data = FALSE; 00107 00108 // Reset the current gdk drawing color 00109 gcw_set_gdk_color(); 00110 00111 #ifdef DEBUG_GCW_1 00112 gcw_debug( "</clear_background>\n" ); 00113 #endif 00114 } 00115 00116 00117 //-------------------------------------------------------------------------- 00118 // gcw_init_canvas() 00119 // 00120 // Initializes a canvas for use with this driver, and installs it into 00121 // the current gcw device. 00122 // 00123 //-------------------------------------------------------------------------- 00124 00125 void gcw_init_canvas( GnomeCanvas* canvas ) 00126 { 00127 GcwPLdev* dev = plsc->dev; 00128 00129 #ifdef DEBUG_GCW_1 00130 gcw_debug( "<gcw_init_canvas>\n" ); 00131 #endif 00132 00133 if ( !GNOME_IS_CANVAS( canvas ) ) 00134 plexit( "GCW driver: Canvas not found" ); 00135 00136 // Add the canvas to the device 00137 dev->canvas = canvas; 00138 00139 // Get the colormap 00140 dev->colormap = gtk_widget_get_colormap( GTK_WIDGET( dev->canvas ) ); 00141 00142 // Size the canvas 00143 gcw_set_canvas_size( canvas, dev->width, dev->height ); 00144 00145 // Create the persistent group, which is always visible 00146 if ( !GNOME_IS_CANVAS_ITEM( 00147 dev->group_persistent = GNOME_CANVAS_GROUP( gnome_canvas_item_new( 00148 gnome_canvas_root( canvas ), 00149 gnome_canvas_clipgroup_get_type(), 00150 "x", 0., 00151 "y", 0., 00152 NULL ) ) 00153 ) ) 00154 { 00155 plexit( "GCW driver <gcw_init_canvas>: Canvas group cannot be created" ); 00156 } 00157 00158 // Set the clip to NULL 00159 g_object_set( G_OBJECT( dev->group_persistent ), "path", NULL, NULL ); 00160 00161 #ifdef DEBUG_GCW1 00162 gcw_debug( "</gcw_init_canvas>\n" ); 00163 #endif 00164 } 00165 00166 00167 //-------------------------------------------------------------------------- 00168 // gcw_install_canvas() 00169 // 00170 // Installs a canvas into the current gcw device's window. The canvas is 00171 // created if necessary. A variety of callbacks are defined for actions 00172 // in the window. 00173 // 00174 //-------------------------------------------------------------------------- 00175 00176 //****************************** 00177 // Main window event callbacks * 00178 //***************************** 00179 00180 // Delete event callback 00181 gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ) 00182 { 00183 return FALSE; // FALSE follows with the destroy signal 00184 } 00185 00186 // Destroy event calback 00187 void destroy( GtkWidget *widget, gpointer data ) 00188 { 00189 gtk_main_quit(); 00190 } 00191 00192 //***************** 00193 // Zoom callbacks * 00194 //**************** 00195 00196 // All-purpose zoom callback. Referred to by specific zoom callbacks given 00197 // below. 00198 // 00199 void zoom( gpointer data, gint flag ) 00200 { 00201 gint n; 00202 00203 GnomeCanvas *canvas; 00204 GtkWidget *scrolled_window; 00205 GList *list; 00206 00207 GcwPLdev * dev = data; 00208 00209 gdouble curmag, dum; 00210 00211 // Get the current canvas 00212 n = gtk_notebook_get_current_page( GTK_NOTEBOOK( dev->notebook ) ); 00213 scrolled_window = gtk_notebook_get_nth_page( GTK_NOTEBOOK( dev->notebook ), n ); 00214 canvas = GNOME_CANVAS( gtk_container_get_children( 00215 GTK_CONTAINER( gtk_container_get_children( 00216 GTK_CONTAINER( scrolled_window ) )->data ) )->data ); 00217 00218 // Determine the new magnification 00219 if ( flag == 2 ) // Zoom in 00220 gcw_set_canvas_zoom( canvas, ZOOMSTEP ); 00221 else if ( flag == 0 ) // Zoom out 00222 00223 { // Don't zoom smaller than the original size: this causes GDK pixmap 00224 // errors. 00225 // 00226 gnome_canvas_c2w( canvas, 1, 0, &curmag, &dum ); 00227 curmag = 1. / curmag; 00228 if ( curmag / ZOOMSTEP > 1. ) 00229 { 00230 gcw_set_canvas_zoom( canvas, 1. / ZOOMSTEP ); 00231 } 00232 else 00233 { 00234 gcw_set_canvas_zoom( canvas, (PLFLT) ( ZOOM100 / curmag ) ); 00235 } 00236 } 00237 else // Zoom 100 00238 { 00239 // Get current magnification 00240 gnome_canvas_c2w( canvas, 1, 0, &curmag, &dum ); 00241 curmag = 1. / curmag; 00242 gcw_set_canvas_zoom( canvas, (PLFLT) ( ZOOM100 / curmag ) ); 00243 } 00244 00245 // Set the focus on the notebook 00246 gtk_window_set_focus( GTK_WINDOW( dev->window ), dev->notebook ); 00247 } 00248 00249 00250 // Callback when zoom in button is pressed 00251 void zoom_in( GtkWidget *widget, gpointer data ) 00252 { 00253 zoom( data, 2 ); 00254 } 00255 00256 // Callback when zoom 100 button is pressed 00257 void zoom_100( GtkWidget *widget, gpointer data ) 00258 { 00259 zoom( data, 1 ); 00260 } 00261 00262 // Callback when zoom out button is pressed 00263 void zoom_out( GtkWidget *widget, gpointer data ) 00264 { 00265 zoom( data, 0 ); 00266 } 00267 00268 //**************************** 00269 // File selection callbacks. * 00270 //*************************** 00271 00272 // Callback to OK file selection. Retrieves the selected filename and 00273 // replays the plot buffer to it through the associated driver. 00274 // 00275 void file_ok_sel( GtkWidget *w, gpointer data ) 00276 { 00277 GcwPLdev * dev = data; 00278 00279 GtkWidget *scrolled_window; 00280 GnomeCanvas *canvas; 00281 00282 gchar *fname; 00283 guint n; 00284 char devname[10], str[100]; 00285 00286 void *save_state; 00287 void *new_state; 00288 00289 PLINT cur_strm, new_strm; 00290 PLStream *plsr; 00291 00292 GtkWidget *fs; 00293 00294 gdouble curmag, dum; 00295 00296 gboolean errflag = FALSE; 00297 00298 struct stat buf; 00299 00300 GtkDialog *dialog; 00301 GtkWidget *hbox, *message, *icon; 00302 gint result; 00303 00304 guint context; 00305 00306 FILE *f; 00307 00308 // Get the file name 00309 if ( ( fname = 00310 strdup( gtk_file_selection_get_filename( GTK_FILE_SELECTION( dev->filew ) ) ) ) 00311 == NULL ) 00312 plabort( "GCW driver <file_ok_sel>: Cannot obtain filename" ); 00313 00314 // Check to see if the file already exists, and respond appropriately 00315 if ( stat( fname, &buf ) == 0 ) 00316 { 00317 // Confirm the user wants to overwrite the existing file 00318 00319 dialog = GTK_DIALOG( gtk_dialog_new_with_buttons( "", 00320 GTK_WINDOW( dev->filew ), 00321 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, 00322 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, 00323 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL ) ); 00324 00325 message = gtk_label_new( "" ); 00326 gtk_label_set_markup( GTK_LABEL( message ), 00327 "<span size=\"large\"><b>File exists. " 00328 "Overwrite?</b></span>" ); 00329 00330 icon = gtk_image_new_from_stock( GTK_STOCK_DIALOG_QUESTION, 00331 GTK_ICON_SIZE_DIALOG ); 00332 00333 hbox = gtk_hbox_new( FALSE, 0 ); 00334 gtk_box_pack_start( GTK_BOX( hbox ), icon, TRUE, TRUE, 10 ); 00335 gtk_box_pack_start( GTK_BOX( hbox ), message, TRUE, TRUE, 10 ); 00336 gtk_container_add( GTK_CONTAINER( dialog->vbox ), hbox ); 00337 00338 gtk_widget_show_all( GTK_WIDGET( dialog ) ); 00339 00340 result = gtk_dialog_run( dialog ); 00341 gtk_widget_destroy( GTK_WIDGET( dialog ) ); 00342 if ( result == GTK_RESPONSE_REJECT ) 00343 return; 00344 } 00345 00346 // Hide the file selection widget 00347 gtk_widget_hide( dev->filew ); 00348 00349 // Put the focus back on the notebook 00350 gtk_window_set_focus( GTK_WINDOW( dev->window ), dev->notebook ); 00351 00352 // Test that we can open and write to the file 00353 if ( ( f = fopen( fname, "w" ) ) == NULL ) 00354 plabort( "GCW driver <file_ok_sel>: Cannot open output file" ); 00355 fclose( f ); 00356 remove( fname ); // Otherwise, we may leave behind a zero-length file 00357 00358 // Get the file extension and make sure we recognize it. Allow names 00359 // of display devices as well. 00360 // 00361 // Note that we can't replot to xwin or tk devices, which can't open a 00362 // display for some reason. 00363 // 00364 // 00365 n = strlen( fname ); 00366 if ( strcasecmp( &fname[n - 3], "png" ) == 0 ) 00367 sprintf( devname, "png" ); 00368 else if ( strcasecmp( &fname[n - 3], "gif" ) == 0 ) 00369 sprintf( devname, "gif" ); 00370 else if ( strcasecmp( &fname[n - 3], "jpg" ) == 0 ) 00371 sprintf( devname, "jpg" ); 00372 else if ( strcasecmp( &fname[n - 4], "jpeg" ) == 0 ) 00373 sprintf( devname, "jpeg" ); 00374 else if ( strcasecmp( &fname[n - 2], "ps" ) == 0 ) 00375 sprintf( devname, "ps" ); 00376 else if ( strcasecmp( &fname[n - 3], "psc" ) == 0 ) 00377 sprintf( devname, "psc" ); 00378 else if ( strcasecmp( &fname[n - 4], "xwin" ) == 0 ) 00379 sprintf( devname, "xwin" ); 00380 else if ( strcasecmp( &fname[n - 3], "gcw" ) == 0 ) 00381 sprintf( devname, "gcw" ); 00382 else if ( strcasecmp( &fname[n - 2], "tk" ) == 0 ) 00383 sprintf( devname, "tk" ); 00384 else 00385 { 00386 if ( dev->statusbar != NULL ) 00387 { 00388 context = gtk_statusbar_get_context_id( GTK_STATUSBAR( dev->statusbar ), 00389 "PLplot" ); 00390 gtk_statusbar_push( GTK_STATUSBAR( dev->statusbar ), context, 00391 " WARNING: File type not recognized (unknown " 00392 "extension). Use one of ps, psc, png, jpg, or " 00393 "gif." 00394 ); 00395 return; 00396 } 00397 else 00398 plabort( "GCW driver <file_ok_sel>: File type not recognized" ); 00399 } 00400 00401 // Check that we are set up appropriately for device 00402 if ( strcmp( devname, "ps" ) == 0 || strcmp( devname, "psc" ) == 0 ) 00403 { 00404 if ( plsc->dev_hrshsym != 1 ) 00405 if ( dev->statusbar != NULL ) 00406 { 00407 context = gtk_statusbar_get_context_id( GTK_STATUSBAR( dev->statusbar ), 00408 "PLplot" ); 00409 00410 gtk_statusbar_push( GTK_STATUSBAR( dev->statusbar ), context, 00411 " NOTE: Use '-drvopt hrshsym' on command-line " 00412 "for complete symbol set in PostScript files." 00413 ); 00414 } 00415 else 00416 plwarn( "GCW driver: Use '-drvopt hrshsym' if symbols are missing in " 00417 "saved PostScript files." ); 00418 } 00419 if ( strcmp( devname, "xwin" ) == 0 || strcmp( devname, "tk" ) == 0 ) 00420 { 00421 if ( plsc->dev_text != 0 ) 00422 plwarn( "GCW driver: Use '-drvopt text=0'" ); 00423 } 00424 00425 // Get the current canvas 00426 n = gtk_notebook_get_current_page( GTK_NOTEBOOK( dev->notebook ) ); 00427 scrolled_window = gtk_notebook_get_nth_page( GTK_NOTEBOOK( dev->notebook ), n ); 00428 canvas = GNOME_CANVAS( gtk_container_get_children( 00429 GTK_CONTAINER( gtk_container_get_children( 00430 GTK_CONTAINER( scrolled_window ) )->data ) )->data ); 00431 00432 // Switch in the previously saved plot state 00433 new_state = g_object_get_data( G_OBJECT( canvas ), "plotbuf" ); 00434 00435 if ( new_state != NULL ) 00436 { 00437 save_state = (void *) plbuf_switch( plsc, new_state ); 00438 00439 plsetopt( "drvopt", "text" ); // Blank out the drvopts (not needed here) 00440 00441 // Get the current stream and make a new one 00442 plgstrm( &cur_strm ); 00443 plsr = plsc; // Save a pointer to the current stream 00444 00445 plmkstrm( &new_strm ); 00446 plsfnam( fname ); // Set the file name 00447 plsdev( devname ); // Set the device 00448 00449 // Copy the current stream to the new stream. 00450 plcpstrm( cur_strm, 0 ); 00451 00452 plreplot(); // do the save by replaying the plot buffer 00453 00454 plend1(); // finish the device 00455 00456 plsstrm( cur_strm ); // return to previous stream 00457 00458 plbuf_restore( plsc, save_state ); 00459 free( save_state ); 00460 } 00461 else 00462 { 00463 plwarn( "GCW driver <file_ok_sel>: Cannot set up output stream." ); 00464 } 00465 } 00466 00467 // Callback to cancel file selection 00468 void file_cancel_sel( GtkWidget *w, gpointer data ) 00469 { 00470 GcwPLdev* dev = data; 00471 00472 // Hide the file selection widget 00473 gtk_widget_hide( dev->filew ); 00474 00475 // Put the focus back on the notebook 00476 gtk_window_set_focus( GTK_WINDOW( dev->window ), dev->notebook ); 00477 } 00478 00479 // Callback to create file selection dialog 00480 void filesel( GtkWidget *widget, gpointer data ) 00481 { 00482 GtkWidget *scrolled_window; 00483 GnomeCanvas *canvas; 00484 00485 GcwPLdev * dev = data; 00486 00487 guint n; 00488 00489 // Get the current canvas 00490 n = gtk_notebook_get_current_page( GTK_NOTEBOOK( dev->notebook ) ); 00491 scrolled_window = gtk_notebook_get_nth_page( GTK_NOTEBOOK( dev->notebook ), n ); 00492 canvas = GNOME_CANVAS( gtk_container_get_children( 00493 GTK_CONTAINER( gtk_container_get_children( 00494 GTK_CONTAINER( scrolled_window ) )->data ) )->data ); 00495 00496 // Create a new file dialog if it doesn't already exist 00497 if ( dev->filew == NULL ) 00498 { 00499 // Create a new file selection widget 00500 dev->filew = gtk_file_selection_new( "File selection" ); 00501 00502 // Connect the ok_button to file_ok_sel function 00503 g_signal_connect( G_OBJECT( GTK_FILE_SELECTION( dev->filew )->ok_button ), 00504 "clicked", G_CALLBACK( file_ok_sel ), (gpointer) dev ); 00505 00506 // Connect the cancel_button to destroy the widget 00507 g_signal_connect( G_OBJECT( GTK_FILE_SELECTION( dev->filew )->cancel_button ), 00508 "clicked", G_CALLBACK( file_cancel_sel ), (gpointer) dev ); 00509 00510 // Lets set the filename, as if this were a save dialog, and we are giving 00511 // a default filename 00512 gtk_file_selection_set_filename( GTK_FILE_SELECTION( dev->filew ), 00513 "plot.psc" ); 00514 } 00515 00516 gtk_widget_show( dev->filew ); 00517 } 00518 00519 //************************* 00520 // Key release callbacks. * 00521 //************************ 00522 00523 void key_release( GtkWidget *widget, GdkEventKey *event, gpointer data ) 00524 { 00525 if ( event->keyval == '+' ) 00526 zoom( data, 2 ); 00527 if ( event->keyval == '=' ) 00528 zoom( data, 1 ); 00529 if ( event->keyval == '-' ) 00530 zoom( data, 0 ); 00531 if ( event->keyval == 'q' ) 00532 destroy( widget, data ); 00533 } 00534 00535 //********************* 00536 // gcw_install_canvas * 00537 //******************** 00538 00539 void gcw_install_canvas( GnomeCanvas *canvas ) 00540 { 00541 GcwPLdev * dev = plsc->dev; 00542 GtkWidget *vbox, *hbox, *button, *image, *scrolled_window; 00543 00544 gboolean flag = FALSE; 00545 00546 PLINT width, height; 00547 00548 #ifdef DEBUG_GCW_1 00549 gcw_debug( "<gcw_install_canvas>\n" ); 00550 #endif 00551 00552 // Create a new canvas if needed 00553 if ( !GNOME_IS_CANVAS( canvas ) ) 00554 { 00555 if ( !GNOME_IS_CANVAS( canvas = GNOME_CANVAS( gnome_canvas_new_aa() ) ) ) 00556 plexit( "GCW driver <gcw_install_canvas>: Could not create Canvas" ); 00557 } 00558 00559 // Initialize canvas 00560 gcw_init_canvas( canvas ); 00561 00562 if ( dev->window == NULL ) // Create a new window and install a notebook 00563 00564 { 00565 flag = TRUE; 00566 00567 // Create a new window 00568 dev->window = gtk_window_new( GTK_WINDOW_TOPLEVEL ); 00569 gtk_window_set_title( GTK_WINDOW( dev->window ), "PLplot" ); 00570 00571 // Connect the signal handlers to the window decorations 00572 g_signal_connect( G_OBJECT( dev->window ), "delete_event", 00573 G_CALLBACK( delete_event ), NULL ); 00574 g_signal_connect( G_OBJECT( dev->window ), "destroy", G_CALLBACK( destroy ), NULL ); 00575 00576 00577 // Create a vbox and put it into the window 00578 vbox = gtk_vbox_new( FALSE, 2 ); 00579 gtk_container_add( GTK_CONTAINER( dev->window ), vbox ); 00580 00581 // Create a hbox and put it into the vbox 00582 hbox = gtk_hbox_new( FALSE, 0 ); 00583 gtk_box_pack_start( GTK_BOX( vbox ), hbox, TRUE, TRUE, 0 ); 00584 00585 // Create a statusbar and put it into the vbox 00586 dev->statusbar = gtk_statusbar_new(); 00587 gtk_box_pack_start( GTK_BOX( vbox ), dev->statusbar, FALSE, FALSE, 0 ); 00588 00589 // Add an vbox to the hbox 00590 vbox = gtk_vbox_new( FALSE, 5 ); 00591 gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 ); 00592 gtk_box_pack_start( GTK_BOX( hbox ), vbox, FALSE, FALSE, 0 ); 00593 00594 // Create the new notebook and add it to the hbox 00595 dev->notebook = gtk_notebook_new(); 00596 gtk_notebook_set_scrollable( GTK_NOTEBOOK( dev->notebook ), TRUE ); 00597 gtk_box_pack_start( GTK_BOX( hbox ), dev->notebook, TRUE, TRUE, 0 ); 00598 g_signal_connect( G_OBJECT( dev->notebook ), "key_release_event", 00599 G_CALLBACK( key_release ), G_OBJECT( dev->notebook ) ); 00600 00601 // Use a few labels as spacers 00602 gtk_box_pack_start( GTK_BOX( vbox ), gtk_label_new( " " ), FALSE, FALSE, 0 ); 00603 gtk_box_pack_start( GTK_BOX( vbox ), gtk_label_new( " " ), FALSE, FALSE, 0 ); 00604 00605 // Add buttons to the vbox 00606 00607 // Add zoom in button and create callbacks 00608 image = gtk_image_new_from_stock( GTK_STOCK_ZOOM_IN, 00609 GTK_ICON_SIZE_SMALL_TOOLBAR ); 00610 button = gtk_button_new(); 00611 gtk_container_add( GTK_CONTAINER( button ), image ); 00612 gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 ); 00613 g_signal_connect( G_OBJECT( button ), "clicked", 00614 G_CALLBACK( zoom_in ), (gpointer) dev ); 00615 g_signal_connect( G_OBJECT( button ), "key_release_event", 00616 G_CALLBACK( key_release ), (gpointer) dev ); 00617 00618 // Add zoom100 button and create callbacks 00619 image = gtk_image_new_from_stock( GTK_STOCK_ZOOM_100, 00620 GTK_ICON_SIZE_SMALL_TOOLBAR ); 00621 button = gtk_button_new(); 00622 gtk_container_add( GTK_CONTAINER( button ), image ); 00623 gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 ); 00624 g_signal_connect( G_OBJECT( button ), "clicked", 00625 G_CALLBACK( zoom_100 ), (gpointer) dev ); 00626 00627 // Add zoom out button and create callbacks 00628 image = gtk_image_new_from_stock( GTK_STOCK_ZOOM_OUT, 00629 GTK_ICON_SIZE_SMALL_TOOLBAR ); 00630 button = gtk_button_new(); 00631 gtk_container_add( GTK_CONTAINER( button ), image ); 00632 gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 ); 00633 g_signal_connect( G_OBJECT( button ), "clicked", 00634 G_CALLBACK( zoom_out ), (gpointer) dev ); 00635 g_signal_connect( G_OBJECT( button ), "key_release_event", 00636 G_CALLBACK( key_release ), (gpointer) dev ); 00637 00638 // Add save button and create callbacks 00639 if ( plsc->plbuf_write ) 00640 { 00641 image = gtk_image_new_from_stock( GTK_STOCK_SAVE, 00642 GTK_ICON_SIZE_SMALL_TOOLBAR ); 00643 button = gtk_button_new(); 00644 gtk_container_add( GTK_CONTAINER( button ), image ); 00645 gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 ); 00646 g_signal_connect( G_OBJECT( button ), "clicked", 00647 G_CALLBACK( filesel ), (gpointer) dev ); 00648 } 00649 } // if(dev->window==NULL) 00650 00651 // Put the canvas in a scrolled window 00652 scrolled_window = gtk_scrolled_window_new( NULL, NULL ); 00653 gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scrolled_window ), 00654 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); 00655 gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( scrolled_window ), 00656 GTK_WIDGET( canvas ) ); 00657 00658 // Install the scrolled window in the notebook 00659 gtk_notebook_append_page( GTK_NOTEBOOK( dev->notebook ), scrolled_window, NULL ); 00660 00661 if ( flag ) 00662 { 00663 // Set the focus on the notebook 00664 gtk_window_set_focus( GTK_WINDOW( dev->window ), dev->notebook ); 00665 00666 // Retrieve the canvas width and height 00667 width = *(PLINT *) g_object_get_data( G_OBJECT( canvas ), "canvas-width" ); 00668 height = *(PLINT *) g_object_get_data( G_OBJECT( canvas ), "canvas-height" ); 00669 00670 // Size the window 00671 gtk_window_resize( GTK_WINDOW( dev->window ), width * ZOOM100 + 65, 00672 height * ZOOM100 + 75 ); 00673 } 00674 00675 // Display everything 00676 gtk_widget_show_all( dev->window ); 00677 00678 #ifdef DEBUG_GCW_1 00679 gcw_debug( "</gcw_install_canvas>\n" ); 00680 #endif 00681 } 00682 00683 00684 //-------------------------------------------------------------------------- 00685 // gcw_set_device_size() 00686 // 00687 // Sets the page size for this device. 00688 // 00689 // Width and height are both measured in device coordinate units. 00690 // 00691 // Note that coordinates in driver-space are measured in device units, 00692 // which correspond to the pixel size on a typical screen. The coordinates 00693 // reported and received from the PLplot core, however, are in virtual 00694 // coordinates, which is just a scaled version of the device coordinates. 00695 // This strategy is used so that the calculations in the PLplot 00696 // core are performed at reasonably high resolution. 00697 // 00698 //-------------------------------------------------------------------------- 00699 00700 void gcw_set_device_size( PLINT width, PLINT height ) 00701 { 00702 GcwPLdev* dev = plsc->dev; 00703 PLINT w, h; 00704 00705 // Set the number of virtual coordinate units per mm 00706 plP_setpxl( (PLFLT) VIRTUAL_PIXELS_PER_MM, (PLFLT) VIRTUAL_PIXELS_PER_MM ); 00707 00708 // Set up physical limits of plotting device, in virtual coord units 00709 w = (PLINT) ( width * VSCALE ); 00710 h = (PLINT) ( height * VSCALE ); 00711 plP_setphy( (PLINT) 0, w, (PLINT) 0, h ); 00712 00713 // Save the width and height for the device, in device units 00714 dev->width = width; 00715 dev->height = height; 00716 } 00717 00718 //-------------------------------------------------------------------------- 00719 // gcw_set_canvas_size() 00720 // 00721 // Sets the canvas size. If resizing is not allowed, this function 00722 // ensures that the canvas size matches the physical page size. 00723 // 00724 //-------------------------------------------------------------------------- 00725 00726 gint count = 0; 00727 00728 void gcw_set_canvas_size( GnomeCanvas* canvas, PLINT width, PLINT height ) 00729 { 00730 GcwPLdev * dev = plsc->dev; 00731 PLINT tmp; 00732 00733 PLINT *w, *h; 00734 00735 GdkGC *gc_new; 00736 GdkGCValues values; 00737 00738 PLINT strm; 00739 00740 GdkPixmap *background; 00741 00742 #ifdef DEBUG_GCW_1 00743 gcw_debug( "<gcw_set_canvas_size>\n" ); 00744 #endif 00745 00746 // Set the device size, if resizing is allowed. 00747 if ( dev->allow_resize ) 00748 gcw_set_device_size( width, height ); 00749 00750 width = dev->width; 00751 height = dev->height; 00752 if ( plsc->portrait ) // Swap width and height of display 00753 { 00754 tmp = width; 00755 width = height; 00756 height = tmp; 00757 } 00758 00759 // The width and height need to be enlarged by 1 pixel for the canvas 00760 width += 1; 00761 height += 1; 00762 00763 // Attach the width and height to the canvas 00764 if ( ( w = (PLINT *) malloc( sizeof ( gint ) ) ) == NULL ) 00765 plwarn( "GCW driver <gcw_set_canvas_size>: Insufficient memory." ); 00766 if ( ( h = (PLINT *) malloc( sizeof ( gint ) ) ) == NULL ) 00767 plwarn( "GCW driver <gcw_set_canvas_size>: Insufficient memory." ); 00768 *w = width; 00769 *h = height; 00770 g_object_set_data( G_OBJECT( canvas ), "canvas-width", (gpointer) w ); 00771 g_object_set_data( G_OBJECT( canvas ), "canvas-height", (gpointer) h ); 00772 00773 // Size the canvas appropriately 00774 gtk_widget_set_size_request( GTK_WIDGET( canvas ), (gint) ( width ), 00775 (gint) ( height ) ); 00776 00777 // Position the canvas appropriately 00778 gnome_canvas_set_scroll_region( canvas, 0., (gdouble) ( -height ), 00779 (gdouble) ( width ), 1. ); 00780 00781 // Set up the background pixmap 00782 if ( dev->background == NULL || dev->allow_resize ) 00783 { 00784 if ( GDK_IS_PIXMAP( dev->background ) ) 00785 g_object_unref( dev->background ); 00786 00787 // Why does this next *useless* command speed up the animation demo? 00788 // If we unref the allocated pixmaps, the benefit goes away!! 00789 // if(count<2) { 00790 // gdk_pixmap_new(NULL,width,height,gdk_visual_get_best_depth()); 00791 // printf("Count %d\n",count); 00792 // count++; 00793 // } 00794 // else { printf("Count %d\n",count); count ++; } 00795 00796 dev->background = gdk_pixmap_new( NULL, width, height, 00797 gtk_widget_get_visual( GTK_WIDGET( canvas ) )->depth ); 00798 } 00799 00800 // Set up the drawing context for the background pixmap 00801 if ( dev->gc == NULL || dev->allow_resize ) 00802 { 00803 // Maintain the old values for pen width, color, etc 00804 if ( GDK_IS_GC( dev->gc ) ) 00805 { 00806 gdk_gc_get_values( dev->gc, &values ); 00807 gdk_gc_unref( dev->gc ); 00808 dev->gc = gdk_gc_new_with_values( dev->background, &values, 00809 GDK_GC_FOREGROUND | GDK_GC_LINE_WIDTH | 00810 GDK_GC_LINE_STYLE | GDK_GC_CAP_STYLE | 00811 GDK_GC_JOIN_STYLE ); 00812 } 00813 else 00814 dev->gc = gdk_gc_new( dev->background ); 00815 } 00816 00817 // Clear the background pixmap 00818 gcw_clear_background( dev ); 00819 00820 // Advance the page if we are allowing resizing. This ensures that 00821 // the physical coordinate system is set up correctly. 00822 // 00823 if ( dev->allow_resize ) 00824 pladv( 0 ); 00825 00826 #ifdef DEBUG_GCW_1 00827 gcw_debug( "</gcw_set_canvas_size>\n" ); 00828 #endif 00829 } 00830 00831 00832 //-------------------------------------------------------------------------- 00833 // gcw_set_canvas_zoom() 00834 // 00835 // Sets the zoom magnification on the canvas and resizes the widget 00836 // appropriately. 00837 //-------------------------------------------------------------------------- 00838 00839 void gcw_set_canvas_zoom( GnomeCanvas* canvas, PLFLT magnification ) 00840 { 00841 gdouble curmag = 1., dum; 00842 00843 PLINT width, height; 00844 00845 #ifdef DEBUG_GCW_1 00846 gcw_debug( "<gcw_set_canvas_zoom>\n" ); 00847 #endif 00848 00849 // Retrieve the device width and height 00850 width = *(PLINT *) g_object_get_data( G_OBJECT( canvas ), "canvas-width" ); 00851 height = *(PLINT *) g_object_get_data( G_OBJECT( canvas ), "canvas-height" ); 00852 00853 // Get the current magnification 00854 gnome_canvas_c2w( canvas, 1, 0, &curmag, &dum ); 00855 curmag = 1. / curmag; 00856 00857 // Apply the new magnification 00858 gnome_canvas_set_pixels_per_unit( canvas, magnification * curmag ); 00859 00860 // Size the canvas appropriately 00861 gtk_widget_set_size_request( GTK_WIDGET( canvas ), 00862 (gint) ( ( width ) * magnification * curmag ), 00863 (gint) ( ( height ) * magnification * curmag ) ); 00864 00865 // Position the canvas appropriately 00866 gnome_canvas_set_scroll_region( canvas, 0., (gdouble) ( -height ), 00867 (gdouble) ( width ), 1. ); 00868 00869 #ifdef DEBUG_GCW_1 00870 gcw_debug( "</gcw_set_canvas_zoom>\n" ); 00871 #endif 00872 } 00873 00874 00875 //-------------------------------------------------------------------------- 00876 // gcw_use_text() 00877 // 00878 // Used to turn text usage on and off for the current device. 00879 //-------------------------------------------------------------------------- 00880 00881 void gcw_use_text( PLINT use_text ) 00882 { 00883 GcwPLdev* dev = plsc->dev; 00884 00885 #ifdef DEBUG_GCW_1 00886 gcw_debug( "<gcw_use_text>\n" ); 00887 #endif 00888 00889 #ifdef PL_HAVE_FREETYPE 00890 00891 if ( use_text ) 00892 plsc->dev_text = 1; // Allow text handling 00893 else 00894 plsc->dev_text = 0; // Disallow text handling 00895 00896 #endif 00897 00898 #ifdef DEBUG_GCW_1 00899 gcw_debug( "</gcw_use_text>\n" ); 00900 #endif 00901 } 00902 00903 00904 //-------------------------------------------------------------------------- 00905 // gcw_use_pixmap() 00906 // 00907 // Used to turn pixmap usage on and off for the current device. 00908 // This is relevant for polygon fills (used during shading calls). 00909 //-------------------------------------------------------------------------- 00910 00911 void gcw_use_pixmap( PLINT use_pixmap ) 00912 { 00913 GcwPLdev* dev = plsc->dev; 00914 00915 #ifdef DEBUG_GCW_1 00916 gcw_debug( "<gcw_use_pixmap>\n" ); 00917 #endif 00918 00919 dev->use_pixmap = (gboolean) use_pixmap; 00920 00921 #ifdef DEBUG_GCW_1 00922 gcw_debug( "</gcw_use_pixmap>\n" ); 00923 #endif 00924 } 00925 00926 00927 //-------------------------------------------------------------------------- 00928 // gcw_use_hrshsym() 00929 // 00930 // Used to turn hershey symbol usage on and off for the current device. 00931 //-------------------------------------------------------------------------- 00932 00933 void gcw_use_hrshsym( PLINT use_hrshsym ) 00934 { 00935 GcwPLdev* dev = plsc->dev; 00936 00937 #ifdef DEBUG_GCW_1 00938 gcw_debug( "<gcw_use_hrshsym>\n" ); 00939 #endif 00940 00941 plsc->dev_hrshsym = use_hrshsym; 00942 00943 #ifdef DEBUG_GCW_1 00944 gcw_debug( "</gcw_use_hrshsym>\n" ); 00945 #endif 00946 } 00947 00948 00949 //-------------------------------------------------------------------------- 00950 // gcw_use_persistence 00951 // 00952 // Directs the GCW driver whether or not the subsequent drawing operations 00953 // should be persistent. 00954 //-------------------------------------------------------------------------- 00955 00956 void gcw_use_persistence( PLINT use_persistence ) 00957 { 00958 GcwPLdev* dev = plsc->dev; 00959 00960 #ifdef DEBUG_GCW_1 00961 gcw_debug( "<gcw_use_persistence>\n" ); 00962 #endif 00963 00964 dev->use_persistence = (gboolean) use_persistence; 00965 00966 #ifdef DEBUG_GCW_1 00967 gcw_debug( "</gcw_use_persistence>\n" ); 00968 #endif 00969 }