wxArt2D
cansim.cpp
Go to the documentation of this file.
1 /*! \file canvas/src/cansim.cpp
2  \author Klaas Holwerda
3 
4  Copyright: 2001-2004 (C) Klaas Holwerda
5 
6  Licence: wxWidgets Licence
7 
8  RCS-ID: $Id: cansim.cpp,v 1.34 2008/08/01 18:32:29 titato Exp $
9 */
10 
11 #include "a2dprec.h"
12 
13 #ifdef __BORLANDC__
14 #pragma hdrstop
15 #endif
16 
17 #ifndef WX_PRECOMP
18 #include "wx/wx.h"
19 #endif
20 
21 #include "wx/canvas/cansim.h"
22 #include "wx/canvas/tools.h"
23 #include "wx/artbase/dcdrawer.h"
24 
25 #include <wx/wfstream.h>
26 
27 
28 //----------------------------------------------------------------------------
29 // globals
30 //----------------------------------------------------------------------------
31 
32 #define WIDTHSCROLLBAR 20
33 
34 //----------------------------------------------------------------------------
35 // a2dCanvas
36 //----------------------------------------------------------------------------
37 
38 //! drawer is actually m_view of base class, only specialized
39 
40 IMPLEMENT_CLASS( a2dCanvasSim, wxScrolledWindow )
41 
42 BEGIN_EVENT_TABLE( a2dCanvasSim, wxScrolledWindow )
43  EVT_PAINT( a2dCanvasSim::OnPaint )
44  EVT_ERASE_BACKGROUND( a2dCanvasSim::OnEraseBackground )
45  EVT_SIZE( a2dCanvasSim::OnSize )
46 END_EVENT_TABLE()
47 
48 
49 a2dCanvasSim::a2dCanvasSim( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ):
50  wxScrolledWindow( parent, id, pos, size, style )
51 {
52  m_border = 0;
53  m_delta = 100;
54 
55  int dvx = size.GetWidth();
56  int dvy = size.GetHeight();
57 
58  if ( size == wxDefaultSize )
59  {
60  dvx = 1000;
61  dvy = 1000;
62  }
63  else
64  GetClientSize( &dvx, &dvy ); //this will be visible width and height in world coordinates
65 
66  m_drawing = new a2dDrawing();
67 
68  m_drawingPart = new a2dDrawingPart( dvx, dvy );
69  m_drawingPart->SetDisplayWindow( this );
70  a2dCanvasGlobals->SetActiveDrawingPart( m_drawingPart );
71  m_drawingPart->SetShowObject( m_drawing->GetRootObject() );
72 
73  m_frozen = false;
74 }
75 
76 a2dDrawing* a2dCanvasSim::GetDrawing() const
77 {
78  if ( m_drawingPart )
79  return m_drawingPart->GetDrawing();
80  return NULL;
81 }
82 
83 void a2dCanvasSim::SetDrawingPart( a2dDrawingPart* drawingPart )
84 {
85  int w, h;
86  if ( m_drawingPart )
87  {
88  w = m_drawingPart->GetDrawer2D()->GetWidth();
89  h = m_drawingPart->GetDrawer2D()->GetHeight();
90  }
91  else
92  {
93  GetClientSize( &w, &h );
94  }
95 
96  m_drawingPart = drawingPart;
97 
98  if ( m_drawingPart )
99  {
100  m_drawingPart->SetBufferSize( w, h );
101  m_drawingPart->Update( a2dCANVIEW_UPDATE_ALL );
102  Enable();
103  }
104 }
105 
107 {
108  SetBackgroundColour( m_drawingPart->GetBackgroundFill().GetColour() );
109 
110  wxWindow::ClearBackground();
111 }
112 
113 void a2dCanvasSim::Refresh( bool eraseBackground, const wxRect* rect )
114 {
115  if ( m_drawingPart && !rect )
116  {
117  m_drawingPart->Update( a2dCANVIEW_UPDATE_ALL );
118  }
119  wxWindow::Refresh( eraseBackground, rect );
120 }
121 
123 {
124  m_drawingPart = NULL;
125  m_drawing = NULL;
126 }
127 
129 {
130  if ( !m_drawingPart )
131  return NULL;
132  return m_drawingPart->SetShowObject( name );
133 }
134 
136 {
137  if ( !m_drawingPart )
138  return false;
139  return m_drawingPart->SetShowObject( obj );
140 }
141 
142 void a2dCanvasSim::SetBackgroundFill( const a2dFill& backgroundfill )
143 {
144  if ( !m_drawingPart )
145  return;
146  m_drawingPart->SetBackgroundFill( backgroundfill );
147  m_drawingPart->Update( a2dCANVIEW_UPDATE_ALL );
148 }
149 
151 {
152  if ( !m_drawingPart )
153  return true;
154  return GetDrawer2D()->GetYaxis();
155 }
156 
158 {
159  wxWindow::Freeze();
160  m_frozen = true;
161 }
162 
164 {
165  wxWindow::Thaw();
166  m_frozen = false;
167 }
168 
169 void a2dCanvasSim::OnPaint( wxPaintEvent& WXUNUSED( event ) )
170 {
171  wxPaintDC dc( this ); //needed to prevent looping
172 
173  // extra wxDC's are created, so we use CalcUnscrolledPosition() instead.
174  //DoPrepareDC(dc);
175 
176  if ( !m_drawingPart )
177  {
178  return;
179  }
180 
181  if ( m_drawingPart->IsFrozen() ) return;
182 
183  //TODOif (!GetDrawer2D()->GetBuffer()->Ok()) return;
184 
185  //first redraw/update that were not yet updated pending areas (if available)
186  //with the magic flag wxNO_FULL_REPAINT_ON_RESIZE blitting
187  //also what is in the blitting list is not usefull
188  //because Onpaint ignores blits outside the rectangles
189  //that it finds damaged, therefore no blit flag for blitting areas.
190  //This is done in idle time.
191 
192  //Mind that Onpaint events received from the m_drawingPart is done with that eventhandler of that specific view disabled, else
193  // the event would directly loop back to that view.
194  //So we enable the event handler here temporarely if needed, in order to get the update event handled.
195  bool eventHandlerEnabledState = m_drawingPart->GetEvtHandlerEnabled();
196  if ( !eventHandlerEnabledState )
197  m_drawingPart->SetEvtHandlerEnabled( true );
198 
199  // now sent the update event
200  //Onpaint events are always coming trough even if OnIdle events are not, for batch redraw etc. we make sure that all pending
201  //areas or first redrawn in the buffer
202  m_drawingPart->Update( a2dCANVIEW_UPDATE_AREAS );
203 
204  //restore state
205  m_drawingPart->SetEvtHandlerEnabled( eventHandlerEnabledState );
206 
207  //ininiate the wxDc's etc. in a2dCanvasView.
208  GetDrawer2D()->BeginDraw();
209 
210  //get the regions to update and add to the list
211  //of areas that need to be blitted
212  wxRegionIterator it( GetUpdateRegion() );
213  while ( it )
214  {
215  int x = it.GetX();
216  int y = it.GetY();
217 
218  int w = it.GetWidth();
219  int h = it.GetHeight();
220 
221  int xx;
222  int yy;
223  CalcUnscrolledPosition( x, y, &xx, &yy );
224  GetDrawer2D()->BlitBuffer( xx, yy, w, h );
225 
226  it++;
227  }
228  GetDrawer2D()->EndDraw();
229 }
230 
232 {
233  if ( !m_drawingPart )
234  return;
235 
236  m_drawingPart->SetMouseEvents( onoff );
237 }
238 
239 void a2dCanvasSim::OnEraseBackground( wxEraseEvent& WXUNUSED( event ) )
240 {
241 }
242 
244  double x, double y,
245  int layer,
246  a2dHitOption option
247 )
248 {
249  if ( !m_drawingPart )
250  return NULL;
251  return m_drawingPart->IsHitWorld( x, y, layer, option );
252 }
253 
254 bool a2dCanvasSim::WriteSVG( const wxString& filename, double Width, double Height, wxString unit )
255 {
256  if ( !m_drawingPart || !GetDrawer2D() )
257  return false;
258 
259  //to make sure
260  return false;//m_drawingPart->GetCanvasDocument()->WriteSVG( m_drawingPart, filename, m_drawingPart->GetShowObject(), Width, Height, unit );
261 }
262 
263 void a2dCanvasSim::SetMappingWidthHeight( double vx1, double vy1, double width, double height )
264 {
265  int dxn, dyn;
266  GetVirtualSize( &dxn, &dyn );
267 
268  if ( dxn == 0 ) dxn = 1000;
269  if ( dyn == 0 ) dyn = 1000;
270 
271  double xupp = width / dxn;
272  double yupp = height / dyn;
273 
274  if ( yupp == 0 || xupp == 0 ) //no drawing at all
275  {
276  yupp = 1; xupp = 1; //some value
277  }
278 
279  if ( yupp > xupp )
280  SetMappingUpp( vx1, vy1, yupp, yupp );
281  else
282  SetMappingUpp( vx1, vy1, xupp, xupp );
283 }
284 
285 // maps the virtual window (Real drawing to the window coordinates
286 // also used for zooming
287 void a2dCanvasSim::SetMappingUpp( double vx1, double vy1, double xpp, double ypp )
288 {
289  if ( !m_drawingPart || !GetDrawer2D() )
290  return;
291 
292  int dxn, dyn;
293  GetVirtualSize( &dxn, &dyn );
294 
295  if ( dxn == 0 ) dxn = 1000;
296  if ( dyn == 0 ) dyn = 1000;
297 
298  GetDrawer2D()->SetMappingDeviceRect( 0, 0, dxn, dyn );
299  GetDrawer2D()->SetMappingUpp( vx1, vy1, xpp, ypp );
300 }
301 
302 void a2dCanvasSim::SetYaxis( bool up )
303 {
304  if ( !m_drawingPart || !GetDrawer2D() )
305  return;
306 
307  GetDrawer2D()->SetYaxis( up );
308 
309  m_drawingPart->Update( a2dCANVIEW_UPDATE_ALL );
310 }
311 
312 bool a2dCanvasSim::GetMouseEvents()
313 {
314  if ( !m_drawingPart || !GetDrawer2D() )
315  return false;
316 
317  return m_drawingPart->GetMouseEvents();
318 }
319 
320 
321 void a2dCanvasSim::OnSize( wxSizeEvent& WXUNUSED( event ) )
322 {
323  if ( !m_drawingPart )
324  return;
325 
326  if ( !GetDrawer2D() )
327  return;
328 
329  //TRICKS!
330  //The buffer is a little bigger then the clientsize.
331  //This is for two reasons.
332  //1- A small resize on the window does not result in redrawing
333  //everything.
334  //1- To be able to ignore onsize events when only scrollbars (dis)appear
335  //which also would cause a redraw here
336 
337  int oldw = GetDrawer2D()->GetBuffer().GetWidth();
338  int oldh = GetDrawer2D()->GetBuffer().GetHeight();
339 
340  int w, h;
341 
342  GetVirtualSize( &w, &h );
343 
344  //the client size may be with are without scrollbars
345  //always draw to a buffer that is inclusif scrollbars
346  w = w + WIDTHSCROLLBAR + m_delta;
347  h = h + WIDTHSCROLLBAR + m_delta;
348 
349  if ( abs( oldw - w ) > m_delta || abs( oldh - h ) > m_delta )
350  {
351  //first redraw/update that were not yet updated pending areas (if available)
352  //blit pending updates to the window/screen
354 
355  m_drawingPart->SetBufferSize( w, h );
356 
357  //only redraw/repaint what was added, so if smaller
358  //do nothing else update only the new areas
359 
360  if ( GetDrawer2D()->GetYaxis() )
361  {
362  if ( oldw < w )
363  m_drawingPart->AddPendingUpdateArea( oldw, 0, w - oldw, h );
364  if ( oldh < h )
365  m_drawingPart->AddPendingUpdateArea( 0, oldh, w, h - oldh );
366  }
367  else
368  {
369  if ( oldw < w )
370  m_drawingPart->AddPendingUpdateArea( oldw, 0, w - oldw, h );
371  if ( oldh < h )
372  m_drawingPart->AddPendingUpdateArea( 0, oldh, w, h - oldh );
373  }
374  }
376 }
377 
379 {
380  if ( !m_drawingPart || !GetDrawer2D() )
381  return;
382 
383  if ( !GetShowObject() )
384  return;
385 
386  m_drawingPart->Update( a2dCANVIEW_UPDATE_OLDNEW );
389  cworld.Invert();
390  untr.MapBbox( cworld );
391 
392  double w = untr.GetWidth();
393  double h = untr.GetHeight();
394 
395  if ( w == 0 )
396  w = 1000;
397  if ( h == 0 )
398  h = 1000;
399 
400  double uppx, uppy;
401  int clientw, clienth;
402  GetVirtualSize( &clientw, &clienth );
403 
404  //what is needed in units per pixel to make height of bbox fit.
405  if ( clientw - m_border > 0 )
406  uppx = w / ( clientw - m_border );
407  else
408  uppx = w / clientw;
409 
410  //what is needed in units per pixel to make width of bbox fit.
411  if ( clienth - m_border > 0 )
412  uppy = h / ( clienth - m_border );
413  else
414  uppy = h / clienth;
415 
416  // now take the largets, to make sure it will fit either in x or y
417  if ( uppy > uppx )
418  uppx = uppy;
419 
421  GetDrawer2D()->SetMappingDeviceRect( 0, 0, clientw, clienth );
422 
423  if ( !centre )
424  {
426  untr.GetMinY(),
427  w,
428  h
429  );
430  }
431  else
432  {
433  double middlexworld = untr.GetMinX() + w / 2.0;
434  double middleyworld = untr.GetMinY() + h / 2.0;
435  GetDrawer2D()->SetMappingUpp( middlexworld - clientw / 2.0 * uppx, middleyworld - clienth / 2.0 * uppx, uppx, uppx );
436  }
437 
438  // if scrolling bars were added are removed because of the above, we do it once more.
439  int clientwNew, clienthNew;
440  GetVirtualSize( &clientwNew, &clienthNew );
441  if ( clientw != clientwNew || clienth != clienthNew )
442  {
443  //what is needed in units per pixel to make height of bbox fit.
444  if ( clientw - m_border > 0 )
445  uppx = w / ( clientw - m_border );
446  else
447  uppx = w / clientw;
448 
449  //what is needed in units per pixel to make width of bbox fit.
450  if ( clienth - m_border > 0 )
451  uppy = h / ( clienth - m_border );
452  else
453  uppy = h / clienth;
454 
455  // now take the largets, to make sure it will fit either in x or y
456  if ( uppy > uppx )
457  uppx = uppy;
458 
459  GetDrawer2D()->SetMappingDeviceRect( 0, 0, clientwNew, clienthNew );
460  if ( !centre )
461  {
463  untr.GetMinY(),
464  w,
465  h
466  );
467  }
468  else
469  {
470  double middlexworld = untr.GetMinX() + w / 2.0;
471  double middleyworld = untr.GetMinY() + h / 2.0;
472  GetDrawer2D()->SetMappingUpp( middlexworld - clientwNew / 2.0 * uppx, middleyworld - clienthNew / 2.0 * uppx, uppx, uppx );
473  }
474  }
475 
476  m_drawingPart->Update( a2dCANVIEW_UPDATE_ALL );
478  Refresh();
479 }
void SetMappingUpp(double vx1, double vy1, double xpp, double ypp)
Give the virtual size to be displayed, the mapping matrix will be calculated.
Definition: drawer2d.cpp:250
virtual void SetYaxis(bool up)
set if the Yaxis goes up or down
Definition: drawer2d.cpp:438
Display Part of a a2dDrawing, in which a2dCanvasObjects are shown.
Definition: drawer.h:470
double GetHeight() const
returns height of the boundingbox
Definition: bbox.cpp:334
void EndRefreshDisplayDisable()
see StartRefreshDisplayDisable()
Definition: drawer2d.cpp:204
void SetMappingUpp(double vx1, double vy1, double xpp, double ypp)
Give the virtual size to be displayed, the mappingmatrix will be calculated.
Definition: cansim.cpp:287
void SetYaxis(bool up)
set if the Yaxis goes up or down
Definition: cansim.cpp:302
void OnPaint(wxPaintEvent &event)
repaint damaged araes, taking into acount non updated araes in a2dCanvasView.
Definition: cansim.cpp:169
const a2dAffineMatrix & GetTransformMatrix() const
get the matrix used to position the object
Definition: canobj.h:500
void Thaw()
allow a2dCanvasView buffer to be changed and blitting it to the window
Definition: cansim.cpp:163
bool IsFrozen()
Returns if canvas is frozen.
Definition: drawer.h:928
simple canvas which takes as view the whole of the scrollable area. While a2dCanvas display and draws...
bool WriteSVG(const wxString &filename, double Width, double Height, wxString unit)
write what you see to an SVG( scalable vector graphics file )
Definition: cansim.cpp:254
void SetMappingDeviceRect(int mapx, int mapy, int mapWidth, int mapHeight, bool remap=false)
to change the default mapping (to the complete buffer).
Definition: drawer2d.cpp:216
Simple canvas using a whole view for all of the scrolled window.
Definition: cansim.h:54
void Update(unsigned int how=(a2dCANVIEW_UPDATE_ALL|a2dCANVIEW_UPDATE_BLIT), wxObject *hintObject=NULL)
see OnUpdate
Definition: drawer.cpp:1744
bool GetYaxis() const
get y axis orientation
Definition: drawer2d.h:280
void SetBackgroundFill(const a2dFill &backgroundfill)
background fill for the canvas
Definition: drawer.cpp:3131
a2dCanvasObject is the base class for Canvas Objects.
Definition: canobj.h:371
virtual void SetBufferSize(int w, int h)
sets buffersize ( if used ) for the a2dDrawer2D
Definition: drawer.cpp:755
bool GetMouseEvents() const
return true if this a2dDrawingPart allows mouse events to be processed.
Definition: drawer.h:631
a2dCanvasObject * GetShowObject() const
Definition: cansim.h:272
void ClearBackground()
Clears the canvas (like wxWindow::ClearBackground)
Definition: cansim.cpp:106
void SetMouseEvents(bool onoff)
Definition: cansim.cpp:231
double GetMinX() const
get minimum X of the boundingbox
Definition: bbox.cpp:304
void AddPendingUpdateArea(a2dCanvasObject *obj, wxUint8 id=0, bool refsalso=true)
add pending update for the area that is the boundingbox of the given object
Definition: drawer.cpp:2891
a2dHitOption
Enum for hit test options.
Definition: canobj.h:76
void SetMappingWidthHeight(double vx1, double vy1, double width, double height)
Give the virtual size to be displayed, the mappingmatrix will be calculated.
Definition: cansim.cpp:263
void SetMappingShowAll(bool centre=true)
use the boundingbox of the ShowObject to set the mapping such that it will be displayed completely...
Definition: cansim.cpp:378
int GetHeight() const
get buffer/device height
Definition: drawer2d.h:395
void SetMouseEvents(bool onoff)
If not set do not process mouse events.
Definition: drawer.cpp:1081
void SetActiveDrawingPart(a2dDrawingPart *part)
get the drawing part that has the focus/is active in a window.
Definition: canglob.cpp:1220
Contains graphical drawing context specific classes. a2dDcDrawer and derived classes are used for dra...
a2dDrawer2D * GetDrawer2D()
get the internal m_drawer2D that is used for rendering the document
Definition: drawer.h:1125
a2dCanvasObject * SetShowObject(const wxString &name)
Definition: cansim.cpp:128
A 2x3 affine matrix class for 2D transformations.
Definition: afmatrix.h:53
void SetBackgroundFill(const a2dFill &backgroundfill)
background fill for the canvas
Definition: cansim.cpp:142
bool GetYaxis() const
get currently used Yaxis setting
Definition: cansim.cpp:150
a2dCanvasObject * IsHitWorld(double x, double y, int layer=wxLAYER_ALL, a2dHitOption option=a2dCANOBJHITOPTION_NOROOT|a2dCANOBJHITOPTION_LAYERS)
do a hittest on the canvas at coordinates x,y
Definition: cansim.cpp:243
int GetWidth() const
get buffer/device width
Definition: drawer2d.h:392
void MapBbox(const a2dAffineMatrix &matrix)
Definition: bbox.cpp:445
virtual wxBitmap GetBuffer() const =0
Return the buffer as a bitmap.
virtual void BeginDraw()=0
start to draw on this context (used to initialize a specific drawer)
double GetWidth() const
returns width of the boundingbox
Definition: bbox.cpp:328
a2dCanvasObject * SetShowObject(const wxString &name)
set object available in the a2dDrawing to be shown on the drawer
Definition: drawer.cpp:2947
void StartRefreshDisplayDisable()
when called a mapping change will result not result in a refresh of the m_display.
Definition: drawer2d.h:383
virtual ~a2dCanvasSim()
destructor
Definition: cansim.cpp:122
void BlitBuffer()
blit whole buffer to device
Definition: drawer2d.cpp:183
void Freeze()
prevent changing the a2dCanvasView buffer and blitting it to the window
Definition: cansim.cpp:157
wxColour GetColour() const
return colour
Definition: stylebase.cpp:5012
a2dCanvasObject * IsHitWorld(double x, double y, int layer=wxLAYER_ALL, a2dHitOption option=a2dCANOBJHITOPTION_NONE, bool filterSelectableLayers=false)
do a hittest on the view at coordinates x,y
Definition: drawer.cpp:1565
base classes for tools and controller on top of the tools.
The a2dBoundingBox class stores one a2dBoundingBox of a a2dCanvasObject.
Definition: bbox.h:39
bool Invert(void)
Invert matrix.
Definition: afmatrix.cpp:197
double GetMinY() const
get minimum Y of the boundingbox
Definition: bbox.cpp:310
a2dDrawing * GetDrawing() const
get drawing via top object
Definition: drawer.cpp:726
virtual void EndDraw()=0
end drawing on this context (used to reset a specific drawer)
a2dCanvasGlobal * a2dCanvasGlobals
global a2dCanvasGlobal to have easy access to global settings
Definition: canglob.cpp:1234
void OnEraseBackground(wxEraseEvent &event)
Not yet implemented.
Definition: cansim.cpp:239
a2dDrawer2D * GetDrawer2D() const
Get the drawer of the view.
Definition: cansim.h:101
virtual void Refresh(bool eraseBackground=true, const wxRect *rect=NULL)
Refresh window.
Definition: cansim.cpp:113
a2dFill & GetBackgroundFill()
get current background fill for the canvas
Definition: drawer.h:875
a2dBoundingBox & GetBbox()
get boundingbox in world coordinates exclusive stroke width relative to its parent ...
Definition: canobj.cpp:3175
Contain one drawing as hierarchical tree of a2dCanvasObject&#39;s.
Definition: drawing.h:434
void OnSize(wxSizeEvent &event)
resize, adjusting buffer of a2dCanvasView if needed.
Definition: cansim.cpp:321
cansim.cpp Source File -- Sun Oct 12 2014 17:04:14 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation