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