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