PageRenderTime 57ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/branches/v5_9_6_debian/drivers/wxwidgets.cpp

#
C++ | 1365 lines | 805 code | 228 blank | 332 comment | 127 complexity | c7e20d6f0670890869632c36c83e45b9 MD5 | raw file
Possible License(s): LGPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, Apache-2.0, GPL-2.0
  1. /* $Id: wxwidgets.cpp 10785 2010-01-31 20:05:17Z hezekiahcarty $
  2. *
  3. * Copyright (C) 2005 Werner Smekal, Sjaak Verdoold
  4. * Copyright (C) 2005 Germain Carrera Corraleche
  5. * Copyright (C) 1999 Frank Huebner
  6. *
  7. * This file is part of PLplot.
  8. *
  9. * PLplot is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Library Public License as published
  11. * by the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * PLplot is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Library General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Library General Public License
  20. * along with PLplot; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* TODO:
  24. * - NA
  25. */
  26. /* wxwidgets headers */
  27. #include <wx/wx.h>
  28. #include <wx/wfstream.h>
  29. #include <wx/except.h>
  30. #include "plDevs.h"
  31. /* plplot headers */
  32. #include "plplotP.h"
  33. #include "drivers.h"
  34. /* C/C++ headers */
  35. #include <cstdio>
  36. #include "wxwidgets.h"
  37. #ifdef __WXMAC__
  38. #include <Carbon/Carbon.h>
  39. extern "C" { void CPSEnableForegroundOperation( ProcessSerialNumber* psn ); }
  40. #endif
  41. DECLARE_PLAPP( wxPLplotApp )
  42. /*--------------------------------------------------------------------------
  43. * void Log_Verbose( const char *fmt, ... )
  44. *
  45. * Print verbose debug message to stderr (printf style).
  46. *--------------------------------------------------------------------------*/
  47. void Log_Verbose( const char *fmt, ... )
  48. {
  49. #ifdef _DEBUG_VERBOSE
  50. va_list args;
  51. va_start( args, fmt );
  52. fprintf( stderr, "Verbose: " );
  53. vfprintf( stderr, fmt, args );
  54. fprintf( stderr, "\n" );
  55. va_end( args );
  56. fflush( stderr );
  57. #endif
  58. }
  59. /*--------------------------------------------------------------------------
  60. * void Log_Debug( const char *fmt, ... )
  61. *
  62. * Print debug message to stderr (printf style).
  63. *--------------------------------------------------------------------------*/
  64. void Log_Debug( const char *fmt, ... )
  65. {
  66. #ifdef _DEBUG
  67. va_list args;
  68. va_start( args, fmt );
  69. fprintf( stderr, "Debug: " );
  70. vfprintf( stderr, fmt, args );
  71. fprintf( stderr, "\n" );
  72. va_end( args );
  73. fflush( stderr );
  74. #endif
  75. }
  76. /*----------------------------------------------------------------------
  77. * In the following you'll find the driver functions which are
  78. * are needed by the plplot core.
  79. *----------------------------------------------------------------------*/
  80. /* Device info */
  81. #ifdef __cplusplus
  82. extern "C" {
  83. #endif
  84. PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_wxwidgets =
  85. #ifdef PLD_wxwidgets
  86. "wxwidgets:wxWidgets Driver:1:wxwidgets:51:wxwidgets\n"
  87. #endif
  88. #ifdef PLD_wxpng
  89. "wxpng:wxWidgets PNG Driver:0:wxwidgets:52:wxpng\n"
  90. #endif
  91. ;
  92. #ifdef __cplusplus
  93. }
  94. #endif
  95. /*--------------------------------------------------------------------------
  96. * wxPLDevBase::wxPLDevBase( void )
  97. *
  98. * Contructor of base class of wxPLDev classes.
  99. *--------------------------------------------------------------------------*/
  100. wxPLDevBase::wxPLDevBase( int bcknd ) : backend( bcknd )
  101. {
  102. // Log_Verbose( "wxPLDevBase::wxPLDevBase()" );
  103. ready = false;
  104. ownGUI = false;
  105. waiting = false;
  106. resizing = false;
  107. exit = false;
  108. comcount = 0;
  109. m_frame = NULL;
  110. xpos = 0;
  111. ypos = 0;
  112. // width, height are set in plD_init_wxwidgets
  113. // bm_width, bm_height are set in install_buffer
  114. // xmin, xmax, ymin, ymax are set in plD_init_wxwidgets
  115. // scalex, scaley are set in plD_init_wxwidgets
  116. plstate_width = false;
  117. plstate_color0 = false;
  118. plstate_color1 = false;
  119. locate_mode = 0;
  120. draw_xhair = false;
  121. newclipregion = true;
  122. clipminx = 1024;
  123. clipmaxx = 0;
  124. clipminy = 800;
  125. clipmaxy = 0;
  126. freetype = 0;
  127. smooth_text = 0;
  128. devName = (const char **) malloc( NDEV * sizeof ( char** ) );
  129. memset( devName, '\0', NDEV * sizeof ( char** ) );
  130. devDesc = (const char **) malloc( NDEV * sizeof ( char** ) );
  131. memset( devDesc, '\0', NDEV * sizeof ( char** ) );
  132. ndev = NDEV;
  133. }
  134. wxPLDevBase::~wxPLDevBase( void )
  135. {
  136. if ( devDesc )
  137. free( devDesc );
  138. if ( devName )
  139. free( devName );
  140. }
  141. void wxPLDevBase::AddtoClipRegion( int x1, int y1, int x2, int y2 )
  142. {
  143. newclipregion = false;
  144. if ( x1 < x2 )
  145. {
  146. if ( x1 < clipminx ) clipminx = x1;
  147. if ( x2 > clipmaxx ) clipmaxx = x2;
  148. }
  149. else
  150. {
  151. if ( x2 < clipminx ) clipminx = x2;
  152. if ( x1 > clipmaxx ) clipmaxx = x1;
  153. }
  154. if ( y1 < y2 )
  155. {
  156. if ( y1 < clipminy ) clipminy = y1;
  157. if ( y2 > clipmaxy ) clipmaxy = y2;
  158. }
  159. else
  160. {
  161. if ( y2 < clipminy ) clipminy = y2;
  162. if ( y1 > clipmaxy ) clipmaxy = y1;
  163. }
  164. }
  165. void wxPLDevBase::PSDrawText( PLUNICODE* ucs4, int ucs4Len, bool drawText )
  166. {
  167. int i = 0;
  168. char utf8_string[max_string_length];
  169. char utf8[5];
  170. memset( utf8_string, '\0', max_string_length );
  171. /* Get PLplot escape character */
  172. char plplotEsc;
  173. plgesc( &plplotEsc );
  174. /* Get the curent font */
  175. fontScale = 1.0;
  176. yOffset = 0.0;
  177. PLUNICODE fci;
  178. plgfci( &fci );
  179. PSSetFont( fci );
  180. textWidth = 0;
  181. textHeight = 0;
  182. while ( i < ucs4Len )
  183. {
  184. if ( ucs4[i] < PL_FCI_MARK ) /* not a font change */
  185. {
  186. if ( ucs4[i] != (PLUNICODE) plplotEsc ) /* a character to display */
  187. {
  188. ucs4_to_utf8( ucs4[i], utf8 );
  189. strncat( utf8_string, utf8, max_string_length );
  190. i++;
  191. continue;
  192. }
  193. i++;
  194. if ( ucs4[i] == (PLUNICODE) plplotEsc ) /* a escape character to display */
  195. {
  196. ucs4_to_utf8( ucs4[i], utf8 );
  197. strncat( utf8_string, utf8, max_string_length );
  198. i++;
  199. continue;
  200. }
  201. else
  202. {
  203. if ( ucs4[i] == (PLUNICODE) 'u' ) /* Superscript */
  204. { // draw string so far
  205. PSDrawTextToDC( utf8_string, drawText );
  206. // change font scale
  207. if ( yOffset < -0.0001 )
  208. fontScale *= 1.25; /* Subscript scaling parameter */
  209. else
  210. fontScale *= 0.8; /* Subscript scaling parameter */
  211. PSSetFont( fci );
  212. yOffset += scaley * fontSize * fontScale / 2.;
  213. }
  214. if ( ucs4[i] == (PLUNICODE) 'd' ) /* Subscript */
  215. { // draw string so far
  216. PSDrawTextToDC( utf8_string, drawText );
  217. // change font scale
  218. double old_fontScale = fontScale;
  219. if ( yOffset > 0.0001 )
  220. fontScale *= 1.25; /* Subscript scaling parameter */
  221. else
  222. fontScale *= 0.8; /* Subscript scaling parameter */
  223. PSSetFont( fci );
  224. yOffset -= scaley * fontSize * old_fontScale / 2.;
  225. }
  226. if ( ucs4[i] == (PLUNICODE) '-' ) /* underline */
  227. { // draw string so far
  228. PSDrawTextToDC( utf8_string, drawText );
  229. underlined = !underlined;
  230. PSSetFont( fci );
  231. }
  232. if ( ucs4[i] == (PLUNICODE) '+' ) /* overline */
  233. { /* not implemented yet */
  234. }
  235. i++;
  236. }
  237. }
  238. else /* a font change */
  239. {
  240. // draw string so far
  241. PSDrawTextToDC( utf8_string, drawText );
  242. // get new font
  243. fci = ucs4[i];
  244. PSSetFont( fci );
  245. i++;
  246. }
  247. }
  248. PSDrawTextToDC( utf8_string, drawText );
  249. }
  250. /*--------------------------------------------------------------------------
  251. * void common_init( PLStream *pls )
  252. *
  253. * Basic initialization for all devices.
  254. *--------------------------------------------------------------------------*/
  255. wxPLDevBase* common_init( PLStream *pls )
  256. {
  257. // Log_Verbose( "common_init()" );
  258. wxPLDevBase* dev;
  259. /* default options */
  260. static PLINT freetype = -1;
  261. static PLINT smooth_text = 1;
  262. static PLINT text = -1;
  263. static PLINT hrshsym = 0;
  264. /* default backend uses wxGraphicsContext, if not available
  265. * the agg library will be used, if not available the basic
  266. * backend will be used. */
  267. static PLINT backend = wxBACKEND_DC;
  268. #if wxUSE_GRAPHICS_CONTEXT
  269. backend = wxBACKEND_GC;
  270. #else
  271. #ifdef HAVE_AGG
  272. backend = wxBACKEND_AGG;
  273. #endif
  274. #endif
  275. DrvOpt wx_options[] = {
  276. #ifdef HAVE_FREETYPE
  277. { "freetype", DRV_INT, &freetype, "Use FreeType library" },
  278. { "smooth", DRV_INT, &smooth_text, "Turn text smoothing on (1) or off (0)" },
  279. #endif
  280. { "hrshsym", DRV_INT, &hrshsym, "Use Hershey symbol set (hrshsym=0|1)" },
  281. { "backend", DRV_INT, &backend, "Choose backend: (0) standard, (1) using AGG library, (2) using wxGraphicsContext" },
  282. { "text", DRV_INT, &text, "Use own text routines (text=0|1)" },
  283. { NULL, DRV_INT, NULL, NULL }
  284. };
  285. /* Check for and set up driver options */
  286. plParseDrvOpts( wx_options );
  287. /* allocate memory for the device storage */
  288. switch ( backend )
  289. {
  290. case wxBACKEND_GC:
  291. /* in case wxGraphicsContext isn't available, the next backend (agg
  292. * if available) in this list will be used */
  293. #if wxUSE_GRAPHICS_CONTEXT
  294. dev = new wxPLDevGC;
  295. /* by default the own text routines are used for wxGC */
  296. if ( text == -1 )
  297. text = 1;
  298. freetype = 0; /* this backend is vector oriented and doesn't know pixels */
  299. break;
  300. #endif
  301. case wxBACKEND_AGG:
  302. /* in case the agg library isn't available, the standard backend
  303. * will be used */
  304. #ifdef HAVE_AGG
  305. dev = new wxPLDevAGG;
  306. /* by default the freetype text routines are used for wxAGG */
  307. text = 0; /* text processing doesn't work yet for the AGG backend */
  308. if ( freetype == -1 )
  309. freetype = 1;
  310. break;
  311. #endif
  312. default:
  313. dev = new wxPLDevDC;
  314. /* by default the own text routines are used for wxDC */
  315. if ( text == -1 )
  316. if ( freetype != 1 )
  317. text = 1;
  318. else
  319. text = 0;
  320. if ( freetype == -1 )
  321. freetype = 0;
  322. break;
  323. }
  324. if ( dev == NULL )
  325. {
  326. plexit( "Insufficient memory" );
  327. }
  328. pls->dev = (void*) dev;
  329. /* be verbose and write out debug messages */
  330. #ifdef _DEBUG
  331. pls->verbose = 1;
  332. pls->debug = 1;
  333. #endif
  334. pls->color = 1; /* Is a color device */
  335. pls->dev_flush = 1; /* Handles flushes */
  336. pls->dev_fill0 = 1; /* Can handle solid fills */
  337. pls->dev_fill1 = 0; /* Can't handle pattern fills */
  338. pls->dev_dash = 0;
  339. pls->dev_clear = 1; /* driver supports clear */
  340. if ( text )
  341. {
  342. pls->dev_text = 1; /* want to draw text */
  343. pls->dev_unicode = 1; /* want unicode */
  344. if ( hrshsym )
  345. pls->dev_hrshsym = 1;
  346. }
  347. #ifdef HAVE_FREETYPE
  348. /* own text routines have higher priority over freetype
  349. * if text and freetype option are set to 1 */
  350. if ( !text )
  351. {
  352. dev->smooth_text = smooth_text;
  353. dev->freetype = freetype;
  354. }
  355. if ( dev->freetype )
  356. {
  357. pls->dev_text = 1; /* want to draw text */
  358. pls->dev_unicode = 1; /* want unicode */
  359. if ( hrshsym )
  360. pls->dev_hrshsym = 1;
  361. init_freetype_lv1( pls );
  362. FT_Data* FT = (FT_Data *) pls->FT;
  363. FT->want_smooth_text = smooth_text;
  364. }
  365. #endif
  366. /* initialize frame size and position */
  367. if ( pls->xlength <= 0 || pls->ylength <= 0 )
  368. plspage( 0.0, 0.0, (PLINT) ( CANVAS_WIDTH * DEVICE_PIXELS_PER_IN ),
  369. (PLINT) ( CANVAS_HEIGHT * DEVICE_PIXELS_PER_IN ), 0, 0 );
  370. dev->width = pls->xlength;
  371. dev->height = pls->ylength;
  372. dev->clipminx = pls->xlength;
  373. dev->clipminy = pls->ylength;
  374. if ( pls->xoffset != 0 || pls->yoffset != 0 )
  375. {
  376. dev->xpos = (int) ( pls->xoffset );
  377. dev->ypos = (int) ( pls->yoffset );
  378. }
  379. /* If portrait mode, apply a rotation and set freeaspect */
  380. if ( pls->portrait )
  381. {
  382. plsdiori( (PLFLT) ( 4 - ORIENTATION ) );
  383. pls->freeaspect = 1;
  384. }
  385. /* Set the number of pixels per mm */
  386. plP_setpxl( (PLFLT) VIRTUAL_PIXELS_PER_MM, (PLFLT) VIRTUAL_PIXELS_PER_MM );
  387. /* Set up physical limits of plotting device (in drawing units) */
  388. plP_setphy( (PLINT) 0, (PLINT) ( CANVAS_WIDTH * VIRTUAL_PIXELS_PER_IN ),
  389. (PLINT) 0, (PLINT) ( CANVAS_HEIGHT * VIRTUAL_PIXELS_PER_IN ) );
  390. /* get physical device limits coordinates */
  391. plP_gphy( &dev->xmin, &dev->xmax, &dev->ymin, &dev->ymax );
  392. /* setting scale factors */
  393. dev->scalex = (PLFLT) ( dev->xmax - dev->xmin ) / ( dev->width );
  394. dev->scaley = (PLFLT) ( dev->ymax - dev->ymin ) / ( dev->height );
  395. /* set dpi */
  396. plspage( VIRTUAL_PIXELS_PER_IN / dev->scalex, VIRTUAL_PIXELS_PER_IN / dev->scaley, 0, 0, 0, 0 );
  397. #ifdef HAVE_FREETYPE
  398. if ( dev->freetype )
  399. init_freetype_lv2( pls );
  400. #endif
  401. /* find out what file drivers are available */
  402. plgFileDevs( &dev->devDesc, &dev->devName, &dev->ndev );
  403. return dev;
  404. }
  405. #ifdef PLD_wxwidgets
  406. /*--------------------------------------------------------------------------
  407. * void plD_dispatch_init_wxwidgets( PLDispatchTable *pdt )
  408. *
  409. * Make wxwidgets driver functions known to plplot.
  410. *--------------------------------------------------------------------------*/
  411. void plD_dispatch_init_wxwidgets( PLDispatchTable *pdt )
  412. {
  413. #ifndef ENABLE_DYNDRIVERS
  414. pdt->pl_MenuStr = "wxWidgets DC";
  415. pdt->pl_DevName = "wxwidgets";
  416. #endif
  417. pdt->pl_type = plDevType_Interactive;
  418. pdt->pl_seq = 51;
  419. pdt->pl_init = (plD_init_fp) plD_init_wxwidgets;
  420. pdt->pl_line = (plD_line_fp) plD_line_wxwidgets;
  421. pdt->pl_polyline = (plD_polyline_fp) plD_polyline_wxwidgets;
  422. pdt->pl_eop = (plD_eop_fp) plD_eop_wxwidgets;
  423. pdt->pl_bop = (plD_bop_fp) plD_bop_wxwidgets;
  424. pdt->pl_tidy = (plD_tidy_fp) plD_tidy_wxwidgets;
  425. pdt->pl_state = (plD_state_fp) plD_state_wxwidgets;
  426. pdt->pl_esc = (plD_esc_fp) plD_esc_wxwidgets;
  427. }
  428. /*--------------------------------------------------------------------------
  429. * plD_init_wxwidgets( PLStream* pls )
  430. *
  431. * Initialize wxWidgets device.
  432. *--------------------------------------------------------------------------*/
  433. void plD_init_wxwidgets( PLStream* pls )
  434. {
  435. // Log_Verbose( "plD_init_wxwidgets()" );
  436. wxPLDevBase* dev;
  437. dev = common_init( pls );
  438. pls->plbuf_write = 1; /* use the plot buffer! */
  439. pls->termin = 1; /* interactive device */
  440. 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) */
  441. dev->showGUI = true;
  442. dev->bitmapType = (wxBitmapType) 0;
  443. }
  444. #endif /* PLD_wxwidgets */
  445. #ifdef PLD_wxpng
  446. /*--------------------------------------------------------------------------
  447. * void plD_dispatch_init_wxpng( PLDispatchTable *pdt )
  448. *
  449. * Make wxpng driver functions known to plplot.
  450. *--------------------------------------------------------------------------*/
  451. void plD_dispatch_init_wxpng( PLDispatchTable *pdt )
  452. {
  453. #ifndef ENABLE_DYNDRIVERS
  454. pdt->pl_MenuStr = "wxWidgets PNG driver";
  455. pdt->pl_DevName = "wxpng";
  456. #endif
  457. pdt->pl_type = plDevType_FileOriented;
  458. pdt->pl_seq = 52;
  459. pdt->pl_init = (plD_init_fp) plD_init_wxpng;
  460. pdt->pl_line = (plD_line_fp) plD_line_wxwidgets;
  461. pdt->pl_polyline = (plD_polyline_fp) plD_polyline_wxwidgets;
  462. pdt->pl_eop = (plD_eop_fp) plD_eop_wxwidgets;
  463. pdt->pl_bop = (plD_bop_fp) plD_bop_wxwidgets;
  464. pdt->pl_tidy = (plD_tidy_fp) plD_tidy_wxwidgets;
  465. pdt->pl_state = (plD_state_fp) plD_state_wxwidgets;
  466. pdt->pl_esc = (plD_esc_fp) plD_esc_wxwidgets;
  467. }
  468. /*--------------------------------------------------------------------------
  469. * void plD_init_wxpng( PLStream *pls )
  470. *
  471. * Initialize wxpng device.
  472. *--------------------------------------------------------------------------*/
  473. void plD_init_wxpng( PLStream *pls )
  474. {
  475. // Log_Verbose( "plD_init_wxwidgets()" );
  476. wxPLDevBase* dev;
  477. dev = common_init( pls );
  478. /* Initialize family file info */
  479. plFamInit( pls );
  480. /* Prompt for a file name if not already set. */
  481. plOpenFile( pls );
  482. pls->plbuf_write = 1; /* use the plot buffer! */
  483. pls->dev_flush = 0; /* No need for flushes */
  484. pls->termin = 0; /* file oriented device */
  485. 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) */
  486. pls->page = 0;
  487. dev->showGUI = false;
  488. dev->bitmapType = wxBITMAP_TYPE_PNG;
  489. }
  490. #endif /* PLD_wxpng */
  491. /*--------------------------------------------------------------------------
  492. * void plD_line_wxwidgets( PLStream *pls, short x1a, short y1a,
  493. * short x2a, short y2a )
  494. *
  495. * Draws a line from (x1a, y1a) to (x2a, y2a).
  496. *--------------------------------------------------------------------------*/
  497. void plD_line_wxwidgets( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
  498. {
  499. // Log_Verbose( "plD_line_wxwidgets(x1a=%d, y1a=%d, x2a=%d, y2a=%d)", x1a, y1a, x2a, y2a );
  500. wxPLDevBase* dev = (wxPLDevBase*) pls->dev;
  501. if ( !( dev->ready ) )
  502. install_buffer( pls );
  503. dev->DrawLine( x1a, y1a, x2a, y2a );
  504. if ( !( dev->resizing ) && dev->ownGUI )
  505. {
  506. dev->comcount++;
  507. if ( dev->comcount > MAX_COMCOUNT )
  508. {
  509. wxRunApp( pls, true );
  510. dev->comcount = 0;
  511. }
  512. }
  513. }
  514. /*--------------------------------------------------------------------------
  515. * void plD_polyline_wxwidgets( PLStream *pls, short *xa, short *ya,
  516. * PLINT npts )
  517. *
  518. * Draw a poly line - points are in xa and ya arrays.
  519. *--------------------------------------------------------------------------*/
  520. void plD_polyline_wxwidgets( PLStream *pls, short *xa, short *ya, PLINT npts )
  521. {
  522. // Log_Verbose( "plD_polyline_wxwidgets()" );
  523. /* should be changed to use the wxDC::DrawLines function? */
  524. wxPLDevBase* dev = (wxPLDevBase*) pls->dev;
  525. if ( !( dev->ready ) )
  526. install_buffer( pls );
  527. dev->DrawPolyline( xa, ya, npts );
  528. if ( !( dev->resizing ) && dev->ownGUI )
  529. {
  530. dev->comcount++;
  531. if ( dev->comcount > MAX_COMCOUNT )
  532. {
  533. wxRunApp( pls, true );
  534. dev->comcount = 0;
  535. }
  536. }
  537. }
  538. /*--------------------------------------------------------------------------
  539. * void plD_eop_wxwidgets( PLStream *pls )
  540. *
  541. * End of Page. This function is called if a "end of page" is send by the
  542. * user. This command is ignored if we have the plot embedded in a
  543. * wxWidgets application, otherwise the application created by the device
  544. * takes over.
  545. *--------------------------------------------------------------------------*/
  546. void plD_eop_wxwidgets( PLStream *pls )
  547. {
  548. // Log_Verbose( "plD_eop_wxwidgets()" );
  549. wxPLDevBase* dev = (wxPLDevBase*) pls->dev;
  550. if ( dev->bitmapType )
  551. {
  552. wxMemoryDC memDC;
  553. wxBitmap bitmap( dev->width, dev->height, -1 );
  554. memDC.SelectObject( bitmap );
  555. dev->BlitRectangle( &memDC, 0, 0, dev->width, dev->height );
  556. wxImage buffer = bitmap.ConvertToImage();
  557. wxFFileOutputStream fstream( pls->OutFile );
  558. if ( !( buffer.SaveFile( fstream, dev->bitmapType ) ) )
  559. puts( "Troubles saving file!" );
  560. memDC.SelectObject( wxNullBitmap );
  561. }
  562. if ( dev->ownGUI )
  563. if ( pls->nopause || !dev->showGUI )
  564. wxRunApp( pls, true );
  565. else
  566. wxRunApp( pls );
  567. }
  568. /*--------------------------------------------------------------------------
  569. * void plD_bop_wxwidgets( PLStream *pls )
  570. *
  571. * Begin of page. Before any plot command, this function is called, If we
  572. * have already a dc the background is cleared in background color and some
  573. * state calls are resent - this is because at the first call of this
  574. * function, a dc does most likely not exist, but state calls are recorded
  575. * and when a new dc is created this function is called again.
  576. *--------------------------------------------------------------------------*/
  577. void plD_bop_wxwidgets( PLStream *pls )
  578. {
  579. // Log_Verbose( "plD_bop_wxwidgets()" );
  580. wxPLDevBase* dev = (wxPLDevBase*) pls->dev;
  581. if ( dev->ready )
  582. {
  583. /*if( pls->termin==0 ) {
  584. * plGetFam( pls );*/
  585. /* force new file if pls->family set for all subsequent calls to plGetFam
  586. * n.b. putting this after plGetFam call is important since plinit calls
  587. * bop, and you don't want the familying sequence started until after
  588. * that first call to bop.*/
  589. /* n.b. pls->dev can change because of an indirect call to plD_init_png
  590. * from plGetFam if familying is enabled. Thus, wait to define dev until
  591. * now. */
  592. /*dev = (wxPLDevBase*)pls->dev;
  593. *
  594. * pls->famadv = 1;
  595. * pls->page++;
  596. * }*/
  597. /* clear background */
  598. PLINT bgr, bgg, bgb; /* red, green, blue */
  599. plgcolbg( &bgr, &bgg, &bgb ); /* get background color information */
  600. dev->ClearBackground( bgr, bgg, bgb );
  601. /* Replay escape calls that come in before PLESC_DEVINIT. All of them
  602. * required a DC that didn't exist yet.
  603. */
  604. if ( dev->plstate_width )
  605. plD_state_wxwidgets( pls, PLSTATE_WIDTH );
  606. dev->plstate_width = false;
  607. if ( dev->plstate_color0 )
  608. plD_state_wxwidgets( pls, PLSTATE_COLOR0 );
  609. dev->plstate_color0 = false;
  610. if ( dev->plstate_color1 )
  611. plD_state_wxwidgets( pls, PLSTATE_COLOR1 );
  612. dev->plstate_color1 = false;
  613. /* why this? xwin driver has this */
  614. /* pls->page++; */
  615. }
  616. }
  617. /*--------------------------------------------------------------------------
  618. * void plD_tidy_wxwidgets( PLStream *pls )
  619. *
  620. * This function is called, if all plots are done.
  621. *--------------------------------------------------------------------------*/
  622. void plD_tidy_wxwidgets( PLStream *pls )
  623. {
  624. // Log_Verbose( "plD_tidy_wxwidgets()" );
  625. wxPLDevBase* dev = (wxPLDevBase*) pls->dev;
  626. #ifdef HAVE_FREETYPE
  627. if ( dev->freetype )
  628. {
  629. FT_Data *FT = (FT_Data *) pls->FT;
  630. plscmap0n( FT->ncol0_org );
  631. plD_FreeType_Destroy( pls );
  632. }
  633. #endif
  634. if ( dev->ownGUI )
  635. {
  636. wxPLGetApp().RemoveFrame( dev->m_frame );
  637. if ( !wxPLGetApp().FrameCount() )
  638. wxUninitialize();
  639. }
  640. delete dev;
  641. pls->dev = NULL; /* since in plcore.c pls->dev is free_mem'd */
  642. }
  643. /*--------------------------------------------------------------------------*\
  644. * void plD_state_wxwidgets( PLStream *pls, PLINT op )
  645. *
  646. * Handler for several state codes. Here we take care of setting the width
  647. * and color of the pen.
  648. \*--------------------------------------------------------------------------*/
  649. void plD_state_wxwidgets( PLStream *pls, PLINT op )
  650. {
  651. // Log_Verbose( "plD_state_wxwidgets(op=%d)", op );
  652. wxPLDevBase* dev = (wxPLDevBase*) pls->dev;
  653. switch ( op )
  654. {
  655. case PLSTATE_WIDTH: /* 1 */
  656. if ( dev->ready )
  657. dev->SetWidth( pls );
  658. else
  659. dev->plstate_width = true;
  660. break;
  661. case PLSTATE_COLOR0: /* 2 */
  662. if ( dev->ready )
  663. dev->SetColor0( pls );
  664. else
  665. dev->plstate_color0 = true;
  666. break;
  667. case PLSTATE_COLOR1: /* 3 */
  668. if ( dev->ready )
  669. dev->SetColor1( pls );
  670. else
  671. dev->plstate_color1 = true;
  672. break;
  673. default:
  674. if ( !( dev->ready ) )
  675. install_buffer( pls );
  676. }
  677. }
  678. /*--------------------------------------------------------------------------*\
  679. * void plD_esc_wxwidgets( PLStream *pls, PLINT op, void *ptr )
  680. *
  681. * Handler for several escape codes. Here we take care of filled polygons,
  682. * XOR or copy mode, initialize device (install dc from outside), and if
  683. * there is freetype support, rerendering of text.
  684. \*--------------------------------------------------------------------------*/
  685. void plD_esc_wxwidgets( PLStream *pls, PLINT op, void *ptr )
  686. {
  687. // Log_Verbose( "plD_esc_wxwidgets(op=%d, ptr=%x)", op, ptr );
  688. wxPLDevBase* dev = (wxPLDevBase*) pls->dev;
  689. switch ( op )
  690. {
  691. case PLESC_FILL:
  692. fill_polygon( pls );
  693. break;
  694. case PLESC_XORMOD:
  695. /* switch between wxXOR and wxCOPY */
  696. /* if( dev->ready ) {
  697. * if( dev->m_dc->GetLogicalFunction() == wxCOPY )
  698. * dev->m_dc->SetLogicalFunction( wxXOR );
  699. * else if( dev->m_dc->GetLogicalFunction() == wxXOR )
  700. * dev->m_dc->SetLogicalFunction( wxCOPY );
  701. * } */
  702. break;
  703. case PLESC_DEVINIT:
  704. dev->SetExternalBuffer( ptr );
  705. /* replay begin of page call and state settings */
  706. plD_bop_wxwidgets( pls );
  707. break;
  708. case PLESC_HAS_TEXT:
  709. if ( !( dev->ready ) )
  710. install_buffer( pls );
  711. if ( dev->freetype )
  712. {
  713. #ifdef HAVE_FREETYPE
  714. plD_render_freetype_text( pls, (EscText *) ptr );
  715. #endif
  716. }
  717. else
  718. dev->ProcessString( pls, (EscText *) ptr );
  719. break;
  720. case PLESC_RESIZE:
  721. {
  722. wxSize* size = (wxSize*) ptr;
  723. wx_set_size( pls, size->GetWidth(), size->GetHeight() );
  724. }
  725. break;
  726. case PLESC_CLEAR:
  727. if ( !( dev->ready ) )
  728. install_buffer( pls );
  729. /* Since the plot is updated only every MAX_COMCOUNT commands (usually 5000)
  730. * before we clear the screen we need to show the plot at least once :) */
  731. if ( !( dev->resizing ) && dev->ownGUI )
  732. {
  733. wxRunApp( pls, true );
  734. dev->comcount = 0;
  735. }
  736. dev->ClearBackground( pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b,
  737. pls->sppxmi, pls->sppymi, pls->sppxma, pls->sppyma );
  738. break;
  739. case PLESC_FLUSH: /* forced update of the window */
  740. if ( !( dev->resizing ) && dev->ownGUI )
  741. {
  742. wxRunApp( pls, true );
  743. dev->comcount = 0;
  744. }
  745. break;
  746. case PLESC_GETC:
  747. if ( dev->ownGUI )
  748. GetCursorCmd( pls, (PLGraphicsIn *) ptr );
  749. break;
  750. case PLESC_GETBACKEND:
  751. *( (int*) ptr ) = dev->backend;
  752. break;
  753. default:
  754. break;
  755. }
  756. }
  757. /*--------------------------------------------------------------------------*\
  758. * static void fill_polygon( PLStream *pls )
  759. *
  760. * Fill polygon described in points pls->dev_x[] and pls->dev_y[].
  761. \*--------------------------------------------------------------------------*/
  762. static void fill_polygon( PLStream *pls )
  763. {
  764. // Log_Verbose( "fill_polygon(), npts=%d, x[0]=%d, y[0]=%d", pls->dev_npts, pls->dev_y[0], pls->dev_y[0] );
  765. wxPLDevBase* dev = (wxPLDevBase*) pls->dev;
  766. if ( !( dev->ready ) )
  767. install_buffer( pls );
  768. dev->FillPolygon( pls );
  769. if ( !( dev->resizing ) && dev->ownGUI )
  770. {
  771. dev->comcount += 10;
  772. if ( dev->comcount > MAX_COMCOUNT )
  773. {
  774. wxRunApp( pls, true );
  775. dev->comcount = 0;
  776. }
  777. }
  778. }
  779. /*--------------------------------------------------------------------------*\
  780. * void wx_set_size( PLStream* pls, int width, int height )
  781. *
  782. * Adds a dc to the stream. The associated device is attached to the canvas
  783. * as the property "dev".
  784. \*--------------------------------------------------------------------------*/
  785. void wx_set_size( PLStream* pls, int width, int height )
  786. {
  787. /* TODO: buffer must be resized here or in wxplotstream */
  788. // Log_Verbose( "wx_set_size()" );
  789. wxPLDevBase* dev = (wxPLDevBase*) pls->dev;
  790. /* set new size and scale parameters */
  791. dev->width = width;
  792. dev->height = height;
  793. dev->scalex = (PLFLT) ( dev->xmax - dev->xmin ) / dev->width;
  794. dev->scaley = (PLFLT) ( dev->ymax - dev->ymin ) / dev->height;
  795. /* recalculate the dpi used in calculation of fontsize */
  796. pls->xdpi = VIRTUAL_PIXELS_PER_IN / dev->scalex;
  797. pls->ydpi = VIRTUAL_PIXELS_PER_IN / dev->scaley;
  798. /* clear background if we have a dc, since it's invalid (TODO: why, since in bop
  799. * it must be cleared anyway?) */
  800. if ( dev->ready )
  801. {
  802. PLINT bgr, bgg, bgb; /* red, green, blue */
  803. plgcolbg( &bgr, &bgg, &bgb ); /* get background color information */
  804. dev->CreateCanvas();
  805. dev->ClearBackground( bgr, bgg, bgb );
  806. }
  807. /* freetype parameters must also be changed */
  808. #ifdef HAVE_FREETYPE
  809. if ( dev->freetype )
  810. {
  811. FT_Data *FT = (FT_Data *) pls->FT;
  812. FT->scalex = dev->scalex;
  813. FT->scaley = dev->scaley;
  814. FT->ymax = dev->height;
  815. }
  816. #endif
  817. }
  818. /*----------------------------------------------------------------------
  819. * int plD_errorexithandler_wxwidgets( const char *errormessage )
  820. *
  821. * If an PLplot error occurs, this function shows a dialog regarding
  822. * this error and than exits.
  823. *----------------------------------------------------------------------*/
  824. int plD_errorexithandler_wxwidgets( const char *errormessage )
  825. {
  826. if ( errormessage[0] )
  827. {
  828. wxMessageDialog dialog( 0, wxString( errormessage, *wxConvCurrent ), wxString( "wxWidgets PLplot App error", *wxConvCurrent ), wxOK | wxICON_ERROR );
  829. dialog.ShowModal();
  830. }
  831. return 0;
  832. }
  833. /*----------------------------------------------------------------------
  834. * void plD_erroraborthandler_wxwidgets( const char *errormessage )
  835. *
  836. * If PLplot aborts, this function shows a dialog regarding
  837. * this error.
  838. *----------------------------------------------------------------------*/
  839. void plD_erroraborthandler_wxwidgets( const char *errormessage )
  840. {
  841. if ( errormessage[0] )
  842. {
  843. wxMessageDialog dialog( 0, ( wxString( errormessage, *wxConvCurrent ) + wxString( " aborting operation...", *wxConvCurrent ) ), wxString( "wxWidgets PLplot App abort", *wxConvCurrent ), wxOK | wxICON_ERROR );
  844. dialog.ShowModal();
  845. }
  846. }
  847. #ifdef HAVE_FREETYPE
  848. /*----------------------------------------------------------------------*\
  849. * static void plD_pixel_wxwidgets( PLStream *pls, short x, short y )
  850. *
  851. * callback function, of type "plD_pixel_fp", which specifies how a single
  852. * pixel is set in the current colour.
  853. \*----------------------------------------------------------------------*/
  854. static void plD_pixel_wxwidgets( PLStream *pls, short x, short y )
  855. {
  856. // Log_Verbose( "plD_pixel_wxwidgets" );
  857. wxPLDevBase *dev = (wxPLDevBase*) pls->dev;
  858. if ( !( dev->ready ) )
  859. install_buffer( pls );
  860. dev->PutPixel( x, y );
  861. if ( !( dev->resizing ) && dev->ownGUI )
  862. {
  863. dev->comcount++;
  864. if ( dev->comcount > MAX_COMCOUNT )
  865. {
  866. wxRunApp( pls, true );
  867. dev->comcount = 0;
  868. }
  869. }
  870. }
  871. /*----------------------------------------------------------------------*\
  872. * static void plD_pixel_wxwidgets( PLStream *pls, short x, short y )
  873. *
  874. * callback function, of type "plD_pixel_fp", which specifies how a single
  875. * pixel is set in the current colour.
  876. \*----------------------------------------------------------------------*/
  877. static void plD_set_pixel_wxwidgets( PLStream *pls, short x, short y, PLINT colour )
  878. {
  879. // Log_Verbose( "plD_set_pixel_wxwidgets" );
  880. wxPLDevBase *dev = (wxPLDevBase*) pls->dev;
  881. if ( !( dev->ready ) )
  882. install_buffer( pls );
  883. dev->PutPixel( x, y, colour );
  884. if ( !( dev->resizing ) && dev->ownGUI )
  885. {
  886. dev->comcount++;
  887. if ( dev->comcount > MAX_COMCOUNT )
  888. {
  889. wxRunApp( pls, true );
  890. dev->comcount = 0;
  891. }
  892. }
  893. }
  894. /*--------------------------------------------------------------------------*\
  895. * void plD_read_pixel_wxwidgets (PLStream *pls, short x, short y)
  896. *
  897. * callback function, of type "plD_pixel_fp", which specifies how a single
  898. * pixel is read.
  899. \*--------------------------------------------------------------------------*/
  900. static PLINT plD_read_pixel_wxwidgets( PLStream *pls, short x, short y )
  901. {
  902. // Log_Verbose( "plD_read_pixel_wxwidgets" );
  903. wxPLDevBase *dev = (wxPLDevBase*) pls->dev;
  904. if ( !( dev->ready ) )
  905. install_buffer( pls );
  906. return dev->GetPixel( x, y );
  907. }
  908. /*----------------------------------------------------------------------*\
  909. * void init_freetype_lv1 (PLStream *pls)
  910. *
  911. * "level 1" initialisation of the freetype library.
  912. * "Level 1" initialisation calls plD_FreeType_init(pls) which allocates
  913. * memory to the pls->FT structure, then sets up the pixel callback
  914. * function.
  915. \*----------------------------------------------------------------------*/
  916. static void init_freetype_lv1( PLStream *pls )
  917. {
  918. // Log_Verbose( "init_freetype_lv1" );
  919. wxPLDevBase *dev = (wxPLDevBase*) pls->dev;
  920. plD_FreeType_init( pls );
  921. FT_Data *FT = (FT_Data *) pls->FT;
  922. FT->pixel = (plD_pixel_fp) plD_pixel_wxwidgets;
  923. /*
  924. * See if we have a 24 bit device (or better), in which case
  925. * we can use the better antialising.
  926. */
  927. // the bitmap we are using in the antialized case has always
  928. // 32 bit depth
  929. FT->BLENDED_ANTIALIASING = 1;
  930. FT->read_pixel = (plD_read_pixel_fp) plD_read_pixel_wxwidgets;
  931. FT->set_pixel = (plD_set_pixel_fp) plD_set_pixel_wxwidgets;
  932. }
  933. /*----------------------------------------------------------------------*\
  934. * void init_freetype_lv2 (PLStream *pls)
  935. *
  936. * "Level 2" initialisation of the freetype library.
  937. * "Level 2" fills in a few setting that aren't public until after the
  938. * graphics sub-syetm has been initialised.
  939. * The "level 2" initialisation fills in a few things that are defined
  940. * later in the initialisation process for the GD driver.
  941. *
  942. * FT->scale is a scaling factor to convert co-ordinates. This is used by
  943. * the GD and other drivers to scale back a larger virtual page and this
  944. * eliminate the "hidden line removal bug". Set it to 1 if your device
  945. * doesn't have scaling.
  946. *
  947. * Some coordinate systems have zero on the bottom, others have zero on
  948. * the top. Freetype does it one way, and most everything else does it the
  949. * other. To make sure everything is working ok, we have to "flip" the
  950. * coordinates, and to do this we need to know how big in the Y dimension
  951. * the page is, and whether we have to invert the page or leave it alone.
  952. *
  953. * FT->ymax specifies the size of the page FT->invert_y=1 tells us to
  954. * invert the y-coordinates, FT->invert_y=0 will not invert the
  955. * coordinates.
  956. \*----------------------------------------------------------------------*/
  957. static void init_freetype_lv2( PLStream *pls )
  958. {
  959. // Log_Verbose( "init_freetype_lv2" );
  960. wxPLDevBase *dev = (wxPLDevBase *) pls->dev;
  961. FT_Data *FT = (FT_Data *) pls->FT;
  962. FT->scalex = dev->scalex;
  963. FT->scaley = dev->scaley;
  964. FT->ymax = dev->height;
  965. FT->invert_y = 1;
  966. FT->smooth_text = 0;
  967. if ( ( FT->want_smooth_text == 1 ) && ( FT->BLENDED_ANTIALIASING == 0 ) ) /* do we want to at least *try* for smoothing ? */
  968. {
  969. FT->ncol0_org = pls->ncol0; /* save a copy of the original size of ncol0 */
  970. FT->ncol0_xtra = 16777216 - ( pls->ncol1 + pls->ncol0 ); /* work out how many free slots we have */
  971. FT->ncol0_width = FT->ncol0_xtra / ( pls->ncol0 - 1 ); /* find out how many different shades of anti-aliasing we can do */
  972. if ( FT->ncol0_width > 4 ) /* are there enough colour slots free for text smoothing ? */
  973. {
  974. if ( FT->ncol0_width > max_number_of_grey_levels_used_in_text_smoothing )
  975. FT->ncol0_width = max_number_of_grey_levels_used_in_text_smoothing; /* set a maximum number of shades */
  976. plscmap0n( FT->ncol0_org + ( FT->ncol0_width * pls->ncol0 ) ); /* redefine the size of cmap0 */
  977. /* the level manipulations are to turn off the plP_state(PLSTATE_CMAP0)
  978. * call in plscmap0 which (a) leads to segfaults since the GD image is
  979. * not defined at this point and (b) would be inefficient in any case since
  980. * setcmap is always called later (see plD_bop_png) to update the driver
  981. * color palette to be consistent with cmap0. */
  982. {
  983. PLINT level_save;
  984. level_save = pls->level;
  985. pls->level = 0;
  986. pl_set_extended_cmap0( pls, FT->ncol0_width, FT->ncol0_org ); /* call the function to add the extra cmap0 entries and calculate stuff */
  987. pls->level = level_save;
  988. }
  989. FT->smooth_text = 1; /* Yippee ! We had success setting up the extended cmap0 */
  990. }
  991. else
  992. plwarn( "Insufficient colour slots available in CMAP0 to do text smoothing." );
  993. }
  994. 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 */
  995. {
  996. FT->smooth_text = 1;
  997. }
  998. }
  999. #endif
  1000. /*--------------------------------------------------------------------------
  1001. * GetCursorCmd()
  1002. *
  1003. * Waits for a graphics input event and returns coordinates.
  1004. *--------------------------------------------------------------------------*/
  1005. static void GetCursorCmd( PLStream* pls, PLGraphicsIn* ptr )
  1006. {
  1007. // Log_Verbose( "GetCursorCmd" );
  1008. wxPLDevBase *dev = (wxPLDevBase *) pls->dev;
  1009. PLGraphicsIn *gin = &( dev->gin );
  1010. /* Initialize */
  1011. plGinInit( gin );
  1012. dev->locate_mode = LOCATE_INVOKED_VIA_API;
  1013. dev->draw_xhair = true;
  1014. /* Run event loop until a point is selected */
  1015. wxRunApp( pls, false );
  1016. *ptr = *gin;
  1017. if ( dev->locate_mode )
  1018. {
  1019. dev->locate_mode = 0;
  1020. dev->draw_xhair = false;
  1021. }
  1022. }
  1023. /*----------------------------------------------------------------------
  1024. * This part includes wxWidgets specific functions, which allow to
  1025. * open a window from the command line, if needed.
  1026. *----------------------------------------------------------------------*/
  1027. /*----------------------------------------------------------------------
  1028. * void install_buffer( PLStream *pls )
  1029. *
  1030. * If this driver is called from a command line executable (and not
  1031. * from within a wxWidgets program), this function prepares a DC and a
  1032. * bitmap to plot into.
  1033. *----------------------------------------------------------------------*/
  1034. static void install_buffer( PLStream *pls )
  1035. {
  1036. // Log_Verbose( "install_buffer" );
  1037. wxPLDevBase * dev = (wxPLDevBase*) pls->dev;
  1038. static bool initApp = false;
  1039. if ( !initApp )
  1040. {
  1041. /* this hack enables to have a GUI on Mac OSX even if the
  1042. * program was called from the command line (and isn't a bundle) */
  1043. #ifdef __WXMAC__
  1044. ProcessSerialNumber psn;
  1045. GetCurrentProcess( &psn );
  1046. CPSEnableForegroundOperation( &psn );
  1047. SetFrontProcess( &psn );
  1048. #endif
  1049. /* initialize wxWidgets */
  1050. wxInitialize();
  1051. wxLog::GetActiveTarget();
  1052. wxTRY {
  1053. wxPLGetApp().CallOnInit();
  1054. }
  1055. wxCATCH_ALL( wxPLGetApp().OnUnhandledException(); plexit( "Can't init wxWidgets!" ); )
  1056. initApp = true;
  1057. }
  1058. wxString title( pls->plwindow, *wxConvCurrent );
  1059. switch ( dev->backend )
  1060. {
  1061. case wxBACKEND_DC:
  1062. title += wxT( " - wxWidgets (basic)" );
  1063. break;
  1064. case wxBACKEND_GC:
  1065. title += wxT( " - wxWidgets (wxGC)" );
  1066. break;
  1067. case wxBACKEND_AGG:
  1068. title += wxT( " - wxWidgets (AGG)" );
  1069. break;
  1070. default:
  1071. break;
  1072. }
  1073. dev->m_frame = new wxPLplotFrame( title, pls );
  1074. wxPLGetApp().AddFrame( dev->m_frame );
  1075. /* set size and position of window */
  1076. dev->m_frame->SetClientSize( dev->width, dev->height );
  1077. if ( dev->xpos != 0 || dev->ypos != 0 )
  1078. dev->m_frame->SetSize( dev->xpos, dev->ypos,
  1079. wxDefaultCoord, wxDefaultCoord,
  1080. wxSIZE_USE_EXISTING );
  1081. if ( dev->showGUI )
  1082. {
  1083. dev->m_frame->Show( true );
  1084. dev->m_frame->Raise();
  1085. }
  1086. else
  1087. dev->m_frame->Show( false );
  1088. /* get a DC and a bitmap or an imagebuffer */
  1089. dev->ownGUI = true;
  1090. dev->bm_width = dev->width;
  1091. dev->bm_height = dev->height;
  1092. dev->CreateCanvas();
  1093. dev->ready = true;
  1094. /* Set wx error handler for various errors in plplot*/
  1095. plsexit( plD_errorexithandler_wxwidgets );
  1096. plsabort( plD_erroraborthandler_wxwidgets );
  1097. /* replay command we may have missed */
  1098. plD_bop_wxwidgets( pls );
  1099. }
  1100. /*----------------------------------------------------------------------
  1101. * void wxRunApp( PLStream *pls, bool runonce )
  1102. *
  1103. * This is a hacked wxEntry-function, so that wxUninitialize is not
  1104. * called twice. Here we actually start the wxApplication.
  1105. *----------------------------------------------------------------------*/
  1106. static void wxRunApp( PLStream *pls, bool runonce )
  1107. {
  1108. // Log_Verbose( "wxRunApp" );
  1109. wxPLDevBase* dev = (wxPLDevBase*) pls->dev;
  1110. dev->waiting = true;
  1111. wxTRY
  1112. {
  1113. class CallOnExit
  1114. {
  1115. public:
  1116. /* only call OnExit if exit is true (i.e. due an exception) */
  1117. ~CallOnExit() { if ( exit ) wxPLGetApp().OnExit();}
  1118. bool exit;
  1119. } callOnExit;
  1120. callOnExit.exit = true;
  1121. wxPLGetApp().SetAdvanceFlag( runonce );
  1122. wxPLGetApp().SetRefreshFlag();
  1123. /* add an idle event is necessary for Linux (wxGTK2)
  1124. * but not for Windows, but it doesn't harm */
  1125. wxIdleEvent event;
  1126. wxPLGetApp().AddPendingEvent( event );
  1127. wxPLGetApp().OnRun(); /* start wxWidgets application */
  1128. callOnExit.exit = false;
  1129. }
  1130. wxCATCH_ALL( wxPLGetApp().OnUnhandledException(); plexit( "Problem running wxWidgets!" ); )
  1131. if ( dev->exit )
  1132. {
  1133. wxPLGetApp().OnExit();
  1134. plexit( "" );
  1135. }
  1136. dev->waiting = false;
  1137. }