PLplot  5.11.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 #ifdef __WXMAC__
44  #include <Carbon/Carbon.h>
45 extern "C" { void CPSEnableForegroundOperation( ProcessSerialNumber* psn ); }
46 #endif
47 
48 
49 //--------------------------------------------------------------------------
50 // void Log_Verbose( const char *fmt, ... )
51 //
52 // Print verbose debug message to stderr (printf style).
53 //--------------------------------------------------------------------------
54 void Log_Verbose( const char *fmt, ... )
55 {
56 #ifdef _DEBUG_VERBOSE
57  va_list args;
58  va_start( args, fmt );
59  fprintf( stderr, "Verbose: " );
60  vfprintf( stderr, fmt, args );
61  fprintf( stderr, "\n" );
62  va_end( args );
63  fflush( stderr );
64 #else
65  (void) fmt; // Cast to void to silence compiler warnings about unused paraemeter
66 #endif
67 }
68 
69 
70 //--------------------------------------------------------------------------
71 // void Log_Debug( const char *fmt, ... )
72 //
73 // Print debug message to stderr (printf style).
74 //--------------------------------------------------------------------------
75 void Log_Debug( const char *fmt, ... )
76 {
77 #ifdef _DEBUG
78  va_list args;
79  va_start( args, fmt );
80  fprintf( stderr, "Debug: " );
81  vfprintf( stderr, fmt, args );
82  fprintf( stderr, "\n" );
83  va_end( args );
84  fflush( stderr );
85 #else
86  (void) fmt; // Cast to void to silence compiler warnings about unused paraemeter
87 #endif
88 }
89 
90 //--------------------------------------------------------------------------
91 // In the following you'll find the driver functions which are
92 // needed by the plplot core.
93 //--------------------------------------------------------------------------
94 
95 // Device info
96 #ifdef __cplusplus
97 extern "C" {
98 #endif
99 
101 #ifdef PLD_wxwidgets
102  "wxwidgets:wxWidgets Driver:1:wxwidgets:51:wxwidgets\n"
103 #endif
104 #ifdef PLD_wxpng
105  "wxpng:wxWidgets PNG Driver:0:wxwidgets:52:wxpng\n"
106 #endif
107 ;
108 
109 #ifdef __cplusplus
110 }
111 #endif
112 
113 
114 #ifdef PLD_wxwidgets
115 
116 //--------------------------------------------------------------------------
117 // void plD_dispatch_init_wxwidgets( PLDispatchTable *pdt )
118 //
119 // Make wxwidgets driver functions known to plplot.
120 //--------------------------------------------------------------------------
122 {
123 #ifndef ENABLE_DYNDRIVERS
124  pdt->pl_MenuStr = "wxWidgets DC";
125  pdt->pl_DevName = "wxwidgets";
126 #endif
128  pdt->pl_seq = 51;
137 }
138 
139 //--------------------------------------------------------------------------
140 // plD_init_wxwidgets( PLStream* pls )
141 //
142 // Initialize wxWidgets device.
143 //--------------------------------------------------------------------------
144 void plD_init_wxwidgets( PLStream* pls )
145 {
146  // Log_Verbose( "plD_init_wxwidgets()" );
147 
148  try
149  {
150  wxPLDevice *device = (wxPLDevice *) pls->dev;
151  if ( device )
152  throw( "plD_init_wxwidgets called when a initialization has already occurred." );
153 
154  // default options
155  static PLINT text = 1;
156  static PLINT hrshsym = 0;
157  static char *mfo = NULL;
158 
159  DrvOpt wx_options[] = {
160  { "hrshsym", DRV_INT, &hrshsym, "Use Hershey symbol set (hrshsym=0|1)" },
161  { "text", DRV_INT, &text, "Use own text routines (text=0|1)" },
162  { "mfo", DRV_STR, &mfo, "output metafile" },
163  { NULL, DRV_INT, NULL, NULL }
164  };
165 
166  // Check for and set up driver options
167  plParseDrvOpts( wx_options );
168 
169  // by default the own text routines are used for wxDC
170  if ( text == -1 )
171  text = 0;
172 
173  // create the new device
174  device = new wxPLDevice( pls, mfo, text, hrshsym );
175 
176  // If portrait mode, apply a rotation and set freeaspect
177  if ( pls->portrait )
178  {
179  plsdiori( (PLFLT) ( 4 - ORIENTATION ) );
180  pls->freeaspect = 1;
181  }
182  }
183  catch ( char *message )
184  {
185  plabort( message );
186  pls->dev = NULL;
187  }
188  catch ( ... )
189  {
190  plabort( "unknown error in plD_init_wxwidgets." );
191  }
192 }
193 
194 #endif // PLD_wxwidgets
195 
196 
197 #ifdef PLD_wxpng
198 
199 //--------------------------------------------------------------------------
200 // void plD_dispatch_init_wxpng( PLDispatchTable *pdt )
201 //
202 // Make wxpng driver functions known to plplot.
203 //--------------------------------------------------------------------------
205 {
206 #ifndef ENABLE_DYNDRIVERS
207  pdt->pl_MenuStr = "wxWidgets PNG driver";
208  pdt->pl_DevName = "wxpng";
209 #endif
211  pdt->pl_seq = 52;
220 }
221 
222 //--------------------------------------------------------------------------
223 // void plD_init_wxpng( PLStream *pls )
224 //
225 // Initialize wxpng device.
226 //--------------------------------------------------------------------------
227 void plD_init_wxpng( PLStream *pls )
228 {
229  // Log_Verbose( "plD_init_wxwidgets()" );
230 
231  wxPLDevBase* dev;
232  dev = common_init( pls );
233 
234  // Initialize family file info
235  plFamInit( pls );
236 
237  // Prompt for a file name if not already set.
238  plOpenFile( pls );
239 
240  pls->plbuf_write = 1; // use the plot buffer!
241  pls->dev_flush = 0; // No need for flushes
242  pls->termin = 0; // file oriented device
243  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)
244  pls->page = 0;
245 
246  dev->showGUI = false;
247  dev->bitmapType = wxBITMAP_TYPE_PNG;
248 }
249 
250 #endif // PLD_wxpng
251 
252 
253 //--------------------------------------------------------------------------
254 // void plD_line_wxwidgets( PLStream *pls, short x1a, short y1a,
255 // short x2a, short y2a )
256 //
257 // Draws a line from (x1a, y1a) to (x2a, y2a).
258 //--------------------------------------------------------------------------
259 void plD_line_wxwidgets( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
260 {
261  // Log_Verbose( "plD_line_wxwidgets(x1a=%d, y1a=%d, x2a=%d, y2a=%d)", x1a, y1a, x2a, y2a );
262  try
263  {
264  wxPLDevice *device = (wxPLDevice *) pls->dev;
265  if ( !device )
266  throw( "plD_line_wxwidgets called before initialization." );
267  device->DrawLine( x1a, y1a, x2a, y2a );
268  }
269  catch ( char* message )
270  {
271  plabort( message );
272  }
273  catch ( ... )
274  {
275  plabort( "unknown error in plD_line_wxwidgets." );
276  }
277 }
278 
279 
280 //--------------------------------------------------------------------------
281 // void plD_polyline_wxwidgets( PLStream *pls, short *xa, short *ya,
282 // PLINT npts )
283 //
284 // Draw a poly line - points are in xa and ya arrays.
285 //--------------------------------------------------------------------------
286 void plD_polyline_wxwidgets( PLStream *pls, short *xa, short *ya, PLINT npts )
287 {
288  // Log_Verbose( "plD_polyline_wxwidgets()" );
289  try
290  {
291  wxPLDevice *device = (wxPLDevice *) pls->dev;
292  if ( !device )
293  throw( "plD_polyline_wxwidgets called before initialization." );
294  device->DrawPolyline( xa, ya, npts );
295  }
296  catch ( char* message )
297  {
298  plabort( message );
299  }
300  catch ( ... )
301  {
302  plabort( "unknown error in plD_polyline_wxwidgets." );
303  }
304 }
305 
306 
307 //--------------------------------------------------------------------------
308 // void plD_eop_wxwidgets( PLStream *pls )
309 //
310 // End of Page. This function is called if a "end of page" is send by the
311 // user. This command is ignored if we have the plot embedded in a
312 // wxWidgets application, otherwise the application created by the device
313 // takes over.
314 //--------------------------------------------------------------------------
316 {
317  // Log_Verbose( "plD_eop_wxwidgets()" );
318  try
319  {
320  wxPLDevice *device = (wxPLDevice *) pls->dev;
321  if ( !device )
322  throw( "plD_eop_wxwidgets called before initialization." );
323  device->EndPage( pls );
324  }
325  catch ( char* message )
326  {
327  plabort( message );
328  }
329  catch ( ... )
330  {
331  plabort( "unknown error in plD_eop_wxwidgets." );
332  }
333 }
334 
335 
336 //--------------------------------------------------------------------------
337 // void plD_bop_wxwidgets( PLStream *pls )
338 //
339 // Begin of page. Before any plot command, this function is called, If we
340 // have already a dc the background is cleared in background color and some
341 // state calls are resent - this is because at the first call of this
342 // function, a dc does most likely not exist, but state calls are recorded
343 // and when a new dc is created this function is called again.
344 //--------------------------------------------------------------------------
346 {
347  // Log_Verbose( "plD_bop_wxwidgets()" );
348  try
349  {
350  wxPLDevice *device = (wxPLDevice *) pls->dev;
351  if ( !device )
352  throw( "plD_bop_wxwidgets called before initialization." );
353  device->BeginPage( pls );
354  }
355  catch ( char* message )
356  {
357  plabort( message );
358  }
359  catch ( ... )
360  {
361  plabort( "unknown error in plD_bop_wxwidgets." );
362  }
363 }
364 
365 
366 //--------------------------------------------------------------------------
367 // void plD_tidy_wxwidgets( PLStream *pls )
368 //
369 // This function is called, if all plots are done.
370 //--------------------------------------------------------------------------
372 {
373  // Log_Verbose( "plD_tidy_wxwidgets()" );
374  if ( !pls->dev )
375  return;
376  try
377  {
378  wxPLDevice *device = (wxPLDevice *) pls->dev;
379  if ( device )
380  delete device;
381  pls->dev = NULL; //so it doesn't get freed elswhere
382  }
383  catch ( char* message )
384  {
385  plabort( message );
386  }
387  catch ( ... )
388  {
389  plabort( "unknown error in plD_tidy_wxwidgets." );
390  }
391 }
392 
393 
394 //--------------------------------------------------------------------------
395 // void plD_state_wxwidgets( PLStream *pls, PLINT op )
396 //
397 // Handler for several state codes. Here we take care of setting the width
398 // and color of the pen.
399 //--------------------------------------------------------------------------
401 {
402  // Log_Verbose( "plD_state_wxwidgets(op=%d)", op );
403  try
404  {
405  wxPLDevice *device = (wxPLDevice *) pls->dev;
406  if ( !device )
407  return; //we can call state functions befor initialization so just return
408  switch ( op )
409  {
410  case PLSTATE_WIDTH: // 1
411  device->SetWidth( pls );
412  break;
413 
414  case PLSTATE_COLOR0: // 2
415  device->SetColor( pls );
416  break;
417 
418  case PLSTATE_COLOR1: // 3
419  device->SetColor( pls );
420  break;
421  }
422  }
423  catch ( char* message )
424  {
425  plabort( message );
426  }
427  catch ( ... )
428  {
429  plabort( "unknown error in plD_state_wxwidgets." );
430  }
431 }
432 
433 
434 //--------------------------------------------------------------------------
435 // void plD_esc_wxwidgets( PLStream *pls, PLINT op, void *ptr )
436 //
437 // Handler for several escape codes. Here we take care of filled polygons,
438 // XOR or copy mode, initialize device (install dc from outside), and if
439 // there is freetype support, rerendering of text.
440 //--------------------------------------------------------------------------
441 void plD_esc_wxwidgets( PLStream *pls, PLINT op, void *ptr )
442 {
443  // Log_Verbose( "plD_esc_wxwidgets(op=%d, ptr=%x)", op, ptr );
444 
445  if ( !pls->dev )
446  return;
447 
448  try
449  {
450  wxPLDevice *device = (wxPLDevice *) pls->dev;
451  if ( !device )
452  throw( "plD_esc_wxwidgets called before initialization." );
453  switch ( op )
454  {
455  case PLESC_FILL:
456  device->FillPolygon( pls );
457  break;
458 
459  case PLESC_XORMOD:
460  // switch between wxXOR and wxCOPY
461  // if( dev->ready ) {
462  // if( dev->m_dc->GetLogicalFunction() == wxCOPY )
463  // dev->m_dc->SetLogicalFunction( wxXOR );
464  // else if( dev->m_dc->GetLogicalFunction() == wxXOR )
465  // dev->m_dc->SetLogicalFunction( wxCOPY );
466  // }
467  break;
468 
469  case PLESC_DEVINIT:
470  device->SetDC( pls, (wxDC *) ptr );
471  break;
472 
473  case PLESC_HAS_TEXT:
474  device->ProcessString( pls, (EscText *) ptr );
475  break;
476 
477  case PLESC_RESIZE:
478  {
479  wxSize* size = (wxSize *) ptr;
480  device->SetSize( pls, size->GetWidth(), size->GetHeight() );
481  }
482  break;
483 
484  case PLESC_CLEAR:
485  device->ClearBackground( pls, pls->sppxmi, pls->sppymi,
486  pls->sppxma, pls->sppyma );
487  break;
488 
489  case PLESC_FLUSH: // forced update of the window
490  device->Flush( pls );
491  break;
492 
493  case PLESC_GETC:
494  device->Locate( pls, (PLGraphicsIn *) ptr );
495  break;
496 
497  case PLESC_FIXASPECT:
498  device->FixAspectRatio( *( (bool *) ptr ) );
499  break;
500 
501  default:
502  break;
503  }
504  }
505  catch ( char* message )
506  {
507  plabort( message );
508  }
509  catch ( ... )
510  {
511  plabort( "unknown error in plD_tidy_wxwidgets." );
512  }
513 }