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