PLplot  5.10.0
wxwidgets.cpp
Go to the documentation of this file.
00001 // Copyright (C) 2005  Werner Smekal, Sjaak Verdoold
00002 // Copyright (C) 2005  Germain Carrera Corraleche
00003 // Copyright (C) 1999  Frank Huebner
00004 //
00005 // This file is part of PLplot.
00006 //
00007 // PLplot is free software; you can redistribute it and/or modify
00008 // it under the terms of the GNU Library General Public License as published
00009 // by the Free Software Foundation; either version 2 of the License, or
00010 // (at your option) any later version.
00011 //
00012 // PLplot is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU Library General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU Library General Public License
00018 // along with PLplot; if not, write to the Free Software
00019 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020 //
00021 
00022 // TODO:
00023 // - NA
00024 //
00025 
00026 // wxwidgets headers
00027 #include <wx/wx.h>
00028 #include <wx/wfstream.h>
00029 #include <wx/except.h>
00030 
00031 #include "plDevs.h"
00032 
00033 // plplot headers
00034 #include "plplotP.h"
00035 #include "drivers.h"
00036 
00037 // C/C++ headers
00038 #include <cstdio>
00039 
00040 #include "wxwidgets.h"
00041 
00042 // Static function prototypes
00043 #ifdef PL_HAVE_FREETYPE
00044 static void plD_pixel_wxwidgets( PLStream *pls, short x, short y );
00045 static PLINT plD_read_pixel_wxwidgets( PLStream *pls, short x, short y );
00046 static void plD_set_pixel_wxwidgets( PLStream *pls, short x, short y, PLINT colour );
00047 static void init_freetype_lv1( PLStream *pls );
00048 static void init_freetype_lv2( PLStream *pls );
00049 #endif
00050 
00051 // private functions needed by the wxwidgets Driver
00052 static void install_buffer( PLStream *pls );
00053 static void wxRunApp( PLStream *pls, bool runonce = false );
00054 static void GetCursorCmd( PLStream *pls, PLGraphicsIn *ptr );
00055 static void fill_polygon( PLStream *pls );
00056 
00057 #ifdef __WXMAC__
00058         #include <Carbon/Carbon.h>
00059 extern "C" { void CPSEnableForegroundOperation( ProcessSerialNumber* psn ); }
00060 #endif
00061 
00062 DECLARE_PLAPP( wxPLplotApp )
00063 
00064 //--------------------------------------------------------------------------
00065 //  void Log_Verbose( const char *fmt, ... )
00066 //
00067 //  Print verbose debug message to stderr (printf style).
00068 //--------------------------------------------------------------------------
00069 void Log_Verbose( const char *fmt, ... )
00070 {
00071 #ifdef _DEBUG_VERBOSE
00072     va_list args;
00073     va_start( args, fmt );
00074     fprintf( stderr, "Verbose: " );
00075     vfprintf( stderr, fmt, args );
00076     fprintf( stderr, "\n" );
00077     va_end( args );
00078     fflush( stderr );
00079 #else
00080     (void) fmt;        // Cast to void to silence compiler warnings about unused paraemeter
00081 #endif
00082 }
00083 
00084 
00085 //--------------------------------------------------------------------------
00086 //  void Log_Debug( const char *fmt, ... )
00087 //
00088 //  Print debug message to stderr (printf style).
00089 //--------------------------------------------------------------------------
00090 void Log_Debug( const char *fmt, ... )
00091 {
00092 #ifdef _DEBUG
00093     va_list args;
00094     va_start( args, fmt );
00095     fprintf( stderr, "Debug: " );
00096     vfprintf( stderr, fmt, args );
00097     fprintf( stderr, "\n" );
00098     va_end( args );
00099     fflush( stderr );
00100 #else
00101     (void) fmt;        // Cast to void to silence compiler warnings about unused paraemeter
00102 #endif
00103 }
00104 
00105 
00106 //--------------------------------------------------------------------------
00107 //  In the following you'll find the driver functions which are
00108 //  are needed by the plplot core.
00109 //--------------------------------------------------------------------------
00110 
00111 // Device info
00112 #ifdef __cplusplus
00113 extern "C" {
00114 #endif
00115 
00116 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_wxwidgets =
00117 #ifdef PLD_wxwidgets
00118     "wxwidgets:wxWidgets Driver:1:wxwidgets:51:wxwidgets\n"
00119 #endif
00120 #ifdef PLD_wxpng
00121     "wxpng:wxWidgets PNG Driver:0:wxwidgets:52:wxpng\n"
00122 #endif
00123 ;
00124 
00125 #ifdef __cplusplus
00126 }
00127 #endif
00128 
00129 
00130 //--------------------------------------------------------------------------
00131 //  wxPLDevBase::wxPLDevBase( void )
00132 //
00133 //  Contructor of base class of wxPLDev classes.
00134 //--------------------------------------------------------------------------
00135 wxPLDevBase::wxPLDevBase( int bcknd ) : backend( bcknd )
00136 {
00137     // Log_Verbose( "wxPLDevBase::wxPLDevBase()" );
00138 
00139     ready    = false;
00140     ownGUI   = false;
00141     waiting  = false;
00142     resizing = false;
00143     exit     = false;
00144 
00145     comcount = 0;
00146 
00147     m_frame = NULL;
00148     xpos    = 0;
00149     ypos    = 0;
00150     // width, height are set in plD_init_wxwidgets
00151     // bm_width, bm_height are set in install_buffer
00152 
00153     // xmin, xmax, ymin, ymax are set in plD_init_wxwidgets
00154     // scalex, scaley are set in plD_init_wxwidgets
00155 
00156     plstate_width  = false;
00157     plstate_color0 = false;
00158     plstate_color1 = false;
00159 
00160     locate_mode = 0;
00161     draw_xhair  = false;
00162 
00163     newclipregion = true;
00164     clipminx      = 1024;
00165     clipmaxx      = 0;
00166     clipminy      = 800;
00167     clipmaxy      = 0;
00168 
00169     freetype    = 0;
00170     smooth_text = 0;
00171 
00172     devName = (const char **) malloc( NDEV * sizeof ( char** ) );
00173     memset( devName, '\0', NDEV * sizeof ( char** ) );
00174     devDesc = (const char **) malloc( NDEV * sizeof ( char** ) );
00175     memset( devDesc, '\0', NDEV * sizeof ( char** ) );
00176     ndev = NDEV;
00177 
00178     lineSpacing = 1.0;
00179 }
00180 
00181 
00182 wxPLDevBase::~wxPLDevBase( void )
00183 {
00184     if ( devDesc )
00185         free( devDesc );
00186     if ( devName )
00187         free( devName );
00188 }
00189 
00190 
00191 void wxPLDevBase::AddtoClipRegion( int x1, int y1, int x2, int y2 )
00192 {
00193     newclipregion = false;
00194     if ( x1 < x2 )
00195     {
00196         if ( x1 < clipminx )
00197             clipminx = x1;
00198         if ( x2 > clipmaxx )
00199             clipmaxx = x2;
00200     }
00201     else
00202     {
00203         if ( x2 < clipminx )
00204             clipminx = x2;
00205         if ( x1 > clipmaxx )
00206             clipmaxx = x1;
00207     }
00208     if ( y1 < y2 )
00209     {
00210         if ( y1 < clipminy )
00211             clipminy = y1;
00212         if ( y2 > clipmaxy )
00213             clipmaxy = y2;
00214     }
00215     else
00216     {
00217         if ( y2 < clipminy )
00218             clipminy = y2;
00219         if ( y1 > clipmaxy )
00220             clipmaxy = y1;
00221     }
00222 }
00223 
00224 
00225 void wxPLDevBase::PSDrawText( PLUNICODE* ucs4, int ucs4Len, bool drawText )
00226 {
00227     int  i = 0;
00228 
00229     char utf8_string[max_string_length];
00230     char utf8[5];
00231     memset( utf8_string, '\0', max_string_length );
00232 
00233     // Get PLplot escape character
00234     char plplotEsc;
00235     plgesc( &plplotEsc );
00236 
00237     //Reset the size metrics
00238     textWidth         = 0;
00239     textHeight        = 0;
00240     superscriptHeight = 0;
00241     subscriptDepth    = 0;
00242 
00243     while ( i < ucs4Len )
00244     {
00245         if ( ucs4[i] < PL_FCI_MARK )                // not a font change
00246         {
00247             if ( ucs4[i] != (PLUNICODE) plplotEsc ) // a character to display
00248             {
00249                 ucs4_to_utf8( ucs4[i], utf8 );
00250                 strncat( utf8_string, utf8,
00251                     sizeof ( utf8_string ) - strlen( utf8_string ) - 1 );
00252                 i++;
00253                 continue;
00254             }
00255             i++;
00256             if ( ucs4[i] == (PLUNICODE) plplotEsc ) // a escape character to display
00257             {
00258                 ucs4_to_utf8( ucs4[i], utf8 );
00259                 strncat( utf8_string, utf8,
00260                     sizeof ( utf8_string ) - strlen( utf8_string ) - 1 );
00261                 i++;
00262                 continue;
00263             }
00264             else
00265             {
00266                 if ( ucs4[i] == (PLUNICODE) 'u' ) // Superscript
00267                 {                                 // draw string so far
00268                     PSDrawTextToDC( utf8_string, drawText );
00269 
00270                     // change font scale
00271                     if ( yOffset < -0.0001 )
00272                         fontScale *= 1.25; // Subscript scaling parameter
00273                     else
00274                         fontScale *= 0.8;  // Subscript scaling parameter
00275                     PSSetFont( fci );
00276 
00277                     yOffset += scaley * fontSize * fontScale / 2.;
00278                 }
00279                 if ( ucs4[i] == (PLUNICODE) 'd' ) // Subscript
00280                 {                                 // draw string so far
00281                     PSDrawTextToDC( utf8_string, drawText );
00282 
00283                     // change font scale
00284                     double old_fontScale = fontScale;
00285                     if ( yOffset > 0.0001 )
00286                         fontScale *= 1.25; // Subscript scaling parameter
00287                     else
00288                         fontScale *= 0.8;  // Subscript scaling parameter
00289                     PSSetFont( fci );
00290 
00291                     yOffset -= scaley * fontSize * old_fontScale / 2.;
00292                 }
00293                 if ( ucs4[i] == (PLUNICODE) '-' ) // underline
00294                 {                                 // draw string so far
00295                     PSDrawTextToDC( utf8_string, drawText );
00296 
00297                     underlined = !underlined;
00298                     PSSetFont( fci );
00299                 }
00300                 if ( ucs4[i] == (PLUNICODE) '+' ) // overline
00301                 {                                 // not implemented yet
00302                 }
00303                 i++;
00304             }
00305         }
00306         else // a font change
00307         {
00308             // draw string so far
00309             PSDrawTextToDC( utf8_string, drawText );
00310 
00311             // get new font
00312             fci = ucs4[i];
00313             PSSetFont( fci );
00314             i++;
00315         }
00316     }
00317 
00318     PSDrawTextToDC( utf8_string, drawText );
00319 }
00320 
00321 
00322 //--------------------------------------------------------------------------
00323 //  void common_init(  PLStream *pls )
00324 //
00325 //  Basic initialization for all devices.
00326 //--------------------------------------------------------------------------
00327 wxPLDevBase* common_init( PLStream *pls )
00328 {
00329     // Log_Verbose( "common_init()" );
00330 
00331     wxPLDevBase* dev;
00332     PLFLT      downscale, downscale2;
00333 
00334     // default options
00335     static PLINT freetype    = -1;
00336     static PLINT smooth_text = 1;
00337     static PLINT text        = -1;
00338     static PLINT hrshsym     = 0;
00339 
00340     // default backend uses wxGraphicsContext, if not available
00341     // the agg library will be used, if not available the basic
00342     // backend will be used.
00343     static PLINT backend = wxBACKEND_DC;
00344   #if wxUSE_GRAPHICS_CONTEXT
00345     backend = wxBACKEND_GC;
00346         #else
00347                 #ifdef HAVE_AGG
00348     backend = wxBACKEND_AGG;
00349                 #endif
00350         #endif
00351 
00352     DrvOpt wx_options[] = {
00353 #ifdef PL_HAVE_FREETYPE
00354         { "freetype", DRV_INT, &freetype,    "Use FreeType library"                                                             },
00355         { "smooth",   DRV_INT, &smooth_text, "Turn text smoothing on (1) or off (0)"                                            },
00356 #endif
00357         { "hrshsym",  DRV_INT, &hrshsym,     "Use Hershey symbol set (hrshsym=0|1)"                                             },
00358         { "backend",  DRV_INT, &backend,     "Choose backend: (0) standard, (1) using AGG library, (2) using wxGraphicsContext" },
00359         { "text",     DRV_INT, &text,        "Use own text routines (text=0|1)"                                                 },
00360         { NULL,       DRV_INT, NULL,         NULL                                                                               }
00361     };
00362 
00363     // Check for and set up driver options
00364     plParseDrvOpts( wx_options );
00365 
00366     // allocate memory for the device storage
00367     switch ( backend )
00368     {
00369     case wxBACKEND_GC:
00370         // in case wxGraphicsContext isn't available, the next backend (agg
00371         // if available) in this list will be used
00372 #if wxUSE_GRAPHICS_CONTEXT
00373         dev = new wxPLDevGC;
00374         // by default the own text routines are used for wxGC
00375         if ( text == -1 )
00376             text = 1;
00377         freetype = 0; // this backend is vector oriented and doesn't know pixels
00378         break;
00379 #endif
00380     case wxBACKEND_AGG:
00381         // in case the agg library isn't available, the standard backend
00382         // will be used
00383 #ifdef HAVE_AGG
00384         dev = new wxPLDevAGG;
00385         // by default the freetype text routines are used for wxAGG
00386         text = 0; // text processing doesn't work yet for the AGG backend
00387         if ( freetype == -1 )
00388             freetype = 1;
00389         break;
00390 #endif
00391     default:
00392         dev = new wxPLDevDC;
00393         // by default the own text routines are used for wxDC
00394         if ( text == -1 )
00395         {
00396             if ( freetype != 1 )
00397                 text = 1;
00398             else
00399                 text = 0;
00400         }
00401         if ( freetype == -1 )
00402             freetype = 0;
00403         break;
00404     }
00405     if ( dev == NULL )
00406     {
00407         plexit( "Insufficient memory" );
00408     }
00409     pls->dev = (void *) dev;
00410 
00411 // be verbose and write out debug messages
00412 #ifdef _DEBUG
00413     pls->verbose = 1;
00414     pls->debug   = 1;
00415 #endif
00416 
00417     pls->color     = 1;             // Is a color device
00418     pls->dev_flush = 1;             // Handles flushes
00419     pls->dev_fill0 = 1;             // Can handle solid fills
00420     pls->dev_fill1 = 0;             // Can't handle pattern fills
00421     pls->dev_dash  = 0;
00422     pls->dev_clear = 1;             // driver supports clear
00423 
00424     if ( text )
00425     {
00426         pls->dev_text    = 1; // want to draw text
00427         pls->dev_unicode = 1; // want unicode
00428         if ( hrshsym )
00429             pls->dev_hrshsym = 1;
00430     }
00431 
00432 #ifdef PL_HAVE_FREETYPE
00433     // own text routines have higher priority over freetype
00434     // if text and freetype option are set to 1
00435     if ( !text )
00436     {
00437         dev->smooth_text = smooth_text;
00438         dev->freetype    = freetype;
00439     }
00440 
00441     if ( dev->freetype )
00442     {
00443         pls->dev_text    = 1; // want to draw text
00444         pls->dev_unicode = 1; // want unicode
00445         if ( hrshsym )
00446             pls->dev_hrshsym = 1;
00447 
00448         init_freetype_lv1( pls );
00449         FT_Data* FT = (FT_Data *) pls->FT;
00450         FT->want_smooth_text = smooth_text;
00451     }
00452 #endif
00453 
00454     // initialize frame size and position
00455     if ( pls->xlength <= 0 || pls->ylength <= 0 )
00456         plspage( 0.0, 0.0, (PLINT) ( CANVAS_WIDTH * DEVICE_PIXELS_PER_IN ),
00457             (PLINT) ( CANVAS_HEIGHT * DEVICE_PIXELS_PER_IN ), 0, 0 );
00458 
00459     dev->width    = pls->xlength;
00460     dev->height   = pls->ylength;
00461     dev->clipminx = pls->xlength;
00462     dev->clipminy = pls->ylength;
00463 
00464     if ( pls->xoffset != 0 || pls->yoffset != 0 )
00465     {
00466         dev->xpos = (int) ( pls->xoffset );
00467         dev->ypos = (int) ( pls->yoffset );
00468     }
00469 
00470 
00471     // If portrait mode, apply a rotation and set freeaspect
00472     if ( pls->portrait )
00473     {
00474         plsdiori( (PLFLT) ( 4 - ORIENTATION ) );
00475         pls->freeaspect = 1;
00476     }
00477 
00478     // Set the number of pixels per mm
00479     plP_setpxl( (PLFLT) VIRTUAL_PIXELS_PER_MM, (PLFLT) VIRTUAL_PIXELS_PER_MM );
00480 
00481     // Set up physical limits of plotting device (in drawing units)
00482     downscale  = (double) dev->width / (double) ( PIXELS_X - 1 );
00483     downscale2 = (double) dev->height / (double) PIXELS_Y;
00484     if ( downscale < downscale2 )
00485         downscale = downscale2;
00486     plP_setphy( (PLINT) 0, (PLINT) ( dev->width / downscale ),
00487         (PLINT) 0, (PLINT) ( dev->height / downscale ) );
00488 
00489     // get physical device limits coordinates
00490     plP_gphy( &dev->xmin, &dev->xmax, &dev->ymin, &dev->ymax );
00491 
00492     // setting scale factors
00493     dev->scalex = (PLFLT) ( dev->xmax - dev->xmin ) / ( dev->width );
00494     dev->scaley = (PLFLT) ( dev->ymax - dev->ymin ) / ( dev->height );
00495 
00496     // set dpi
00497     plspage( VIRTUAL_PIXELS_PER_IN / dev->scalex, VIRTUAL_PIXELS_PER_IN / dev->scaley, 0, 0, 0, 0 );
00498 
00499 #ifdef PL_HAVE_FREETYPE
00500     if ( dev->freetype )
00501         init_freetype_lv2( pls );
00502 #endif
00503 
00504     // find out what file drivers are available
00505     plgFileDevs( &dev->devDesc, &dev->devName, &dev->ndev );
00506 
00507     return dev;
00508 }
00509 
00510 
00511 #ifdef PLD_wxwidgets
00512 
00513 //--------------------------------------------------------------------------
00514 //  void plD_dispatch_init_wxwidgets( PLDispatchTable *pdt )
00515 //
00516 //  Make wxwidgets driver functions known to plplot.
00517 //--------------------------------------------------------------------------
00518 void plD_dispatch_init_wxwidgets( PLDispatchTable *pdt )
00519 {
00520 #ifndef ENABLE_DYNDRIVERS
00521     pdt->pl_MenuStr = "wxWidgets DC";
00522     pdt->pl_DevName = "wxwidgets";
00523 #endif
00524     pdt->pl_type     = plDevType_Interactive;
00525     pdt->pl_seq      = 51;
00526     pdt->pl_init     = (plD_init_fp) plD_init_wxwidgets;
00527     pdt->pl_line     = (plD_line_fp) plD_line_wxwidgets;
00528     pdt->pl_polyline = (plD_polyline_fp) plD_polyline_wxwidgets;
00529     pdt->pl_eop      = (plD_eop_fp) plD_eop_wxwidgets;
00530     pdt->pl_bop      = (plD_bop_fp) plD_bop_wxwidgets;
00531     pdt->pl_tidy     = (plD_tidy_fp) plD_tidy_wxwidgets;
00532     pdt->pl_state    = (plD_state_fp) plD_state_wxwidgets;
00533     pdt->pl_esc      = (plD_esc_fp) plD_esc_wxwidgets;
00534 }
00535 
00536 //--------------------------------------------------------------------------
00537 //  plD_init_wxwidgets( PLStream* pls )
00538 //
00539 //  Initialize wxWidgets device.
00540 //--------------------------------------------------------------------------
00541 void plD_init_wxwidgets( PLStream* pls )
00542 {
00543     // Log_Verbose( "plD_init_wxwidgets()" );
00544 
00545     wxPLDevBase* dev;
00546     dev = common_init( pls );
00547 
00548     pls->plbuf_write = 1;             // use the plot buffer!
00549     pls->termin      = 1;             // interactive device
00550     pls->graphx      = GRAPHICS_MODE; //  No text mode for this driver (at least for now, might add a console window if I ever figure it out and have the inclination)
00551 
00552     dev->showGUI    = true;
00553     dev->bitmapType = (wxBitmapType) 0;
00554 }
00555 
00556 #endif  // PLD_wxwidgets
00557 
00558 
00559 #ifdef PLD_wxpng
00560 
00561 //--------------------------------------------------------------------------
00562 //  void plD_dispatch_init_wxpng( PLDispatchTable *pdt )
00563 //
00564 //  Make wxpng driver functions known to plplot.
00565 //--------------------------------------------------------------------------
00566 void plD_dispatch_init_wxpng( PLDispatchTable *pdt )
00567 {
00568 #ifndef ENABLE_DYNDRIVERS
00569     pdt->pl_MenuStr = "wxWidgets PNG driver";
00570     pdt->pl_DevName = "wxpng";
00571 #endif
00572     pdt->pl_type     = plDevType_FileOriented;
00573     pdt->pl_seq      = 52;
00574     pdt->pl_init     = (plD_init_fp) plD_init_wxpng;
00575     pdt->pl_line     = (plD_line_fp) plD_line_wxwidgets;
00576     pdt->pl_polyline = (plD_polyline_fp) plD_polyline_wxwidgets;
00577     pdt->pl_eop      = (plD_eop_fp) plD_eop_wxwidgets;
00578     pdt->pl_bop      = (plD_bop_fp) plD_bop_wxwidgets;
00579     pdt->pl_tidy     = (plD_tidy_fp) plD_tidy_wxwidgets;
00580     pdt->pl_state    = (plD_state_fp) plD_state_wxwidgets;
00581     pdt->pl_esc      = (plD_esc_fp) plD_esc_wxwidgets;
00582 }
00583 
00584 //--------------------------------------------------------------------------
00585 //  void plD_init_wxpng( PLStream *pls )
00586 //
00587 //  Initialize wxpng device.
00588 //--------------------------------------------------------------------------
00589 void plD_init_wxpng( PLStream *pls )
00590 {
00591     // Log_Verbose( "plD_init_wxwidgets()" );
00592 
00593     wxPLDevBase* dev;
00594     dev = common_init( pls );
00595 
00596     // Initialize family file info
00597     plFamInit( pls );
00598 
00599     // Prompt for a file name if not already set.
00600     plOpenFile( pls );
00601 
00602     pls->plbuf_write = 1;             // use the plot buffer!
00603     pls->dev_flush   = 0;             // No need for flushes
00604     pls->termin      = 0;             // file oriented device
00605     pls->graphx      = GRAPHICS_MODE; //  No text mode for this driver (at least for now, might add a console window if I ever figure it out and have the inclination)
00606     pls->page        = 0;
00607 
00608     dev->showGUI    = false;
00609     dev->bitmapType = wxBITMAP_TYPE_PNG;
00610 }
00611 
00612 #endif  // PLD_wxpng
00613 
00614 
00615 //--------------------------------------------------------------------------
00616 //  void plD_line_wxwidgets( PLStream *pls, short x1a, short y1a,
00617 //                                                                                                       short x2a, short y2a )
00618 //
00619 //  Draws a line from (x1a, y1a) to (x2a, y2a).
00620 //--------------------------------------------------------------------------
00621 void plD_line_wxwidgets( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
00622 {
00623     // Log_Verbose( "plD_line_wxwidgets(x1a=%d, y1a=%d, x2a=%d, y2a=%d)", x1a, y1a, x2a, y2a );
00624 
00625     wxPLDevBase* dev = (wxPLDevBase *) pls->dev;
00626 
00627     if ( !( dev->ready ) )
00628         install_buffer( pls );
00629 
00630     dev->DrawLine( x1a, y1a, x2a, y2a );
00631 
00632     if ( !( dev->resizing ) && dev->ownGUI )
00633     {
00634         dev->comcount++;
00635         if ( dev->comcount > MAX_COMCOUNT )
00636         {
00637             wxRunApp( pls, true );
00638             dev->comcount = 0;
00639         }
00640     }
00641 }
00642 
00643 
00644 //--------------------------------------------------------------------------
00645 //  void plD_polyline_wxwidgets( PLStream *pls, short *xa, short *ya,
00646 //                                                                                                                       PLINT npts )
00647 //
00648 //  Draw a poly line - points are in xa and ya arrays.
00649 //--------------------------------------------------------------------------
00650 void plD_polyline_wxwidgets( PLStream *pls, short *xa, short *ya, PLINT npts )
00651 {
00652     // Log_Verbose( "plD_polyline_wxwidgets()" );
00653 
00654     // should be changed to use the wxDC::DrawLines function?
00655     wxPLDevBase* dev = (wxPLDevBase *) pls->dev;
00656 
00657     if ( !( dev->ready ) )
00658         install_buffer( pls );
00659 
00660     dev->DrawPolyline( xa, ya, npts );
00661 
00662     if ( !( dev->resizing ) && dev->ownGUI )
00663     {
00664         dev->comcount++;
00665         if ( dev->comcount > MAX_COMCOUNT )
00666         {
00667             wxRunApp( pls, true );
00668             dev->comcount = 0;
00669         }
00670     }
00671 }
00672 
00673 
00674 //--------------------------------------------------------------------------
00675 //  void plD_eop_wxwidgets( PLStream *pls )
00676 //
00677 //  End of Page. This function is called if a "end of page" is send by the
00678 //  user. This command is ignored if we have the plot embedded in a
00679 //  wxWidgets application, otherwise the application created by the device
00680 //  takes over.
00681 //--------------------------------------------------------------------------
00682 void plD_eop_wxwidgets( PLStream *pls )
00683 {
00684     // Log_Verbose( "plD_eop_wxwidgets()" );
00685 
00686     wxPLDevBase* dev = (wxPLDevBase *) pls->dev;
00687 
00688     if ( dev->bitmapType )
00689     {
00690         wxMemoryDC memDC;
00691         wxBitmap   bitmap( dev->width, dev->height, -1 );
00692         memDC.SelectObject( bitmap );
00693 
00694         dev->BlitRectangle( &memDC, 0, 0, dev->width, dev->height );
00695         wxImage             buffer = bitmap.ConvertToImage();
00696         wxFFileOutputStream fstream( pls->OutFile );
00697         if ( !( buffer.SaveFile( fstream, dev->bitmapType ) ) )
00698             puts( "Troubles saving file!" );
00699         memDC.SelectObject( wxNullBitmap );
00700     }
00701 
00702     if ( dev->ownGUI )
00703     {
00704         if ( pls->nopause || !dev->showGUI )
00705             wxRunApp( pls, true );
00706         else
00707             wxRunApp( pls );
00708     }
00709 }
00710 
00711 
00712 //--------------------------------------------------------------------------
00713 //  void plD_bop_wxwidgets( PLStream *pls )
00714 //
00715 //  Begin of page. Before any plot command, this function is called, If we
00716 //  have already a dc the background is cleared in background color and some
00717 //  state calls are resent - this is because at the first call of this
00718 //  function, a dc does most likely not exist, but state calls are recorded
00719 //  and when a new dc is created this function is called again.
00720 //--------------------------------------------------------------------------
00721 void plD_bop_wxwidgets( PLStream *pls )
00722 {
00723     // Log_Verbose( "plD_bop_wxwidgets()" );
00724 
00725     wxPLDevBase* dev = (wxPLDevBase *) pls->dev;
00726 
00727     if ( dev->ready )
00728     {
00729         //if( pls->termin==0 ) {
00730         // plGetFam( pls );
00731         // force new file if pls->family set for all subsequent calls to plGetFam
00732         // n.b. putting this after plGetFam call is important since plinit calls
00733         // bop, and you don't want the familying sequence started until after
00734         // that first call to bop.
00735 
00736         // n.b. pls->dev can change because of an indirect call to plD_init_png
00737         // from plGetFam if familying is enabled.  Thus, wait to define dev until
00738         // now.
00739         //dev = (wxPLDevBase*)pls->dev;
00740         //
00741         // pls->famadv = 1;
00742         // pls->page++;
00743         // }
00744 
00745         // clear background
00746         PLINT bgr, bgg, bgb;                  // red, green, blue
00747         plgcolbg( &bgr, &bgg, &bgb );         // get background color information
00748         dev->ClearBackground( bgr, bgg, bgb );
00749 
00750         // Replay escape calls that come in before PLESC_DEVINIT.  All of them
00751         // required a DC that didn't exist yet.
00752         //
00753         if ( dev->plstate_width )
00754             plD_state_wxwidgets( pls, PLSTATE_WIDTH );
00755         dev->plstate_width = false;
00756 
00757         if ( dev->plstate_color0 )
00758             plD_state_wxwidgets( pls, PLSTATE_COLOR0 );
00759         dev->plstate_color0 = false;
00760 
00761         if ( dev->plstate_color1 )
00762             plD_state_wxwidgets( pls, PLSTATE_COLOR1 );
00763         dev->plstate_color1 = false;
00764 
00765         // why this? xwin driver has this
00766         // pls->page++;
00767     }
00768 }
00769 
00770 
00771 //--------------------------------------------------------------------------
00772 //  void plD_tidy_wxwidgets( PLStream *pls )
00773 //
00774 //  This function is called, if all plots are done.
00775 //--------------------------------------------------------------------------
00776 void plD_tidy_wxwidgets( PLStream *pls )
00777 {
00778     // Log_Verbose( "plD_tidy_wxwidgets()" );
00779 
00780     wxPLDevBase* dev = (wxPLDevBase *) pls->dev;
00781 
00782 #ifdef PL_HAVE_FREETYPE
00783     if ( dev->freetype )
00784     {
00785         FT_Data *FT = (FT_Data *) pls->FT;
00786         plscmap0n( FT->ncol0_org );
00787         plD_FreeType_Destroy( pls );
00788     }
00789 #endif
00790 
00791     if ( dev->ownGUI )
00792     {
00793         wxPLGetApp().RemoveFrame( dev->m_frame );
00794         if ( !wxPLGetApp().FrameCount() )
00795             wxUninitialize();
00796     }
00797 
00798     delete dev;
00799     pls->dev = NULL; // since in plcore.c pls->dev is free_mem'd
00800 }
00801 
00802 
00803 //--------------------------------------------------------------------------
00804 //  void plD_state_wxwidgets( PLStream *pls, PLINT op )
00805 //
00806 //  Handler for several state codes. Here we take care of setting the width
00807 //  and color of the pen.
00808 //--------------------------------------------------------------------------
00809 void plD_state_wxwidgets( PLStream *pls, PLINT op )
00810 {
00811     // Log_Verbose( "plD_state_wxwidgets(op=%d)", op );
00812 
00813     wxPLDevBase* dev = (wxPLDevBase *) pls->dev;
00814 
00815     switch ( op )
00816     {
00817     case PLSTATE_WIDTH: // 1
00818         if ( dev->ready )
00819             dev->SetWidth( pls );
00820         else
00821             dev->plstate_width = true;
00822         break;
00823 
00824     case PLSTATE_COLOR0: // 2
00825         if ( dev->ready )
00826             dev->SetColor0( pls );
00827         else
00828             dev->plstate_color0 = true;
00829         break;
00830 
00831     case PLSTATE_COLOR1: // 3
00832         if ( dev->ready )
00833             dev->SetColor1( pls );
00834         else
00835             dev->plstate_color1 = true;
00836         break;
00837 
00838     default:
00839         if ( !( dev->ready ) )
00840             install_buffer( pls );
00841     }
00842 }
00843 
00844 
00845 //--------------------------------------------------------------------------
00846 //  void plD_esc_wxwidgets( PLStream *pls, PLINT op, void *ptr )
00847 //
00848 //  Handler for several escape codes. Here we take care of filled polygons,
00849 //  XOR or copy mode, initialize device (install dc from outside), and if
00850 //  there is freetype support, rerendering of text.
00851 //--------------------------------------------------------------------------
00852 void plD_esc_wxwidgets( PLStream *pls, PLINT op, void *ptr )
00853 {
00854     // Log_Verbose( "plD_esc_wxwidgets(op=%d, ptr=%x)", op, ptr );
00855 
00856     wxPLDevBase* dev = (wxPLDevBase *) pls->dev;
00857 
00858     switch ( op )
00859     {
00860     case PLESC_FILL:
00861         fill_polygon( pls );
00862         break;
00863 
00864     case PLESC_XORMOD:
00865         // switch between wxXOR and wxCOPY
00866         // if( dev->ready ) {
00867         //                  if( dev->m_dc->GetLogicalFunction() == wxCOPY )
00868         //                          dev->m_dc->SetLogicalFunction( wxXOR );
00869         //                  else if( dev->m_dc->GetLogicalFunction() == wxXOR )
00870         //                          dev->m_dc->SetLogicalFunction( wxCOPY );
00871         //          }
00872         break;
00873 
00874     case PLESC_DEVINIT:
00875         dev->SetExternalBuffer( ptr );
00876 
00877         // replay begin of page call and state settings
00878         plD_bop_wxwidgets( pls );
00879         break;
00880 
00881     case PLESC_HAS_TEXT:
00882         if ( !( dev->ready ) )
00883             install_buffer( pls );
00884 
00885         if ( dev->freetype )
00886         {
00887 #ifdef PL_HAVE_FREETYPE
00888             plD_render_freetype_text( pls, (EscText *) ptr );
00889 #endif
00890         }
00891         else
00892             dev->ProcessString( pls, (EscText *) ptr );
00893         break;
00894 
00895     case PLESC_RESIZE:
00896     {
00897         wxSize* size = (wxSize *) ptr;
00898         wx_set_size( pls, size->GetWidth(), size->GetHeight() );
00899     }
00900     break;
00901 
00902     case PLESC_CLEAR:
00903         if ( !( dev->ready ) )
00904             install_buffer( pls );
00905         // Since the plot is updated only every MAX_COMCOUNT commands (usually 5000)
00906         //       before we clear the screen we need to show the plot at least once :)
00907         if ( !( dev->resizing ) && dev->ownGUI )
00908         {
00909             wxRunApp( pls, true );
00910             dev->comcount = 0;
00911         }
00912         dev->ClearBackground( pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b,
00913             pls->sppxmi, pls->sppymi, pls->sppxma, pls->sppyma );
00914         break;
00915 
00916     case PLESC_FLUSH:        // forced update of the window
00917         if ( !( dev->resizing ) && dev->ownGUI )
00918         {
00919             wxRunApp( pls, true );
00920             dev->comcount = 0;
00921         }
00922         break;
00923 
00924     case PLESC_GETC:
00925         if ( dev->ownGUI )
00926             GetCursorCmd( pls, (PLGraphicsIn *) ptr );
00927         break;
00928 
00929     case PLESC_GETBACKEND:
00930         *( (int *) ptr ) = dev->backend;
00931         break;
00932 
00933     default:
00934         break;
00935     }
00936 }
00937 
00938 
00939 //--------------------------------------------------------------------------
00940 //  static void fill_polygon( PLStream *pls )
00941 //
00942 //  Fill polygon described in points pls->dev_x[] and pls->dev_y[].
00943 //--------------------------------------------------------------------------
00944 static void fill_polygon( PLStream *pls )
00945 {
00946     // Log_Verbose( "fill_polygon(), npts=%d, x[0]=%d, y[0]=%d", pls->dev_npts, pls->dev_y[0], pls->dev_y[0] );
00947 
00948     wxPLDevBase* dev = (wxPLDevBase *) pls->dev;
00949 
00950     if ( !( dev->ready ) )
00951         install_buffer( pls );
00952 
00953     dev->FillPolygon( pls );
00954 
00955     if ( !( dev->resizing ) && dev->ownGUI )
00956     {
00957         dev->comcount += 10;
00958         if ( dev->comcount > MAX_COMCOUNT )
00959         {
00960             wxRunApp( pls, true );
00961             dev->comcount = 0;
00962         }
00963     }
00964 }
00965 
00966 
00967 //--------------------------------------------------------------------------
00968 //  void wx_set_size( PLStream* pls, int width, int height )
00969 //
00970 //  Adds a dc to the stream. The associated device is attached to the canvas
00971 //  as the property "dev".
00972 //--------------------------------------------------------------------------
00973 void wx_set_size( PLStream* pls, int width, int height )
00974 {
00975     // TODO: buffer must be resized here or in wxplotstream
00976     // Log_Verbose( "wx_set_size()" );
00977 
00978     wxPLDevBase* dev = (wxPLDevBase *) pls->dev;
00979 
00980     // set new size and scale parameters
00981     dev->width  = width;
00982     dev->height = height;
00983     dev->scalex = (PLFLT) ( dev->xmax - dev->xmin ) / dev->width;
00984     dev->scaley = (PLFLT) ( dev->ymax - dev->ymin ) / dev->height;
00985 
00986     // recalculate the dpi used in calculation of fontsize
00987     pls->xdpi = VIRTUAL_PIXELS_PER_IN / dev->scalex;
00988     pls->ydpi = VIRTUAL_PIXELS_PER_IN / dev->scaley;
00989 
00990     // clear background if we have a dc, since it's invalid (TODO: why, since in bop
00991     // it must be cleared anyway?)
00992     if ( dev->ready )
00993     {
00994         PLINT bgr, bgg, bgb;                  // red, green, blue
00995         plgcolbg( &bgr, &bgg, &bgb );         // get background color information
00996 
00997         dev->CreateCanvas();
00998         dev->ClearBackground( bgr, bgg, bgb );
00999     }
01000 
01001     // freetype parameters must also be changed
01002 #ifdef PL_HAVE_FREETYPE
01003     if ( dev->freetype )
01004     {
01005         FT_Data *FT = (FT_Data *) pls->FT;
01006         FT->scalex = dev->scalex;
01007         FT->scaley = dev->scaley;
01008         FT->ymax   = dev->height;
01009     }
01010 #endif
01011 }
01012 
01013 
01014 //--------------------------------------------------------------------------
01015 //  int plD_errorexithandler_wxwidgets( const char *errormessage )
01016 //
01017 //  If an PLplot error occurs, this function shows a dialog regarding
01018 //  this error and than exits.
01019 //--------------------------------------------------------------------------
01020 int plD_errorexithandler_wxwidgets( const char *errormessage )
01021 {
01022     if ( errormessage[0] )
01023     {
01024         wxMessageDialog dialog( 0, wxString( errormessage, *wxConvCurrent ), wxString( "wxWidgets PLplot App error", *wxConvCurrent ), wxOK | wxICON_ERROR );
01025         dialog.ShowModal();
01026     }
01027 
01028     return 0;
01029 }
01030 
01031 
01032 //--------------------------------------------------------------------------
01033 //  void plD_erroraborthandler_wxwidgets( const char *errormessage )
01034 //
01035 //  If PLplot aborts, this function shows a dialog regarding
01036 //  this error.
01037 //--------------------------------------------------------------------------
01038 void plD_erroraborthandler_wxwidgets( const char *errormessage )
01039 {
01040     if ( errormessage[0] )
01041     {
01042         wxMessageDialog dialog( 0, ( wxString( errormessage, *wxConvCurrent ) + wxString( " aborting operation...", *wxConvCurrent ) ), wxString( "wxWidgets PLplot App abort", *wxConvCurrent ), wxOK | wxICON_ERROR );
01043         dialog.ShowModal();
01044     }
01045 }
01046 
01047 
01048 
01049 
01050 #ifdef PL_HAVE_FREETYPE
01051 
01052 //--------------------------------------------------------------------------
01053 //  static void plD_pixel_wxwidgets( PLStream *pls, short x, short y )
01054 //
01055 //  callback function, of type "plD_pixel_fp", which specifies how a single
01056 //  pixel is set in the current colour.
01057 //--------------------------------------------------------------------------
01058 static void plD_pixel_wxwidgets( PLStream *pls, short x, short y )
01059 {
01060     // Log_Verbose( "plD_pixel_wxwidgets" );
01061 
01062     wxPLDevBase *dev = (wxPLDevBase *) pls->dev;
01063 
01064     if ( !( dev->ready ) )
01065         install_buffer( pls );
01066 
01067     dev->PutPixel( x, y );
01068 
01069     if ( !( dev->resizing ) && dev->ownGUI )
01070     {
01071         dev->comcount++;
01072         if ( dev->comcount > MAX_COMCOUNT )
01073         {
01074             wxRunApp( pls, true );
01075             dev->comcount = 0;
01076         }
01077     }
01078 }
01079 
01080 
01081 //--------------------------------------------------------------------------
01082 //  static void plD_pixel_wxwidgets( PLStream *pls, short x, short y )
01083 //
01084 //  callback function, of type "plD_pixel_fp", which specifies how a single
01085 //  pixel is set in the current colour.
01086 //--------------------------------------------------------------------------
01087 static void plD_set_pixel_wxwidgets( PLStream *pls, short x, short y, PLINT colour )
01088 {
01089     // Log_Verbose( "plD_set_pixel_wxwidgets" );
01090 
01091     wxPLDevBase *dev = (wxPLDevBase *) pls->dev;
01092 
01093     if ( !( dev->ready ) )
01094         install_buffer( pls );
01095 
01096     dev->PutPixel( x, y, colour );
01097 
01098     if ( !( dev->resizing ) && dev->ownGUI )
01099     {
01100         dev->comcount++;
01101         if ( dev->comcount > MAX_COMCOUNT )
01102         {
01103             wxRunApp( pls, true );
01104             dev->comcount = 0;
01105         }
01106     }
01107 }
01108 
01109 
01110 //--------------------------------------------------------------------------
01111 //  void plD_read_pixel_wxwidgets (PLStream *pls, short x, short y)
01112 //
01113 //  callback function, of type "plD_pixel_fp", which specifies how a single
01114 //  pixel is read.
01115 //--------------------------------------------------------------------------
01116 static PLINT plD_read_pixel_wxwidgets( PLStream *pls, short x, short y )
01117 {
01118     // Log_Verbose( "plD_read_pixel_wxwidgets" );
01119 
01120     wxPLDevBase *dev = (wxPLDevBase *) pls->dev;
01121 
01122     if ( !( dev->ready ) )
01123         install_buffer( pls );
01124 
01125     return dev->GetPixel( x, y );
01126 }
01127 
01128 
01129 //--------------------------------------------------------------------------
01130 //  void init_freetype_lv1 (PLStream *pls)
01131 //
01132 //  "level 1" initialisation of the freetype library.
01133 //  "Level 1" initialisation calls plD_FreeType_init(pls) which allocates
01134 //  memory to the pls->FT structure, then sets up the pixel callback
01135 //  function.
01136 //--------------------------------------------------------------------------
01137 static void init_freetype_lv1( PLStream *pls )
01138 {
01139     // Log_Verbose( "init_freetype_lv1" );
01140 
01141     plD_FreeType_init( pls );
01142 
01143     FT_Data *FT = (FT_Data *) pls->FT;
01144     FT->pixel = (plD_pixel_fp) plD_pixel_wxwidgets;
01145 
01146     //
01147     //  See if we have a 24 bit device (or better), in which case
01148     //  we can use the better antialising.
01149     //
01150     // the bitmap we are using in the antialized case has always
01151     // 32 bit depth
01152     FT->BLENDED_ANTIALIASING = 1;
01153     FT->read_pixel           = (plD_read_pixel_fp) plD_read_pixel_wxwidgets;
01154     FT->set_pixel            = (plD_set_pixel_fp) plD_set_pixel_wxwidgets;
01155 }
01156 
01157 
01158 //--------------------------------------------------------------------------
01159 //  void init_freetype_lv2 (PLStream *pls)
01160 //
01161 //  "Level 2" initialisation of the freetype library.
01162 //  "Level 2" fills in a few setting that aren't public until after the
01163 //  graphics sub-syetm has been initialised.
01164 //  The "level 2" initialisation fills in a few things that are defined
01165 //  later in the initialisation process for the GD driver.
01166 //
01167 //  FT->scale is a scaling factor to convert co-ordinates. This is used by
01168 //  the GD and other drivers to scale back a larger virtual page and this
01169 //  eliminate the "hidden line removal bug". Set it to 1 if your device
01170 //  doesn't have scaling.
01171 //
01172 //  Some coordinate systems have zero on the bottom, others have zero on
01173 //  the top. Freetype does it one way, and most everything else does it the
01174 //  other. To make sure everything is working ok, we have to "flip" the
01175 //  coordinates, and to do this we need to know how big in the Y dimension
01176 //  the page is, and whether we have to invert the page or leave it alone.
01177 //
01178 //  FT->ymax specifies the size of the page FT->invert_y=1 tells us to
01179 //  invert the y-coordinates, FT->invert_y=0 will not invert the
01180 //  coordinates.
01181 //--------------------------------------------------------------------------
01182 
01183 static void init_freetype_lv2( PLStream *pls )
01184 {
01185     // Log_Verbose( "init_freetype_lv2" );
01186 
01187     wxPLDevBase *dev = (wxPLDevBase *) pls->dev;
01188     FT_Data     *FT  = (FT_Data *) pls->FT;
01189 
01190     FT->scalex      = dev->scalex;
01191     FT->scaley      = dev->scaley;
01192     FT->ymax        = dev->height;
01193     FT->invert_y    = 1;
01194     FT->smooth_text = 0;
01195 
01196     if ( ( FT->want_smooth_text == 1 ) && ( FT->BLENDED_ANTIALIASING == 0 ) ) // do we want to at least *try* for smoothing ?
01197     {
01198         FT->ncol0_org   = pls->ncol0;                                         // save a copy of the original size of ncol0
01199         FT->ncol0_xtra  = 16777216 - ( pls->ncol1 + pls->ncol0 );             // work out how many free slots we have
01200         FT->ncol0_width = FT->ncol0_xtra / ( pls->ncol0 - 1 );                // find out how many different shades of anti-aliasing we can do
01201         if ( FT->ncol0_width > 4 )                                            // are there enough colour slots free for text smoothing ?
01202         {
01203             if ( FT->ncol0_width > max_number_of_grey_levels_used_in_text_smoothing )
01204                 FT->ncol0_width = max_number_of_grey_levels_used_in_text_smoothing;           // set a maximum number of shades
01205             plscmap0n( FT->ncol0_org + ( FT->ncol0_width * pls->ncol0 ) );                    // redefine the size of cmap0
01206             // the level manipulations are to turn off the plP_state(PLSTATE_CMAP0)
01207             // call in plscmap0 which (a) leads to segfaults since the GD image is
01208             // not defined at this point and (b) would be inefficient in any case since
01209             // setcmap is always called later (see plD_bop_png) to update the driver
01210             // color palette to be consistent with cmap0.
01211             {
01212                 PLINT level_save;
01213                 level_save = pls->level;
01214                 pls->level = 0;
01215                 pl_set_extended_cmap0( pls, FT->ncol0_width, FT->ncol0_org ); // call the function to add the extra cmap0 entries and calculate stuff
01216                 pls->level = level_save;
01217             }
01218             FT->smooth_text = 1; // Yippee ! We had success setting up the extended cmap0
01219         }
01220         else
01221             plwarn( "Insufficient colour slots available in CMAP0 to do text smoothing." );
01222     }
01223     else if ( ( FT->want_smooth_text == 1 ) && ( FT->BLENDED_ANTIALIASING == 1 ) )    // If we have a truecolour device, we wont even bother trying to change the palette
01224     {
01225         FT->smooth_text = 1;
01226     }
01227 }
01228 
01229 #endif
01230 
01231 
01232 //--------------------------------------------------------------------------
01233 // GetCursorCmd()
01234 //
01235 // Waits for a graphics input event and returns coordinates.
01236 //--------------------------------------------------------------------------
01237 static void GetCursorCmd( PLStream* pls, PLGraphicsIn* ptr )
01238 {
01239     // Log_Verbose( "GetCursorCmd" );
01240 
01241     wxPLDevBase  *dev = (wxPLDevBase *) pls->dev;
01242     PLGraphicsIn *gin = &( dev->gin );
01243 
01244     // Initialize
01245     plGinInit( gin );
01246     dev->locate_mode = LOCATE_INVOKED_VIA_API;
01247     dev->draw_xhair  = true;
01248 
01249     // Run event loop until a point is selected
01250     wxRunApp( pls, false );
01251 
01252     *ptr = *gin;
01253     if ( dev->locate_mode )
01254     {
01255         dev->locate_mode = 0;
01256         dev->draw_xhair  = false;
01257     }
01258 }
01259 
01260 
01261 
01262 
01263 //--------------------------------------------------------------------------
01264 //  This part includes wxWidgets specific functions, which allow to
01265 //  open a window from the command line, if needed.
01266 //--------------------------------------------------------------------------
01267 
01268 
01269 //--------------------------------------------------------------------------
01270 //  void install_buffer( PLStream *pls )
01271 //
01272 //  If this driver is called from a command line executable (and not
01273 //  from within a wxWidgets program), this function prepares a DC and a
01274 //  bitmap to plot into.
01275 //--------------------------------------------------------------------------
01276 static void install_buffer( PLStream *pls )
01277 {
01278     // Log_Verbose( "install_buffer" );
01279 
01280     wxPLDevBase * dev   = (wxPLDevBase *) pls->dev;
01281     static bool initApp = false;
01282 
01283     if ( !initApp )
01284     {
01285         // this hack enables to have a GUI on Mac OSX even if the
01286         // program was called from the command line (and isn't a bundle)
01287 #ifdef __WXMAC__
01288         ProcessSerialNumber psn;
01289 
01290         GetCurrentProcess( &psn );
01291         CPSEnableForegroundOperation( &psn );
01292         SetFrontProcess( &psn );
01293 #endif
01294 
01295         // initialize wxWidgets
01296         wxInitialize();
01297         wxLog::GetActiveTarget();
01298         wxTRY {
01299             wxPLGetApp().CallOnInit();
01300         }
01301         wxCATCH_ALL( wxPLGetApp().OnUnhandledException(); plexit( "Can't init wxWidgets!" ); )
01302         initApp = true;
01303     }
01304 
01305 
01306     wxString title( pls->plwindow, *wxConvCurrent );
01307     switch ( dev->backend )
01308     {
01309     case wxBACKEND_DC:
01310         title += wxT( " - wxWidgets (basic)" );
01311         break;
01312     case wxBACKEND_GC:
01313         title += wxT( " - wxWidgets (wxGC)" );
01314         break;
01315     case wxBACKEND_AGG:
01316         title += wxT( " - wxWidgets (AGG)" );
01317         break;
01318     default:
01319         break;
01320     }
01321     dev->m_frame = new wxPLplotFrame( title, pls );
01322     wxPLGetApp().AddFrame( dev->m_frame );
01323 
01324     // set size and position of window
01325     dev->m_frame->SetClientSize( dev->width, dev->height );
01326     if ( dev->xpos != 0 || dev->ypos != 0 )
01327         dev->m_frame->SetSize( dev->xpos, dev->ypos,
01328             wxDefaultCoord, wxDefaultCoord,
01329             wxSIZE_USE_EXISTING );
01330 
01331     if ( dev->showGUI )
01332     {
01333         dev->m_frame->Show( true );
01334         dev->m_frame->Raise();
01335     }
01336     else
01337         dev->m_frame->Show( false );
01338 
01339     // get a DC and a bitmap or an imagebuffer
01340     dev->ownGUI    = true;
01341     dev->bm_width  = dev->width;
01342     dev->bm_height = dev->height;
01343     dev->CreateCanvas();
01344     dev->ready = true;
01345 
01346     // Set wx error handler for various errors in plplot
01347     plsexit( plD_errorexithandler_wxwidgets );
01348     plsabort( plD_erroraborthandler_wxwidgets );
01349 
01350     // replay command we may have missed
01351     plD_bop_wxwidgets( pls );
01352 }
01353 
01354 
01355 //--------------------------------------------------------------------------
01356 //  void wxRunApp( PLStream *pls, bool runonce )
01357 //
01358 //  This is a hacked wxEntry-function, so that wxUninitialize is not
01359 //  called twice. Here we actually start the wxApplication.
01360 //--------------------------------------------------------------------------
01361 static void wxRunApp( PLStream *pls, bool runonce )
01362 {
01363     // Log_Verbose( "wxRunApp" );
01364 
01365     wxPLDevBase* dev = (wxPLDevBase *) pls->dev;
01366 
01367     dev->waiting = true;
01368     wxTRY
01369     {
01370         class CallOnExit
01371         {
01372 public:
01373             // only call OnExit if exit is true (i.e. due an exception)
01374             ~CallOnExit() { if ( exit ) wxPLGetApp().OnExit();}
01375             bool exit;
01376         } callOnExit;
01377 
01378         callOnExit.exit = true;
01379         wxPLGetApp().SetAdvanceFlag( runonce );
01380         wxPLGetApp().SetRefreshFlag();
01381 
01382         // add an idle event is necessary for Linux (wxGTK2)
01383         // but not for Windows, but it doesn't harm
01384         wxIdleEvent event;
01385         wxPLGetApp().AddPendingEvent( event );
01386         wxPLGetApp().OnRun();           // start wxWidgets application
01387         callOnExit.exit = false;
01388     }
01389     wxCATCH_ALL( wxPLGetApp().OnUnhandledException(); plexit( "Problem running wxWidgets!" ); )
01390 
01391     if ( dev->exit )
01392     {
01393         wxPLGetApp().OnExit();
01394         plexit( "" );
01395     }
01396 
01397     dev->waiting = false;
01398 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines