PLplot 5.15.0
Loading...
Searching...
No Matches
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.
36template <class WXWINDOW>
37class wxPLplotwindow : public WXWINDOW
38{
39public:
40 wxPLplotwindow( bool useGraphicsContext = true, wxSize clientSize = wxDefaultSize,
41 int resizeRenderDelay_ms = 0 );
42 virtual ~wxPLplotwindow( void );
43
44 void RenewPlot( void );
45 bool SavePlot( const wxString& driver, const wxString& filename );
46 wxPLplotstream* GetStream() { return m_created ? &m_stream : NULL; }
47 void setUseGraphicsContext( bool useGraphicsContext );
48 void setCanvasColour( const wxColour &colour );
49 bool IsReady() { return GetStream() != NULL; }
50
51protected:
52 virtual void OnPaint( wxPaintEvent& event );
53 virtual void OnSize( wxSizeEvent & event );
54 virtual void OnErase( wxEraseEvent &event );
55 virtual void OnCreate( wxWindowCreateEvent &event );
56 void OnRenderTimer( wxTimerEvent &event );
57 void OnMouse( wxMouseEvent &event );
59 bool m_created;
60
61private:
63 wxBitmap m_bitmap;
64 // The memory dc and wrapping gc dc for drawing. Note we
65 //use pointers and reallocate them whenever the bitmap is
66 //resized because reusing either of these causes problems
67 //for rendering on a wxGCDC - at least on Windows.
68 wxMemoryDC *m_memoryDc;
70#ifdef wxUSE_GRAPHICS_CONTEXT
71 wxGCDC *m_gcDc;
72#endif
74 virtual void OnLocate( const PLGraphicsIn &graphicsIn ){}
75
76 //these are to allow delayed repainting on resize. This causes
77 //jerky resizing for large plots
82 static const int ID_RENDERTIMER;
83};
84
85template<class WXWINDOW>
86const int wxPLplotwindow<WXWINDOW>::ID_RENDERTIMER = ::wxNewId();
87
92
93template<class WXWINDOW>
94wxPLplotwindow<WXWINDOW>::wxPLplotwindow( bool useGraphicsContext, wxSize clientSize, int resizeRenderDelay_ms )
95 : m_created( false ), m_initialSize( clientSize ), m_resizing( false ), m_completedFirstRender( false ), m_renderTimer( this, ID_RENDERTIMER ), m_resizeRenderDelay( resizeRenderDelay_ms )
96
97{
98 PLPLOT_wxLogDebug( "wxPLplotwindow::wxPLplotwindow" );
99 m_memoryDc = NULL;
100#ifdef wxUSE_GRAPHICS_CONTEXT
101 m_gcDc = NULL;
102 // Force initialization of m_useGraphicsContext and
103 // drawDc when setUseGraphicsContext is called below.
104 m_useGraphicsContext = !useGraphicsContext;
105#endif
106 setUseGraphicsContext( useGraphicsContext );
107 m_canvasColour = *wxBLACK;
108
109 //We use connect instead of Bind for compatibility with wxWidgets 2.8
110 //but should move to bind in the future.
111 WXWINDOW::Connect( wxEVT_SIZE, wxSizeEventHandler( wxPLplotwindow<WXWINDOW>::OnSize ) );
112 WXWINDOW::Connect( wxEVT_PAINT, wxPaintEventHandler( wxPLplotwindow<WXWINDOW>::OnPaint ) );
113 WXWINDOW::Connect( wxEVT_ERASE_BACKGROUND, wxEraseEventHandler( wxPLplotwindow<WXWINDOW>::OnErase ) );
114 WXWINDOW::Connect( wxEVT_CREATE, wxWindowCreateEventHandler( wxPLplotwindow<WXWINDOW>::OnCreate ) );
115 WXWINDOW::Connect( wxEVT_MOTION, wxMouseEventHandler( wxPLplotwindow<WXWINDOW>::OnMouse ) );
116 WXWINDOW::Connect( wxEVT_LEFT_UP, wxMouseEventHandler( wxPLplotwindow<WXWINDOW>::OnMouse ) );
117 WXWINDOW::Connect( wxEVT_MIDDLE_UP, wxMouseEventHandler( wxPLplotwindow<WXWINDOW>::OnMouse ) );
118 WXWINDOW::Connect( wxEVT_RIGHT_UP, wxMouseEventHandler( wxPLplotwindow<WXWINDOW>::OnMouse ) );
119 WXWINDOW::Connect( ID_RENDERTIMER, wxEVT_TIMER, wxTimerEventHandler( wxPLplotwindow<WXWINDOW>::OnRenderTimer ) );
120}
121
122
125
126template<class WXWINDOW>
128{
129 if ( m_memoryDc )
130 delete m_memoryDc;
131 if ( m_gcDc )
132 delete m_gcDc;
133}
134
140
141template<class WXWINDOW>
142void wxPLplotwindow<WXWINDOW>::OnPaint( wxPaintEvent &WXUNUSED( event ) )
143{
144 //Really this should be in the constructor, but it caused a segfault
145 //on at least one system (CentOS with intel compiler and wxWidgets 2.8.12).
146 //Moving it here after WXWINDOW::Create has been called stops this and
147 //the call does nothing if the style is the same as previous calls so
148 //should be safe to call here.
149 //WXWINDOW::SetBackgroundStyle( wxBG_STYLE_CUSTOM );
150
151 //wxAutoBufferedPaintDC dc( (WXWINDOW*)this );
152 int width = WXWINDOW::GetClientSize().GetWidth();
153 int height = WXWINDOW::GetClientSize().GetHeight();
154
155 wxPaintDC paintDc( this );
156
157 //if we are still resizing (i.e. the useris still messing
158 //with the size) then just fill the invalidated area with
159 //the background colour for now. A full rerender will
160 //happen once the size has stopped changing.
161 if ( m_resizing )
162 {
163 //fill the area with the background colour
164 paintDc.SetBackground( wxBrush( m_canvasColour ) );
165 paintDc.Clear();
166 //also blit on the previous image - it may have
167 //been invalidated, e.g. by shrinking then expanding
168 //the window.
169 paintDc.Blit( 0, 0, width, height, m_memoryDc, 0, 0 );
170
171 return;
172 }
173
174 //resize the plot if needed
175 bool needResize = width != m_bitmap.GetWidth() || height != m_bitmap.GetHeight();
176 if ( needResize )
177 {
178 m_bitmap.Create( width, height, 32 );
179 if ( m_memoryDc )
180 delete m_memoryDc;
181 m_memoryDc = new wxMemoryDC;
182 m_memoryDc->SelectObject( m_bitmap );
183 wxDC *drawDc = m_memoryDc;
184#ifdef wxUSE_GRAPHICS_CONTEXT
185 if ( m_useGraphicsContext )
186 {
187 if ( m_gcDc )
188 delete m_gcDc;
189 m_gcDc = new wxGCDC( *m_memoryDc );
190 drawDc = m_gcDc;
191 }
192#endif
193 if ( IsReady() )
194 m_stream.SetDC( drawDc );
195 drawDc->SetBackground( wxBrush( m_canvasColour ) );
196 drawDc->Clear();
197 if ( IsReady() )
198 m_stream.SetSize( width, height );
199 }
200
201 paintDc.Blit( 0, 0, width, height, m_memoryDc, 0, 0 );
202
203 if ( width > 0 && height > 0 )
204 m_completedFirstRender = true;
205}
206
209
210template<class WXWINDOW>
211void wxPLplotwindow<WXWINDOW>::OnSize( wxSizeEvent& event )
212{
213 //Once the window has been displayed properly for the first time we
214 //want to delay rendering on resize, this ensures that complex plots
215 //don't cause unresponsive or even nearly impossible resizing.
216
217 //Don't delay the first render or if the size hasn't actually
218 //changed (this can be caused by a resize call from PlPlot but
219 //with the size the same).
220 int width = WXWINDOW::GetClientSize().GetWidth();
221 int height = WXWINDOW::GetClientSize().GetHeight();
222 int oldWidth = m_bitmap.IsOk() ? m_bitmap.GetWidth() : 0;
223 int oldHeight = m_bitmap.IsOk() ? m_bitmap.GetHeight() : 0;
224 if ( !m_completedFirstRender || ( m_resizeRenderDelay == 0 ) ||
225 ( width == oldWidth && height == oldHeight ) )
226 {
227 //++m_nResizes;
228 //Invalidate the whole window so it is all redrawn, otherwise only
229 //newly exposed parts of the window get redrawn
230 RenewPlot();
231 return;
232 }
233
234 //If we wish to delay rerendering while the size settles down then
235 //invalidate the newly exposed area and flag that we are still resizing
236 //(this tells OnPaint to just fill the new area with the background
237 //colour), then set up a timer to trigger a proper rerender once the
238 //size has stopped changing.
239 m_resizing = true;
240 if ( width > oldWidth )
241 WXWINDOW::RefreshRect( wxRect( width, 0, width - oldWidth, height ) );
242 if ( height > oldHeight )
243 WXWINDOW::RefreshRect( wxRect( 0, oldHeight, oldWidth, height - oldHeight ) );
244
245 //Start the timer, note that this resets the timer to 0 if it is still running
246 m_renderTimer.Start( m_resizeRenderDelay, true );
247}
248
251
252template<class WXWINDOW>
253void wxPLplotwindow<WXWINDOW>::OnErase( wxEraseEvent& WXUNUSED( event ) )
254{
255 //Do nothing. This stops screen flicker.
256}
257
263
264template<class WXWINDOW>
265void wxPLplotwindow<WXWINDOW>::OnCreate( wxWindowCreateEvent &event )
266{
267 PLPLOT_wxLogDebug( "wxPLplotwindow::OnCreate" );
268 if ( !m_created )
269 {
270 //set the client size if requested
271 if ( m_initialSize != wxDefaultSize )
272 WXWINDOW::SetClientSize( m_initialSize );
273 //create the stream
274 int width = WXWINDOW::GetClientSize().GetWidth();
275 int height = WXWINDOW::GetClientSize().GetHeight();
276 m_bitmap.Create( width, height );
277 if ( m_memoryDc )
278 delete m_memoryDc;
279 m_memoryDc = new wxMemoryDC;
280 m_memoryDc->SelectObject( m_bitmap );
281 wxDC * drawDc = m_memoryDc;
282#ifdef wxUSE_GRAPHICS_CONTEXT
283 if ( m_useGraphicsContext )
284 {
285 if ( m_gcDc )
286 delete m_gcDc;
287 m_gcDc = new wxGCDC( *m_memoryDc );
288 drawDc = m_gcDc;
289 }
290#endif
291 if ( !m_stream.IsValid() )
292 m_stream.Create( drawDc, width, height, wxPLPLOT_DRAW_TEXT );
293 else
294 m_stream.SetDC( drawDc );
295 drawDc->SetBackground( wxBrush( m_canvasColour ) );
296 drawDc->Clear();
297
298 m_created = true;
299 RenewPlot();
300 }
301}
302
303template<class WXWINDOW>
305{
306 if ( m_resizing )
307 {
308 m_resizing = false;
309 RenewPlot();
310 }
311}
312
313//Capture Mouse events and pass the
314template<class WXWINDOW>
315void wxPLplotwindow<WXWINDOW>::OnMouse( wxMouseEvent &event )
316{
317 PLGraphicsIn graphicsIn;
318 wxPoint cursorPosition = event.GetPosition();
319 wxSize clientSize = WXWINDOW::GetClientSize();
320
321 graphicsIn.pX = cursorPosition.x;
322 graphicsIn.pY = cursorPosition.y;
323 graphicsIn.dX = PLFLT( cursorPosition.x + 0.5 ) / PLFLT( clientSize.GetWidth() );
324 graphicsIn.dY = 1.0 - PLFLT( cursorPosition.y + 0.5 ) / PLFLT( clientSize.GetHeight() );
325 graphicsIn.keysym = 0x20;
326 graphicsIn.state = 0;
327 graphicsIn.subwindow = -1;
328 graphicsIn.type = 0;
329 graphicsIn.string[0] = '\0';
330 if ( event.LeftUp() )
331 {
332 graphicsIn.button = 1;
333 graphicsIn.state |= PL_MASK_BUTTON1;
334 }
335 else if ( event.MiddleUp() )
336 {
337 graphicsIn.button = 2;
338 graphicsIn.state |= PL_MASK_BUTTON2;
339 }
340 else if ( event.RightUp() )
341 {
342 graphicsIn.button = 3;
343 graphicsIn.state |= PL_MASK_BUTTON3;
344 }
345 else if ( event.Aux1Up() )
346 {
347 graphicsIn.button = 4;
348 graphicsIn.state |= PL_MASK_BUTTON4;
349 }
350 else if ( event.Aux2Up() )
351 {
352 graphicsIn.button = 5;
353 graphicsIn.state |= PL_MASK_BUTTON5;
354 }
355 else
356 {
357 //If we get here we have just captured motion
358 //not a click
359 graphicsIn.button = 0;
360 graphicsIn.state = 0;
361 graphicsIn.keysym = 0;
362 }
363
364 if ( wxGetKeyState( WXK_SHIFT ) )
365 graphicsIn.state |= PL_MASK_SHIFT;
366 if ( wxGetKeyState( WXK_CAPITAL ) )
367 graphicsIn.state |= PL_MASK_CAPS;
368 if ( wxGetKeyState( WXK_ALT ) && wxGetKeyState( WXK_CONTROL ) )
369 graphicsIn.state |= PL_MASK_ALTGR;
370 else if ( wxGetKeyState( WXK_CONTROL ) )
371 graphicsIn.state |= PL_MASK_CONTROL;
372 else if ( wxGetKeyState( WXK_ALT ) )
373 graphicsIn.state |= PL_MASK_ALT;
374 if ( wxGetKeyState( WXK_NUMLOCK ) )
375 graphicsIn.state |= PL_MASK_NUM;
376 if ( wxGetKeyState( WXK_SCROLL ) )
377 graphicsIn.state |= PL_MASK_SCROLL;
378 //Note I can't find a way to catch the windows key
379
380 if ( IsReady() )
381 m_stream.translatecursor( &graphicsIn );
382 this->OnLocate( graphicsIn );
383}
384
387
388template<class WXWINDOW>
390{
391 if ( m_created )
392 {
393 WXWINDOW::Refresh();
394 }
395}
396
397
400
401template<class WXWINDOW>
402bool wxPLplotwindow<WXWINDOW>::SavePlot( const wxString& devname, const wxString& filename )
403{
404 int pls, pls_save;
405 FILE *sfile;
406
407 if ( ( sfile = fopen( filename.mb_str(), "wb+" ) ) == NULL )
408 {
409 return false;
410 }
411
412 plgstrm( &pls );
413 plmkstrm( &pls_save );
414 if ( pls_save < 0 )
415 {
416 fclose( sfile );
417 return false;
418 }
419 plsdev( devname.mb_str() );
420 plsfile( sfile );
421
422 plspage( 0., 0., 800, 600, 0, 0 );
423 plcpstrm( pls, 0 );
424 pladv( 0 );
425 plreplot();
426 plend1();
427 plsstrm( pls );
428
429 return true;
430}
431
434
435template<class WXWINDOW>
437{
438 wxDC *drawDc;
439#ifdef wxUSE_GRAPHICS_CONTEXT
440 m_useGraphicsContext = useGraphicsContext;
441 drawDc = m_useGraphicsContext ? (wxDC *) m_gcDc : (wxDC *) m_memoryDc;
442#else
443 drawDc = &m_memoryDc;
444 m_useGraphicsContext = false;
445#endif
446 if ( IsReady() )
447 {
448 m_stream.SetDC( drawDc );
449 RenewPlot();
450 }
451}
452
453template<class WXWINDOW>
454void wxPLplotwindow<WXWINDOW>::setCanvasColour( const wxColour &colour )
455{
456 m_canvasColour = colour;
457 RenewPlot();
458}
459
460#endif // !defined( WXPLPLOTWINDOW_H__INCLUDED_ )
wxPLplotstream is inherited from plstream, which is the C++ interface
virtual void OnCreate(wxWindowCreateEvent &event)
Window created event.
wxTimer m_renderTimer
void RenewPlot(void)
Redo plot.
static const int ID_RENDERTIMER
void setUseGraphicsContext(bool useGraphicsContext)
wxPLplotwindow(bool useGraphicsContext=true, wxSize clientSize=wxDefaultSize, int resizeRenderDelay_ms=0)
Constructor.
wxMemoryDC * m_memoryDc
wxPLplotstream m_stream
The wxPLplotstream which belongs to this plot widget.
virtual void OnPaint(wxPaintEvent &event)
Paint event.
wxColour m_canvasColour
wxPLplotstream * GetStream()
Get pointer to wxPLplotstream of this widget.
void setCanvasColour(const wxColour &colour)
virtual void OnSize(wxSizeEvent &event)
Size event.
size_t m_resizeRenderDelay
void OnRenderTimer(wxTimerEvent &event)
Timer used in delayed rendering after resize.
virtual void OnErase(wxEraseEvent &event)
Background erase event.
virtual ~wxPLplotwindow(void)
Destructor.
bool m_completedFirstRender
bool m_created
Flag to indicate the window has been Created.
virtual void OnLocate(const PLGraphicsIn &graphicsIn)
bool SavePlot(const wxString &driver, const wxString &filename)
Save plot using a different driver.
void OnMouse(wxMouseEvent &event)
Mouse events.
bool m_useGraphicsContext
Flag to indicate whether we should use a wxGCDC.
void plsfile(FILE *file)
Definition plcore.c:3802
static PLStream * pls[PL_NSTREAMS]
Definition plcore.h:88
#define plgstrm
Definition plplot.h:744
#define PL_MASK_BUTTON2
Definition plplot.h:428
#define PL_MASK_BUTTON5
Definition plplot.h:431
float PLFLT
Definition plplot.h:163
#define PL_MASK_SHIFT
Definition plplot.h:419
#define PL_MASK_SCROLL
Definition plplot.h:426
#define plsdev
Definition plplot.h:806
#define PL_MASK_BUTTON1
Definition plplot.h:427
#define PL_MASK_BUTTON4
Definition plplot.h:430
#define plspage
Definition plplot.h:831
#define PL_MASK_ALT
Definition plplot.h:422
#define plsstrm
Definition plplot.h:835
#define PL_MASK_NUM
Definition plplot.h:423
#define PL_MASK_CAPS
Definition plplot.h:420
#define plcpstrm
Definition plplot.h:707
#define PL_MASK_ALTGR
Definition plplot.h:424
#define plmkstrm
Definition plplot.h:772
#define PL_MASK_BUTTON3
Definition plplot.h:429
#define pladv
Definition plplot.h:692
#define plend1
Definition plplot.h:710
#define plreplot
Definition plplot.h:788
#define PL_MASK_CONTROL
Definition plplot.h:421
char string[PL_MAXKEY]
Definition plplot.h:440
PLINT subwindow
Definition plplot.h:439
PLFLT dY
Definition plplot.h:442
unsigned int state
Definition plplot.h:436
unsigned int keysym
Definition plplot.h:437
PLFLT dX
Definition plplot.h:442
unsigned int button
Definition plplot.h:438
#define PLPLOT_wxLogDebug(string)
@ wxPLPLOT_DRAW_TEXT