PLplot  5.15.0
wxwidgets.cpp
Go to the documentation of this file.
1 // Copyright (C) 2015 Phil Rosenberg
2 // Copyright (C) 2005 Werner Smekal, Sjaak Verdoold
3 // Copyright (C) 2005 Germain Carrera Corraleche
4 // Copyright (C) 1999 Frank Huebner
5 //
6 // This file is part of PLplot.
7 //
8 // PLplot is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU Library General Public License as published
10 // by the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // PLplot is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Library General Public License for more details.
17 //
18 // You should have received a copy of the GNU Library General Public License
19 // along with PLplot; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 //
22 
23 // TODO:
24 // - NA
25 //
26 
27 // wxwidgets headers
28 #include <wx/wx.h>
29 #include <wx/wfstream.h>
30 #include <wx/except.h>
31 
32 #include "plDevs.h"
33 
34 // plplot headers
35 #include "plplotP.h"
36 #include "drivers.h"
37 
38 // C/C++ headers
39 #include <cstdio>
40 
41 #include "wxwidgets.h"
42 
43 bool g_weInitializedWx = false;
44 
45 #ifdef __WXMAC__
46  #include <Carbon/Carbon.h>
47 extern "C" { void CPSEnableForegroundOperation( ProcessSerialNumber* psn ); }
48 #endif
49 
50 
51 //--------------------------------------------------------------------------
52 // void Log_Verbose( const char *fmt, ... )
53 //
54 // Print verbose debug message to stderr (printf style).
55 //--------------------------------------------------------------------------
56 void Log_Verbose( const char *fmt, ... )
57 {
58 #ifdef _DEBUG_VERBOSE
59  va_list args;
60  va_start( args, fmt );
61  fprintf( stderr, "Verbose: " );
62  vfprintf( stderr, fmt, args );
63  fprintf( stderr, "\n" );
64  va_end( args );
65  fflush( stderr );
66 #else
67  (void) fmt; // Cast to void to silence compiler warnings about unused parameter
68 #endif
69 }
70 
71 
72 //--------------------------------------------------------------------------
73 // void Log_Debug( const char *fmt, ... )
74 //
75 // Print debug message to stderr (printf style).
76 //--------------------------------------------------------------------------
77 void Log_Debug( const char *fmt, ... )
78 {
79 #ifdef _DEBUG
80  va_list args;
81  va_start( args, fmt );
82  fprintf( stderr, "Debug: " );
83  vfprintf( stderr, fmt, args );
84  fprintf( stderr, "\n" );
85  va_end( args );
86  fflush( stderr );
87 #else
88  (void) fmt; // Cast to void to silence compiler warnings about unused parameter
89 #endif
90 }
91 
92 //--------------------------------------------------------------------------
93 // In the following you'll find the driver functions which are
94 // needed by the plplot core.
95 //--------------------------------------------------------------------------
96 
97 // Device info
98 #ifdef __cplusplus
99 extern "C" {
100 #endif
101 
103 #ifdef PLD_wxwidgets
104  "wxwidgets:wxWidgets Driver:1:wxwidgets:51:wxwidgets\n"
105 #endif
106 #ifdef PLD_wxpng
107  "wxpng:wxWidgets PNG Driver:0:wxwidgets:52:wxpng\n"
108 #endif
109 ;
110 
111 #ifdef __cplusplus
112 }
113 #endif
114 
115 
116 #ifdef PLD_wxwidgets
117 
118 //--------------------------------------------------------------------------
119 // void plD_dispatch_init_wxwidgets( PLDispatchTable *pdt )
120 //
121 // Make wxwidgets driver functions known to plplot.
122 //--------------------------------------------------------------------------
124 {
125 #ifndef ENABLE_DYNDRIVERS
126  pdt->pl_MenuStr = "wxWidgets DC";
127  pdt->pl_DevName = "wxwidgets";
128 #endif
130  pdt->pl_seq = 51;
140 }
141 
142 //--------------------------------------------------------------------------
143 // plD_init_wxwidgets( PLStream* pls )
144 //
145 // Initialize wxWidgets device.
146 //--------------------------------------------------------------------------
148 {
149  PLPLOT_wxLogDebug( "plD_init_wxwidgets(): enter" );
150 
151  try
152  {
153  wxPLDevice *device = (wxPLDevice *) pls->dev;
154  if ( device )
155  throw( "plD_init_wxwidgets called when a initialization has already occurred." );
156 
157  //initialise wxWidgets - this is required in order to allow some wxWidgets functions to
158  //be called from within the driver when the user isn't passing a wxDC in. See e.g
159  //http://stackoverflow.com/questions/208373
160  if ( !wxTheApp )
161  {
162  wxApp::SetInstance( new wxApp() );
163  int argc = 0;
164  char* argv[1];
165  g_weInitializedWx = wxEntryStart( argc, (char **) NULL );
166  if ( !g_weInitializedWx )
167  throw( "plD_init_wxWidgets could not initialise wxWidgets" );
168  }
169  else
170  g_weInitializedWx = false;
171 
172  // default options
173  static PLINT text = 1;
174  static PLINT hrshsym = 0;
175  static char *mfo = NULL;
176 
177  DrvOpt wx_options[] = {
178  { "hrshsym", DRV_INT, &hrshsym, "Use Hershey symbol set (hrshsym=0|1)" },
179  { "text", DRV_INT, &text, "Use own text routines (text=0|1)" },
180  { "mfo", DRV_STR, &mfo, "output metafile" },
181  { NULL, DRV_INT, NULL, NULL }
182  };
183 
184  // Check for and set up driver options
185  plParseDrvOpts( wx_options );
186 
187  // by default the own text routines are used for wxDC
188  if ( text == -1 )
189  text = 0;
190 
191  // create the new device
192  device = new wxPLDevice( pls, mfo, text, hrshsym );
193 
194  // If portrait mode, apply a rotation and set freeaspect
195  if ( pls->portrait )
196  {
197  plsdiori( (PLFLT) ( 4 - ORIENTATION ) );
198  pls->freeaspect = 1;
199  }
200 
201  //indicate that we support getting string length
202  pls->has_string_length = 1;
203 
204  //indicate that we support xor rendering
205  pls->dev_xor = 1;
206  }
207  catch ( const char *message )
208  {
209  plabort( message );
210  plabort( "error in plD_init_wxwidgets." );
211  pls->dev = NULL;
212  }
213  catch ( ... )
214  {
215  plabort( "unknown error in plD_init_wxwidgets." );
216  }
217  PLPLOT_wxLogDebug( "plD_init_wxwidgets(): leave" );
218 }
219 
220 #endif // PLD_wxwidgets
221 
222 
223 #ifdef PLD_wxpng
224 
225 //--------------------------------------------------------------------------
226 // void plD_dispatch_init_wxpng( PLDispatchTable *pdt )
227 //
228 // Make wxpng driver functions known to plplot.
229 //--------------------------------------------------------------------------
231 {
232 #ifndef ENABLE_DYNDRIVERS
233  pdt->pl_MenuStr = "wxWidgets PNG driver";
234  pdt->pl_DevName = "wxpng";
235 #endif
237  pdt->pl_seq = 52;
246 }
247 
248 //--------------------------------------------------------------------------
249 // void plD_init_wxpng( PLStream *pls )
250 //
251 // Initialize wxpng device.
252 //--------------------------------------------------------------------------
253 void plD_init_wxpng( PLStream *pls )
254 {
255  PLPLOT_wxLogDebug( "plD_init_wxpng()" );
256 
257  wxPLDevBase* dev;
258  dev = common_init( pls );
259 
260  // Initialize family file info
261  plFamInit( pls );
262 
263  // Prompt for a file name if not already set.
264  plOpenFile( pls );
265 
266  pls->plbuf_write = 1; // use the plot buffer!
267  pls->dev_flush = 0; // No need for flushes
268  pls->termin = 0; // file oriented device
269  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)
270  pls->page = 0;
271 
272  dev->showGUI = false;
273  dev->bitmapType = wxBITMAP_TYPE_PNG;
274 }
275 
276 #endif // PLD_wxpng
277 
278 
279 //--------------------------------------------------------------------------
280 // void plD_line_wxwidgets( PLStream *pls, short x1a, short y1a,
281 // short x2a, short y2a )
282 //
283 // Draws a line from (x1a, y1a) to (x2a, y2a).
284 //--------------------------------------------------------------------------
285 void plD_line_wxwidgets( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
286 {
287  // Log_Verbose( "plD_line_wxwidgets(x1a=%d, y1a=%d, x2a=%d, y2a=%d)", x1a, y1a, x2a, y2a );
288  try
289  {
290  wxPLDevice *device = (wxPLDevice *) pls->dev;
291  if ( !device )
292  throw( "plD_line_wxwidgets called before initialization." );
293  device->DrawLine( x1a, y1a, x2a, y2a );
294  }
295  catch ( const char* message )
296  {
297  plabort( message );
298  plabort( "error in plD_line_wxwidgets." );
299  }
300  catch ( ... )
301  {
302  plabort( "unknown error in plD_line_wxwidgets." );
303  }
304 }
305 
306 
307 //--------------------------------------------------------------------------
308 // void plD_polyline_wxwidgets( PLStream *pls, short *xa, short *ya,
309 // PLINT npts )
310 //
311 // Draw a poly line - points are in xa and ya arrays.
312 //--------------------------------------------------------------------------
313 void plD_polyline_wxwidgets( PLStream *pls, short *xa, short *ya, PLINT npts )
314 {
315  // PLPLOT_wxLogDebug( "plD_polyline_wxwidgets()" );
316  try
317  {
318  wxPLDevice *device = (wxPLDevice *) pls->dev;
319  if ( !device )
320  throw( "plD_polyline_wxwidgets called before initialization." );
321  device->DrawPolyline( xa, ya, npts );
322  }
323  catch ( const char* message )
324  {
325  plabort( message );
326  plabort( "error in plD_polyline_wxwidgets." );
327  }
328  catch ( ... )
329  {
330  plabort( "unknown error in plD_polyline_wxwidgets." );
331  }
332 }
333 
334 
335 //--------------------------------------------------------------------------
336 // void plD_eop_wxwidgets( PLStream *pls )
337 //
338 // End of Page. This function is called if a "end of page" is send by the
339 // user. This command is ignored if we have the plot embedded in a
340 // wxWidgets application, otherwise the application created by the device
341 // takes over.
342 //--------------------------------------------------------------------------
344 {
345  // PLPLOT_wxLogDebug( "plD_eop_wxwidgets()" );
346  try
347  {
348  wxPLDevice *device = (wxPLDevice *) pls->dev;
349  if ( !device )
350  throw( "plD_eop_wxwidgets called before initialization." );
351  if ( pls->nopause )
352  device->EndPage( pls );
353  }
354  catch ( const char* message )
355  {
356  plabort( message );
357  plabort( "error in plD_eop_wxwidgets." );
358  }
359  catch ( ... )
360  {
361  plabort( "unknown error in plD_eop_wxwidgets." );
362  }
363 }
364 
365 
366 //--------------------------------------------------------------------------
367 // void plD_wait_wxwidgets( PLStream *pls )
368 //
369 // Wait for user input. This command is ignored if we have the plot embedded in a
370 // wxWidgets application, otherwise the application created by the device
371 // takes over.
372 //--------------------------------------------------------------------------
374 {
375  // PLPLOT_wxLogDebug( "plD_wait_wxwidgets()" );
376  try
377  {
378  wxPLDevice *device = (wxPLDevice *) pls->dev;
379  if ( !device )
380  throw( "plD_wait_wxwidgets called before initialization." );
381  device->EndPage( pls );
382  }
383  catch ( const char* message )
384  {
385  plabort( message );
386  plabort( "error in plD_wait_wxwidgets." );
387  }
388  catch ( ... )
389  {
390  plabort( "unknown error in plD_wait_wxwidgets." );
391  }
392 }
393 
394 //--------------------------------------------------------------------------
395 // void plD_bop_wxwidgets( PLStream *pls )
396 //
397 // Begin of page. Before any plot command, this function is called, If we
398 // have already a dc the background is cleared in background color and some
399 // state calls are resent - this is because at the first call of this
400 // function, a dc does most likely not exist, but state calls are recorded
401 // and when a new dc is created this function is called again.
402 //--------------------------------------------------------------------------
404 {
405  // PLPLOT_wxLogDebug( "plD_bop_wxwidgets()" );
406  try
407  {
408  wxPLDevice *device = (wxPLDevice *) pls->dev;
409  if ( !device )
410  throw( "plD_bop_wxwidgets called before initialization." );
411  device->BeginPage( pls );
412  }
413  catch ( const char* message )
414  {
415  plabort( message );
416  plabort( "error in plD_bop_wxwidgets." );
417  }
418  catch ( ... )
419  {
420  plabort( "unknown error in plD_bop_wxwidgets." );
421  }
422 }
423 
424 //--------------------------------------------------------------------------
425 // void plD_tidy_wxwidgets( PLStream *pls )
426 //
427 // This function is called, if all plots are done.
428 //--------------------------------------------------------------------------
430 {
431  // PLPLOT_wxLogDebug( "plD_tidy_wxwidgets()" );
432  if ( !pls->dev )
433  return;
434  try
435  {
436  wxPLDevice *device = (wxPLDevice *) pls->dev;
437  if ( device )
438  {
439  device->PreDestructorTidy( pls );
440  delete device;
441  }
442  pls->dev = NULL; //so it doesn't get freed elsewhere
443  if ( g_weInitializedWx )
444  wxEntryCleanup();
445  }
446  catch ( const char* message )
447  {
448  plabort( message );
449  plabort( "error in plD_tidy_wxwidgets." );
450  }
451  catch ( ... )
452  {
453  plabort( "unknown error in plD_tidy_wxwidgets." );
454  }
455 }
456 
457 //--------------------------------------------------------------------------
458 // void plD_state_wxwidgets( PLStream *pls, PLINT op )
459 //
460 // Handler for several state codes. Here we take care of setting the width
461 // and color of the pen.
462 //--------------------------------------------------------------------------
464 {
465  // Log_Verbose( "plD_state_wxwidgets(op=%d)", op );
466  try
467  {
468  wxPLDevice *device = (wxPLDevice *) pls->dev;
469  if ( !device )
470  return; //we can call state functions before initialization so just return
471  switch ( op )
472  {
473  case PLSTATE_WIDTH: // 1
474  device->SetWidth( pls );
475  break;
476 
477  case PLSTATE_COLOR0: // 2
478  device->SetColor( pls );
479  break;
480 
481  case PLSTATE_COLOR1: // 3
482  device->SetColor( pls );
483  break;
484  }
485  }
486  catch ( const char* message )
487  {
488  plabort( message );
489  plabort( "error in plD_state_wxwidgets." );
490  }
491  catch ( ... )
492  {
493  plabort( "unknown error in plD_state_wxwidgets." );
494  }
495 }
496 
497 //--------------------------------------------------------------------------
498 // void plD_esc_wxwidgets( PLStream *pls, PLINT op, void *ptr )
499 //
500 // Handler for several escape codes. Here we take care of filled polygons,
501 // XOR or copy mode, initialize device (install dc from outside), and if
502 // there is freetype support, re-rendering of text.
503 //--------------------------------------------------------------------------
504 void plD_esc_wxwidgets( PLStream *pls, PLINT op, void *ptr )
505 {
506  // Log_Verbose( "plD_esc_wxwidgets(op=%d, ptr=%x)", op, ptr );
507 
508  if ( !pls->dev )
509  return;
510 
511  try
512  {
513  wxPLDevice *device = (wxPLDevice *) pls->dev;
514  if ( !device )
515  throw( "plD_esc_wxwidgets called before initialization." );
516  switch ( op )
517  {
518  case PLESC_FILL:
519  device->FillPolygon( pls );
520  break;
521 
522  case PLESC_XORMOD:
523  device->SetXorMode( *( (PLINT *) ptr ) == 0 ? false : true );
524  break;
525 
526  case PLESC_DEVINIT:
527  device->SetDC( pls, (wxDC *) ptr );
528  break;
529 
530  case PLESC_HAS_TEXT:
531  device->drawText( pls, (EscText *) ptr );
532  break;
533 
534  case PLESC_RESIZE:
535  {
536  wxSize* size = (wxSize *) ptr;
537  device->SetSize( pls, size->GetWidth(), size->GetHeight() );
538  }
539  break;
540 
541  case PLESC_CLEAR:
542  device->ClearBackground( pls, pls->sppxmi, pls->sppymi,
543  pls->sppxma, pls->sppyma );
544  break;
545 
546  case PLESC_FLUSH: // forced update of the window
547  device->Flush( pls );
548  break;
549 
550  case PLESC_GETC:
551  device->Locate( pls, (PLGraphicsIn *) ptr );
552  break;
553 
554  case PLESC_FIXASPECT:
555  device->FixAspectRatio( *( (bool *) ptr ) );
556  break;
557 
558  default:
559  break;
560  }
561  }
562  catch ( const char* message )
563  {
564  plabort( message );
565  plabort( "error in plD_tidy_wxwidgets." );
566  }
567  catch ( ... )
568  {
569  plabort( "unknown error in plD_tidy_wxwidgets." );
570  }
571 }
int plParseDrvOpts(DrvOpt *acc_opt)
Definition: plargs.c:1461
void SetColor(PLStream *pls)
void Flush(PLStream *pls)
static char ** argv
Definition: qt.cpp:49
#define PLESC_XORMOD
Definition: plplot.h:286
PLDLLIMPEXP_DRIVER void plD_dispatch_init_wxwidgets(PLDispatchTable *pdt)
#define PLESC_DEVINIT
Definition: plplot.h:296
void Locate(PLStream *pls, PLGraphicsIn *graphicsIn)
#define PLESC_FILL
Definition: plplot.h:279
PLINT sppxma
Definition: plstrm.h:703
plD_esc_fp pl_esc
Definition: disptab.h:90
void plOpenFile(PLStream *pls)
Definition: plctrl.c:2571
void plD_eop_wxwidgets(PLStream *pls)
Definition: wxwidgets.cpp:343
void(* plD_tidy_fp)(struct PLStream_struct *)
Definition: disptab.h:72
void SetWidth(PLStream *pls)
static int argc
Definition: qt.cpp:48
const char * pl_MenuStr
Definition: disptab.h:79
PLDLLIMPEXP_DRIVER void plD_dispatch_init_wxpng(PLDispatchTable *pdt)
plD_tidy_fp pl_tidy
Definition: disptab.h:88
PLINT plbuf_write
Definition: plstrm.h:567
void(* plD_init_fp)(struct PLStream_struct *)
Definition: disptab.h:67
#define plsdiori
Definition: plplot.h:809
PLDLLIMPEXP_DRIVER const char * plD_DEVICE_INFO_wxwidgets
Definition: wxwidgets.cpp:102
void SetXorMode(bool on)
void(* plD_eop_fp)(struct PLStream_struct *)
Definition: disptab.h:70
void(* plD_wait_fp)(struct PLStream_struct *)
Definition: disptab.h:75
const char * pl_DevName
Definition: disptab.h:80
#define PLSTATE_COLOR0
Definition: plplotP.h:363
plD_init_fp pl_init
Definition: disptab.h:83
void plabort(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1894
void plD_bop_wxwidgets(PLStream *pls)
Definition: wxwidgets.cpp:403
void FillPolygon(PLStream *pls)
void DrawLine(short x1a, short y1a, short x2a, short y2a)
void ClearBackground(PLStream *pls, PLINT x1=-1, PLINT y1=-1, PLINT x2=-1, PLINT y2=-1)
#define PLSTATE_COLOR1
Definition: plplotP.h:364
PLINT sppxmi
Definition: plstrm.h:703
void plFamInit(PLStream *pls)
Definition: plctrl.c:2751
#define PLSTATE_WIDTH
Definition: plplotP.h:362
void DrawPolyline(short *xa, short *ya, PLINT npts)
int PLINT
Definition: plplot.h:181
void PreDestructorTidy(PLStream *pls)
PLINT portrait
Definition: plstrm.h:665
void plD_line_wxwidgets(PLStream *pls, short x1a, short y1a, short x2a, short y2a)
Definition: wxwidgets.cpp:285
void(* plD_line_fp)(struct PLStream_struct *, short, short, short, short)
Definition: disptab.h:68
PLINT sppyma
Definition: plstrm.h:703
#define PLESC_FIXASPECT
Definition: plplot.h:308
void(* plD_esc_fp)(struct PLStream_struct *, PLINT, void *)
Definition: disptab.h:74
void(* plD_polyline_fp)(struct PLStream_struct *, short *, short *, PLINT)
Definition: disptab.h:69
PLINT termin
Definition: plstrm.h:568
void plD_esc_wxwidgets(PLStream *pls, PLINT op, void *ptr)
Definition: wxwidgets.cpp:504
#define PLESC_RESIZE
Definition: plplot.h:275
void drawText(PLStream *pls, EscText *args)
plD_bop_fp pl_bop
Definition: disptab.h:87
bool g_weInitializedWx
Definition: wxwidgets.cpp:43
void Log_Verbose(const char *fmt,...)
Definition: wxwidgets.cpp:56
void plD_polyline_wxwidgets(PLStream *pls, short *xa, short *ya, PLINT npts)
Definition: wxwidgets.cpp:313
#define PLESC_CLEAR
Definition: plplot.h:288
#define ORIENTATION
Definition: plplotP.h:358
plD_line_fp pl_line
Definition: disptab.h:84
#define PLDLLIMPEXP_DRIVER
Definition: pldll.h:81
PLINT dev_xor
Definition: plstrm.h:572
static PLStream * pls[PL_NSTREAMS]
Definition: plcore.h:88
void FixAspectRatio(bool fix)
static int text
Definition: ps.c:77
void EndPage(PLStream *pls)
plD_wait_fp pl_wait
Definition: disptab.h:91
float PLFLT
Definition: plplot.h:163
PLINT graphx
Definition: plstrm.h:568
PLINT page
Definition: plstrm.h:578
void(* plD_bop_fp)(struct PLStream_struct *)
Definition: disptab.h:71
void plD_init_wxwidgets(PLStream *)
void plD_state_wxwidgets(PLStream *pls, PLINT op)
Definition: wxwidgets.cpp:463
#define PLPLOT_wxLogDebug(string)
#define PLESC_HAS_TEXT
Definition: plplot.h:290
PLINT nopause
Definition: plstrm.h:568
void SetSize(PLStream *pls, int width, int height)
void SetDC(PLStream *pls, wxDC *dc)
void plD_init_wxpng(PLStream *)
void plD_tidy_wxwidgets(PLStream *pls)
Definition: wxwidgets.cpp:429
plD_state_fp pl_state
Definition: disptab.h:89
void BeginPage(PLStream *pls)
static int hrshsym
Definition: ps.c:79
plD_eop_fp pl_eop
Definition: disptab.h:86
#define PLESC_GETC
Definition: plplot.h:283
PLINT dev_flush
Definition: plstrm.h:571
plD_polyline_fp pl_polyline
Definition: disptab.h:85
void(* plD_state_fp)(struct PLStream_struct *, PLINT)
Definition: disptab.h:73
void * dev
Definition: plstrm.h:594
void Log_Debug(const char *fmt,...)
Definition: wxwidgets.cpp:77
PLINT freeaspect
Definition: plstrm.h:665
PLINT sppymi
Definition: plstrm.h:703
void plD_wait_wxwidgets(PLStream *pls)
Definition: wxwidgets.cpp:373
#define PLESC_FLUSH
Definition: plplot.h:281
#define GRAPHICS_MODE
Definition: plplotP.h:288
PLINT has_string_length
Definition: plstrm.h:785