PLplot  5.12.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 
77 // methods with events. The WXWINDOW default constructor is used.
78 //
79 template<class WXWINDOW>
80 wxPLplotwindow<WXWINDOW>::wxPLplotwindow( bool useGraphicsContext, wxSize clientSize )
81  : m_created( false ), m_initialSize( clientSize )
82 
83 {
84  PLPLOT_wxLogDebug( "wxPLplotwindow::wxPLplotwindow" );
85  m_memoryDc = NULL;
86 #ifdef wxUSE_GRAPHICS_CONTEXT
87  m_gcDc = NULL;
88 #endif
89  setUseGraphicsContext( useGraphicsContext );
90  m_canvasColour = *wxBLACK;
91 
92  //We use connect instead of Bind for compatiblity with wxWidgets 2.8
93  //but should move to bind in the future.
94  WXWINDOW::Connect( wxEVT_SIZE, wxSizeEventHandler( wxPLplotwindow<WXWINDOW>::OnSize ) );
95  WXWINDOW::Connect( wxEVT_PAINT, wxPaintEventHandler( wxPLplotwindow<WXWINDOW>::OnPaint ) );
96  WXWINDOW::Connect( wxEVT_ERASE_BACKGROUND, wxEraseEventHandler( wxPLplotwindow<WXWINDOW>::OnErase ) );
97  WXWINDOW::Connect( wxEVT_CREATE, wxWindowCreateEventHandler( wxPLplotwindow<WXWINDOW>::OnCreate ) );
98  WXWINDOW::Connect( wxEVT_MOTION, wxMouseEventHandler( wxPLplotwindow<WXWINDOW>::OnMouse ) );
99  WXWINDOW::Connect( wxEVT_LEFT_UP, wxMouseEventHandler( wxPLplotwindow<WXWINDOW>::OnMouse ) );
100  WXWINDOW::Connect( wxEVT_MIDDLE_UP, wxMouseEventHandler( wxPLplotwindow<WXWINDOW>::OnMouse ) );
101  WXWINDOW::Connect( wxEVT_RIGHT_UP, wxMouseEventHandler( wxPLplotwindow<WXWINDOW>::OnMouse ) );
102 }
103 
104 
106 //
107 template<class WXWINDOW>
109 {
110  if ( m_memoryDc )
111  delete m_memoryDc;
112  if ( m_gcDc )
113  delete m_gcDc;
114 }
115 
117 // later), we also implement our own double buffering here (since the PLplot wxWidgets driver draws
118 // into a wxMemoryDC)
119 //
120 template<class WXWINDOW>
121 void wxPLplotwindow<WXWINDOW>::OnPaint( wxPaintEvent &WXUNUSED( event ) )
122 {
123  //Really this should be in the constructor, but it caused a segfault
124  //on at least one system (CentOS with intel compiler and wxWidgets 2.8.12).
125  //Moving it here after WXWINDOW::Create has been called stops this and
126  //the call does nothing if the style is the same as previous calls so
127  //should be safe to call here.
128  //WXWINDOW::SetBackgroundStyle( wxBG_STYLE_CUSTOM );
129 
130 
131  //wxAutoBufferedPaintDC dc( (WXWINDOW*)this );
132  int width = WXWINDOW::GetClientSize().GetWidth();
133  int height = WXWINDOW::GetClientSize().GetHeight();
134 
135  wxPaintDC paintDc( this );
136 
137  //resize the plot if needed
138  bool needResize = width != m_bitmap.GetWidth() || height != m_bitmap.GetHeight();
139  if ( needResize )
140  {
141  m_bitmap.Create( width, height, 32 );
142  if ( m_memoryDc )
143  delete m_memoryDc;
144  m_memoryDc = new wxMemoryDC;
145  m_memoryDc->SelectObject( m_bitmap );
146  wxDC *drawDc = m_memoryDc;
147 #ifdef wxUSE_GRAPHICS_CONTEXT
148  if ( m_useGraphicsContext )
149  {
150  if ( m_gcDc )
151  delete m_gcDc;
152  m_gcDc = new wxGCDC( *m_memoryDc );
153  drawDc = m_gcDc;
154  }
155 #endif
156  if ( IsReady() )
157  m_stream.SetDC( drawDc );
158  drawDc->SetBackground( wxBrush( m_canvasColour ) );
159  drawDc->Clear();
160  if ( IsReady() )
161  m_stream.SetSize( width, height );
162  }
163 
164  paintDc.Blit( 0, 0, width, height, m_memoryDc, 0, 0 );
165 }
166 
168 //
169 template<class WXWINDOW>
170 void wxPLplotwindow<WXWINDOW>::OnSize( wxSizeEvent& WXUNUSED( event ) )
171 {
172  //Invalidate the whole window so it is all redrawn, otherwise only
173  //newly exposed parts of the window get redrawn
174  RenewPlot();
175 }
176 
178 //
179 template<class WXWINDOW>
180 void wxPLplotwindow<WXWINDOW>::OnErase( wxEraseEvent& WXUNUSED( event ) )
181 {
182  //Do nothing. This stops screen flicker.
183 }
184 
186 // has been called. We note that this has been called to avoid attempting
187 // to redraw a plot on a window that hasn't been created yet.
188 template<class WXWINDOW>
189 void wxPLplotwindow<WXWINDOW>::OnCreate( wxWindowCreateEvent &event )
190 {
191  PLPLOT_wxLogDebug( "wxPLplotwindow::OnCreate" );
192  if ( !m_created )
193  {
194  //set the client size if requested
195  if ( m_initialSize != wxDefaultSize )
196  WXWINDOW::SetClientSize( m_initialSize );
197  //create the stream
198  int width = WXWINDOW::GetClientSize().GetWidth();
199  int height = WXWINDOW::GetClientSize().GetHeight();
200  m_bitmap.Create( width, height );
201  if ( m_memoryDc )
202  delete m_memoryDc;
203  m_memoryDc = new wxMemoryDC;
204  m_memoryDc->SelectObject( m_bitmap );
205  wxDC * drawDc = m_memoryDc;
206 #ifdef wxUSE_GRAPHICS_CONTEXT
207  if ( m_useGraphicsContext )
208  {
209  if ( m_gcDc )
210  delete m_gcDc;
211  m_gcDc = new wxGCDC( *m_memoryDc );
212  drawDc = m_gcDc;
213  }
214 #endif
215  if ( !m_stream.IsValid() )
216  m_stream.Create( drawDc, width, height, wxPLPLOT_DRAW_TEXT );
217  else
218  m_stream.SetDC( drawDc );
219  drawDc->SetBackground( wxBrush( m_canvasColour ) );
220  drawDc->Clear();
221 
222  m_created = true;
223  RenewPlot();
224  }
225 }
226 
227 //Capture Mouse events and pass the
228 template<class WXWINDOW>
229 void wxPLplotwindow<WXWINDOW>::OnMouse( wxMouseEvent &event )
230 {
231  PLGraphicsIn graphicsIn;
232  wxPoint cursorPosition = event.GetPosition();
233  wxSize clientSize = WXWINDOW::GetClientSize();
234 
235  graphicsIn.pX = cursorPosition.x;
236  graphicsIn.pY = cursorPosition.y;
237  graphicsIn.dX = PLFLT( cursorPosition.x + 0.5 ) / PLFLT( clientSize.GetWidth() );
238  graphicsIn.dY = 1.0 - PLFLT( cursorPosition.y + 0.5 ) / PLFLT( clientSize.GetHeight() );
239  graphicsIn.keysym = 0x20;
240  graphicsIn.state = 0;
241  graphicsIn.subwindow = -1;
242  graphicsIn.type = 0;
243  graphicsIn.string[0] = '\0';
244  if ( event.LeftUp() )
245  {
246  graphicsIn.button = 1;
247  graphicsIn.state |= PL_MASK_BUTTON1;
248  }
249  else if ( event.MiddleUp() )
250  {
251  graphicsIn.button = 2;
252  graphicsIn.state |= PL_MASK_BUTTON2;
253  }
254  else if ( event.RightUp() )
255  {
256  graphicsIn.button = 3;
257  graphicsIn.state |= PL_MASK_BUTTON3;
258  }
259  else if ( event.Aux1Up() )
260  {
261  graphicsIn.button = 4;
262  graphicsIn.state |= PL_MASK_BUTTON4;
263  }
264  else if ( event.Aux2Up() )
265  {
266  graphicsIn.button = 5;
267  graphicsIn.state |= PL_MASK_BUTTON5;
268  }
269  else
270  {
271  //If we get here we have just captured motion
272  //not a click
273  graphicsIn.button = 0;
274  graphicsIn.state = 0;
275  graphicsIn.keysym = 0;
276  }
277 
278  if ( wxGetKeyState( WXK_SHIFT ) )
279  graphicsIn.state |= PL_MASK_SHIFT;
280  if ( wxGetKeyState( WXK_CAPITAL ) )
281  graphicsIn.state |= PL_MASK_CAPS;
282  if ( wxGetKeyState( WXK_ALT ) && wxGetKeyState( WXK_CONTROL ) )
283  graphicsIn.state |= PL_MASK_ALTGR;
284  else if ( wxGetKeyState( WXK_CONTROL ) )
285  graphicsIn.state |= PL_MASK_CONTROL;
286  else if ( wxGetKeyState( WXK_ALT ) )
287  graphicsIn.state |= PL_MASK_ALT;
288  if ( wxGetKeyState( WXK_NUMLOCK ) )
289  graphicsIn.state |= PL_MASK_NUM;
290  if ( wxGetKeyState( WXK_SCROLL ) )
291  graphicsIn.state |= PL_MASK_SCROLL;
292  //Note I can't find a way to catch the windows key
293 
294  if ( IsReady() )
295  m_stream.translatecursor( &graphicsIn );
296  this->OnLocate( graphicsIn );
297 }
298 
300 //
301 template<class WXWINDOW>
303 {
304  if ( m_created )
305  {
306  WXWINDOW::Refresh();
307  }
308 }
309 
310 
312 //
313 template<class WXWINDOW>
314 bool wxPLplotwindow<WXWINDOW>::SavePlot( const wxString& devname, const wxString& filename )
315 {
316  int pls, pls_save;
317  FILE *sfile;
318 
319  if ( ( sfile = fopen( filename.mb_str(), "wb+" ) ) == NULL )
320  {
321  return false;
322  }
323 
324  plgstrm( &pls );
325  plmkstrm( &pls_save );
326  if ( pls_save < 0 )
327  {
328  fclose( sfile );
329  return false;
330  }
331  plsdev( devname.mb_str() );
332  plsfile( sfile );
333 
334  plspage( 0., 0., 800, 600, 0, 0 );
335  plcpstrm( pls, 0 );
336  pladv( 0 );
337  plreplot();
338  plend1();
339  plsstrm( pls );
340 
341  return true;
342 }
343 
345 template<class WXWINDOW>
346 void wxPLplotwindow<WXWINDOW>::setUseGraphicsContext( bool useGraphicsContext )
347 {
348  wxDC *drawDc;
349 #ifdef wxUSE_GRAPHICS_CONTEXT
350  if ( useGraphicsContext != m_useGraphicsContext )
351  {
352  m_useGraphicsContext = useGraphicsContext;
353  drawDc = m_useGraphicsContext ? (wxDC *) m_gcDc : (wxDC *) m_memoryDc;
354  }
355 #else
356  drawDc = &m_memoryDc;
357  m_useGraphicsContext = false;
358 #endif
359  if ( IsReady() )
360  {
361  m_stream.SetDC( drawDc );
362  RenewPlot();
363  }
364 }
365 
366 template<class WXWINDOW>
367 void wxPLplotwindow<WXWINDOW>::setCanvasColour( const wxColour &colour )
368 {
369  m_canvasColour = colour;
370  RenewPlot();
371 }
372 
373 #endif // !defined( WXPLPLOTWINDOW_H__INCLUDED_ )
#define PL_MASK_BUTTON3
Definition: plplot.h:440
#define plsstrm
Definition: plplot.h:836
#define plspage
Definition: plplot.h:832
virtual void OnLocate(const PLGraphicsIn &graphicsIn)
#define plsdev
Definition: plplot.h:809
PLFLT dX
Definition: plplot.h:453
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:430
#define plend1
Definition: plplot.h:706
bool m_useGraphicsContext
Flag to indicate whether we should use a wxGCDC.
#define plcpstrm
Definition: plplot.h:703
bool m_created
Flag to indicate the window has been Created.
virtual void OnCreate(wxWindowCreateEvent &event)
Window created event.
int type
Definition: plplot.h:446
#define PL_MASK_SCROLL
Definition: plplot.h:437
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:448
wxBitmap m_bitmap
static PLStream * pls[PL_NSTREAMS]
Definition: plcore.h:88
#define PL_MASK_CAPS
Definition: plplot.h:431
wxPLplotstream * GetStream()
Get pointer to wxPLplotstream of this widget.
#define PL_MASK_NUM
Definition: plplot.h:434
PLINT subwindow
Definition: plplot.h:450
#define PL_MASK_BUTTON2
Definition: plplot.h:439
#define plmkstrm
Definition: plplot.h:770
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:441
#define PL_MASK_ALTGR
Definition: plplot.h:435
virtual void OnErase(wxEraseEvent &event)
Background erase event.
#define PL_MASK_ALT
Definition: plplot.h:433
unsigned int state
Definition: plplot.h:447
#define PLPLOT_wxLogDebug(string)
#define PL_MASK_BUTTON1
Definition: plplot.h:438
#define plreplot
Definition: plplot.h:786
unsigned int button
Definition: plplot.h:449
#define PL_MASK_CONTROL
Definition: plplot.h:432
void setCanvasColour(const wxColour &colour)
PLFLT dY
Definition: plplot.h:453
virtual ~wxPLplotwindow(void)
Destructor.
#define pladv
Definition: plplot.h:688
#define plgstrm
Definition: plplot.h:739
char string[PL_MAXKEY]
Definition: plplot.h:451
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:442