PLplot  5.11.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
wxPLplotwindow.h
Go to the documentation of this file.
1 // Copyright (C) 2015 Phil Rosenberg
2 // Copyright (C) 2005 Werner Smekal
3 //
4 // This file is part of PLplot.
5 //
6 // PLplot is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU Library General Public License as published
8 // by the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // PLplot is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU Library General Public License for more details.
15 //
16 // You should have received a copy of the GNU Library General Public License
17 // along with PLplot; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 //
20 
21 #if !defined ( WXPLPLOTWINDOW_H__INCLUDED_ )
22 #define WXPLPLOTWINDOW_H__INCLUDED_
23 
24 #include "plplot.h"
25 #include "wxPLplotstream.h"
26 #include <wx/window.h>
27 #include <wx/dcmemory.h>
28 #include <wx/dcclient.h>
29 #include <wx/dcgraph.h>
30 #include <wx/dcbuffer.h>
31 
32 // A plplot wxWindow template. To create an actual plplot wxWindow use
33 // the type of wxWindow you wish to inherit from at the template parameter
34 // For example to create a plplot wxFrame create a wxPLplotwindow<wxFrame>
35 // then call the base wxWindow's Create method to initialise.
36 template <class WXWINDOW>
37 class wxPLplotwindow : public WXWINDOW
38 {
39 public:
40  wxPLplotwindow( bool useGraphicsContext = true, wxSize clientSize = wxDefaultSize );
41  virtual ~wxPLplotwindow( void );
42 
43  void RenewPlot( void );
44  bool SavePlot( const wxString& driver, const wxString& filename );
45  wxPLplotstream* GetStream() { return m_created ? &m_stream : NULL; }
46  void setUseGraphicsContext( bool useGraphicsContext );
47  void setCanvasColour( const wxColour &colour );
48 
49 protected:
50  virtual void OnPaint( wxPaintEvent& event );
51  virtual void OnSize( wxSizeEvent & event );
52  virtual void OnErase( wxEraseEvent &event );
53  virtual void OnCreate( wxWindowCreateEvent &event );
54  void OnMouse( wxMouseEvent &event );
56  bool m_created;
57 
58 private:
60  wxBitmap m_bitmap;
61  // The memory dc and wrapping gc dc for drawing. Note we
62  //use pointers and reallocate them whenever the bitmap is
63  //resized because reusing either of these causes problems
64  //for rendering on a wxGCDC - at least on Windows.
65  wxMemoryDC *m_memoryDc;
66  wxSize m_initialSize;
67 #ifdef wxUSE_GRAPHICS_CONTEXT
68  wxGCDC *m_gcDc;
69 #endif
70  wxColour m_canvasColour;
71  virtual void OnLocate( const PLGraphicsIn &graphicsIn ){}
72 };
73 
74 
76 // methods with events. The WXWINDOW default constructor is used.
77 //
78 template<class WXWINDOW>
79 wxPLplotwindow<WXWINDOW>::wxPLplotwindow( bool useGraphicsContext, wxSize clientSize )
80  : m_created( false ), m_initialSize( clientSize )
81 
82 {
83  m_memoryDc = NULL;
84 #ifdef wxUSE_GRAPHICS_CONTEXT
85  m_gcDc = NULL;
86 #endif
87  setUseGraphicsContext( useGraphicsContext );
88  m_canvasColour = *wxBLACK;
89 
90  //We use connect instead of Bind for compatiblity with wxWidgets 2.8
91  //but should move to bind in the future.
92  WXWINDOW::Connect( wxEVT_SIZE, wxSizeEventHandler( wxPLplotwindow<WXWINDOW>::OnSize ) );
93  WXWINDOW::Connect( wxEVT_PAINT, wxPaintEventHandler( wxPLplotwindow<WXWINDOW>::OnPaint ) );
94  WXWINDOW::Connect( wxEVT_ERASE_BACKGROUND, wxEraseEventHandler( wxPLplotwindow<WXWINDOW>::OnErase ) );
95  WXWINDOW::Connect( wxEVT_CREATE, wxWindowCreateEventHandler( wxPLplotwindow<WXWINDOW>::OnCreate ) );
96  WXWINDOW::Connect( wxEVT_MOTION, wxMouseEventHandler( wxPLplotwindow<WXWINDOW>::OnMouse ) );
97  WXWINDOW::Connect( wxEVT_LEFT_UP, wxMouseEventHandler( wxPLplotwindow<WXWINDOW>::OnMouse ) );
98  WXWINDOW::Connect( wxEVT_MIDDLE_UP, wxMouseEventHandler( wxPLplotwindow<WXWINDOW>::OnMouse ) );
99  WXWINDOW::Connect( wxEVT_RIGHT_UP, wxMouseEventHandler( wxPLplotwindow<WXWINDOW>::OnMouse ) );
100 }
101 
102 
104 //
105 template<class WXWINDOW>
107 {
108  if ( m_memoryDc )
109  delete m_memoryDc;
110  if ( m_gcDc )
111  delete m_gcDc;
112 }
113 
114 
116 // later), we also implement our own double buffering here (since the PLplot wxWidgets driver draws
117 // into a wxMemoryDC)
118 //
119 template<class WXWINDOW>
120 void wxPLplotwindow<WXWINDOW>::OnPaint( wxPaintEvent &WXUNUSED( event ) )
121 {
122  //Really this should be in the constructor, but it caused a segfault
123  //on at least one system (CentOS with intel compiler and wxWidgets 2.8.12).
124  //Moving it here after WXWINDOW::Create has been called stops this and
125  //the call does nothing if the style is the same as previous calls so
126  //should be safe to call here.
127  //WXWINDOW::SetBackgroundStyle( wxBG_STYLE_CUSTOM );
128 
129 
130  //wxAutoBufferedPaintDC dc( (WXWINDOW*)this );
131  int width = WXWINDOW::GetClientSize().GetWidth();
132  int height = WXWINDOW::GetClientSize().GetHeight();
133 
134  wxPaintDC paintDc( this );
135 
136  //resize the plot if needed
137  bool needResize = width != m_bitmap.GetWidth() || height != m_bitmap.GetHeight();
138  if ( needResize )
139  {
140  m_bitmap.Create( width, height, 32 );
141  if ( m_memoryDc )
142  delete m_memoryDc;
143  m_memoryDc = new wxMemoryDC;
144  m_memoryDc->SelectObject( m_bitmap );
145  wxDC *drawDc = m_memoryDc;
146 #ifdef wxUSE_GRAPHICS_CONTEXT
147  if ( m_useGraphicsContext )
148  {
149  if ( m_gcDc )
150  delete m_gcDc;
151  m_gcDc = new wxGCDC( *m_memoryDc );
152  drawDc = m_gcDc;
153  }
154 #endif
155  m_stream.SetDC( drawDc );
156  drawDc->SetBackground( wxBrush( m_canvasColour ) );
157  drawDc->Clear();
158  m_stream.SetSize( width, height );
159  }
160 
161  paintDc.Blit( 0, 0, width, height, m_memoryDc, 0, 0 );
162 }
163 
165 //
166 template<class WXWINDOW>
167 void wxPLplotwindow<WXWINDOW>::OnSize( wxSizeEvent& WXUNUSED( event ) )
168 {
169  //Invalidate the whole window so it is all redrawn, otherwise only
170  //newly exposed parts of the window get redrawn
171  RenewPlot();
172 }
173 
175 //
176 template<class WXWINDOW>
177 void wxPLplotwindow<WXWINDOW>::OnErase( wxEraseEvent& WXUNUSED( event ) )
178 {
179  //Do nothing. This stops screen flicker.
180 }
181 
183 // has been called. We note that this has been called to avoid attempting
184 // to redraw a plot on a window that hasn't been created yet.
185 template<class WXWINDOW>
186 void wxPLplotwindow<WXWINDOW>::OnCreate( wxWindowCreateEvent &event )
187 {
188  if ( !m_created )
189  {
190  //set the client size if requested
191  if ( m_initialSize != wxDefaultSize )
192  WXWINDOW::SetClientSize( m_initialSize );
193  //create the stream
194  int width = WXWINDOW::GetClientSize().GetWidth();
195  int height = WXWINDOW::GetClientSize().GetHeight();
196  m_bitmap.Create( width, height );
197  if ( m_memoryDc )
198  delete m_memoryDc;
199  m_memoryDc = new wxMemoryDC;
200  m_memoryDc->SelectObject( m_bitmap );
201  wxDC * drawDc = m_memoryDc;
202 #ifdef wxUSE_GRAPHICS_CONTEXT
203  if ( m_useGraphicsContext )
204  {
205  if ( m_gcDc )
206  delete m_gcDc;
207  m_gcDc = new wxGCDC( *m_memoryDc );
208  drawDc = m_gcDc;
209  }
210 #endif
211  if ( !m_stream.IsValid() )
212  m_stream.Create( drawDc, width, height, wxPLPLOT_DRAW_TEXT );
213  else
214  m_stream.SetDC( drawDc );
215  drawDc->SetBackground( wxBrush( m_canvasColour ) );
216  drawDc->Clear();
217 
218  m_created = true;
219  RenewPlot();
220  }
221 }
222 
223 //Capture Mouse events and pass the
224 template<class WXWINDOW>
225 void wxPLplotwindow<WXWINDOW>::OnMouse( wxMouseEvent &event )
226 {
227  PLGraphicsIn graphicsIn;
228  wxPoint cursorPosition = event.GetPosition();
229  wxSize clientSize = WXWINDOW::GetClientSize();
230 
231  graphicsIn.pX = cursorPosition.x;
232  graphicsIn.pY = cursorPosition.y;
233  graphicsIn.dX = PLFLT( cursorPosition.x + 0.5 ) / PLFLT( clientSize.GetWidth() );
234  graphicsIn.dY = 1.0 - PLFLT( cursorPosition.y + 0.5 ) / PLFLT( clientSize.GetHeight() );
235  graphicsIn.keysym = 0x20;
236  graphicsIn.state = 0;
237  graphicsIn.subwindow = -1;
238  graphicsIn.type = 0;
239  graphicsIn.string[0] = '\0';
240  if ( event.LeftUp() )
241  {
242  graphicsIn.button = 1;
243  graphicsIn.state |= PL_MASK_BUTTON1;
244  }
245  else if ( event.MiddleUp() )
246  {
247  graphicsIn.button = 2;
248  graphicsIn.state |= PL_MASK_BUTTON2;
249  }
250  else if ( event.RightUp() )
251  {
252  graphicsIn.button = 3;
253  graphicsIn.state |= PL_MASK_BUTTON3;
254  }
255  else if ( event.Aux1Up() )
256  {
257  graphicsIn.button = 4;
258  graphicsIn.state |= PL_MASK_BUTTON4;
259  }
260  else if ( event.Aux2Up() )
261  {
262  graphicsIn.button = 5;
263  graphicsIn.state |= PL_MASK_BUTTON5;
264  }
265  else
266  {
267  //If we get here we have just captured motion
268  //not a click
269  graphicsIn.button = 0;
270  graphicsIn.state = 0;
271  graphicsIn.keysym = 0;
272  }
273 
274  if ( wxGetKeyState( WXK_SHIFT ) )
275  graphicsIn.state |= PL_MASK_SHIFT;
276  if ( wxGetKeyState( WXK_CAPITAL ) )
277  graphicsIn.state |= PL_MASK_CAPS;
278  if ( wxGetKeyState( WXK_ALT ) && wxGetKeyState( WXK_CONTROL ) )
279  graphicsIn.state |= PL_MASK_ALTGR;
280  else if ( wxGetKeyState( WXK_CONTROL ) )
281  graphicsIn.state |= PL_MASK_CONTROL;
282  else if ( wxGetKeyState( WXK_ALT ) )
283  graphicsIn.state |= PL_MASK_ALT;
284  if ( wxGetKeyState( WXK_NUMLOCK ) )
285  graphicsIn.state |= PL_MASK_NUM;
286  if ( wxGetKeyState( WXK_SCROLL ) )
287  graphicsIn.state |= PL_MASK_SCROLL;
288  //Note I can't find a way to catch the windows key
289 
290  m_stream.translatecursor( &graphicsIn );
291  this->OnLocate( graphicsIn );
292 }
293 
295 //
296 template<class WXWINDOW>
298 {
299  if ( m_created )
300  {
301  WXWINDOW::Refresh();
302  }
303 }
304 
305 
307 //
308 template<class WXWINDOW>
309 bool wxPLplotwindow<WXWINDOW>::SavePlot( const wxString& devname, const wxString& filename )
310 {
311  int pls, pls_save;
312  FILE *sfile;
313 
314  if ( ( sfile = fopen( filename.mb_str(), "wb+" ) ) == NULL )
315  {
316  return false;
317  }
318 
319  plgstrm( &pls );
320  plmkstrm( &pls_save );
321  if ( pls_save < 0 )
322  {
323  fclose( sfile );
324  return false;
325  }
326  plsdev( devname.mb_str() );
327  plsfile( sfile );
328 
329  plspage( 0., 0., 800, 600, 0, 0 );
330  plcpstrm( pls, 0 );
331  pladv( 0 );
332  plreplot();
333  plend1();
334  plsstrm( pls );
335 
336  return true;
337 }
338 
340 template<class WXWINDOW>
341 void wxPLplotwindow<WXWINDOW>::setUseGraphicsContext( bool useGraphicsContext )
342 {
343  wxDC *drawDc;
344 #ifdef wxUSE_GRAPHICS_CONTEXT
345  if ( useGraphicsContext != m_useGraphicsContext )
346  {
347  m_useGraphicsContext = useGraphicsContext;
348  drawDc = m_useGraphicsContext ? (wxDC *) m_gcDc : (wxDC *) m_memoryDc;
349  }
350 #else
351  drawDc = &m_memoryDc;
352  m_useGraphicsContext = false;
353 #endif
354  if ( m_created )
355  {
356  m_stream.SetDC( drawDc );
357  RenewPlot();
358  }
359 }
360 
361 template<class WXWINDOW>
362 void wxPLplotwindow<WXWINDOW>::setCanvasColour( const wxColour &colour )
363 {
364  m_canvasColour = colour;
365  RenewPlot();
366 }
367 
368 #endif // !defined( WXPLPLOTWINDOW_H__INCLUDED_ )
#define PL_MASK_BUTTON3
Definition: plplot.h:378
#define plsstrm
Definition: plplot.h:773
#define plspage
Definition: plplot.h:769
virtual void OnLocate(const PLGraphicsIn &graphicsIn)
#define plsdev
Definition: plplot.h:746
PLFLT dX
Definition: plplot.h:391
void setUseGraphicsContext(bool useGraphicsContext)
Set whether we wish to use wxGCDC instead of a wxDC.
wxColour m_canvasColour
wxPLplotstream is inherited from plstream, which is the C++ interface
wxMemoryDC * m_memoryDc
void plsfile(FILE *file)
Definition: plcore.c:3781
#define PL_MASK_SHIFT
Definition: plplot.h:368
#define plend1
Definition: plplot.h:643
bool m_useGraphicsContext
Flag to indicate whether we should use a wxGCDC.
#define plcpstrm
Definition: plplot.h:640
bool m_created
Flag to indicate the window has been Created.
virtual void OnCreate(wxWindowCreateEvent &event)
Window created event.
int type
Definition: plplot.h:384
#define PL_MASK_SCROLL
Definition: plplot.h:375
wxSize m_initialSize
void OnMouse(wxMouseEvent &event)
Mouse events.
wxPLplotwindow(bool useGraphicsContext=true, wxSize clientSize=wxDefaultSize)
Constructor.
wxPLplotstream m_stream
The wxPLplotstream which belongs to this plot widget.
unsigned int keysym
Definition: plplot.h:386
wxBitmap m_bitmap
static PLStream * pls[PL_NSTREAMS]
Definition: plcore.h:88
#define PL_MASK_CAPS
Definition: plplot.h:369
wxPLplotstream * GetStream()
Get pointer to wxPLplotstream of this widget.
#define PL_MASK_NUM
Definition: plplot.h:372
PLINT subwindow
Definition: plplot.h:388
#define PL_MASK_BUTTON2
Definition: plplot.h:377
#define plmkstrm
Definition: plplot.h:707
float PLFLT
Definition: plplot.h:157
virtual void OnPaint(wxPaintEvent &event)
Paint event.
void RenewPlot(void)
Redo plot.
#define PL_MASK_BUTTON4
Definition: plplot.h:379
#define PL_MASK_ALTGR
Definition: plplot.h:373
virtual void OnErase(wxEraseEvent &event)
Background erase event.
#define PL_MASK_ALT
Definition: plplot.h:371
unsigned int state
Definition: plplot.h:385
#define PL_MASK_BUTTON1
Definition: plplot.h:376
#define plreplot
Definition: plplot.h:723
unsigned int button
Definition: plplot.h:387
#define PL_MASK_CONTROL
Definition: plplot.h:370
void setCanvasColour(const wxColour &colour)
PLFLT dY
Definition: plplot.h:391
virtual ~wxPLplotwindow(void)
Destructor.
#define pladv
Definition: plplot.h:625
#define plgstrm
Definition: plplot.h:676
char string[PL_MAXKEY]
Definition: plplot.h:389
virtual void OnSize(wxSizeEvent &event)
Size event.
bool SavePlot(const wxString &driver, const wxString &filename)
Save plot using a different driver.
#define PL_MASK_BUTTON5
Definition: plplot.h:380