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 );
41  ~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 );
55  bool m_created;
56 
57 private:
59  wxBitmap m_bitmap;
60  // The memory dc and wrapping gc dc for drawing. Note we
61  //use pointers and reallocate them whenever the bitmap is
62  //resized because reusing either of these causes problems
63  //for rendering on a wxGCDC - at least on Windows.
64  wxMemoryDC *m_memoryDc;
65 #ifdef wxUSE_GRAPHICS_CONTEXT
66  wxGCDC *m_gcDc;
67 #endif
68  wxColour m_canvasColour;
69 };
70 
71 
73 // methods with events. The WXWINDOW default constructor is used.
74 //
75 template<class WXWINDOW>
76 wxPLplotwindow<WXWINDOW>::wxPLplotwindow( bool useGraphicsContext )
77  : m_created( false )
78 
79 {
80  m_memoryDc = NULL;
81 #ifdef wxUSE_GRAPHICS_CONTEXT
82  m_gcDc = NULL;
83 #endif
84  setUseGraphicsContext( useGraphicsContext );
85  m_canvasColour = *wxBLACK;
86 
87  //We use connect instead of Bind for compatiblity with wxWidgets 2.8
88  //but should move to bind in the future.
89  WXWINDOW::Connect( wxEVT_SIZE, wxSizeEventHandler( wxPLplotwindow<WXWINDOW>::OnSize ) );
90  WXWINDOW::Connect( wxEVT_PAINT, wxPaintEventHandler( wxPLplotwindow<WXWINDOW>::OnPaint ) );
91  WXWINDOW::Connect( wxEVT_ERASE_BACKGROUND, wxEraseEventHandler( wxPLplotwindow<WXWINDOW>::OnErase ) );
92  WXWINDOW::Connect( wxEVT_CREATE, wxWindowCreateEventHandler( wxPLplotwindow<WXWINDOW>::OnCreate ) );
93  //Bind( wxEVT_SIZE, &wxPLplotwindow<WXWINDOW>::OnSize, this );
94  //Bind( wxEVT_PAINT, &wxPLplotwindow<WXWINDOW>::OnPaint, this );
95 }
96 
97 
99 //
100 template<class WXWINDOW>
102 {
103  if ( m_memoryDc )
104  delete m_memoryDc;
105  if ( m_gcDc )
106  delete m_gcDc;
107 }
108 
109 
111 // later), we also implement our own double buffering here (since the PLplot wxWidgets driver draws
112 // into a wxMemoryDC)
113 //
114 template<class WXWINDOW>
115 void wxPLplotwindow<WXWINDOW>::OnPaint( wxPaintEvent &WXUNUSED( event ) )
116 {
117  //Really this should be in the constructor, but it caused a segfault
118  //on at least one system (CentOS with intel compiler and wxWidgets 2.8.12).
119  //Moving it here after WXWINDOW::Create has been called stops this and
120  //the call does nothing if the style is the same as previous calls so
121  //should be safe to call here.
122  //WXWINDOW::SetBackgroundStyle( wxBG_STYLE_CUSTOM );
123 
124 
125  //wxAutoBufferedPaintDC dc( (WXWINDOW*)this );
126  int width = WXWINDOW::GetClientSize().GetWidth();
127  int height = WXWINDOW::GetClientSize().GetHeight();
128 
129  wxPaintDC paintDc( this );
130 
131  //resize the plot if needed
132  bool needResize = width != m_bitmap.GetWidth() || height != m_bitmap.GetHeight();
133  if ( needResize )
134  {
135  m_bitmap.Create( width, height, 32 );
136  if ( m_memoryDc )
137  delete m_memoryDc;
138  m_memoryDc = new wxMemoryDC;
139  m_memoryDc->SelectObject( m_bitmap );
140  wxDC *drawDc = m_memoryDc;
141 #ifdef wxUSE_GRAPHICS_CONTEXT
142  if ( m_useGraphicsContext )
143  {
144  if ( m_gcDc )
145  delete m_gcDc;
146  m_gcDc = new wxGCDC( *m_memoryDc );
147  drawDc = m_gcDc;
148  }
149 #endif
150  m_stream.SetDC( drawDc );
151  drawDc->SetBackground( wxBrush( m_canvasColour ) );
152  drawDc->Clear();
153  m_stream.SetSize( width, height );
154  }
155 
156  paintDc.Blit( 0, 0, width, height, m_memoryDc, 0, 0 );
157 }
158 
160 //
161 template<class WXWINDOW>
162 void wxPLplotwindow<WXWINDOW>::OnSize( wxSizeEvent& WXUNUSED( event ) )
163 {
164  //Invalidate the whole window so it is all redrawn, otherwise only
165  //newly exposed parts of the window get redrawn
166  RenewPlot();
167 }
168 
170 //
171 template<class WXWINDOW>
172 void wxPLplotwindow<WXWINDOW>::OnErase( wxEraseEvent& WXUNUSED( event ) )
173 {
174  //Do nothing. This stops screen flicker.
175 }
176 
178 // has been called. We note that this has been called to avoid attempting
179 // to redraw a plot on a window that hasn't been created yet.
180 template<class WXWINDOW>
181 void wxPLplotwindow<WXWINDOW>::OnCreate( wxWindowCreateEvent &event )
182 {
183  if ( !m_created )
184  {
185  //create the stream
186  int width = WXWINDOW::GetClientSize().GetWidth();
187  int height = WXWINDOW::GetClientSize().GetHeight();
188  m_bitmap.Create( width, height );
189  if ( m_memoryDc )
190  delete m_memoryDc;
191  m_memoryDc = new wxMemoryDC;
192  m_memoryDc->SelectObject( m_bitmap );
193  wxDC * drawDc = m_memoryDc;
194 #ifdef wxUSE_GRAPHICS_CONTEXT
195  if ( m_useGraphicsContext )
196  {
197  if ( m_gcDc )
198  delete m_gcDc;
199  m_gcDc = new wxGCDC( *m_memoryDc );
200  drawDc = m_gcDc;
201  }
202 #endif
203  if ( !m_stream.IsValid() )
204  m_stream.Create( drawDc, width, height, wxPLPLOT_DRAW_TEXT );
205  else
206  m_stream.SetDC( drawDc );
207  drawDc->SetBackground( wxBrush( m_canvasColour ) );
208  drawDc->Clear();
209 
210  m_created = true;
211  RenewPlot();
212  }
213 }
214 
215 
217 //
218 template<class WXWINDOW>
220 {
221  if ( m_created )
222  {
223  WXWINDOW::Refresh();
224  }
225 }
226 
227 
229 //
230 template<class WXWINDOW>
231 bool wxPLplotwindow<WXWINDOW>::SavePlot( const wxString& devname, const wxString& filename )
232 {
233  int pls, pls_save;
234  FILE *sfile;
235 
236  if ( ( sfile = fopen( filename.mb_str(), "wb+" ) ) == NULL )
237  {
238  return false;
239  }
240 
241  plgstrm( &pls );
242  plmkstrm( &pls_save );
243  if ( pls_save < 0 )
244  {
245  fclose( sfile );
246  return false;
247  }
248  plsdev( devname.mb_str() );
249  plsfile( sfile );
250 
251  plspage( 0., 0., 800, 600, 0, 0 );
252  plcpstrm( pls, 0 );
253  pladv( 0 );
254  plreplot();
255  plend1();
256  plsstrm( pls );
257 
258  return true;
259 }
260 
262 template<class WXWINDOW>
263 void wxPLplotwindow<WXWINDOW>::setUseGraphicsContext( bool useGraphicsContext )
264 {
265  wxDC *drawDc;
266 #ifdef wxUSE_GRAPHICS_CONTEXT
267  if ( useGraphicsContext != m_useGraphicsContext )
268  {
269  m_useGraphicsContext = useGraphicsContext;
270  drawDc = m_useGraphicsContext ? (wxDC *) m_gcDc : (wxDC *) m_memoryDc;
271  }
272 #else
273  drawDc = &m_memoryDc;
274  m_useGraphicsContext = false;
275 #endif
276  if ( m_created )
277  {
278  m_stream.SetDC( drawDc );
279  RenewPlot();
280  }
281 }
282 
283 template<class WXWINDOW>
284 void wxPLplotwindow<WXWINDOW>::setCanvasColour( const wxColour &colour )
285 {
286  m_canvasColour = colour;
287  RenewPlot();
288 }
289 
290 #endif // !defined( WXPLPLOTWINDOW_H__INCLUDED_ )