PLplot  5.12.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 paraemeter
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 paraemeter
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;
139 }
140 
141 //--------------------------------------------------------------------------
142 // plD_init_wxwidgets( PLStream* pls )
143 //
144 // Initialize wxWidgets device.
145 //--------------------------------------------------------------------------
147 {
148  PLPLOT_wxLogDebug( "plD_init_wxwidgets(): enter" );
149 
150  try
151  {
152  wxPLDevice *device = (wxPLDevice *) pls->dev;
153  if ( device )
154  throw( "plD_init_wxwidgets called when a initialization has already occurred." );
155 
156  //initialise wxWidgets - this is required in order to allow some wxWidgets functions to
157  //be called frm within the driver when the user isn't passing a wxDC in. See e.g
158  //http://stackoverflow.com/questions/208373
159  if ( !wxTheApp )
160  {
161  wxApp::SetInstance( new wxApp() );
162  int argc = 0;
163  char* argv[1];
164  g_weInitializedWx = wxEntryStart( argc, (char **) NULL );
165  if ( !g_weInitializedWx )
166  throw( "plD_init_wxWidgets could not initialise wxWidgets" );
167  }
168  else
169  g_weInitializedWx = false;
170 
171  // default options
172  static PLINT text = 1;
173  static PLINT hrshsym = 0;
174  static char *mfo = NULL;
175 
176  DrvOpt wx_options[] = {
177  { "hrshsym", DRV_INT, &hrshsym, "Use Hershey symbol set (hrshsym=0|1)" },
178  { "text", DRV_INT, &text, "Use own text routines (text=0|1)" },
179  { "mfo", DRV_STR, &mfo, "output metafile" },
180  { NULL, DRV_INT, NULL, NULL }
181  };
182 
183  // Check for and set up driver options
184  plParseDrvOpts( wx_options );
185 
186  // by default the own text routines are used for wxDC
187  if ( text == -1 )
188  text = 0;
189 
190  // create the new device
191  device = new wxPLDevice( pls, mfo, text, hrshsym );
192 
193  // If portrait mode, apply a rotation and set freeaspect
194  if ( pls->portrait )
195  {
196  plsdiori( (PLFLT) ( 4 - ORIENTATION ) );
197  pls->freeaspect = 1;
198  }
199  pls->has_string_length = 1;
200  }
201  catch ( char *message )
202  {
203  plabort( message );
204  pls->dev = NULL;
205  }
206  catch ( ... )
207  {
208  plabort( "unknown error in plD_init_wxwidgets." );
209  }
210  PLPLOT_wxLogDebug( "plD_init_wxwidgets(): leave" );
211 }
212 
213 #endif // PLD_wxwidgets
214 
215 
216 #ifdef PLD_wxpng
217 
218 //--------------------------------------------------------------------------
219 // void plD_dispatch_init_wxpng( PLDispatchTable *pdt )
220 //
221 // Make wxpng driver functions known to plplot.
222 //--------------------------------------------------------------------------
224 {
225 #ifndef ENABLE_DYNDRIVERS
226  pdt->pl_MenuStr = "wxWidgets PNG driver";
227  pdt->pl_DevName = "wxpng";
228 #endif
230  pdt->pl_seq = 52;
239 }
240 
241 //--------------------------------------------------------------------------
242 // void plD_init_wxpng( PLStream *pls )
243 //
244 // Initialize wxpng device.
245 //--------------------------------------------------------------------------
246 void plD_init_wxpng( PLStream *pls )
247 {
248  PLPLOT_wxLogDebug( "plD_init_wxpng()" );
249 
250  wxPLDevBase* dev;
251  dev = common_init( pls );
252 
253  // Initialize family file info
254  plFamInit( pls );
255 
256  // Prompt for a file name if not already set.
257  plOpenFile( pls );
258 
259  pls->plbuf_write = 1; // use the plot buffer!
260  pls->dev_flush = 0; // No need for flushes
261  pls->termin = 0; // file oriented device
262  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)
263  pls->page = 0;
264 
265  dev->showGUI = false;
266  dev->bitmapType = wxBITMAP_TYPE_PNG;
267 }
268 
269 #endif // PLD_wxpng
270 
271 
272 //--------------------------------------------------------------------------
273 // void plD_line_wxwidgets( PLStream *pls, short x1a, short y1a,
274 // short x2a, short y2a )
275 //
276 // Draws a line from (x1a, y1a) to (x2a, y2a).
277 //--------------------------------------------------------------------------
278 void plD_line_wxwidgets( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
279 {
280  // Log_Verbose( "plD_line_wxwidgets(x1a=%d, y1a=%d, x2a=%d, y2a=%d)", x1a, y1a, x2a, y2a );
281  try
282  {
283  wxPLDevice *device = (wxPLDevice *) pls->dev;
284  if ( !device )
285  throw( "plD_line_wxwidgets called before initialization." );
286  device->DrawLine( x1a, y1a, x2a, y2a );
287  }
288  catch ( char* message )
289  {
290  plabort( message );
291  }
292  catch ( ... )
293  {
294  plabort( "unknown error in plD_line_wxwidgets." );
295  }
296 }
297 
298 
299 //--------------------------------------------------------------------------
300 // void plD_polyline_wxwidgets( PLStream *pls, short *xa, short *ya,
301 // PLINT npts )
302 //
303 // Draw a poly line - points are in xa and ya arrays.
304 //--------------------------------------------------------------------------
305 void plD_polyline_wxwidgets( PLStream *pls, short *xa, short *ya, PLINT npts )
306 {
307  // PLPLOT_wxLogDebug( "plD_polyline_wxwidgets()" );
308  try
309  {
310  wxPLDevice *device = (wxPLDevice *) pls->dev;
311  if ( !device )
312  throw( "plD_polyline_wxwidgets called before initialization." );
313  device->DrawPolyline( xa, ya, npts );
314  }
315  catch ( char* message )
316  {
317  plabort( message );
318  }
319  catch ( ... )
320  {
321  plabort( "unknown error in plD_polyline_wxwidgets." );
322  }
323 }
324 
325 
326 //--------------------------------------------------------------------------
327 // void plD_eop_wxwidgets( PLStream *pls )
328 //
329 // End of Page. This function is called if a "end of page" is send by the
330 // user. This command is ignored if we have the plot embedded in a
331 // wxWidgets application, otherwise the application created by the device
332 // takes over.
333 //--------------------------------------------------------------------------
335 {
336  // PLPLOT_wxLogDebug( "plD_eop_wxwidgets()" );
337  try
338  {
339  wxPLDevice *device = (wxPLDevice *) pls->dev;
340  if ( !device )
341  throw( "plD_eop_wxwidgets called before initialization." );
342  device->EndPage( pls );
343  }
344  catch ( char* message )
345  {
346  plabort( message );
347  }
348  catch ( ... )
349  {
350  plabort( "unknown error in plD_eop_wxwidgets." );
351  }
352 }
353 
354 
355 //--------------------------------------------------------------------------
356 // void plD_bop_wxwidgets( PLStream *pls )
357 //
358 // Begin of page. Before any plot command, this function is called, If we
359 // have already a dc the background is cleared in background color and some
360 // state calls are resent - this is because at the first call of this
361 // function, a dc does most likely not exist, but state calls are recorded
362 // and when a new dc is created this function is called again.
363 //--------------------------------------------------------------------------
365 {
366  // PLPLOT_wxLogDebug( "plD_bop_wxwidgets()" );
367  try
368  {
369  wxPLDevice *device = (wxPLDevice *) pls->dev;
370  if ( !device )
371  throw( "plD_bop_wxwidgets called before initialization." );
372  device->BeginPage( pls );
373  }
374  catch ( char* message )
375  {
376  plabort( message );
377  }
378  catch ( ... )
379  {
380  plabort( "unknown error in plD_bop_wxwidgets." );
381  }
382 }
383 
384 
385 //--------------------------------------------------------------------------
386 // void plD_tidy_wxwidgets( PLStream *pls )
387 //
388 // This function is called, if all plots are done.
389 //--------------------------------------------------------------------------
391 {
392  // PLPLOT_wxLogDebug( "plD_tidy_wxwidgets()" );
393  if ( !pls->dev )
394  return;
395  try
396  {
397  wxPLDevice *device = (wxPLDevice *) pls->dev;
398  if ( device )
399  {
400  device->PreDestructorTidy( pls );
401  delete device;
402  }
403  pls->dev = NULL; //so it doesn't get freed elswhere
404  if ( g_weInitializedWx )
405  wxEntryCleanup();
406  }
407  catch ( char* message )
408  {
409  plabort( message );
410  }
411  catch ( ... )
412  {
413  plabort( "unknown error in plD_tidy_wxwidgets." );
414  }
415 }
416 
417 
418 //--------------------------------------------------------------------------
419 // void plD_state_wxwidgets( PLStream *pls, PLINT op )
420 //
421 // Handler for several state codes. Here we take care of setting the width
422 // and color of the pen.
423 //--------------------------------------------------------------------------
425 {
426  // Log_Verbose( "plD_state_wxwidgets(op=%d)", op );
427  try
428  {
429  wxPLDevice *device = (wxPLDevice *) pls->dev;
430  if ( !device )
431  return; //we can call state functions befor initialization so just return
432  switch ( op )
433  {
434  case PLSTATE_WIDTH: // 1
435  device->SetWidth( pls );
436  break;
437 
438  case PLSTATE_COLOR0: // 2
439  device->SetColor( pls );
440  break;
441 
442  case PLSTATE_COLOR1: // 3
443  device->SetColor( pls );
444  break;
445  }
446  }
447  catch ( char* message )
448  {
449  plabort( message );
450  }
451  catch ( ... )
452  {
453  plabort( "unknown error in plD_state_wxwidgets." );
454  }
455 }
456 
457 
458 //--------------------------------------------------------------------------
459 // void plD_esc_wxwidgets( PLStream *pls, PLINT op, void *ptr )
460 //
461 // Handler for several escape codes. Here we take care of filled polygons,
462 // XOR or copy mode, initialize device (install dc from outside), and if
463 // there is freetype support, rerendering of text.
464 //--------------------------------------------------------------------------
465 void plD_esc_wxwidgets( PLStream *pls, PLINT op, void *ptr )
466 {
467  // Log_Verbose( "plD_esc_wxwidgets(op=%d, ptr=%x)", op, ptr );
468 
469  if ( !pls->dev )
470  return;
471 
472  try
473  {
474  wxPLDevice *device = (wxPLDevice *) pls->dev;
475  if ( !device )
476  throw( "plD_esc_wxwidgets called before initialization." );
477  switch ( op )
478  {
479  case PLESC_FILL:
480  device->FillPolygon( pls );
481  break;
482 
483  case PLESC_XORMOD:
484  // switch between wxXOR and wxCOPY
485  // if( dev->ready ) {
486  // if( dev->m_dc->GetLogicalFunction() == wxCOPY )
487  // dev->m_dc->SetLogicalFunction( wxXOR );
488  // else if( dev->m_dc->GetLogicalFunction() == wxXOR )
489  // dev->m_dc->SetLogicalFunction( wxCOPY );
490  // }
491  break;
492 
493  case PLESC_DEVINIT:
494  device->SetDC( pls, (wxDC *) ptr );
495  break;
496 
497  case PLESC_HAS_TEXT:
498  device->drawText( pls, (EscText *) ptr );
499  break;
500 
501  case PLESC_RESIZE:
502  {
503  wxSize* size = (wxSize *) ptr;
504  device->SetSize( pls, size->GetWidth(), size->GetHeight() );
505  }
506  break;
507 
508  case PLESC_CLEAR:
509  device->ClearBackground( pls, pls->sppxmi, pls->sppymi,
510  pls->sppxma, pls->sppyma );
511  break;
512 
513  case PLESC_FLUSH: // forced update of the window
514  device->Flush( pls );
515  break;
516 
517  case PLESC_GETC:
518  device->Locate( pls, (PLGraphicsIn *) ptr );
519  break;
520 
521  case PLESC_FIXASPECT:
522  device->FixAspectRatio( *( (bool *) ptr ) );
523  break;
524 
525  default:
526  break;
527  }
528  }
529  catch ( char* message )
530  {
531  plabort( message );
532  }
533  catch ( ... )
534  {
535  plabort( "unknown error in plD_tidy_wxwidgets." );
536  }
537 }
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:287
PLDLLIMPEXP_DRIVER void plD_dispatch_init_wxwidgets(PLDispatchTable *pdt)
#define PLESC_DEVINIT
Definition: plplot.h:297
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:280
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:334
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:812
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
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:364
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:278
void(* plD_bop_fp)(struct PLStream_struct *)
Definition: disptab.h:71
PLINT sppyma
Definition: plstrm.h:702
#define PLESC_FIXASPECT
Definition: plplot.h:309
PLINT termin
Definition: plstrm.h:567
void plD_esc_wxwidgets(PLStream *pls, PLINT op, void *ptr)
Definition: wxwidgets.cpp:465
#define PLESC_RESIZE
Definition: plplot.h:276
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:305
#define PLESC_CLEAR
Definition: plplot.h:289
#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)
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:424
#define PLPLOT_wxLogDebug(string)
#define PLESC_HAS_TEXT
Definition: plplot.h:291
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:390
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:284
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_init_fp)(struct PLStream_struct *)
Definition: disptab.h:67
#define PLESC_FLUSH
Definition: plplot.h:282
#define GRAPHICS_MODE
Definition: plplotP.h:288
PLINT has_string_length
Definition: plstrm.h:784