PLplot  5.13.0
 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  bool IsReady() { return GetStream() != NULL; }
49 
50 protected:
51  virtual void OnPaint( wxPaintEvent& event );
52  virtual void OnSize( wxSizeEvent & event );
53  virtual void OnErase( wxEraseEvent &event );
54  virtual void OnCreate( wxWindowCreateEvent &event );
55  void OnMouse( wxMouseEvent &event );
57  bool m_created;
58 
59 private:
61  wxBitmap m_bitmap;
62  // The memory dc and wrapping gc dc for drawing. Note we
63  //use pointers and reallocate them whenever the bitmap is
64  //resized because reusing either of these causes problems
65  //for rendering on a wxGCDC - at least on Windows.
66  wxMemoryDC *m_memoryDc;
67  wxSize m_initialSize;
68 #ifdef wxUSE_GRAPHICS_CONTEXT
69  wxGCDC *m_gcDc;
70 #endif
71  wxColour m_canvasColour;
72  virtual void OnLocate( const PLGraphicsIn &graphicsIn ){}
73 };
74 
75 
80 
81 template<class WXWINDOW>
82 wxPLplotwindow<WXWINDOW>::wxPLplotwindow( bool useGraphicsContext, wxSize clientSize )
83  : m_created( false ), m_initialSize( clientSize )
84 
85 {
86  PLPLOT_wxLogDebug( "wxPLplotwindow::wxPLplotwindow" );
87  m_memoryDc = NULL;
88 #ifdef wxUSE_GRAPHICS_CONTEXT
89  m_gcDc = NULL;
90  // Force initialization of m_useGraphicsContext and
91  // drawDc when setUseGraphicsContext is called below.
92  m_useGraphicsContext = !useGraphicsContext;
93 #endif
94  setUseGraphicsContext( useGraphicsContext );
95  m_canvasColour = *wxBLACK;
96 
97  //We use connect instead of Bind for compatibility with wxWidgets 2.8
98  //but should move to bind in the future.
99  WXWINDOW::Connect( wxEVT_SIZE, wxSizeEventHandler( wxPLplotwindow<WXWINDOW>::OnSize ) );
100  WXWINDOW::Connect( wxEVT_PAINT, wxPaintEventHandler( wxPLplotwindow<WXWINDOW>::OnPaint ) );
101  WXWINDOW::Connect( wxEVT_ERASE_BACKGROUND, wxEraseEventHandler( wxPLplotwindow<WXWINDOW>::OnErase ) );
102  WXWINDOW::Connect( wxEVT_CREATE, wxWindowCreateEventHandler( wxPLplotwindow<WXWINDOW>::OnCreate ) );
103  WXWINDOW::Connect( wxEVT_MOTION, wxMouseEventHandler( wxPLplotwindow<WXWINDOW>::OnMouse ) );
104  WXWINDOW::Connect( wxEVT_LEFT_UP, wxMouseEventHandler( wxPLplotwindow<WXWINDOW>::OnMouse ) );
105  WXWINDOW::Connect( wxEVT_MIDDLE_UP, wxMouseEventHandler( wxPLplotwindow<WXWINDOW>::OnMouse ) );
106  WXWINDOW::Connect( wxEVT_RIGHT_UP, wxMouseEventHandler( wxPLplotwindow<WXWINDOW>::OnMouse ) );
107 }
108 
109 
112 
113 template<class WXWINDOW>
115 {
116  if ( m_memoryDc )
117  delete m_memoryDc;
118  if ( m_gcDc )
119  delete m_gcDc;
120 }
121 
127 
128 template<class WXWINDOW>
129 void wxPLplotwindow<WXWINDOW>::OnPaint( wxPaintEvent &WXUNUSED( event ) )
130 {
131  //Really this should be in the constructor, but it caused a segfault
132  //on at least one system (CentOS with intel compiler and wxWidgets 2.8.12).
133  //Moving it here after WXWINDOW::Create has been called stops this and
134  //the call does nothing if the style is the same as previous calls so
135  //should be safe to call here.
136  //WXWINDOW::SetBackgroundStyle( wxBG_STYLE_CUSTOM );
137 
138 
139  //wxAutoBufferedPaintDC dc( (WXWINDOW*)this );
140  int width = WXWINDOW::GetClientSize().GetWidth();
141  int height = WXWINDOW::GetClientSize().GetHeight();
142 
143  wxPaintDC paintDc( this );
144 
145  //resize the plot if needed
146  bool needResize = width != m_bitmap.GetWidth() || height != m_bitmap.GetHeight();
147  if ( needResize )
148  {
149  m_bitmap.Create( width, height, 32 );
150  if ( m_memoryDc )
151  delete m_memoryDc;
152  m_memoryDc = new wxMemoryDC;
153  m_memoryDc->SelectObject( m_bitmap );
154  wxDC *drawDc = m_memoryDc;
155 #ifdef wxUSE_GRAPHICS_CONTEXT
156  if ( m_useGraphicsContext )
157  {
158  if ( m_gcDc )
159  delete m_gcDc;
160  m_gcDc = new wxGCDC( *m_memoryDc );
161  drawDc = m_gcDc;
162  }
163 #endif
164  if ( IsReady() )
165  m_stream.SetDC( drawDc );
166  drawDc->SetBackground( wxBrush( m_canvasColour ) );
167  drawDc->Clear();
168  if ( IsReady() )
169  m_stream.SetSize( width, height );
170  }
171 
172  paintDc.Blit( 0, 0, width, height, m_memoryDc, 0, 0 );
173 }
174 
177 
178 template<class WXWINDOW>
179 void wxPLplotwindow<WXWINDOW>::OnSize( wxSizeEvent& WXUNUSED( event ) )
180 {
181  //Invalidate the whole window so it is all redrawn, otherwise only
182  //newly exposed parts of the window get redrawn
183  RenewPlot();
184 }
185 
188 
189 template<class WXWINDOW>
190 void wxPLplotwindow<WXWINDOW>::OnErase( wxEraseEvent& WXUNUSED( event ) )
191 {
192  //Do nothing. This stops screen flicker.
193 }
194 
200 
201 template<class WXWINDOW>
202 void wxPLplotwindow<WXWINDOW>::OnCreate( wxWindowCreateEvent &event )
203 {
204  PLPLOT_wxLogDebug( "wxPLplotwindow::OnCreate" );
205  if ( !m_created )
206  {
207  //set the client size if requested
208  if ( m_initialSize != wxDefaultSize )
209  WXWINDOW::SetClientSize( m_initialSize );
210  //create the stream
211  int width = WXWINDOW::GetClientSize().GetWidth();
212  int height = WXWINDOW::GetClientSize().GetHeight();
213  m_bitmap.Create( width, height );
214  if ( m_memoryDc )
215  delete m_memoryDc;
216  m_memoryDc = new wxMemoryDC;
217  m_memoryDc->SelectObject( m_bitmap );
218  wxDC * drawDc = m_memoryDc;
219 #ifdef wxUSE_GRAPHICS_CONTEXT
220  if ( m_useGraphicsContext )
221  {
222  if ( m_gcDc )
223  delete m_gcDc;
224  m_gcDc = new wxGCDC( *m_memoryDc );
225  drawDc = m_gcDc;
226  }
227 #endif
228  if ( !m_stream.IsValid() )
229  m_stream.Create( drawDc, width, height, wxPLPLOT_DRAW_TEXT );
230  else
231  m_stream.SetDC( drawDc );
232  drawDc->SetBackground( wxBrush( m_canvasColour ) );
233  drawDc->Clear();
234 
235  m_created = true;
236  RenewPlot();
237  }
238 }
239 
240 //Capture Mouse events and pass the
241 template<class WXWINDOW>
242 void wxPLplotwindow<WXWINDOW>::OnMouse( wxMouseEvent &event )
243 {
244  PLGraphicsIn graphicsIn;
245  wxPoint cursorPosition = event.GetPosition();
246  wxSize clientSize = WXWINDOW::GetClientSize();
247 
248  graphicsIn.pX = cursorPosition.x;
249  graphicsIn.pY = cursorPosition.y;
250  graphicsIn.dX = PLFLT( cursorPosition.x + 0.5 ) / PLFLT( clientSize.GetWidth() );
251  graphicsIn.dY = 1.0 - PLFLT( cursorPosition.y + 0.5 ) / PLFLT( clientSize.GetHeight() );
252  graphicsIn.keysym = 0x20;
253  graphicsIn.state = 0;
254  graphicsIn.subwindow = -1;
255  graphicsIn.type = 0;
256  graphicsIn.string[0] = '\0';
257  if ( event.LeftUp() )
258  {
259  graphicsIn.button = 1;
260  graphicsIn.state |= PL_MASK_BUTTON1;
261  }
262  else if ( event.MiddleUp() )
263  {
264  graphicsIn.button = 2;
265  graphicsIn.state |= PL_MASK_BUTTON2;
266  }
267  else if ( event.RightUp() )
268  {
269  graphicsIn.button = 3;
270  graphicsIn.state |= PL_MASK_BUTTON3;
271  }
272  else if ( event.Aux1Up() )
273  {
274  graphicsIn.button = 4;
275  graphicsIn.state |= PL_MASK_BUTTON4;
276  }
277  else if ( event.Aux2Up() )
278  {
279  graphicsIn.button = 5;
280  graphicsIn.state |= PL_MASK_BUTTON5;
281  }
282  else
283  {
284  //If we get here we have just captured motion
285  //not a click
286  graphicsIn.button = 0;
287  graphicsIn.state = 0;
288  graphicsIn.keysym = 0;
289  }
290 
291  if ( wxGetKeyState( WXK_SHIFT ) )
292  graphicsIn.state |= PL_MASK_SHIFT;
293  if ( wxGetKeyState( WXK_CAPITAL ) )
294  graphicsIn.state |= PL_MASK_CAPS;
295  if ( wxGetKeyState( WXK_ALT ) && wxGetKeyState( WXK_CONTROL ) )
296  graphicsIn.state |= PL_MASK_ALTGR;
297  else if ( wxGetKeyState( WXK_CONTROL ) )
298  graphicsIn.state |= PL_MASK_CONTROL;
299  else if ( wxGetKeyState( WXK_ALT ) )
300  graphicsIn.state |= PL_MASK_ALT;
301  if ( wxGetKeyState( WXK_NUMLOCK ) )
302  graphicsIn.state |= PL_MASK_NUM;
303  if ( wxGetKeyState( WXK_SCROLL ) )
304  graphicsIn.state |= PL_MASK_SCROLL;
305  //Note I can't find a way to catch the windows key
306 
307  if ( IsReady() )
308  m_stream.translatecursor( &graphicsIn );
309  this->OnLocate( graphicsIn );
310 }
311 
314 
315 template<class WXWINDOW>
317 {
318  if ( m_created )
319  {
320  WXWINDOW::Refresh();
321  }
322 }
323 
324 
327 
328 template<class WXWINDOW>
329 bool wxPLplotwindow<WXWINDOW>::SavePlot( const wxString& devname, const wxString& filename )
330 {
331  int pls, pls_save;
332  FILE *sfile;
333 
334  if ( ( sfile = fopen( filename.mb_str(), "wb+" ) ) == NULL )
335  {
336  return false;
337  }
338 
339  plgstrm( &pls );
340  plmkstrm( &pls_save );
341  if ( pls_save < 0 )
342  {
343  fclose( sfile );
344  return false;
345  }
346  plsdev( devname.mb_str() );
347  plsfile( sfile );
348 
349  plspage( 0., 0., 800, 600, 0, 0 );
350  plcpstrm( pls, 0 );
351  pladv( 0 );
352  plreplot();
353  plend1();
354  plsstrm( pls );
355 
356  return true;
357 }
358 
361 
362 template<class WXWINDOW>
363 void wxPLplotwindow<WXWINDOW>::setUseGraphicsContext( bool useGraphicsContext )
364 {
365  wxDC *drawDc;
366 #ifdef wxUSE_GRAPHICS_CONTEXT
367  if ( useGraphicsContext != m_useGraphicsContext )
368  {
369  m_useGraphicsContext = useGraphicsContext;
370  drawDc = m_useGraphicsContext ? (wxDC *) m_gcDc : (wxDC *) m_memoryDc;
371  }
372 #else
373  drawDc = &m_memoryDc;
374  m_useGraphicsContext = false;
375 #endif
376  if ( IsReady() )
377  {
378  m_stream.SetDC( drawDc );
379  RenewPlot();
380  }
381 }
382 
383 template<class WXWINDOW>
384 void wxPLplotwindow<WXWINDOW>::setCanvasColour( const wxColour &colour )
385 {
386  m_canvasColour = colour;
387  RenewPlot();
388 }
389 
390 #endif // !defined( WXPLPLOTWINDOW_H__INCLUDED_ )
#define PL_MASK_BUTTON3
Definition: plplot.h:441
#define plsstrm
Definition: plplot.h:837
#define plspage
Definition: plplot.h:833
virtual void OnLocate(const PLGraphicsIn &graphicsIn)
#define plsdev
Definition: plplot.h:810
PLFLT dX
Definition: plplot.h:454
void setUseGraphicsContext(bool useGraphicsContext)
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:431
#define plend1
Definition: plplot.h:707
bool m_useGraphicsContext
Flag to indicate whether we should use a wxGCDC.
#define plcpstrm
Definition: plplot.h:704
bool m_created
Flag to indicate the window has been Created.
virtual void OnCreate(wxWindowCreateEvent &event)
Window created event.
int type
Definition: plplot.h:447
#define PL_MASK_SCROLL
Definition: plplot.h:438
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:449
wxBitmap m_bitmap
static PLStream * pls[PL_NSTREAMS]
Definition: plcore.h:88
#define PL_MASK_CAPS
Definition: plplot.h:432
wxPLplotstream * GetStream()
Get pointer to wxPLplotstream of this widget.
#define PL_MASK_NUM
Definition: plplot.h:435
PLINT subwindow
Definition: plplot.h:451
#define PL_MASK_BUTTON2
Definition: plplot.h:440
#define plmkstrm
Definition: plplot.h:771
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:442
#define PL_MASK_ALTGR
Definition: plplot.h:436
virtual void OnErase(wxEraseEvent &event)
Background erase event.
#define PL_MASK_ALT
Definition: plplot.h:434
unsigned int state
Definition: plplot.h:448
#define PLPLOT_wxLogDebug(string)
#define PL_MASK_BUTTON1
Definition: plplot.h:439
#define plreplot
Definition: plplot.h:787
unsigned int button
Definition: plplot.h:450
#define PL_MASK_CONTROL
Definition: plplot.h:433
void setCanvasColour(const wxColour &colour)
PLFLT dY
Definition: plplot.h:454
virtual ~wxPLplotwindow(void)
Destructor.
#define pladv
Definition: plplot.h:689
#define plgstrm
Definition: plplot.h:740
char string[PL_MAXKEY]
Definition: plplot.h:452
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:443