PLplot  5.13.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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  pls->has_string_length = 1;
201  }
202  catch ( const char *message )
203  {
204  plabort( message );
205  plabort( "error in plD_init_wxwidgets." );
206  pls->dev = NULL;
207  }
208  catch ( ... )
209  {
210  plabort( "unknown error in plD_init_wxwidgets." );
211  }
212  PLPLOT_wxLogDebug( "plD_init_wxwidgets(): leave" );
213 }
214 
215 #endif // PLD_wxwidgets
216 
217 
218 #ifdef PLD_wxpng
219 
220 //--------------------------------------------------------------------------
221 // void plD_dispatch_init_wxpng( PLDispatchTable *pdt )
222 //
223 // Make wxpng driver functions known to plplot.
224 //--------------------------------------------------------------------------
226 {
227 #ifndef ENABLE_DYNDRIVERS
228  pdt->pl_MenuStr = "wxWidgets PNG driver";
229  pdt->pl_DevName = "wxpng";
230 #endif
232  pdt->pl_seq = 52;
241 }
242 
243 //--------------------------------------------------------------------------
244 // void plD_init_wxpng( PLStream *pls )
245 //
246 // Initialize wxpng device.
247 //--------------------------------------------------------------------------
248 void plD_init_wxpng( PLStream *pls )
249 {
250  PLPLOT_wxLogDebug( "plD_init_wxpng()" );
251 
252  wxPLDevBase* dev;
253  dev = common_init( pls );
254 
255  // Initialize family file info
256  plFamInit( pls );
257 
258  // Prompt for a file name if not already set.
259  plOpenFile( pls );
260 
261  pls->plbuf_write = 1; // use the plot buffer!
262  pls->dev_flush = 0; // No need for flushes
263  pls->termin = 0; // file oriented device
264  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)
265  pls->page = 0;
266 
267  dev->showGUI = false;
268  dev->bitmapType = wxBITMAP_TYPE_PNG;
269 }
270 
271 #endif // PLD_wxpng
272 
273 
274 //--------------------------------------------------------------------------
275 // void plD_line_wxwidgets( PLStream *pls, short x1a, short y1a,
276 // short x2a, short y2a )
277 //
278 // Draws a line from (x1a, y1a) to (x2a, y2a).
279 //--------------------------------------------------------------------------
280 void plD_line_wxwidgets( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
281 {
282  // Log_Verbose( "plD_line_wxwidgets(x1a=%d, y1a=%d, x2a=%d, y2a=%d)", x1a, y1a, x2a, y2a );
283  try
284  {
285  wxPLDevice *device = (wxPLDevice *) pls->dev;
286  if ( !device )
287  throw( "plD_line_wxwidgets called before initialization." );
288  device->DrawLine( x1a, y1a, x2a, y2a );
289  }
290  catch ( const char* message )
291  {
292  plabort( message );
293  plabort( "error in plD_line_wxwidgets." );
294  }
295  catch ( ... )
296  {
297  plabort( "unknown error in plD_line_wxwidgets." );
298  }
299 }
300 
301 
302 //--------------------------------------------------------------------------
303 // void plD_polyline_wxwidgets( PLStream *pls, short *xa, short *ya,
304 // PLINT npts )
305 //
306 // Draw a poly line - points are in xa and ya arrays.
307 //--------------------------------------------------------------------------
308 void plD_polyline_wxwidgets( PLStream *pls, short *xa, short *ya, PLINT npts )
309 {
310  // PLPLOT_wxLogDebug( "plD_polyline_wxwidgets()" );
311  try
312  {
313  wxPLDevice *device = (wxPLDevice *) pls->dev;
314  if ( !device )
315  throw( "plD_polyline_wxwidgets called before initialization." );
316  device->DrawPolyline( xa, ya, npts );
317  }
318  catch ( const char* message )
319  {
320  plabort( message );
321  plabort( "error in plD_polyline_wxwidgets." );
322  }
323  catch ( ... )
324  {
325  plabort( "unknown error in plD_polyline_wxwidgets." );
326  }
327 }
328 
329 
330 //--------------------------------------------------------------------------
331 // void plD_eop_wxwidgets( PLStream *pls )
332 //
333 // End of Page. This function is called if a "end of page" is send by the
334 // user. This command is ignored if we have the plot embedded in a
335 // wxWidgets application, otherwise the application created by the device
336 // takes over.
337 //--------------------------------------------------------------------------
339 {
340  // PLPLOT_wxLogDebug( "plD_eop_wxwidgets()" );
341  try
342  {
343  wxPLDevice *device = (wxPLDevice *) pls->dev;
344  if ( !device )
345  throw( "plD_eop_wxwidgets called before initialization." );
346  if ( pls->nopause )
347  device->EndPage( pls );
348  }
349  catch ( const char* message )
350  {
351  plabort( message );
352  plabort( "error in plD_eop_wxwidgets." );
353  }
354  catch ( ... )
355  {
356  plabort( "unknown error in plD_eop_wxwidgets." );
357  }
358 }
359 
360 
361 //--------------------------------------------------------------------------
362 // void plD_wait_wxwidgets( PLStream *pls )
363 //
364 // Wait for user input. This command is ignored if we have the plot embedded in a
365 // wxWidgets application, otherwise the application created by the device
366 // takes over.
367 //--------------------------------------------------------------------------
369 {
370  // PLPLOT_wxLogDebug( "plD_wait_wxwidgets()" );
371  try
372  {
373  wxPLDevice *device = (wxPLDevice *) pls->dev;
374  if ( !device )
375  throw( "plD_wait_wxwidgets called before initialization." );
376  device->EndPage( pls );
377  }
378  catch ( const char* message )
379  {
380  plabort( message );
381  plabort( "error in plD_wait_wxwidgets." );
382  }
383  catch ( ... )
384  {
385  plabort( "unknown error in plD_wait_wxwidgets." );
386  }
387 }
388 
389 //--------------------------------------------------------------------------
390 // void plD_bop_wxwidgets( PLStream *pls )
391 //
392 // Begin of page. Before any plot command, this function is called, If we
393 // have already a dc the background is cleared in background color and some
394 // state calls are resent - this is because at the first call of this
395 // function, a dc does most likely not exist, but state calls are recorded
396 // and when a new dc is created this function is called again.
397 //--------------------------------------------------------------------------
399 {
400  // PLPLOT_wxLogDebug( "plD_bop_wxwidgets()" );
401  try
402  {
403  wxPLDevice *device = (wxPLDevice *) pls->dev;
404  if ( !device )
405  throw( "plD_bop_wxwidgets called before initialization." );
406  device->BeginPage( pls );
407  }
408  catch ( const char* message )
409  {
410  plabort( message );
411  plabort( "error in plD_bop_wxwidgets." );
412  }
413  catch ( ... )
414  {
415  plabort( "unknown error in plD_bop_wxwidgets." );
416  }
417 }
418 
419 //--------------------------------------------------------------------------
420 // void plD_tidy_wxwidgets( PLStream *pls )
421 //
422 // This function is called, if all plots are done.
423 //--------------------------------------------------------------------------
425 {
426  // PLPLOT_wxLogDebug( "plD_tidy_wxwidgets()" );
427  if ( !pls->dev )
428  return;
429  try
430  {
431  wxPLDevice *device = (wxPLDevice *) pls->dev;
432  if ( device )
433  {
434  device->PreDestructorTidy( pls );
435  delete device;
436  }
437  pls->dev = NULL; //so it doesn't get freed elsewhere
438  if ( g_weInitializedWx )
439  wxEntryCleanup();
440  }
441  catch ( const char* message )
442  {
443  plabort( message );
444  plabort( "error in plD_tidy_wxwidgets." );
445  }
446  catch ( ... )
447  {
448  plabort( "unknown error in plD_tidy_wxwidgets." );
449  }
450 }
451 
452 //--------------------------------------------------------------------------
453 // void plD_state_wxwidgets( PLStream *pls, PLINT op )
454 //
455 // Handler for several state codes. Here we take care of setting the width
456 // and color of the pen.
457 //--------------------------------------------------------------------------
459 {
460  // Log_Verbose( "plD_state_wxwidgets(op=%d)", op );
461  try
462  {
463  wxPLDevice *device = (wxPLDevice *) pls->dev;
464  if ( !device )
465  return; //we can call state functions before initialization so just return
466  switch ( op )
467  {
468  case PLSTATE_WIDTH: // 1
469  device->SetWidth( pls );
470  break;
471 
472  case PLSTATE_COLOR0: // 2
473  device->SetColor( pls );
474  break;
475 
476  case PLSTATE_COLOR1: // 3
477  device->SetColor( pls );
478  break;
479  }
480  }
481  catch ( const char* message )
482  {
483  plabort( message );
484  plabort( "error in plD_state_wxwidgets." );
485  }
486  catch ( ... )
487  {
488  plabort( "unknown error in plD_state_wxwidgets." );
489  }
490 }
491 
492 //--------------------------------------------------------------------------
493 // void plD_esc_wxwidgets( PLStream *pls, PLINT op, void *ptr )
494 //
495 // Handler for several escape codes. Here we take care of filled polygons,
496 // XOR or copy mode, initialize device (install dc from outside), and if
497 // there is freetype support, re-rendering of text.
498 //--------------------------------------------------------------------------
499 void plD_esc_wxwidgets( PLStream *pls, PLINT op, void *ptr )
500 {
501  // Log_Verbose( "plD_esc_wxwidgets(op=%d, ptr=%x)", op, ptr );
502 
503  if ( !pls->dev )
504  return;
505 
506  try
507  {
508  wxPLDevice *device = (wxPLDevice *) pls->dev;
509  if ( !device )
510  throw( "plD_esc_wxwidgets called before initialization." );
511  switch ( op )
512  {
513  case PLESC_FILL:
514  device->FillPolygon( pls );
515  break;
516 
517  case PLESC_XORMOD:
518  // switch between wxXOR and wxCOPY
519  // if( dev->ready ) {
520  // if( dev->m_dc->GetLogicalFunction() == wxCOPY )
521  // dev->m_dc->SetLogicalFunction( wxXOR );
522  // else if( dev->m_dc->GetLogicalFunction() == wxXOR )
523  // dev->m_dc->SetLogicalFunction( wxCOPY );
524  // }
525  break;
526 
527  case PLESC_DEVINIT:
528  device->SetDC( pls, (wxDC *) ptr );
529  break;
530 
531  case PLESC_HAS_TEXT:
532  device->drawText( pls, (EscText *) ptr );
533  break;
534 
535  case PLESC_RESIZE:
536  {
537  wxSize* size = (wxSize *) ptr;
538  device->SetSize( pls, size->GetWidth(), size->GetHeight() );
539  }
540  break;
541 
542  case PLESC_CLEAR:
543  device->ClearBackground( pls, pls->sppxmi, pls->sppymi,
544  pls->sppxma, pls->sppyma );
545  break;
546 
547  case PLESC_FLUSH: // forced update of the window
548  device->Flush( pls );
549  break;
550 
551  case PLESC_GETC:
552  device->Locate( pls, (PLGraphicsIn *) ptr );
553  break;
554 
555  case PLESC_FIXASPECT:
556  device->FixAspectRatio( *( (bool *) ptr ) );
557  break;
558 
559  default:
560  break;
561  }
562  }
563  catch ( const char* message )
564  {
565  plabort( message );
566  plabort( "error in plD_tidy_wxwidgets." );
567  }
568  catch ( ... )
569  {
570  plabort( "unknown error in plD_tidy_wxwidgets." );
571  }
572 }
int plParseDrvOpts(DrvOpt *acc_opt)
Definition: plargs.c:1461
void SetColor(PLStream *pls)
void Flush(PLStream *pls)
static char ** argv
Definition: qt.cpp:40
void(* plD_line_fp)(struct PLStream_struct *, short, short, short, short)
Definition: disptab.h:68
#define PLESC_XORMOD
Definition: plplot.h:288
PLDLLIMPEXP_DRIVER void plD_dispatch_init_wxwidgets(PLDispatchTable *pdt)
#define PLESC_DEVINIT
Definition: plplot.h:298
void Locate(PLStream *pls, PLGraphicsIn *graphicsIn)
void(* plD_eop_fp)(struct PLStream_struct *)
Definition: disptab.h:70
void(* plD_state_fp)(struct PLStream_struct *, PLINT)
Definition: disptab.h:73
#define PLESC_FILL
Definition: plplot.h:281
PLINT sppxma
Definition: plstrm.h:702
void(* plD_tidy_fp)(struct PLStream_struct *)
Definition: disptab.h:72
plD_esc_fp pl_esc
Definition: disptab.h:90
void plOpenFile(PLStream *pls)
Definition: plctrl.c:2561
void plD_eop_wxwidgets(PLStream *pls)
Definition: wxwidgets.cpp:338
void SetWidth(PLStream *pls)
static int argc
Definition: qt.cpp:39
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:566
#define plsdiori
Definition: plplot.h:813
PLDLLIMPEXP_DRIVER const char * plD_DEVICE_INFO_wxwidgets
Definition: wxwidgets.cpp:102
const char * pl_DevName
Definition: disptab.h:80
#define PLSTATE_COLOR0
Definition: plplotP.h:363
void(* plD_wait_fp)(struct PLStream_struct *)
Definition: disptab.h:75
plD_init_fp pl_init
Definition: disptab.h:83
void plabort(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1884
void plD_bop_wxwidgets(PLStream *pls)
Definition: wxwidgets.cpp:398
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:702
void plFamInit(PLStream *pls)
Definition: plctrl.c:2741
void(* plD_polyline_fp)(struct PLStream_struct *, short *, short *, PLINT)
Definition: disptab.h:69
#define PLSTATE_WIDTH
Definition: plplotP.h:362
void DrawPolyline(short *xa, short *ya, PLINT npts)
int PLINT
Definition: plplot.h:174
void PreDestructorTidy(PLStream *pls)
void(* plD_esc_fp)(struct PLStream_struct *, PLINT, void *)
Definition: disptab.h:74
PLINT portrait
Definition: plstrm.h:664
void plD_line_wxwidgets(PLStream *pls, short x1a, short y1a, short x2a, short y2a)
Definition: wxwidgets.cpp:280
void(* plD_bop_fp)(struct PLStream_struct *)
Definition: disptab.h:71
PLINT sppyma
Definition: plstrm.h:702
#define PLESC_FIXASPECT
Definition: plplot.h:310
PLINT termin
Definition: plstrm.h:567
void plD_esc_wxwidgets(PLStream *pls, PLINT op, void *ptr)
Definition: wxwidgets.cpp:499
#define PLESC_RESIZE
Definition: plplot.h:277
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:308
#define PLESC_CLEAR
Definition: plplot.h:290
#define ORIENTATION
Definition: plplotP.h:358
plD_line_fp pl_line
Definition: disptab.h:84
#define PLDLLIMPEXP_DRIVER
Definition: pldll.h:69
static PLStream * pls[PL_NSTREAMS]
Definition: plcore.h:88
void FixAspectRatio(bool fix)
void EndPage(PLStream *pls)
plD_wait_fp pl_wait
Definition: disptab.h:91
float PLFLT
Definition: plplot.h:157
PLINT graphx
Definition: plstrm.h:567
PLINT page
Definition: plstrm.h:577
void plD_init_wxwidgets(PLStream *)
void plD_state_wxwidgets(PLStream *pls, PLINT op)
Definition: wxwidgets.cpp:458
#define PLPLOT_wxLogDebug(string)
#define PLESC_HAS_TEXT
Definition: plplot.h:292
PLINT nopause
Definition: plstrm.h:567
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:424
plD_state_fp pl_state
Definition: disptab.h:89
void BeginPage(PLStream *pls)
plD_eop_fp pl_eop
Definition: disptab.h:86
#define PLESC_GETC
Definition: plplot.h:285
PLINT dev_flush
Definition: plstrm.h:570
plD_polyline_fp pl_polyline
Definition: disptab.h:85
void * dev
Definition: plstrm.h:593
void Log_Debug(const char *fmt,...)
Definition: wxwidgets.cpp:77
PLINT freeaspect
Definition: plstrm.h:664
PLINT sppymi
Definition: plstrm.h:702
void plD_wait_wxwidgets(PLStream *pls)
Definition: wxwidgets.cpp:368
void(* plD_init_fp)(struct PLStream_struct *)
Definition: disptab.h:67
#define PLESC_FLUSH
Definition: plplot.h:283
#define GRAPHICS_MODE
Definition: plplotP.h:288
PLINT has_string_length
Definition: plstrm.h:784