PLplot
5.10.0
|
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 }