wxArt2D
canvas.cpp
Go to the documentation of this file.
1 /*! \file canvas/src/canvas.cpp
2  \author Robert Roebling and Klaas Holwerda
3 
4  Copyright: 2000-2004 (c) Robert Roebling
5 
6  Licence: wxWidgets Licence
7 
8  RCS-ID: $Id: canvas.cpp,v 1.114 2008/10/31 22:43:43 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/canvas.h"
22 #include "wx/artbase/dcdrawer.h"
23 
24 #if wxART2D_USE_AGGDRAWER
25 #include "wx/aggdrawer/aggdrawer.h"
26 #endif
27 //----------------------------------------------------------------------------
28 // globals
29 //----------------------------------------------------------------------------
30 
31 //----------------------------------------------------------------------------
32 // a2dCanvas
33 //----------------------------------------------------------------------------
34 
35 #define MIN_MAPSIZE 10
36 
37 IMPLEMENT_CLASS( a2dCanvas, wxWindow )
38 
39 BEGIN_EVENT_TABLE( a2dCanvas, wxWindow )
40  EVT_PAINT( a2dCanvas::OnPaint )
41  EVT_ERASE_BACKGROUND( a2dCanvas::OnEraseBackground )
42  EVT_SCROLLWIN( a2dCanvas::OnScroll )
43  EVT_CHAR( a2dCanvas::OnChar )
44  EVT_SIZE( a2dCanvas::OnSize )
45  EVT_MOUSEWHEEL( a2dCanvas::OnWheel )
46  EVT_ACTIVATE( a2dCanvas::OnActivate )
47 END_EVENT_TABLE()
48 
49 
50 a2dCanvas::a2dCanvas( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, a2dDrawer2D* drawer2D ):
51  wxWindow( parent, id, pos, size, style | wxWANTS_CHARS )
52 {
53  m_delta = 20;
54  m_wantScroll = false;
55  if ( style & wxVSCROLL || style & wxHSCROLL )
56  m_wantScroll = true;
57 
58  m_inSetScrollMaximum = false;
59  int dvx = size.GetWidth();
60  int dvy = size.GetHeight();
61 
62  if ( size == wxDefaultSize )
63  {
64  dvx = 1000;
65  dvy = 1000;
66  }
67  else
68  GetSaveClientSize( &dvx, &dvy ); //this will be visible width and height in world coordinates
69 
70  m_oversizeX = 0;
71  m_oversizeY = 0;
72 
73  m_drawing = new a2dDrawing();
74 
75  m_drawingPart = new a2dDrawingPart( dvx + m_oversizeX * 2, dvy + m_oversizeY * 2 );
76  m_drawingPart->SetDisplayWindow( this );
77 
78  if ( !drawer2D )
79  drawer2D = new a2dMemDcDrawer( dvx + m_oversizeX * 2, dvy + m_oversizeY * 2 );
80  else
81  drawer2D->SetBufferSize( dvx + m_oversizeX * 2, dvy + m_oversizeY * 2 );
82 
83  m_drawingPart->SetDrawer2D( drawer2D );
84 
85  //make some maximum virtual area for this window, that fits at least the view
86  m_virtm_minX = 0;
87  m_virtm_minY = 0;
88  m_virtm_maxX = drawer2D->GetWidth();
89  if ( m_virtm_maxX == 0 )
90  m_virtm_maxX = 1000;
91  m_virtm_maxY = drawer2D->GetHeight();
92  if ( m_virtm_maxY == 0 )
93  m_virtm_maxY = 1000;
94 
95  Init( dvx, dvy );
96  GetDrawer2D()->SetMappingDeviceRect( m_oversizeX, m_oversizeY, dvx, dvy );
97  m_drawingPart->SetShowObject( m_drawing->GetRootObject() );
98 
99  //following sets m_scrollrangex and m_scrollrangey;
100  //SetScrollStepX(GetDrawer2D()->GetWidth()/10);
101  //SetScrollStepY(GetDrawer2D()->GetHeight()/10);
102 
103  m_drawingPart->Update( a2dCANVIEW_UPDATE_ALL );
104 }
105 
106 a2dCanvas::a2dCanvas( a2dDrawingPart* drawingPart, wxWindow* parent, wxWindowID id,
107  const wxPoint& position, const wxSize& size, long style ) :
108  wxWindow( parent, id, position, size, style | wxWANTS_CHARS )
109 {
110  m_delta = 20;
111  m_wantScroll = false;
112  if ( style & wxVSCROLL || style & wxHSCROLL )
113  m_wantScroll = true;
114 
115  m_inSetScrollMaximum = false;
116  m_drawing = NULL;
117 
118  m_drawingPart = drawingPart;
119  drawingPart->SetDisplayWindow( this );
120  drawingPart->GetDrawer2D()->SetDisplay( this );
121 
122  m_virtm_minX = 0;
123  m_virtm_minY = 0;
124 
125  m_virtm_maxX = size.GetWidth();
126  if ( m_virtm_maxX == 0 )
127  m_virtm_maxX = 1000;
128 
129  m_virtm_maxY = size.GetHeight();
130  if ( m_virtm_maxY == 0 )
131  m_virtm_maxY = 1000;
132 
133  int dvx, dvy;
134  GetSaveClientSize( &dvx, &dvy ); //this will be used for visible width and height in world coordinates
135 
136  m_oversizeX = 0;
137  m_oversizeY = 0;
138 
139  Init( dvx, dvy );
140 
141  //following sets m_scrollrangex and m_scrollrangey;
142  SetScrollStepX( size.GetWidth() / 10 );
143  SetScrollStepY( size.GetHeight() / 10 );
144 
145  m_drawingPart->Update( a2dCANVIEW_UPDATE_ALL );
146 }
147 
148 bool a2dCanvas::ProcessEvent( wxEvent& event )
149 {
150  //some wxViewEvents go upstream ( document -> view -> window -> frame )
151  //These event are of the commandevent type, so they do get processed by the parent window
152  //of this window ( when not processed here ).a
153 
154  // most events will be processed first by the m_drawingPart
155  if ( m_drawingPart &&
156  m_drawingPart->ProcessEvent( event ) )
157  return true;
158 
159  return wxEvtHandler::ProcessEvent( event );
160 }
161 
162 a2dDrawing* a2dCanvas::GetDrawing() const
163 {
164  if ( m_drawingPart )
165  return m_drawingPart->GetDrawing();
166  return NULL;
167 }
168 
169 void a2dCanvas::SetDrawing( a2dDrawing* drawing )
170 {
171  if ( !drawing )
172  {
173  m_drawingPart = NULL;
174  m_drawing = NULL;
175  }
176  else
177  {
178  m_drawingPart->SetShowObject( drawing->GetRootObject() );
179  m_drawing = drawing;
180  }
181 }
182 
183 void a2dCanvas::SetDrawingPart( a2dDrawingPart* drawingPart )
184 {
185  int w, h;
186  if ( m_drawingPart )
187  {
188  w = m_drawingPart->GetDrawer2D()->GetWidth();
189  h = m_drawingPart->GetDrawer2D()->GetHeight();
190  }
191  else
192  {
193  GetSaveClientSize( &w, &h );
194  }
195 
196  m_drawingPart = drawingPart;
197 
198  if ( m_drawingPart )
199  {
200  if ( m_drawingPart->GetDrawing() )
201  a2dCanvasGlobals->SetActiveDrawingPart( m_drawingPart );
202  m_drawingPart->SetBufferSize( w, h );
203  m_drawingPart->Update( a2dCANVIEW_UPDATE_ALL );
204  Enable();
205  }
206 }
207 
208 void a2dCanvas::Init( int dvx, int dvy )
209 {
210  m_normalize = 10000;
211 
213  m_clipToScrollMax = true;
214 
215  double dmvx = m_virtm_maxX - m_virtm_minX; //total scrollable width
216  double dmvy = m_virtm_maxY - m_virtm_minY; //total scrollable height
217 
218  //following sets m_scrollrangex and m_scrollrangey;
219  m_scrollstepx = dmvx / 10; //step to scroll in width
220  m_thumbx = ( int )( dvx / m_scrollstepx * m_normalize ); //thumb is visible size in scroll steps
221  m_scrollrangex = ( int )( dmvx / m_scrollstepx * m_normalize );
222 
223  m_scrollstepy = dmvy / 10; //step to scroll in height
224  m_thumby = ( int ) ( dvy / m_scrollstepy * m_normalize ); //thumb is visible size in scroll steps
225  m_scrollrangey = ( int )( dmvy / m_scrollstepy * m_normalize );
226 
227  m_scaleonresize = false;
228  m_ContinuesSizeUpdate = true;
229 
230  m_scrollmaxfixed = false;
231 
232  m_xscroll_changed = false;
233  m_yscroll_changed = false;
234  m_has_x_scroll = false;
235  m_has_y_scroll = false;
236 
237  m_scrolled = false;
238  m_scrollTrackDraw = true;
239 
240  m_oldw = m_oldh = m_prevh = 0;
241  m_prevClientW = m_prevClientH = 0;
242  if ( m_scaleonresize )
243  m_delta = 20;
244  else
245  m_delta = 100;
246 
247  m_frozen = false;
248 }
249 
250 void a2dCanvas::GetSaveClientSize( int* dvx, int* dvy ) const
251 {
252  GetClientSize( dvx, dvy );
253 
254  if ( *dvx == 0 ) *dvx = MIN_MAPSIZE;
255  if ( *dvy == 0 ) *dvy = MIN_MAPSIZE;
256 }
257 
259 {
260  SetBackgroundColour( m_drawingPart->GetBackgroundFill().GetColour() );
261 
262  wxWindow::ClearBackground();
263 }
264 
265 void a2dCanvas::Refresh( bool eraseBackground, const wxRect* rect )
266 {
267  if ( m_drawingPart && !rect )
268  {
269  m_drawingPart->Update( a2dCANVIEW_UPDATE_ALL );
273  }
274  wxWindow::Refresh( eraseBackground, rect );
275 }
276 
278 {
279  if ( m_drawingPart )
280  {
281  }
282  m_drawingPart = NULL;
283  m_drawing = NULL;
284 }
285 
286 void a2dCanvas::SetBackgroundFill( const a2dFill& backgroundfill )
287 {
288  if ( !m_drawingPart )
289  return;
290  m_drawingPart->SetBackgroundFill( backgroundfill );
291  m_drawingPart->Update( a2dCANVIEW_UPDATE_ALL );
292 }
293 
295 {
296  if ( !m_drawingPart )
297  return NULL;
298  return m_drawingPart->SetShowObject( name );
299 }
300 
302 {
303  if ( !m_drawingPart )
304  return false;
305  return m_drawingPart->SetShowObject( obj );
306 }
307 
309 {
310  m_wantScroll = onoff;
312 }
313 
314 void a2dCanvas::AppendEventHandler( wxEvtHandler* handler )
315 {
316  wxEvtHandler* handlerA = GetEventHandler();
317  while ( handlerA->GetNextHandler() )
318  {
319  handlerA = ( wxEvtHandler* )handlerA->GetNextHandler();
320  }
321  handlerA->SetNextHandler( handler );
322  handler->SetNextHandler( ( wxEvtHandler* )NULL );
323 }
324 
325 wxEvtHandler* a2dCanvas::RemoveLastEventHandler( bool deleteHandler )
326 {
327  //always the first in the row
328  wxEvtHandler* handlerA = GetEventHandler();
329  wxEvtHandler* handlerB = handlerA;
330  //goto the end
331  while ( handlerA->GetNextHandler() )
332  {
333  handlerB = handlerA;
334  handlerA = ( wxEvtHandler* )handlerA->GetNextHandler();
335  }
336 
337  handlerB->SetNextHandler( ( wxEvtHandler* )NULL );
338  if ( deleteHandler )
339  {
340  delete handlerA;
341  }
342 
343  return GetEventHandler();
344 }
345 
347 {
348  if ( !m_drawingPart )
349  return 0;
350  return GetDrawer2D()->GetVisibleMinX();
351 }
352 
354 {
355  if ( !m_drawingPart )
356  return 0;
357  return GetDrawer2D()->GetVisibleMinY();
358 }
359 
360 double a2dCanvas::GetUppX() const
361 {
362  if ( !m_drawingPart )
363  return 1;
364  return GetDrawer2D()->GetUppX();
365 }
366 
367 double a2dCanvas::GetUppY() const
368 {
369  if ( !m_drawingPart )
370  return 1;
371  return GetDrawer2D()->GetUppY();
372 }
373 
375 {
376  int dx, dy;
377  GetSaveClientSize( &dx, &dy );
378  return GetVisibleMinX() + GetUppX() * dx;
379 }
380 
382 {
383  int dx, dy;
384  GetSaveClientSize( &dx, &dy );
385  return GetVisibleMinY() + GetUppY() * dy;
386 }
387 
389 {
390  int dx, dy;
391  GetSaveClientSize( &dx, &dy );
392  return GetUppX() * dx;
393 }
394 
396 {
397  int dx, dy;
398  GetSaveClientSize( &dx, &dy );
399  return GetUppY() * dy;
400 }
401 
403 {
404  if ( !GetDrawer2D() )
405  return true;
406  return GetDrawer2D()->GetYaxis();
407 }
408 
410 {
411  wxWindow::Freeze();
412  m_frozen = true;
413 }
414 
416 {
417  wxWindow::Thaw();
418  m_frozen = false;
419 }
420 
421 void a2dCanvas::OnPaint( wxPaintEvent& WXUNUSED( event ) )
422 {
423  wxPaintDC dc( this ); //needed to prevent looping
424 
425  if ( !m_drawingPart )
426  {
427  return;
428  }
429 
430  if ( m_drawingPart->IsFrozen() ) return;
431 
432  //TODOif (!GetDrawer2D()->GetBuffer()->Ok()) return;
433 
434  //first redraw/update that were not yet updated pending areas (if available)
435  //with the magic flag wxNO_FULL_REPAINT_ON_RESIZE blitting
436  //also what is in the blitting list is not usefull
437  //because Onpaint ignores blits outside the rectangles
438  //that it finds damaged, therefore now blit flag for blitting areas.
439  //This is done in idle time.
440 
441  //Mind that Onpaint events received from the GetCanvasView() is done with that eventhandler of that specific view disabled, else
442  // the event would directly loop back to that view.
443  //So we enable the event handler here temporarely if needed, in order to get the update event handled.
444  bool eventHandlerEnabledState = m_drawingPart->GetEvtHandlerEnabled();
445  if ( !eventHandlerEnabledState )
446  m_drawingPart->SetEvtHandlerEnabled( true );
447 
448  // now sent the update event
449  //Onpaint events are always coming through even if OnIdle events are not, for batch redraw etc. we make sure that all pending
450  //areas are first redrawn in the buffer
451  m_drawingPart->Update( a2dCANVIEW_UPDATE_AREAS );
452 
453  //restore state
454  m_drawingPart->SetEvtHandlerEnabled( eventHandlerEnabledState );
455 
456  //ininiate the wxDc's etc. in a2dCanvasView.
457  GetDrawer2D()->BeginDraw();
458 
459  //get the regions to update and add to the list
460  //of areas that need to be blitted
461  wxRegionIterator it( GetUpdateRegion() );
462  while ( it )
463  {
464  int x = it.GetX();
465  int y = it.GetY();
466 
467  int w = it.GetWidth();
468  int h = it.GetHeight();
469 
470  //this rect is in device coordinates,
471  m_drawingPart->BlitBuffer( x + m_oversizeX, y + m_oversizeY, w, h, m_oversizeX, m_oversizeY );
472 
473  it++;
474  }
475  GetDrawer2D()->EndDraw();
476 }
477 
478 void a2dCanvas::SetMouseEvents( bool onoff )
479 {
480  m_drawingPart->SetMouseEvents( onoff );
481 }
482 
483 void a2dCanvas::OnEraseBackground( wxEraseEvent& WXUNUSED( event ) )
484 {
485  //Update all needed? TODO
486  //m_view->Update( a2dCANVIEW_UPDATE_ALL | a2dCANVIEW_UPDATE_BLIT );
487 }
488 
490  double x, double y,
491  int layer,
492  a2dHitOption option
493 )
494 {
495  return m_drawingPart->IsHitWorld( x, y, layer, option );
496 }
497 
498 bool a2dCanvas::WriteSVG( const wxString& filename, double Width, double Height, wxString unit )
499 {
500  return false;//m_drawingPart->WriteSVG( GetCanvasView(), filename, GetShowObject(), Width, Height, unit );
501 }
502 
503 void a2dCanvas::SetMappingWidthHeight( double vx1, double vy1, double width, double height, bool scrollbars )
504 {
505  int dxn, dyn;
506  GetSaveClientSize( &dxn, &dyn );
507 
508  double xupp = width / dxn;
509  double yupp = height / dyn;
510 
511  if ( yupp == 0 || xupp == 0 ) //no drawing at all
512  {
513  yupp = 1; xupp = 1; //some value
514  }
515 
516  if ( yupp > xupp )
517  {
518  SetMappingUpp( vx1, vy1, yupp, yupp );
519  //scroll region eqaul
520  if ( scrollbars )
521  SetScrollMaximum( vx1, vy1, vx1 + yupp * dyn, vy1 + yupp * dyn );
522  }
523  else
524  {
525  SetMappingUpp( vx1, vy1, xupp, xupp );
526  //scroll region eqaul
527  if ( scrollbars )
528  SetScrollMaximum( vx1, vy1, vx1 + xupp * dxn, vy1 + xupp * dxn );
529  }
530 }
531 
532 // maps the virtual window (Real drawing to the window coordinates
533 // also used for zooming
534 void a2dCanvas::SetMappingUpp( double vx1, double vy1, double xpp, double ypp )
535 {
536  int dxn, dyn;
537  GetSaveClientSize( &dxn, &dyn );
538 
541  GetDrawer2D()->SetMappingUpp( vx1, vy1, xpp, ypp );
542 
545  m_drawingPart->Update( a2dCANVIEW_UPDATE_ALL );
546 }
547 
548 void a2dCanvas::SetMappingShowAll( bool centre )
549 {
550  if ( !GetShowObject() || !GetDrawing() )
551  return;
552 
553  wxUint16 border = m_drawingPart->GetZoomOutBorder();
554  m_drawingPart->Update( a2dCANVIEW_UPDATE_OLDNEW );
557  cworld.Invert();
558  untr.MapBbox( cworld );
559 
560  double w = untr.GetWidth();
561  double h = untr.GetHeight();
562 
563  if ( w == 0 )
564  w = 1000;
565  if ( h == 0 )
566  h = 1000;
567 
568  if ( !m_scrollmaxfixed )
569  SetScrollMaximum( untr.GetMinX(), untr.GetMinY(), untr.GetMinX() + w, untr.GetMinY() + h );
570 
571  double uppx, uppy;
572  int clientw, clienth;
573  GetSaveClientSize( &clientw, &clienth );
574 
575  //what is needed in units per pixel to make height of bbox fit.
576  if ( clientw - border > 0 )
577  uppx = w / ( clientw - border );
578  else
579  uppx = w / clientw;
580 
581  //what is needed in units per pixel to make width of bbox fit.
582  if ( clienth - border > 0 )
583  uppy = h / ( clienth - border );
584  else
585  uppy = h / clienth;
586 
587  // now take the largets, to make sure it will fit either in x or y
588  if ( uppy > uppx )
589  uppx = uppy;
590 
592  GetDrawer2D()->SetMappingDeviceRect( m_oversizeX, m_oversizeY, clientw, clienth, false );
593 
594  if ( !centre )
595  {
597  untr.GetMinY(),
598  w,
599  h,
600  false
601  );
602  }
603  else
604  {
605  double middlexworld = untr.GetMinX() + w / 2.0;
606  double middleyworld = untr.GetMinY() + h / 2.0;
607  GetDrawer2D()->SetMappingUpp( middlexworld - clientw / 2.0 * uppx, middleyworld - clienth / 2.0 * uppx, uppx, uppx );
608  }
609 
610  // if scrolling bars were added are removed because of the above, we do it once more.
611  int clientwNew, clienthNew;
612  GetSaveClientSize( &clientwNew, &clienthNew );
613  if ( clientw != clientwNew || clienth != clienthNew )
614  {
615  //what is needed in units per pixel to make height of bbox fit.
616  if ( clientw - border > 0 )
617  uppx = w / ( clientw - border );
618  else
619  uppx = w / clientw;
620 
621  //what is needed in units per pixel to make width of bbox fit.
622  if ( clienth - border > 0 )
623  uppy = h / ( clienth - border );
624  else
625  uppy = h / clienth;
626 
627  // now take the largets, to make sure it will fit either in x or y
628  if ( uppy > uppx )
629  uppx = uppy;
630 
631  GetDrawer2D()->SetMappingDeviceRect( m_oversizeX, m_oversizeY, clientwNew, clienthNew, false );
632  if ( !centre )
633  {
635  untr.GetMinY(),
636  w,
637  h,
638  false
639  );
640  }
641  else
642  {
643  double middlexworld = untr.GetMinX() + w / 2.0;
644  double middleyworld = untr.GetMinY() + h / 2.0;
645  GetDrawer2D()->SetMappingUpp( middlexworld - clientwNew / 2.0 * uppx, middleyworld - clienthNew / 2.0 * uppx, uppx, uppx );
646  }
647  }
648 
649  m_drawingPart->Update( a2dCANVIEW_UPDATE_OLDNEW );
650  //Refresh() already result in the next
651  //| a2dCANVIEW_UPDATE_ALL | a2dCANVIEW_UPDATE_AREAS | a2dCANVIEW_UPDATE_BLIT );
653  Refresh();
654 }
655 
656 void a2dCanvas::ZoomOut( double n )
657 {
658  int dx, dy;
659  GetClientSize( &dx, &dy );
660  if ( dy > dx ) dx = dy;
661 
662  SetMappingUpp( GetDrawer2D()->GetVisibleMinX() + ( 1 - n ) * GetDrawer2D()->GetUppX() * dx * 0.5,
663  GetDrawer2D()->GetVisibleMinY() + ( 1 - n ) * GetDrawer2D()->GetUppY() * dy * 0.5,
664  GetDrawer2D()->GetUppX()*n, GetDrawer2D()->GetUppY()*n );
665 }
666 
667 void a2dCanvas::ZoomOutAtXy( int x, int y, double n )
668 {
669  int dx, dy;
670  GetClientSize( &dx, &dy );
671  if ( dy > dx ) dx = dy;
672 
673  double mouse_worldx, mouse_worldy;
674  m_drawingPart->MouseToToolWorld( x, y, mouse_worldx, mouse_worldy );
675 
676  mouse_worldx -= ( mouse_worldx - GetDrawer2D()->GetVisibleMinX() ) * n;
677  mouse_worldy -= ( mouse_worldy - GetDrawer2D()->GetVisibleMinY() ) * n;
678 
679  SetMappingUpp( mouse_worldx, mouse_worldy, GetDrawer2D()->GetUppX()*n, GetDrawer2D()->GetUppY()*n );
680 }
681 
682 void a2dCanvas::SetScrollbars( double pixelsPerUnitX, double pixelsPerUnitY,
683  double noUnitsX, double noUnitsY,
684  double xPos , double yPos )
685 {
686  //set mapping to one pixel per user unit
687  //and yaxis false (may also be true)
688  //this will give exactly a one to one mapping (pixel based)
689  //Device to World etc. still does the calculation but this is fast.
690  GetDrawer2D()->SetYaxis( false );
691  //A Zerobased mapping is just a normal mapping for a2dCanvas,
692  //and result in a pixel 1 to 1 for wxWindow.
693 
694  int dxn, dyn;
695  GetSaveClientSize( &dxn, &dyn );
696 
697  m_scrollstepx = dxn / pixelsPerUnitX;
698  m_scrollstepy = dyn / pixelsPerUnitY;
699  SetScrollMaximum( 0, 0, dxn / pixelsPerUnitX * noUnitsX, dyn / pixelsPerUnitY * noUnitsY );
700 
701  SetMappingUpp( xPos, yPos, 1, 1 );
702 }
703 
705 {
706 
707  // all checks have a tolerance of 0.6 pixels for rounding
708  double tol = 1 * GetUppX();
709 
711  bool visAreaSizeChange = false;
712  bool old_has_y_scroll = m_has_y_scroll;
713  bool old_has_x_scroll = m_has_x_scroll;
714 
715  // Avoid endless recursion via size events
717  {
719  return false;
720  }
721  m_inSetScrollMaximum = true;
722 
723  //always use the real client size to set the scrollbars
724  int dx, dy;
725  GetSaveClientSize( &dx, &dy );
726 
727  //visible width in world coordinates
728  double dvx = GetUppX() * dx;
729  //visible height in world coordinates
730  double dvy = GetUppY() * dy;
731 
732  double dmvx = m_virtm_maxX - m_virtm_minX;
733  double dmvy = m_virtm_maxY - m_virtm_minY;
734 
735  //THE MAXIMUM SCROLLABLE AREA is leading here.
736  // Anything else might change, if it is not allowed to change THE MAXIMUM SCROLLABLE AREA itself.
737 
738  assert( dmvx > 0 );
739  assert( dmvy > 0 );
740 
741  // a start up issue.
742  if ( !GetDrawer2D()->GetVirtualAreaSet() )
743  {
744  //set a visible area eqaul to the maximum scrollable area.
745  double uppnew;
746  if ( dmvx > dmvy )
747  uppnew = dmvx / dvx;
748  else
749  uppnew = dmvy / dvy;
750 
751  SetMappingUpp( m_virtm_minX, m_virtm_minY, uppnew, uppnew );
752  visAreaSizeChange = true;
753  }
754 
755  // what is the visible on the canvas window in world coordinates according
756  // to the a2dCanvasView it drawing context.
757  double minvx = GetDrawer2D()->GetVisibleMinX();
758  double minvy = GetDrawer2D()->GetVisibleMinY();
759  double maxvx = GetDrawer2D()->GetVisibleMinX() + dvx;
760  double maxvy = GetDrawer2D()->GetVisibleMinY() + dvy;
761 
762  if ( !m_scrollmaxfixed )
763  {
764  //adjust/enlarge maximum allowed scrollable visible area, to include the current visible area.
765  if ( m_virtm_minX - tol >= minvx ) m_virtm_minX = minvx;
766  if ( m_virtm_maxX + tol <= maxvx ) m_virtm_maxX = maxvx;
767  if ( m_virtm_minY - tol >= minvy ) m_virtm_minY = minvy;
768  if ( m_virtm_maxY + tol <= maxvy ) m_virtm_maxY = maxvy;
769 
770  dmvx = m_virtm_maxX - m_virtm_minX;
771  dmvy = m_virtm_maxY - m_virtm_minY;
772 
773  visAreaSizeChange = false;
774  }
775  else
776  {
777  // we can not go out the maximum scrollable area, we need to adjust the virtual area
778  // such that it stays within this area, or if not possible, adjust its size to stay in this area.
779 
780  if ( m_clipToScrollMax )
781  {
782  bool clip = false;
783  //the clipped values of current visible area towards the maximum scrollable area.
784  if ( m_virtm_minX - tol >= minvx )
785  { minvx = m_virtm_minX; clip = true; }
786  if ( m_virtm_maxX + tol <= maxvx )
787  { maxvx = m_virtm_maxX; clip = true; }
788  if ( m_virtm_minY - tol >= minvy )
789  { minvy = m_virtm_minY; clip = true; }
790  if ( m_virtm_maxY + tol <= maxvy )
791  { maxvy = m_virtm_maxY; clip = true; }
792 
793  // The visible rectangle now fits the scrollable area,
794  // but we want to preserve the same Upp as much as possible.
795  // Therefore we adjust to the old values to get the same virtual size again,
796  // or else extend to the maximum possible.
797 
798  if ( clip )
799  {
800  // there was a clip and we need to adjust
801  if ( dmvx > dvx || dmvy > dvy )
802  {
803  // the orginal size does fit in the maximum scrollable area for sure.
804  // We will adjust opposite a clipped side.
805  if ( minvx == m_virtm_minX ) maxvx = m_virtm_minX + dvx;
806  else if ( maxvx == m_virtm_maxX ) minvx = m_virtm_maxX - dvx;
807  //else
808  //no clip in X
809 
810  if ( minvy == m_virtm_minY ) maxvy = m_virtm_minY + dvy;
811  else if ( maxvy == m_virtm_maxY ) minvy = m_virtm_maxY - dvy;
812  //else
813  //no clip in Y
814 
815  GetDrawer2D()->SetMinX( minvx );
816  GetDrawer2D()->SetMinY( minvy );
817  }
818  else
819  {
820  //the original virtual size does not fit in the maximum scrollable area.
821  // We will adjust to the maximum possible Upp.
822  // The maximum height or width should be adjusted to fit within the scrollable area
823  double uppX = dmvx / ( dx + 1 ); //units needed to display the whole x range in window
824  double uppY = dmvy / ( dy + 1 ); //units needed to display the whole y range in window
825 
826  if ( uppY > uppX )
827  uppX = uppY;
828 
829  GetDrawer2D()->SetMappingUpp( minvx, minvy, uppX, uppX );
830 
831  dvx = GetUppX() * dx;
832  dvy = GetUppY() * dy;
833  }
834 
835  visAreaSizeChange = true;
836  }
837  }
838  }
839 
840 
841  //All should be oke now:
842  // Maximum Scrollable area is bigger than the visible area.
843  /*
844  assert (m_virtm_minX - tol <= GetVisibleMinX());
845  assert (m_virtm_maxX + tol >= GetVisibleMinX()+dvx);
846  assert (m_virtm_minY - tol <= GetVisibleMinY());
847  assert (m_virtm_maxY + tol >= GetVisibleMinY()+dvy);
848  */
849 
850  if ( !m_wantScroll )
851  {
852  m_inSetScrollMaximum = false;
853  m_drawingPart->UpdateViewDependentObjects();
855  //remove scroll bars if in cased they are there.
856  if ( HasScrollbar( wxHORIZONTAL ) )
857  SetScrollbar( wxHORIZONTAL, 0, 1, 1, true );
858  if ( HasScrollbar( wxVERTICAL ) )
859  SetScrollbar( wxVERTICAL, 0, 1, 1, true );
860  return visAreaSizeChange;
861  }
862 
863  // FROM NOW ON down here we are sure we want scrolling bars.
864 
865 
866  // Now check, if we need a vertical scrollbar and set them to get the right sizes
867  // of the client screen.
868  m_has_y_scroll = dmvy > fabs( dvy );
869  if( m_has_y_scroll )
870  {
871  // virtual area is larger than visible area => need vertical scrollbar
872  SetScrollbar( wxVERTICAL, 0, 1, 2, false );
873  // reget client size with this scrollbar
874  //GetSaveClientSize(&dx,&dy);
875  //dvx = GetUppX()*dx;
876  //dvy = GetUppY()*dy;
877  }
878 
879  // Now check, if we need a horizontal scrollbar
880  m_has_x_scroll = dmvx > fabs( dvx );
881  if( m_has_x_scroll )
882  {
883  // virtual area is larger than visible area => need horizontal scrollbar
884  SetScrollbar( wxHORIZONTAL, 0, 1, 2, false );
885  // reget client size with this scrollbar
886  //GetSaveClientSize(&dx,&dy);
887  //dvx = GetUppX()*dx;
888  //dvy = GetUppY()*dy;
889 
890  // If we don't have a vertical scrollbar yet, we might need one cause of
891  // the horizontal scrollbar
892  if( !m_has_y_scroll )
893  {
894  m_has_y_scroll = dmvy > fabs( dvy );
895  if( m_has_y_scroll )
896  {
897  // virtual area is larger than visible area => need vertical scrollbar
898  SetScrollbar( wxVERTICAL, 0, 1, 2, false );
899  // reget client size with this scrollbar
900  //GetSaveClientSize(&dx,&dy);
901  //dvx = GetUppX()*dx;
902  //dvy = GetUppY()*dy;
903  }
904  }
905  }
906 
907  // Now we have the scrollbars enabled and set
909 
910  // Set the scrollbars in the right state.
911  if( m_has_x_scroll )
912  {
913  // Recalculate thumb size and range and draw the scrollbar
914  // always use the real client size to set the scrollbars
915  m_thumbx = ( int )floor( dvx / m_scrollstepx * m_normalize ); //thumb is visible size in scroll steps
916 
917  m_scrollrangex = ( int ) ( dmvx / m_scrollstepx * m_normalize );
918 
919  //set the scroll bar to the right position
920  //in SetScrollbar there will directly be a call to onsize
921  //if scrollbar visibility changes
922  m_xscroll_changed = true;
923  int position = ( int )( ( GetVisibleMinX() - m_virtm_minX ) / dmvx * m_scrollrangex );
924  SetScrollbar( wxHORIZONTAL, position, m_thumbx, m_scrollrangex, true );
925 
926  m_xscroll_changed = false;
927 
928  }
929  else
930  {
931  // Just redraw a non existing scrollbar
932  SetScrollbar( wxHORIZONTAL, 0, 1, 1, true );
933  }
934 
935  if( m_has_y_scroll )
936  {
937  // Recalculate thumb size and range and draw the scrollbar
938  m_thumby = ( int ) ( dvy / m_scrollstepy * m_normalize );
939 
940  m_scrollrangey = ( int ) ( dmvy / m_scrollstepy * m_normalize );
941 
942  m_yscroll_changed = true;
943 
944  if ( GetYaxis() )
945  {
946  // The y-Axis is going up (mathematical coords / screen inverted )
947 
948  //set the scroll bar to the right position
949  //in SetScrollbar there will directly be a call to onsize
950  //if scrollbar visibility changes
951  int position = ( int ) ( ( m_virtm_maxY - ( GetVisibleMinY() + dvy ) ) / dmvy * m_scrollrangey );
952  SetScrollbar( wxVERTICAL, position, m_thumby, m_scrollrangey, true );
953  }
954  else
955  {
956  // The y-Axis is going down (word processing coords / like screen )
957 
958  //set the scroll bar to the right position
959  //in SetScrollbar there will directly be a call to onsize
960  //if scrollbar visibility changes
961  int position = ( int ) ( ( GetVisibleMinY() - m_virtm_minY ) / dmvy * m_scrollrangey );
962  SetScrollbar( wxVERTICAL, position, m_thumby, m_scrollrangey, true );
963  }
964  m_yscroll_changed = false;
965  }
966  else
967  {
968  // Just redraw a non existing scrollbar
969  SetScrollbar( wxVERTICAL, 0, 1, 1, true );
970  }
971 
972  m_inSetScrollMaximum = false;
973 
974  if ( old_has_y_scroll != m_has_y_scroll || old_has_x_scroll != m_has_x_scroll )
975  visAreaSizeChange = true;
976 
977  m_drawingPart->UpdateViewDependentObjects();
979 
980  return visAreaSizeChange;
981 }
982 
983 bool a2dCanvas::SetScrollMaximum( double vx1, double vy1, double vx2, double vy2 )
984 {
985  if( !GetDrawer2D() )
986  return false;
987 
988  wxASSERT_MSG( vx1 < vx2, wxT( "min X bigger than max X" ) );
989  wxASSERT_MSG( vy1 < vy2, wxT( "min Y bigger than max Y" ) );
990 
991  m_virtm_minX = vx1;
992  m_virtm_minY = vy1;
993  m_virtm_maxX = vx2;
994  m_virtm_maxY = vy2;
995 
997 }
998 
999 void a2dCanvas::SetMinX( double vxmin )
1000 {
1001  GetDrawer2D()->SetMinX( vxmin );
1003 }
1004 
1005 void a2dCanvas::SetMinY( double vymin )
1006 {
1007  GetDrawer2D()->SetMinY( vymin );
1009 }
1010 
1011 void a2dCanvas::SetYaxis( bool up )
1012 {
1013  if ( !GetDrawer2D() )
1014  return;
1015  GetDrawer2D()->SetYaxis( up );
1017 
1018  m_drawingPart->Update( a2dCANVIEW_UPDATE_ALL );
1019 }
1020 
1022 {
1023  m_scrollstepx = x;
1024 
1026 }
1027 
1029 {
1030  m_scrollstepy = y;
1031 
1033 }
1034 
1036 {
1037  int dvx, dvy;
1038  GetSaveClientSize( &dvx, &dvy );
1039 
1040  double dyworld = GetDrawer2D()->DeviceToWorldYRel( dy );
1041  double dxworld = GetDrawer2D()->DeviceToWorldXRel( dx );
1042  double worldminy = GetVisibleMinY() - dyworld;
1043  double worldminx = GetVisibleMinX() - dxworld;
1044 
1045  return CheckInsideScrollMaximum( worldminx, worldminy );
1046 }
1047 
1048 bool a2dCanvas::CheckInsideScrollMaximum( double worldminx, double worldminy )
1049 {
1050  if( !m_scrollmaxfixed )
1051  return true;
1052 
1053  int dvx, dvy;
1054  GetSaveClientSize( &dvx, &dvy );
1055  double worlddvx = GetUppX() * dvx;
1056  double worlddvy = GetUppY() * dvy;
1057 
1058  return
1059  ( m_virtm_minX <= worldminx ) &&
1060  ( m_virtm_maxX >= worldminx + worlddvx ) &&
1061  ( m_virtm_minY <= worldminy ) &&
1062  ( m_virtm_maxY >= worldminy + worlddvy );
1063 }
1064 
1066 {
1067  if ( !m_drawingPart )
1068  return false;
1069 
1070  return m_drawingPart->GetMouseEvents();
1071 }
1072 
1073 // ----------------------------------------------------------------------------
1074 // scrolling behaviour
1075 // ----------------------------------------------------------------------------
1076 
1077 void a2dCanvas::OnScroll( wxScrollWinEvent& event )
1078 {
1079  //always use the real client size to set the scrollbars
1080  int dx, dy;
1081  GetSaveClientSize( &dx, &dy );
1082 
1083  if ( event.GetEventType() == wxEVT_SCROLLWIN_THUMBRELEASE ||
1084  ( m_scrollTrackDraw && event.GetEventType() == wxEVT_SCROLLWIN_THUMBTRACK )
1085  )
1086  {
1087  if ( event.GetOrientation() == wxHORIZONTAL )
1088  {
1089  double x = m_virtm_minX + event.GetPosition() / ( m_scrollrangex * 1.0 ) * ( m_virtm_maxX - m_virtm_minX );
1090  x = x - GetVisibleMinX();
1091  ScrollWindowConstrained( x, 0 );
1092  }
1093  else
1094  {
1095  double y;
1096  int position = event.GetPosition();
1097  if ( GetDrawer2D()->GetYaxis() )
1098  {
1099  double dvy = GetUppY() * dy;
1100 
1101  y = m_virtm_maxY - position / ( m_scrollrangey * 1.0 ) * ( m_virtm_maxY - m_virtm_minY );
1102  y = y - dvy - GetVisibleMinY();
1103  }
1104  else
1105  {
1106  y = m_virtm_minY + position / ( m_scrollrangey * 1.0 ) * ( m_virtm_maxY - m_virtm_minY );
1107  y = y - GetVisibleMinY();
1108  }
1109  ScrollWindowConstrained( 0, y );
1110  }
1111  // rounded pixel problems, redraw at end
1112  //if ( event.GetEventType() == wxEVT_SCROLLWIN_THUMBRELEASE )
1113  // m_drawingPart->Update( a2dCANVIEW_UPDATE_ALL );
1114  }
1115  else if ( event.GetEventType() == wxEVT_SCROLLWIN_PAGEUP )
1116  {
1117  //thumb is visible size in scroll steps
1118  if ( event.GetOrientation() == wxHORIZONTAL )
1119  ScrollWindowConstrained( -m_scrollstepx * ( m_thumbx / m_normalize ), 0 );
1120  else
1121  {
1122  if ( GetDrawer2D()->GetYaxis() )
1123  ScrollWindowConstrained( 0, m_scrollstepy * ( m_thumby / m_normalize ) );
1124  else
1125  ScrollWindowConstrained( 0, -m_scrollstepy * ( m_thumby / m_normalize ) );
1126  }
1127  }
1128  else if ( event.GetEventType() == wxEVT_SCROLLWIN_PAGEDOWN )
1129  {
1130  if ( event.GetOrientation() == wxHORIZONTAL )
1131  ScrollWindowConstrained( m_scrollstepx * ( m_thumbx / m_normalize ), 0 );
1132  else
1133  {
1134  if ( GetDrawer2D()->GetYaxis() )
1135  ScrollWindowConstrained( 0, -m_scrollstepy * ( m_thumby / m_normalize ) );
1136  else
1137  ScrollWindowConstrained( 0, m_scrollstepy * ( m_thumby / m_normalize ) );
1138  }
1139  }
1140  else if ( event.GetEventType() == wxEVT_SCROLLWIN_LINEUP )
1141  {
1142  if ( event.GetOrientation() == wxHORIZONTAL )
1144  else
1145  {
1146  if ( GetDrawer2D()->GetYaxis() )
1148  else
1150  }
1151  }
1152  else if ( event.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN )
1153  {
1154  if ( event.GetOrientation() == wxHORIZONTAL )
1156  else
1157  {
1158  if ( GetDrawer2D()->GetYaxis() )
1160  else
1162  }
1163  }
1164 
1165 }
1166 
1167 void a2dCanvas::OnChar( wxKeyEvent& event )
1168 {
1169  //always use the real client size to set the scrollbars
1170  int dx, dy;
1171  GetSaveClientSize( &dx, &dy );
1172 
1173  switch ( event.GetKeyCode() )
1174  {
1175  case WXK_PAGEUP:
1176  //case WXK_PAGEUP:
1177  {
1178  double y = -m_scrollstepy * m_thumby / m_normalize ;
1179  if ( GetDrawer2D()->GetYaxis() )
1180  y = -y;
1181  ScrollWindowConstrained( 0, y );
1182  }
1183  break;
1184  case WXK_PAGEDOWN:
1185  //case WXK_PAGEDOWN:
1186  {
1187  double y = m_scrollstepy * m_thumby / m_normalize;
1188  if ( GetDrawer2D()->GetYaxis() )
1189  y = -y;
1190  ScrollWindowConstrained( 0, y );
1191  }
1192  break;
1193  case WXK_HOME:
1194  {
1195  double y;
1196  if ( GetDrawer2D()->GetYaxis() )
1197  {
1198  double dvy = GetUppY() * dy;
1199  y = m_virtm_maxY - dvy - GetVisibleMinY();
1200  }
1201  else
1202  y = m_virtm_minY - GetVisibleMinY();
1203  ScrollWindowConstrained( 0, y );
1204  }
1205  break;
1206  case WXK_END:
1207  {
1208  double y;
1209  if ( GetDrawer2D()->GetYaxis() )
1210  y = m_virtm_minY - GetVisibleMinY();
1211  else
1212  {
1213  double dvy = GetUppY() * dy;
1214  y = m_virtm_maxY - GetVisibleMinY() - dvy;
1215  }
1216  ScrollWindowConstrained( 0, y );
1217  }
1218  break;
1219  case WXK_UP:
1220  {
1221  double y;
1222  if ( !event.ControlDown() )
1223  y = -m_scrollstepy;
1224  else
1226 
1227  if ( GetDrawer2D()->GetYaxis() )
1228  y = -y;
1229 
1230  ScrollWindowConstrained( 0, y );
1231  }
1232  break;
1233 
1234  case WXK_DOWN:
1235  {
1236  double y;
1237  if ( !event.ControlDown() )
1238  y = m_scrollstepy;
1239  else
1241 
1242  if ( GetDrawer2D()->GetYaxis() )
1243  y = -y;
1244 
1245  ScrollWindowConstrained( 0, y );
1246  }
1247  break;
1248 
1249  case WXK_LEFT:
1250  {
1251  double x;
1252  if ( !event.ControlDown() )
1253  x = -m_scrollstepx;
1254  else
1256  ScrollWindowConstrained( x, 0 );
1257  }
1258  break;
1259  case WXK_RIGHT:
1260  {
1261  double x;
1262  if ( !event.ControlDown() )
1263  x = m_scrollstepx;
1264  else
1266  ScrollWindowConstrained( x, 0 );
1267  }
1268  break;
1269  default:
1270  // not for us
1271  {
1272  event.ResumePropagation( wxEVENT_PROPAGATE_MAX );
1273  event.Skip();
1274  }
1275  }
1276 }
1277 
1278 bool a2dCanvas::ScrollWindowConstrained( double dxworld, double dyworld )
1279 {
1280  bool oke = true;
1281 
1282  // If any updates are pending, do them now since they will
1283  // expect the current mapping.
1284 
1285  //first redraw/update that were not yet updated pending areas (if available)
1286  //blit pending updates to the window/screen
1287  m_drawingPart->Update( a2dCANVIEW_UPDATE_AREAS );//| a2dCANVIEW_UPDATE_BLIT );
1288 
1289  double dx = -GetDrawer2D()->WorldToDeviceXRel( dxworld );
1290  double dy = -GetDrawer2D()->WorldToDeviceYRel( dyworld );
1291 
1292  //If dx/yworld is so small, that dx/y become zero, although dx/yworld!=0
1293  //we scroll at least one pixel
1294  if( dxworld != 0 && dx == 0 )
1295  {
1296  dx = -GetDrawer2D()->WorldToDeviceXRelNoRnd( dxworld ) < 0 ? -1 : 1;
1297  }
1298  if( dyworld != 0 && dy == 0 )
1299  {
1300  dy = -GetDrawer2D()->WorldToDeviceYRelNoRnd( dyworld ) < 0 ? -1 : 1;
1301  }
1302 
1303  //NOW based on the rounded dy which is an integer, set the dyworld again to have
1304  //proper mapping in combination with shifting contents of m_buffer.
1305  //THIS means we do not exactly step in the given amount of worldcoordinates,
1306  //but more a "pixel rounded" amount.
1307  dyworld = -GetDrawer2D()->DeviceToWorldYRel( floor( dy + 0.5 ) );
1308  dxworld = -GetDrawer2D()->DeviceToWorldXRel( floor( dx + 0.5 ) );
1309 
1310  //what are the new wanted minimum values in world coodinates for x an y
1311  double newworldminx = GetVisibleMinX() + dxworld;
1312  double newworldminy = GetVisibleMinY() + dyworld;
1313 
1315  GetDrawer2D()->SetMinY( newworldminy );
1316  GetDrawer2D()->SetMinX( newworldminx );
1318  {
1319  //the next does shift DIRECTLY the contents of the WINDOW and
1320  //will generate proper Onpaint events for area to re-blit from buffer
1321  // when rect = NULL total buffer will be blitted (fast enough)
1322  wxWindow::ScrollWindow( ( int ) dx, ( int ) dy, NULL );
1323 
1324  //do a scroll of the drawer its buffer preserving what is already in it.
1325  //This also adds the right pending area and redraws them to the drawer buffer.
1326 
1327  // reset to old value, because m_drawingPart->Scroll() uses RedrawPendingUpdateAreas()
1328  // to directly redraw what must be redrawn.
1329  GetDrawer2D()->SetMinX( newworldminx - dxworld );
1330 
1331  if ( dy != 0 || !oke )
1332  //buffer is bigger than window, so shift is oke and redraw also,
1333  //as far as buffer being fully updated.
1334  m_drawingPart->Scroll( ( int ) dy, true, !oke );
1335 
1336  // no scroll x and so set it just now, and not earlier
1337  GetDrawer2D()->SetMinX( newworldminx );
1338 
1339  if ( dx != 0 || !oke )
1340  //buffer is bigger than window, so shift is oke and redraw also,
1341  //as far as buffer being fully updated.
1342  m_drawingPart->Scroll( ( int ) dx, false, !oke );
1343 
1344  // wxWindow::ScrollWindow() did shift the window botmap by dx,dy.
1345  // We should only blit those parts, but the whole is fast enough.
1346  // The buffer is already oke.
1347  // We do blit here, in order not to wait for OnPaint to do it in Idle time.
1348  if ( dx != 0 || dy != 0 || !oke )
1349  {
1350  int w, h;
1351  GetSaveClientSize( &w, &h );
1352  m_drawingPart->BlitBuffer( 0, 0, w, h, 0, 0 );
1353  }
1354  }
1355  else
1356  m_drawingPart->Update( a2dCANVIEW_UPDATE_ALL );
1357 
1359 
1360  return oke;
1361 }
1362 
1363 void a2dCanvas::OnSize( wxSizeEvent& WXUNUSED( event ) )
1364 {
1365  if ( !m_drawingPart )
1366  return;
1367 
1368  //TRICKS!
1369  //The buffer is a little bigger then the clientsize.
1370  //This is for two reasons.
1371  //1- A small resize on the window does not result in redrawing
1372  //everything.
1373  //1- To be able to ignore onsize events when only scrollbars (dis)appear
1374  //which also would cause a redraw here
1375 
1376  //Setting scrollbars (after a zoom in or out) normally can result
1377  //in 1 or 2 Onsize events, since scrollbars can (dis)appear.
1378  //This actually changes the clientsize, so Onsize events.
1379  //to prevent in this case redrawing, those onsize events are
1380  //ignored. The Onpaint events resulting from setting scrollbars or
1381  //processed as normal, so the buffer size must be at least with scrollbars.
1382 
1383  //ignore size events due to scrollbars on off,
1384  //while window itself did not change in size
1385  //Those changes are detected when setting the scrollbars
1386  //Two separate size events or generated, so handle them one
1387  //by one
1388  if ( m_xscroll_changed == true )
1389  {
1390  m_xscroll_changed = false;
1391  return;
1392  }
1393  if ( m_yscroll_changed == true )
1394  {
1395  m_yscroll_changed = false;
1396  return;
1397  }
1398 
1399  int clientw, clienth;
1400  int w, h;
1401 
1402  GetSaveClientSize( &clientw, &clienth );
1403  //the client size may be with are without scrollbars
1404  //always draw to a buffer that is inclusif scrollbars
1405  w = clientw + m_delta;
1406  if ( m_has_y_scroll )
1407  w += wxSystemSettings::GetMetric( wxSYS_VSCROLL_X );
1408  h = clienth + m_delta;
1409  if ( m_has_x_scroll )
1410  h += wxSystemSettings::GetMetric( wxSYS_HSCROLL_Y );
1411 
1412  //wxLogDebug( wxT("ow %d oh %d"), m_oldw, m_oldh );
1413  //wxLogDebug( wxT("w %d h %d"), w, h );
1414 
1415  if ( abs( m_oldw - w ) > m_delta || abs( m_oldh - h ) > m_delta )
1416  {
1417  //wxLogDebug( wxT(" change w %d h %d"), w, h );
1418  m_drawingPart->SetBufferSize( w + m_oversizeX * 2, h + m_oversizeY * 2 );
1419 
1420  //first redraw/update that were not yet updated pending areas (if available)
1421  //blit pending updates to the window/screen
1423  if ( GetScaleOnResize() )
1424  {
1426  if ( m_oldw != 0 && m_oldh != 0 && clientw > MIN_MAPSIZE && clienth > MIN_MAPSIZE )
1427  {
1428  if ( m_prevClientW == 0 )
1429  m_prevClientW = clientw;
1430  if ( m_prevClientH == 0 )
1431  m_prevClientH = clienth;
1432 
1433  double worldoldw = GetDrawer2D()->GetVisibleWidth();
1434  double worldoldh = GetDrawer2D()->GetVisibleHeight();
1435 
1436  double upp;
1437 
1438  if ( clientw < clienth )
1439  upp = worldoldw / clientw;
1440  else
1441  upp = worldoldh / clienth;
1442 
1443  double middlexworld = GetDrawer2D()->DeviceToWorldX( m_prevClientW / 2.0 );
1444  double middleyworld = GetDrawer2D()->DeviceToWorldY( m_prevClientH / 2.0 );
1445  GetDrawer2D()->SetMappingDeviceRect( m_oversizeX, m_oversizeY, clientw, clienth, false );
1446  GetDrawer2D()->SetMappingUpp( middlexworld - clientw / 2.0 * upp, middleyworld - clienth / 2.0 * upp, upp, upp );
1447 
1449 
1450  m_prevClientW = clientw;
1451  m_prevClientH = clienth;
1452  }
1453 
1455 
1456  //although an onpaint event will follow, DO it now
1457  //since Onpaint ignores blits outside what is outside what he thinks
1458  //was damaged
1459  //This in case of Style wxNO_FULL_REPAINT_ON_RESIZE for wxFrame
1460  //which is needed for a2dCanvas
1462  }
1463  else
1464  {
1466  GetDrawer2D()->SetMappingDeviceRect( m_oversizeX, m_oversizeY, clientw, clienth, false );
1467 
1468  //only redraw/repaint what was added, so if smaller
1469  //do nothing else update only the new areas
1470 
1471  if ( GetDrawer2D()->GetYaxis() )
1472  {
1473  //calculate the new minimum Y to set the mapping
1474  //without changing what is displayed already
1475 
1476  if ( m_oldh && m_oldw ) //first time at start up those are zero
1477  GetDrawer2D()->SetMinY( GetVisibleMinY() - ( h - m_prevh )*GetUppY() );
1478 
1479  if ( m_oldw < w )
1480  m_drawingPart->AddPendingUpdateArea( m_oldw, 0, w - m_oldw, h );
1481  if ( m_oldh < h )
1482  m_drawingPart->AddPendingUpdateArea( 0, m_oldh, w, h - m_oldh );
1483  }
1484  else
1485  {
1486  if ( m_oldw < w )
1487  m_drawingPart->AddPendingUpdateArea( m_oldw, 0, w - m_oldw, h );
1488  if ( m_oldh < h )
1489  m_drawingPart->AddPendingUpdateArea( 0, m_oldh, w, h - m_oldh );
1490  }
1491 
1494 
1495  // now directly update those above areas and blit them to the window.
1496  // else we would get an ugly black border while sizing.
1498  }
1499 
1500  //also used for rescale!
1501  m_oldw = w; m_oldh = h;
1502  }
1503  else
1504  {
1505  if ( GetScaleOnResize() )
1506  {
1507  if ( m_ContinuesSizeUpdate )
1508  {
1510  if ( m_oldw != 0 && m_oldh != 0 && clientw > MIN_MAPSIZE && clienth > MIN_MAPSIZE )
1511  {
1512  if ( m_prevClientW == 0 )
1513  m_prevClientW = clientw;
1514  if ( m_prevClientH == 0 )
1515  m_prevClientH = clienth;
1516 
1517  double worldoldw = GetDrawer2D()->GetVisibleWidth();
1518  double worldoldh = GetDrawer2D()->GetVisibleHeight();
1519 
1520  double upp;
1521 
1522  if ( clientw < clienth )
1523  upp = worldoldw / clientw;
1524  else
1525  upp = worldoldh / clienth;
1526 
1527  double middlexworld = GetDrawer2D()->DeviceToWorldX( m_prevClientW / 2.0 );
1528  double middleyworld = GetDrawer2D()->DeviceToWorldY( m_prevClientH / 2.0 );
1529  GetDrawer2D()->SetMappingDeviceRect( m_oversizeX, m_oversizeY, clientw, clienth, false );
1530  GetDrawer2D()->SetMappingUpp( middlexworld - clientw / 2.0 * upp, middleyworld - clienth / 2.0 * upp, upp, upp );
1531 
1533 
1534  m_prevClientW = clientw;
1535  m_prevClientH = clienth;
1536  }
1537 
1539 
1540  //although an onpaint event will follow, DO it now
1541  //since Onpaint ignores blits outside what is outside what he thinks
1542  //was damaged
1543  //This in case of Style wxNO_FULL_REPAINT_ON_RESIZE for wxFrame
1544  //which is needed for a2dCanvas
1546  }
1547  }
1548  else if ( GetDrawer2D()->GetYaxis() )
1549  {
1551  //new size still within the buffer only adjust mapping
1552  double uppy = GetUppY();
1553  /*
1554  //wxLogDebug( "xmin %f", GetDrawer2D()->GetVisibleMinX() );
1555  //wxLogDebug( "xmax %f", GetDrawer2D()->GetVisibleMaxX() );
1556  wxLogDebug( "ymin %f", GetDrawer2D()->GetVisibleMinY() );
1557  wxLogDebug( " yminw %f", GetVisibleMinY() );
1558  wxLogDebug( "ymax %f", GetDrawer2D()->GetVisibleMaxY() );
1559  wxLogDebug( " ymaxw %f", GetVisibleMaxY() );
1560  */
1561  //set the new mapping area, based on what is visible on the window (not the buffer)
1562  GetDrawer2D()->SetMappingDeviceRect( m_oversizeX, m_oversizeY, clientw, clienth, false );
1563  GetDrawer2D()->SetMinY( GetVisibleMinY() - ( h - m_prevh )*uppy );
1564 
1566  m_drawingPart->Update( a2dCANVIEW_UPDATE_ALL );
1567 
1569 
1570  }
1571 
1572  }
1573  m_prevw = w;
1574  m_prevh = h;
1575 }
1576 
1577 
1578 void a2dCanvas::OnWheel( wxMouseEvent& event )
1579 {
1580  int rot = event.GetWheelRotation();
1581 
1582  if ( rot > 0 )
1583  {
1584  if ( event.AltDown() )
1585  {
1586  if ( !event.ShiftDown() )
1587  {
1588  double y;
1589  if ( !event.ControlDown() )
1590  y = -m_scrollstepy;
1591  else
1593 
1594  if ( GetDrawer2D()->GetYaxis() )
1595  y = -y;
1596 
1597  ScrollWindowConstrained( 0, y );
1598  }
1599  else
1600  {
1601  double x;
1602  if ( !event.ControlDown() )
1603  x = -m_scrollstepx;
1604  else
1606  ScrollWindowConstrained( x, 0 );
1607  }
1608  }
1609  else
1610  {
1611  ZoomOutAtXy( event.m_x, event.m_y, 0.75 );
1612  }
1613  }
1614  else
1615  {
1616  if ( event.AltDown() )
1617  {
1618  if ( !event.ShiftDown() )
1619  {
1620  double y;
1621  if ( !event.ControlDown() )
1622  y = m_scrollstepy;
1623  else
1625 
1626  if ( GetDrawer2D()->GetYaxis() )
1627  y = -y;
1628 
1629  ScrollWindowConstrained( 0, y );
1630  }
1631  else
1632  {
1633  double x;
1634  if ( !event.ControlDown() )
1635  x = m_scrollstepx;
1636  else
1638  ScrollWindowConstrained( x, 0 );
1639  }
1640  }
1641  else
1642  {
1643  ZoomOutAtXy( event.m_x, event.m_y, 1.5 );
1644  }
1645  }
1646 }
1647 
1648 void a2dCanvas::OnActivate( wxActivateEvent& event )
1649 {
1650 }
bool GetYaxis() const
get currently used Yaxis setting
Definition: canvas.cpp:402
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
int WorldToDeviceXRel(double x) const
convert x relative from world to device coordinates
Definition: drawer2d.h:460
void SetScrollBarsVisible(bool onoff)
show scrollbars if set true.
Definition: canvas.cpp:308
double GetHeight() const
returns height of the boundingbox
Definition: bbox.cpp:334
int m_oldw
to optimize onsize events
Definition: canvas.h:563
int m_normalize
used to normalize scroll thumb and range
Definition: canvas.h:589
void OnScroll(wxScrollWinEvent &event)
what to do while scrollling
Definition: canvas.cpp:1077
void EndRefreshDisplayDisable()
see StartRefreshDisplayDisable()
Definition: drawer2d.cpp:204
double GetVisibleMaxY() const
get Maximum Y of the visible part in world coordinates
Definition: canvas.cpp:381
void SetBackgroundFill(const a2dFill &backgroundfill)
background fill for the canvas
Definition: canvas.cpp:286
void OnPaint(wxPaintEvent &event)
repaint damaged araes, taking into acount non updated araes in a2dCanvasView.
Definition: canvas.cpp:421
const a2dAffineMatrix & GetTransformMatrix() const
get the matrix used to position the object
Definition: canobj.h:500
void SetMouseEvents(bool onoff)
Definition: canvas.cpp:478
bool m_aboveScrolledFixedAdjustUpp
when because resizing or setting maximum scrollable area, it becomes smaller then the visible area...
Definition: canvas.h:496
double GetVisibleMinX() const
get Minimal X of the visible part in world coordinates
Definition: drawer2d.cpp:403
bool IsFrozen()
Returns if canvas is frozen.
Definition: drawer.h:928
void Freeze()
prevent changing the a2dCanvasView buffer and blitting it to the window
Definition: canvas.cpp:409
a2dCanvasObject * GetRootObject() const
get the root object, which holds the objects in the document
Definition: drawing.h:521
bool m_ContinuesSizeUpdate
at small resize also update the buffer directly.
Definition: canvas.h:586
wxUint16 GetZoomOutBorder()
Definition: drawer.h:540
bool m_has_x_scroll
flag if there is a horizontal scrollbar
Definition: canvas.h:548
void ClearBackground()
Clears the canvas (like wxWindow::ClearBackground)
Definition: canvas.cpp:258
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
void SetScrollStepY(double y)
set granularity (step size) for scrolling in world units for Vertical Scrollbar
Definition: canvas.cpp:1028
double DeviceToWorldYRel(double y) const
convert y relative from device to world coordinates
Definition: drawer2d.h:449
bool SetScrollMaximum(double vx1, double vy1, double vx2, double vy2)
to set the total area in world coordinates that can be scrolled to.
Definition: canvas.cpp:983
virtual void Scroll(int dxy, bool yscroll, bool total)
scroll up down or left right
Definition: drawer.cpp:3398
int m_delta
oversize of buffer compared to screen width and height
Definition: canvas.h:566
void Update(unsigned int how=(a2dCANVIEW_UPDATE_ALL|a2dCANVIEW_UPDATE_BLIT), wxObject *hintObject=NULL)
see OnUpdate
Definition: drawer.cpp:1744
a2dCanvasObject * GetShowObject() const
return pointer of then currently shown object on the canvas.
Definition: canvas.h:421
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
This class implements drawing functions for wxDC based drawing.
Definition: dcdrawer.h:203
double GetVisibleMinY() const
get Minimal X of the visible part in world coordinates
Definition: drawer2d.cpp:408
int m_thumbx
current thumbsize of X scrollbar which gets always adjusted by the m_scrollstepx
Definition: canvas.h:524
void SetYaxis(bool up)
set if the Yaxis goes up or down
Definition: canvas.cpp:1011
a2dCanvasObject is the base class for Canvas Objects.
Definition: canobj.h:371
void SetMinX(double vxmin)
Set horizontal scrollbar position in world coordinates.
Definition: canvas.cpp:999
int m_oversizeX
in future the offset from window to drawer in X
Definition: canvas.h:572
virtual void SetBufferSize(int w, int h)
sets buffersize ( if used ) for the a2dDrawer2D
Definition: drawer.cpp:755
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: canvas.cpp:489
void AppendEventHandler(wxEvtHandler *handler)
append an eventhandler to the list, this event handler will be called if the other skipped the event ...
Definition: canvas.cpp:314
bool GetMouseEvents() const
return true if this a2dDrawingPart allows mouse events to be processed.
Definition: drawer.h:631
void SetMappingUpp(double vx1, double vy1, double xpp, double ypp)
Give the virtual size to be displayed, the mappingmatrix will be calculated.
Definition: canvas.cpp:534
bool m_scrolled
are scroll bars active?
Definition: canvas.h:539
a2dCanvas uses a2dCanvasView for displaying a view on a a2dCanvasDocument.
void GetSaveClientSize(int *dvx, int *dvy) const
same as normal client size, but when dx or dy is zero, it will be set to 1000.
Definition: canvas.cpp:250
double GetVisibleMaxX() const
get Maximum X of the visible part in world coordinates
Definition: canvas.cpp:374
void SetScrollStepX(double x)
set granularity (step size) for scrolling in world units for Horizontal Scrollbar ...
Definition: canvas.cpp:1021
virtual void BlitBuffer(int x, int y, int width, int height, int xbuf, int ybuf)
blit part of the drawing buffer to the canvas
Definition: drawer.cpp:2154
bool m_frozen
prevent updating activity if true
Definition: canvas.h:569
bool MakeVirtualMaxFitVisibleArea()
Definition: canvas.cpp:704
int m_oversizeY
in future the offset from window to drawer in Y
Definition: canvas.h:575
double GetUppX() const
return xpp Number of user units per pixel in x
Definition: drawer2d.h:353
virtual double GetVisibleHeight() const
get Height of visible part in world coordinates
Definition: drawer2d.cpp:428
bool m_yscroll_changed
a flag for ignoring size events when scrollbars change
Definition: canvas.h:545
a2dCanvas(wxWindow *parent, wxWindowID id=-1, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxScrolledWindowStyle, a2dDrawer2D *drawer2D=0)
constructor
Definition: canvas.cpp:50
void SetMappingShowAll(bool centre=true)
use the boundingbox of the ShowObject to set the mapping such that it will be displayed completely...
Definition: canvas.cpp:548
int WorldToDeviceYRel(double y) const
convert y relative from world to device coordinates
Definition: drawer2d.h:465
bool m_xscroll_changed
a flag for ignoring size events when scrollbars change
Definition: canvas.h:542
virtual void SetDisplayWindow(wxWindow *display)
next to the base its m_display, this also sets m_drawer2d to this display
Definition: drawer.cpp:745
double DeviceToWorldY(double y) const
convert y from device to world coordinates
Definition: drawer2d.h:439
double GetMinX() const
get minimum X of the boundingbox
Definition: bbox.cpp:304
bool GetScaleOnResize()
get current setting for ScaleOnResize
Definition: canvas.h:210
void SetMappingWidthHeight(double vx1, double vy1, double width, double height, bool scrollbars)
Give the virtual size to be displayed, the mappingmatrix will be calculated.
Definition: canvas.cpp:503
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
void ZoomOutAtXy(int x, int y, double n)
zoom out from position x,y by a factor n (zoomin if &lt;1 )
Definition: canvas.cpp:667
double GetVisibleMinX() const
get Minimal X of the visible part in world coordinates
Definition: canvas.cpp:346
the antigrain based drawing context derived from a2dDrawer2D
a2dHitOption
Enum for hit test options.
Definition: canobj.h:76
bool ScrollWindowConstrained(double dx, double dy)
scroll the window in world coordinates
Definition: canvas.cpp:1278
virtual double GetVisibleWidth() const
get Width of visible part in world coordinates
Definition: drawer2d.cpp:423
Drawing context abstraction.
Definition: drawer2d.h:177
void OnWheel(wxMouseEvent &event)
mouse wheel handler
Definition: canvas.cpp:1578
void OnEraseBackground(wxEraseEvent &event)
Not yet implemented.
Definition: canvas.cpp:483
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
double GetUppY() const
return ypp Number of user units per pixel in y
Definition: drawer2d.h:356
Contains graphical drawing context specific classes. a2dDcDrawer and derived classes are used for dra...
double m_virtm_minX
virtual coordinates of total scrollable area for the drawing, used to set scrollbars ...
Definition: canvas.h:462
int m_thumby
current thumbsize of Y scrollbar which gets always adjusted by the m_scrollstepy
Definition: canvas.h:530
a2dDrawer2D * GetDrawer2D()
get the internal m_drawer2D that is used for rendering the document
Definition: drawer.h:1125
double GetUppY() const
Definition: canvas.cpp:367
void SetScrollbars(double pixelsPerUnitX, double pixelsPerUnitY, double noUnitsX, double noUnitsY, double xPos=0, double yPos=0)
set scrollbars
Definition: canvas.cpp:682
double GetUppX() const
Definition: canvas.cpp:360
bool m_wantScroll
set true by wxWindow style parameter wxVSCROLL | wxHSCROLL
Definition: canvas.h:491
double GetVisibleMinY() const
get Minimal X of the visible part in world coordinates
Definition: canvas.cpp:353
wxEvtHandler * RemoveLastEventHandler(bool deleteHandler)
remove last event handler in the list
Definition: canvas.cpp:325
bool GetMouseEvents()
Definition: canvas.cpp:1065
bool m_scrollTrackDraw
redraw at drag fo scrollbars
Definition: canvas.h:560
void Thaw()
allow a2dCanvasView buffer to be changed and blitting it to the window
Definition: canvas.cpp:415
void SetDisplay(wxWindow *window)
the display
Definition: drawer2d.h:208
double m_scrollstepy
step for Y line up and down in world coordinates
Definition: canvas.h:536
bool m_clipToScrollMax
see ClipToScrollMaximum()
Definition: canvas.h:557
A 2x3 affine matrix class for 2D transformations.
Definition: afmatrix.h:53
a2dCanvas is used to display one of the a2dCanvasObjects which are part of a a2dCanvasDocument object...
Definition: canvas.h:68
virtual ~a2dCanvas()
destructor
Definition: canvas.cpp:277
int GetWidth() const
get buffer/device width
Definition: drawer2d.h:392
double GetVisibleHeight() const
get Height of visible part in world coordinates
Definition: canvas.cpp:395
void MapBbox(const a2dAffineMatrix &matrix)
Definition: bbox.cpp:445
void OnChar(wxKeyEvent &event)
what to do for characters received
Definition: canvas.cpp:1167
void SetMinX(double x)
Set Minimal X of the visible part in world coordinates.
Definition: drawer2d.cpp:226
int m_scrollrangex
Total range of X scroll bar, which gets always adjusted by the m_scrollstepx.
Definition: canvas.h:512
bool WriteSVG(const wxString &filename, double Width, double Height, wxString unit)
write what you see to an SVG( scalable vector graphics file )
Definition: canvas.cpp:498
double WorldToDeviceXRelNoRnd(double x) const
convert x relative from world to device coordinates (result not rounded to integer) ...
Definition: drawer2d.h:470
a2dDrawingPtr m_drawing
set if the canvas own the drawing
Definition: canvas.h:592
virtual void BeginDraw()=0
start to draw on this context (used to initialize a specific drawer)
double DeviceToWorldX(double x) const
convert x from device to world coordinates
Definition: drawer2d.h:437
double GetWidth() const
returns width of the boundingbox
Definition: bbox.cpp:328
bool m_has_y_scroll
flag if there is a vertical scrollbar
Definition: canvas.h:551
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
bool m_inSetScrollMaximum
prevent SetScrollMaximum beeing called recursively
Definition: canvas.h:580
double GetVisibleWidth() const
get Width of visible part in world coordinates
Definition: canvas.cpp:388
a2dDrawer2D * GetDrawer2D() const
Get the drawer of the view.
Definition: canvas.h:128
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
int m_scrollrangey
Total range of Y scroll bar, which gets always adjusted by the m_scrollstepy.
Definition: canvas.h:518
void SetMinY(double y)
Set Minimal Y of the visible part in world coordinates.
Definition: drawer2d.cpp:232
The a2dBoundingBox class stores one a2dBoundingBox of a a2dCanvasObject.
Definition: bbox.h:39
bool Invert(void)
Invert matrix.
Definition: afmatrix.cpp:197
void ZoomOut(double n)
zoom out from the center by a factor n (zoomin if &lt;1 )
Definition: canvas.cpp:656
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
void UpdateViewDependentObjects()
update the transform matrix for objects with property &#39;PROPID_viewDependent&#39;
Definition: drawer.cpp:2288
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
bool CheckInsideScrollMaximum(double worldminx, double worldminy)
check if the given scroll in worldcoordinates (X and Y) will stay within ScrollMaximum.
Definition: canvas.cpp:1048
a2dCanvasObject * SetShowObject(const wxString &name)
set object available in the a2dCanvasDocument to be shown on the canvas
Definition: canvas.cpp:294
double WorldToDeviceYRelNoRnd(double y) const
convert y relative from world to device coordinates (result not rounded to integer) ...
Definition: drawer2d.h:475
bool m_scrollmaxfixed
stay within maximum scrollable area
Definition: canvas.h:554
double m_scrollstepx
step for X line up and down in world coordinates
Definition: canvas.h:533
void OnSize(wxSizeEvent &event)
resize, adjusting buffer of a2dCanvasView if needed.
Definition: canvas.cpp:1363
void MouseToToolWorld(int x, int y, double &xWorldLocal, double &yWorldLocal)
Definition: drawer.cpp:1097
void SetMinY(double vymin)
Set vertical scrollbar position in world coordinates.
Definition: canvas.cpp:1005
double DeviceToWorldXRel(double x) const
convert x relative from device to world coordinates
Definition: drawer2d.h:444
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
bool m_scaleonresize
are scroll bars active?
Definition: canvas.h:488
virtual void Refresh(bool eraseBackground=true, const wxRect *rect=NULL)
Refresh window.
Definition: canvas.cpp:265
virtual bool ProcessEvent(wxEvent &event)
Special event handling for a2dDrawingPart class.
Definition: drawer.cpp:803
canvas.cpp Source File -- Sun Oct 12 2014 17:04:14 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation