wxArt2D
canobj.cpp
Go to the documentation of this file.
1 /*! \file canvas/src/canobj.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: canobj.cpp,v 1.435 2009/09/30 18:38:57 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/module.h"
22 
23 #include <wx/wfstream.h>
24 #include <wx/tokenzr.h>
25 
26 #include <algorithm>
27 #include <math.h>
28 
29 #include "wx/canvas/canobj.h"
30 #include "wx/canvas/drawer.h"
31 #include "wx/canvas/drawing.h"
32 #include "wx/canvas/canvas.h"
33 #include "wx/canvas/tools.h"
34 #include "wx/canvas/wire.h"
35 #include "wx/canvas/canglob.h"
36 #include "wx/canvas/algos.h"
37 
38 #if defined(__WXMSW__) && defined(__MEMDEBUG__)
39 #include <wx/msw/msvcrt.h>
40 #endif
41 
42 
43 //#include "wx/general/id.inl"
44 #include "wx/general/smrtptr.inl"
45 
46 //#define CANVASDEBUG
47 //#define _DEBUG_REPORTHIT
48 
49 //----------------------------------------------------------------------------
50 // globals
51 //----------------------------------------------------------------------------
52 
53 #define CIRCLE_STEPS 128
54 
55 #if (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4))
56 
57 // MSVC warning 4660 is quite stupid. It says that the template is already instantiated
58 // by using it, but it is not fully instantiated as required for a library
59 #ifdef _MSC_VER
60 #pragma warning(disable: 4660)
61 #endif
62 
65 
66 
67 #ifdef _MSC_VER
68 #pragma warning(default: 4660)
69 #endif
70 
71 #endif // (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4))
72 
73 #ifdef _DEBUG
74 // Here are two globals that can be used as registers in the debugger
75 a2dCanvasObject* _dbco1 = 0;
76 a2dCanvasObject* _dbco2 = 0;
77 #endif
78 
79 //----------------------------------------------------------------------------
80 // a2dCanvasObjectFilterLayerMask
81 //----------------------------------------------------------------------------
83 {
84  if ( canvasObject->m_layer != m_layer && m_layer != wxLAYER_ALL && !canvasObject->GetIgnoreLayer() )
85  {
86  //the object itself will NOT be rendered for sure, but maybe its children still will!
87 
88  //object not on this layer, then children will NOT be rendered also in following cases
89  if ( canvasObject->m_childobjects == wxNullCanvasObjectList ||
90  !canvasObject->m_flags.m_visiblechilds || canvasObject->m_flags.m_childrenOnSameLayer )
91  return false;
92  }
93 
94  if ( m_layer != wxLAYER_ALL && !canvasObject->GetIgnoreLayer() &&
95 
96  ( !ic.GetDrawingPart()->GetLayerRenderArray()[ m_layer ].DoRenderLayer() ||
97  canvasObject->m_root && canvasObject->m_root->GetLayerSetup() &&
98  !canvasObject->m_root->GetLayerSetup()->GetVisible( m_layer ) //&&
99  //!canvasObject->m_root->GetLayerSetup()->GetSelectable(m_layer)
100  )
101 
102  )
103  return false;
104 
105  if ( m_layer == wxLAYER_ALL && !canvasObject->GetIgnoreLayer() && canvasObject->m_root->GetLayerSetup() &&
106  ! canvasObject->m_root->GetLayerSetup()->GetVisible( canvasObject->GetLayer() )
107  )
108  return false;
109 
110  if ( !( canvasObject->CheckMask( m_mask ) || ic.GetLevel() == 0 ) )
111  return false;
112 
113  if ( !( m_antimask == a2dCanvasOFlags::NON || !canvasObject->CheckMask( m_antimask ) || ic.GetLevel() == 0 ) )
114  return false;
115 
116  return true;
117 }
118 
119 
120 //----------------------------------------------------------------------------
121 // a2dCanvasObjectFilterLayerMaskNoToolNoEdit
122 //----------------------------------------------------------------------------
123 
125 {
126  if ( a2dCanvasObjectFilterLayerMask::Filter( ic, canvasObject ) )
127  return !canvasObject->m_flags.m_editingCopy && ! a2dCanvasObject::PROPID_ToolObject->GetPropertyValue( canvasObject );
128  return false;
129 }
130 
131 void a2dCanvasObjectFilterLayerMaskNoToolNoEdit::EndFilter( a2dIterC& WXUNUSED( ic ), a2dCanvasObject* WXUNUSED( canvasObject ) )
132 {
133 }
134 
135 
136 //----------------------------------------------------------------------------
137 // a2dCanvasObjectFilterOnlyNoMaskBlind
138 //----------------------------------------------------------------------------
140 {
141  if ( canvasObject->CheckMask( m_mask ) )
142  {
143  m_maskedCanvasObject = canvasObject;
144  ic.GetDrawer2D()->SetDisableDrawing( false );
145  return true;
146  }
147 
148  if ( !m_maskedCanvasObject )
149  ic.GetDrawer2D()->SetDisableDrawing( true );
150  return true;
151 }
152 
154 {
155  if ( canvasObject == m_maskedCanvasObject )
156  ic.GetDrawer2D()->SetDisableDrawing( true );
157 }
158 
159 //----------------------------------------------------------------------------
160 // a2dCanvasObjectFilterPropertyNoMaskBlind
161 //----------------------------------------------------------------------------
163 {
164  if ( m_maskedCanvasObject ) // we are in an object with the property set ( or deeper down in it)
165  {
166  //ic.GetDrawer2D()->SetDisableDrawing( false );
167  return canvasObject->CheckMask( m_mask );
168  }
169  else if ( canvasObject->HasProperty( m_id ) )
170  {
171  //switch on drawing, and remember the object where this happened
172  m_maskedCanvasObject = canvasObject;
173  ic.GetDrawer2D()->SetDisableDrawing( false );
174  return canvasObject->CheckMask( m_mask );
175  }
176 
177  //all other parts of the drawing ( objects not containing the property), will be drawn, but invisible.
178  //so drawn invisible.
179  ic.GetDrawer2D()->SetDisableDrawing( true );
180  return true;
181 }
182 
184 {
185  //switch the filter back to non drawing when all children and the object
186  // itself are drawn.
187  if ( canvasObject == m_maskedCanvasObject )
188  {
189  m_maskedCanvasObject = NULL; //prepare for new search.
190  ic.GetDrawer2D()->SetDisableDrawing( true ); //blind drawing again
191  }
192 }
193 
194 //----------------------------------------------------------------------------
195 // a2dCanvasObjectFilterSelected
196 //----------------------------------------------------------------------------
198 {
199  if ( m_maskedCanvasObject )
200  // all below a selected object will be rendered is right mask.
201  return canvasObject->CheckMask( m_mask );
202  else
203  {
204  if ( canvasObject->GetSelected() )
205  {
206  //switch on drawing, and remember the object where this happened
207  m_maskedCanvasObject = canvasObject;
208  ic.GetDrawer2D()->SetDisableDrawing( false );
209  return canvasObject->CheckMask( m_mask );
210  }
211  else
212  {
213  //all non selected will not be rendered.
214  return ic.GetDrawingPart()->GetShowObject() == canvasObject;
215  //canvasObject->CheckMask(m_mask);
216  }
217  /*
218  if ( canvasObject->GetHasSelectedObjectsBelow() )
219  {
220  if ( canvasObject->GetSelected() )
221  { //switch on drawing, and remember the object where this happened
222  m_maskedCanvasObject = canvasObject;
223  ic.GetDrawer2D()->SetDisableDrawing( false );
224  return canvasObject->CheckMask(m_mask);
225  }
226  else
227  {
228  return canvasObject->CheckMask(m_mask);
229  }
230  }
231  else
232  {
233  //all other parts of the drawing ( objects not selected), will be drawn, but invisible.
234  //so drawn invisible.
235  ic.GetDrawer2D()->SetDisableDrawing( true );
236  return false;
237  }
238  */
239  }
240 }
241 
243 {
244  //switch the filter back to non drawing when all children and the object
245  // itself are drawn.
246  if ( canvasObject == m_maskedCanvasObject )
247  {
248  m_maskedCanvasObject = NULL; //prepare for new search.
249  ic.GetDrawer2D()->SetDisableDrawing( true ); //blind drawing again
250  }
251 }
252 
253 //----------------------------------------------------------------------------
254 // a2dCanvasObjectFilterSelected2
255 //----------------------------------------------------------------------------
257 {
258  if ( m_maskedCanvasObject )
259  // all below a selected object will be rendered is right mask.
260  return canvasObject->CheckMask( m_mask );
261  else
262  {
263  if ( canvasObject->GetSelected2() )
264  {
265  //switch on drawing, and remember the object where this happened
266  m_maskedCanvasObject = canvasObject;
267  ic.GetDrawer2D()->SetDisableDrawing( false );
268  return canvasObject->CheckMask( m_mask );
269  }
270  else
271  {
272  //all non selected will not be rendered.
273  return ic.GetDrawingPart()->GetShowObject() == canvasObject;
274  //canvasObject->CheckMask(m_mask);
275  }
276  }
277 }
278 
280 {
281  //switch the filter back to non drawing when all children and the object
282  // itself are drawn.
283  if ( canvasObject == m_maskedCanvasObject )
284  {
285  m_maskedCanvasObject = NULL; //prepare for new search.
286  ic.GetDrawer2D()->SetDisableDrawing( true ); //blind drawing again
287  }
288 }
289 
290 //----------------------------------------------------------------------------
291 // a2dCanvasObjectFilterHighLighted
292 //----------------------------------------------------------------------------
294 {
295  if ( m_maskedCanvasObject )
296  // all below a selected object will be rendered is right mask.
297  return canvasObject->CheckMask( m_mask );
298  else
299  {
300  if ( canvasObject->GetHighLight() )
301  {
302  //switch on drawing, and remember the object where this happened
303  m_maskedCanvasObject = canvasObject;
304  ic.GetDrawer2D()->SetDisableDrawing( false );
305  return canvasObject->CheckMask( m_mask );
306  }
307  else
308  {
309  //all non selected will not be rendered.
310  return ic.GetDrawingPart()->GetShowObject() == canvasObject;
311  //canvasObject->CheckMask(m_mask);
312  }
313  /*
314  if ( canvasObject->GetHasSelectedObjectsBelow() )
315  {
316  if ( canvasObject->GetSelected() )
317  { //switch on drawing, and remember the object where this happened
318  m_maskedCanvasObject = canvasObject;
319  ic.GetDrawer2D()->SetDisableDrawing( false );
320  return canvasObject->CheckMask(m_mask);
321  }
322  else
323  {
324  return canvasObject->CheckMask(m_mask);
325  }
326  }
327  else
328  {
329  //all other parts of the drawing ( objects not selected), will be drawn, but invisible.
330  //so drawn invisible.
331  ic.GetDrawer2D()->SetDisableDrawing( true );
332  return false;
333  }
334  */
335  }
336 }
337 
339 {
340  //switch the filter back to non drawing when all children and the object
341  // itself are drawn.
342  if ( canvasObject == m_maskedCanvasObject )
343  {
344  m_maskedCanvasObject = NULL; //prepare for new search.
345  ic.GetDrawer2D()->SetDisableDrawing( true ); //blind drawing again
346  }
347 }
348 
349 //----------------------------------------------------------------------------
350 // a2dCanvasObjectFilterToolObjects
351 //----------------------------------------------------------------------------
353 {
354  if ( m_maskedCanvasObject )
355  return canvasObject->CheckMask( m_mask );
356  else
357  {
358  if ( canvasObject->GetHasToolObjectsBelow() )
359  {
360  if ( canvasObject->HasProperty( m_id ) )
361  {
362  //switch on drawing, and remember the object where this happened
363  m_maskedCanvasObject = canvasObject;
364  ic.GetDrawer2D()->SetDisableDrawing( false );
365  return canvasObject->CheckMask( m_mask );
366  }
367  else
368  {
369  return canvasObject->CheckMask( m_mask );
370  }
371  }
372  else
373  {
374  //all other parts of the drawing ( objects not selected), will be drawn, but invisible.
375  //so drawn invisible.
376  ic.GetDrawer2D()->SetDisableDrawing( true );
377  return false;
378  }
379  }
380 }
381 
383 {
384  //switch the filter back to non drawing when all children and the object
385  // itself are drawn.
386  if ( canvasObject == m_maskedCanvasObject )
387  {
388  m_maskedCanvasObject = NULL; //prepare for new search.
389  ic.GetDrawer2D()->SetDisableDrawing( true ); //blind drawing again
390  }
391 }
392 
393 //----------------------------------------------------------------------------
394 // a2dIterCU
395 //----------------------------------------------------------------------------
397 {
398  m_pp = ic.Push( matrix, clip );
399  m_iterC = &ic;
400 }
401 
403 {
404  m_pp = ic.Push( object, clip );
405  m_iterC = &ic;
406 }
407 
409 {
410  m_iterC->m_drawingPart->GetDrawer2D()->PopTransform();
411 
412  if ( !m_iterC->GetDeepestHit() )
413  m_iterC->m_contextListDeep.pop_back();
414 
415  m_iterC->m_contextList.pop_back();
416 }
417 
419 {
420 }
421 
422 //----------------------------------------------------------------------------
423 // a2dIterPP
424 //----------------------------------------------------------------------------
426 {
427  m_refcount = 0;
428 
429  m_localtransform = matrix;
430  m_objectLevel = false;
431  m_clip = clip;
432 
433  //m_iterC->m_drawingPart->GetDrawer2D()->PushTransform( matrix );
434  if( ic.m_contextList.size() )
435  {
436  m_object = NULL;
437 
438  m_relativetransform = ic.m_contextList.back()->m_relativetransform;
439  m_relativetransform *= matrix;
440  }
441  else
442  {
443  m_object = NULL;
444  m_relativetransform = matrix;
445  }
446 
447  if ( !ic.m_disableInvert )
448  {
451  }
452 }
453 
455 {
456  m_refcount = 0;
457  m_objectLevel = true;
458  m_clip = clip;
459  m_type = type;
460 
461  m_object = object;
462 
463  if( ic.m_contextList.size() )
464  {
465  m_relativetransform = ic.m_contextList.back()->m_relativetransform;
466  m_relativetransform *= object->GetTransformMatrix();
467  }
468  else
469  {
470  m_relativetransform *= object->GetTransformMatrix();
471  }
472  if ( !ic.m_disableInvert )
473  {
476  }
477 }
478 
480 {
481 }
482 
484 {
486  m_object = cu.m_object;
489 }
490 
491 //----------------------------------------------------------------------------
492 // a2dIterC
493 //----------------------------------------------------------------------------
494 
496 {
497  m_disableInvert = false;
498  m_levels = 0;
499  m_foundCorridorEnd = false;
500 
501  m_hitmargin_world = a2dCanvasGlobals->GetHabitat()->GetHitMarginWorld();
502  m_worldStrokeExtend = 0;
503 
504  m_drawingPart = new a2dDrawingPart( 100, 100, new a2dBlindDrawer2D() );
505  m_ownDrawer = true;
506  m_drawstyle = RenderLAYERED;
507  m_layer = wxLAYER_ALL;
508  m_perLayerMode = true;
509  m_generateCommands = false;
510  m_renderChildDerived = true;
511  m_updateHint = a2dCANVIEW_UPDATE_NON;
512 }
513 
514 a2dIterC::a2dIterC( a2dDrawingPart* drawer, int level )
515 {
516  // variables set by a2dIterPP
517  m_disableInvert = false;
518  m_levels = level;
519  m_foundCorridorEnd = false;
520 
521  m_drawingPart = drawer;
522  m_drawstyle = RenderLAYERED;
523 
524  m_usertodevice = drawer->GetDrawer2D()->GetUserToDeviceTransform();
525 
526  m_mapping = drawer->GetDrawer2D()->GetMappingMatrix();
527 
528  m_hitmargin_world = drawer->GetHitMarginWorld();
529  m_worldStrokeExtend = 0;
530  m_layer = 0;
531  m_generateCommands = false;
532  m_ownDrawer = false;
533  m_perLayerMode = true;
534  m_renderChildDerived = true;
535  m_updateHint = a2dCANVIEW_UPDATE_NON;
536 }
537 
539 {
540  //if ( m_ownDrawer )
541  // m_drawingPart->SetClosed();
542 }
543 
544 a2dIterPP* a2dIterC::Push( const a2dAffineMatrix& matrix, OVERLAP clip )
545 {
546  a2dIterPP* pp = new a2dIterPP( *this, matrix, clip );
547  m_contextList.push_back( pp );
548 
549  m_drawingPart->GetDrawer2D()->PushTransform( matrix );
550 
551  if ( !GetDeepestHit() )
552  {
553  a2dIterPP* cup = new a2dIterPP( *this, matrix, clip );
554  m_contextListDeep.push_back( cup );
555  }
556  return pp;
557 }
558 
559 a2dIterPP* a2dIterC::Push( a2dCanvasObject* object, OVERLAP clip )
560 {
561  a2dIterPP* pp = new a2dIterPP( *this, object );
562  m_contextList.push_back( pp );
563  m_levels++;
564 
565  m_drawingPart->GetDrawer2D()->PushTransform( object->GetTransformMatrix() );
566 
567  if ( !GetDeepestHit() )
568  {
569  a2dIterPP* cup = new a2dIterPP( *this, object );
570  m_contextListDeep.push_back( cup );
571  }
572  return pp;
573 }
574 
575 void a2dIterC::Pop()
576 {
577  m_drawingPart->GetDrawer2D()->PopTransform();
578 
579  if ( m_contextList.size () && m_contextList.back()->m_objectLevel )
580  m_levels--;
581 
582  if ( !GetDeepestHit() )
583  m_contextListDeep.pop_back();
584 
585  m_contextList.pop_back();
586 }
587 
589 {
590  m_worldStrokeExtend = 0;
591  m_perLayerMode = true;
592  m_renderChildDerived = true;
593  m_updateHint = a2dCANVIEW_UPDATE_NON;
594 }
595 
597 {
598  m_hitmargin_world = GetDrawer2D()->DeviceToWorldXRel( pixels );
599 }
600 
601 void a2dIterC::SetHitMarginWorld( double world )
602 {
603  m_hitmargin_world = world;
604 }
605 
607 {
608  return m_hitmargin_world;
609 }
610 
611 double a2dIterC::ExtendDeviceToWorld( int extend )
612 {
613  return GetDrawer2D()->DeviceToWorldXRel( extend );
614 }
615 
617 {
618  return GetInverseParentTransform().TransformDistance( m_hitmargin_world );
619 }
620 
622 {
623  return m_drawingPart->GetDrawer2D()->GetMappingMatrix();
624 }
625 
627 {
628  return m_drawingPart->GetDrawer2D()->GetUserToDeviceTransform();
629 }
630 
632 {
633  return m_drawingPart;
634 }
635 
637 {
638  return m_drawingPart->GetDrawer2D();
639 }
640 
642 {
643  if ( m_contextList.size() > 2 )
644  {
645  a2dSmrtPtrList< a2dIterPP >::const_iterator iter = m_contextList.end();
646  iter--;
647  iter--;
648  a2dIterPP* pp = *iter;
649  return pp->GetObject();
650  }
651  else
652  return NULL;
653 }
654 
656 {
657  if ( m_contextList.size() )
658  return m_contextList.back()->GetObject();
659  else
660  return NULL;
661 }
662 
664 {
665  if ( m_contextList.size() )
666  return m_contextList.back()->m_relativetransform;
667  else
669 }
670 
672 {
673  if ( m_contextList.size() )
674  return m_contextList.back()->m_clip;
675  else
676  return _IN;
677 }
678 
680 {
681  if ( m_contextList.size() > 2 )
682  {
683  a2dSmrtPtrList< a2dIterPP >::const_iterator iter = m_contextList.end();
684  iter--;
685  iter--;
686  a2dIterPP* pp = *iter;
687  return pp->m_clip;
688  }
689  else
690  return _ON;
691 }
692 
694 {
695  if ( m_contextList.size() )
696  m_contextList.back()->m_clip = status;
697 }
698 
700 {
701  assert( !m_disableInvert );
702 
703  if ( m_contextList.size() )
704  return m_contextList.back()->m_inverseRelativetransform;
705  else
707 }
708 
710 {
711  if ( m_contextList.size() > 2 )
712  {
713  a2dSmrtPtrList< a2dIterPP >::const_iterator iter = m_contextList.end();
714  iter--;
715  iter--;
716  a2dIterPP* pp = *iter;
717  return pp->m_relativetransform;
718  }
719  else
721 }
722 
724 {
725  assert( !m_disableInvert );
726 
727  if ( m_contextList.size() > 2 )
728  {
729  a2dSmrtPtrList< a2dIterPP >::const_iterator iter = m_contextList.end();
730  iter--;
731  iter--;
732  a2dIterPP* pp = *iter;
733  return pp->m_inverseRelativetransform;
734  }
735  else
737 }
738 
739 void a2dIterC::SetCorridorPath( bool OnOff, a2dCanvasObject* captureObject )
740 {
742 
743  m_foundCorridorEnd = false;
744 
745  for( a2dSmrtPtrList< a2dIterPP >::iterator iter = m_contextList.begin(); iter != m_contextList.end(); iter++ )
746  {
747  a2dIterPP* pp = *iter;
748  a2dCanvasObject* obj = pp->GetObject();
749  if ( obj )
750  {
751  obj->SetIsOnCorridorPath( OnOff );
752  //wxLogDebug( "corridor %s ", iter->m_object->GetClassInfo()->GetClassName() );
753  }
754  }
755 
756  if ( OnOff )
757  {
758  //wxLogDebug( "on" );
759  if ( m_contextList.size() )
760  GetDrawingPart()->SetEndCorridorObject( m_contextList.back()->m_object );
761  else
762  GetDrawingPart()->SetEndCorridorObject( GetDrawingPart()->GetShowObject() );
763 
764  GetDrawingPart()->SetCaptured( captureObject );
765  }
766  else
767  {
768  //wxLogDebug( "off" );
770  GetDrawingPart()->SetCaptured( NULL );
771  }
772 }
773 
774 void a2dIterC::SetCorridorPathToParent()
775 {
776  m_foundCorridorEnd = false;
777 
778  for( a2dSmrtPtrList< a2dIterPP >::iterator iter = m_contextList.begin(); iter != m_contextList.end(); iter++ )
779  {
780  a2dIterPP* pp = *iter;
781  a2dCanvasObject* obj = pp->GetObject();
782  if ( obj )
783  {
784  obj->SetIsOnCorridorPath( true );
785  //wxLogDebug( "corridor %s ", iter->m_object->GetClassInfo()->GetClassName() );
786  }
787  }
788  if ( m_contextList.back()->m_object )
789  m_contextList.back()->m_object->SetIsOnCorridorPath( false );
790 
791  //wxLogDebug( "on" );
792  if ( GetParent() )
794  else
795  GetDrawingPart()->SetEndCorridorObject( GetDrawingPart()->GetShowObject() );
796  GetDrawingPart()->SetCaptured( NULL );
797 }
798 
800 {
801  m_foundCorridorEnd = false;
802  if ( m_contextList.back()->m_object )
803  GetDrawingPart()->SetEndCorridorObject( m_contextList.back()->m_object );
804  else
805  GetDrawingPart()->SetEndCorridorObject( GetDrawingPart()->GetShowObject() );
806  GetDrawingPart()->SetCaptured( captureObject );
807 }
808 
810 {
811  if ( m_objectFilter )
812  return m_objectFilter->Filter( *this, canvasObject );
813  else
814  return true;
815 }
816 
818 {
819  if ( m_objectFilter )
820  m_objectFilter->EndFilter( *this, canvasObject );
821 }
822 
823 //----------------------------------------------------------------------------
824 // a2dExtendedResult
825 //----------------------------------------------------------------------------
826 
827 
829 {
830 }
831 
833 {
834 }
835 
836 //----------------------------------------------------------------------------
837 // a2dCanvasObject
838 //----------------------------------------------------------------------------
839 
840 bool operator < ( const a2dSmrtPtr<a2dCanvasObject>& a, const a2dSmrtPtr<a2dCanvasObject>& b )
841 {
842  return ( *( s_a2dCanvasObjectSorter ) ) ( a, b );
843 }
844 
845 a2dCanvasObjectSorter s_a2dCanvasObjectSorter = NULL;
846 
848 
849 a2dPropertyIdMatrix* a2dCanvasObject::PROPID_TransformMatrix = NULL;
850 a2dPropertyIdPoint2D* a2dCanvasObject::PROPID_Position = NULL;
851 a2dPropertyIdUint16* a2dCanvasObject::PROPID_Layer = NULL;
852 a2dPropertyIdBool* a2dCanvasObject::PROPID_Selected = NULL;
853 a2dPropertyIdBool* a2dCanvasObject::PROPID_Selectable = NULL;
854 a2dPropertyIdBool* a2dCanvasObject::PROPID_SubEdit = NULL;
855 a2dPropertyIdBool* a2dCanvasObject::PROPID_SubEditAsChild = NULL;
856 a2dPropertyIdBool* a2dCanvasObject::PROPID_Visible = NULL;
857 a2dPropertyIdBool* a2dCanvasObject::PROPID_Draggable = NULL;
858 a2dPropertyIdBool* a2dCanvasObject::PROPID_Showshadow = NULL;
859 a2dPropertyIdBool* a2dCanvasObject::PROPID_Filled = NULL;
860 a2dPropertyIdBool* a2dCanvasObject::PROPID_GroupA = NULL;
861 a2dPropertyIdBool* a2dCanvasObject::PROPID_GroupB = NULL;
862 a2dPropertyIdBool* a2dCanvasObject::PROPID_GeneratePins = NULL;
863 a2dPropertyIdBool* a2dCanvasObject::PROPID_Bin = NULL;
864 a2dPropertyIdBool* a2dCanvasObject::PROPID_Bin2 = NULL;
865 a2dPropertyIdBool* a2dCanvasObject::PROPID_Pending = NULL;
866 a2dPropertyIdBool* a2dCanvasObject::PROPID_Snap = NULL;
867 a2dPropertyIdBool* a2dCanvasObject::PROPID_SnapTo = NULL;
868 a2dPropertyIdBool* a2dCanvasObject::PROPID_Pushin = NULL;
869 a2dPropertyIdBool* a2dCanvasObject::PROPID_Prerenderaschild = NULL;
870 a2dPropertyIdBool* a2dCanvasObject::PROPID_Visiblechilds = NULL;
871 a2dPropertyIdBool* a2dCanvasObject::PROPID_Editable = NULL;
872 a2dPropertyIdBool* a2dCanvasObject::PROPID_Editing = NULL;
873 a2dPropertyIdBool* a2dCanvasObject::PROPID_EditingRender = NULL;
874 a2dPropertyIdBool* a2dCanvasObject::PROPID_ChildrenOnSameLayer = NULL;
875 a2dPropertyIdBool* a2dCanvasObject::PROPID_DoConnect = NULL;
876 a2dPropertyIdBool* a2dCanvasObject::PROPID_IsOnCorridorPath = NULL;
877 a2dPropertyIdBool* a2dCanvasObject::PROPID_HasPins = NULL;
878 a2dPropertyIdBool* a2dCanvasObject::PROPID_IsProperty = NULL;
879 a2dPropertyIdBool* a2dCanvasObject::PROPID_MouseInObject = NULL;
880 a2dPropertyIdBool* a2dCanvasObject::PROPID_HighLight = NULL;
881 a2dPropertyIdBool* a2dCanvasObject::PROPID_Template = NULL;
882 a2dPropertyIdBool* a2dCanvasObject::PROPID_External = NULL;
883 a2dPropertyIdBool* a2dCanvasObject::PROPID_Used = NULL;
884 a2dPropertyIdBool* a2dCanvasObject::PROPID_Release = NULL;
885 a2dPropertyIdCanvasObject* a2dCanvasObject::PROPID_Begin = NULL;
886 a2dPropertyIdCanvasObject* a2dCanvasObject::PROPID_End = NULL;
887 a2dPropertyIdDouble* a2dCanvasObject::PROPID_EndScaleX = NULL;
888 a2dPropertyIdDouble* a2dCanvasObject::PROPID_EndScaleY = NULL;
889 a2dPropertyIdBool* a2dCanvasObject::PROPID_Spline = NULL;
890 a2dPropertyIdDouble* a2dCanvasObject::PROPID_ContourWidth = NULL;
891 a2dPropertyIdBool* a2dCanvasObject::PROPID_DisableFeedback = NULL;
892 a2dPropertyIdBool* a2dCanvasObject::PROPID_Allowrotation = NULL;
893 a2dPropertyIdBool* a2dCanvasObject::PROPID_Allowsizing = NULL;
894 a2dPropertyIdBool* a2dCanvasObject::PROPID_Allowskew = NULL;
895 a2dPropertyIdBool* a2dCanvasObject::PROPID_IncludeChildren = NULL;
896 a2dPropertyIdRefObjectAutoZero* a2dCanvasObject::PROPID_Controller = NULL;
897 a2dPropertyIdCanvasObject* a2dCanvasObject::PROPID_Original = NULL;
898 a2dPropertyIdCanvasObject* a2dCanvasObject::PROPID_Editcopy = NULL;
899 a2dPropertyIdCanvasObject* a2dCanvasObject::PROPID_Parent = NULL;
900 a2dPropertyIdCanvasObject* a2dCanvasObject::PROPID_Objecttip = NULL;
901 a2dPropertyIdUint16* a2dCanvasObject::PROPID_Editmode = NULL;
902 a2dPropertyIdUint16* a2dCanvasObject::PROPID_Editstyle = NULL;
903 a2dPropertyIdUint16* a2dCanvasObject::PROPID_Index = NULL;
904 a2dPropertyIdCanvasShadowStyle* a2dCanvasObject::PROPID_Shadowstyle = NULL;
905 a2dPropertyIdFill* a2dCanvasObject::PROPID_Fill = NULL;
906 a2dPropertyIdStroke* a2dCanvasObject::PROPID_Stroke = NULL;
907 a2dPropertyIdUint32* a2dCanvasObject::PROPID_RefDesCount = NULL;
908 a2dPropertyIdUint32* a2dCanvasObject::PROPID_RefDesNr = NULL;
913 a2dPropertyIdColour* a2dCanvasObject::PROPID_StrokeColour = NULL;
914 a2dPropertyIdColour* a2dCanvasObject::PROPID_FillColour = NULL;
921 a2dPropertyIdDateTime* a2dCanvasObject::PROPID_ModificationDateTime = NULL;
922 a2dPropertyIdDateTime* a2dCanvasObject::PROPID_AccessDateTime = NULL;
926 
927 //INITIALIZE_PROPERTIES( a2dCanvasObject, a2dObject )
928 a2dDynamicIdMap& a2dCanvasObject::GetPropertyIdMap()
929 {
930  return sm_dymPropIds;
931 }
932 bool a2dCanvasObject::AddPropertyId( a2dPropertyId* dynproperty )
933 {
934  if ( sm_dymPropIds.find( dynproperty->GetName() ) == sm_dymPropIds.end() )
935  sm_dymPropIds[ dynproperty->GetName() ] = dynproperty;
936  else
937  wxASSERT_MSG( 0, _( "The property id name '" ) + dynproperty->GetName() + _( "' already exists in #a2dCanvasObject" ) );
938  return true;
939 }
940 bool a2dCanvasObject::HasPropertyId( const a2dPropertyId* id ) const
941 {
942  a2dDynamicIdMap::iterator iter = sm_dymPropIds.find( id->GetName() );
943  if ( iter != sm_dymPropIds.end() )
944  return true;
945  return a2dObject::HasPropertyId( id );
946 }
947 a2dPropertyId* a2dCanvasObject::HasPropertyId( const wxString& name )
948 {
949  a2dDynamicIdMap::iterator iter = sm_dymPropIds.find( name );
950  if ( iter != sm_dymPropIds.end() )
951  return sm_dymPropIds[ name ];
952 
953  return a2dObject::HasPropertyId( name );
954 }
955 const a2dNamedProperty* a2dCanvasObject::FindProperty( const wxString& idName ) const
956 {
957  a2dDynamicIdMap::iterator iter = sm_dymPropIds.find( idName );
958  if ( iter != sm_dymPropIds.end() )
959  {
960  a2dPropertyIdPtr propId = ( *iter ).second;
961  /* if ( propId->GetName() == idName ) //assume right */
962  return GetProperty( propId );
963  }
964  return a2dObject::FindProperty( idName );
965 }
966 void a2dCanvasObject::CollectProperties2( a2dNamedPropertyList* total, const a2dPropertyId* id, a2dPropertyId::Flags flags ) const
967 {
968  for ( a2dDynamicIdMap::iterator i = sm_dymPropIds.begin(); i != sm_dymPropIds.end(); i++ )
969  {
970  //wxString name = ( *i ).first;
971  a2dPropertyIdPtr p = ( *i ).second;
972  if( p->CheckCollect( id, flags ) )
973  {
974  a2dNamedProperty* dprop = p->GetPropertyAsNamedProperty( this );
975  if ( dprop )
976  total->push_back( dprop );
977  }
978  }
979  return a2dObject::CollectProperties2( total, id, flags );
980 }
981 a2dDynamicIdMap a2dCanvasObject::sm_dymPropIds;
982 static bool initPropa2dCanvasObject = a2dCanvasObject::InitializePropertyIds();
983 bool a2dCanvasObject::InitializePropertyIds()
984 {
985  PROPID_TransformMatrix = new a2dPropertyIdMatrix( wxT( "TransformMatrix" ),
987  a2dPropertyIdMatrix::Get( &a2dCanvasObject::GetTransform ),
988  a2dPropertyIdMatrix::Set( &a2dCanvasObject::SetTransform ) );
989  AddPropertyId( PROPID_TransformMatrix );
990 
991  PROPID_Position = new a2dPropertyIdPoint2D( wxT( "Position" ),
993  a2dPropertyIdPoint2D::Get( &a2dCanvasObject::GetPosXY ),
994  a2dPropertyIdPoint2D::ConstSet( &a2dCanvasObject::SetPosXyPoint ) );
995  AddPropertyId( PROPID_Position );
996 
997  PROPID_Layer = new a2dPropertyIdUint16( wxT( "Layer" ),
999  a2dPropertyIdUint16::Get( &a2dCanvasObject::GetLayer ),
1000  a2dPropertyIdUint16::Set( &a2dCanvasObject::SetLayer ) );
1001  AddPropertyId( PROPID_Layer );
1002 
1003  PROPID_Selected = new a2dPropertyIdBool( wxT( "Selected" ),
1004  a2dPropertyId::flag_none, false,
1005  a2dPropertyIdBool::Get( &a2dCanvasObject::GetSelected ),
1006  a2dPropertyIdBool::Set( &a2dCanvasObject::SetSelected ) );
1007  AddPropertyId( PROPID_Selected );
1008 
1009  PROPID_Selectable = new a2dPropertyIdBool( wxT( "Selectable" ),
1010  a2dPropertyId::flag_none, false,
1011  a2dPropertyIdBool::Get( &a2dCanvasObject::GetSelectable ),
1012  a2dPropertyIdBool::Set( &a2dCanvasObject::SetSelectable ) );
1013  AddPropertyId( PROPID_Selectable );
1014 
1015  PROPID_SubEdit = new a2dPropertyIdBool( wxT( "SubEdit" ),
1016  a2dPropertyId::flag_none, false,
1017  a2dPropertyIdBool::Get( &a2dCanvasObject::GetSubEdit ),
1018  a2dPropertyIdBool::Set( &a2dCanvasObject::SetSubEdit ) );
1019  AddPropertyId( PROPID_SubEdit );
1020 
1021  PROPID_SubEditAsChild = new a2dPropertyIdBool( wxT( "SubEditAsChild" ),
1022  a2dPropertyId::flag_none, false,
1023  a2dPropertyIdBool::Get( &a2dCanvasObject::GetSubEditAsChild ),
1024  a2dPropertyIdBool::Set( &a2dCanvasObject::SetSubEditAsChild ) );
1025  AddPropertyId( PROPID_SubEditAsChild );
1026 
1027  PROPID_Visible = new a2dPropertyIdBool( wxT( "Visible" ),
1028  a2dPropertyId::flag_none, false,
1029  a2dPropertyIdBool::Get( &a2dCanvasObject::GetVisible ),
1030  a2dPropertyIdBool::Set( &a2dCanvasObject::SetVisible ) );
1031  AddPropertyId( PROPID_Visible );
1032 
1033  PROPID_Draggable = new a2dPropertyIdBool( wxT( "Draggable" ),
1034  a2dPropertyId::flag_none, false,
1035  a2dPropertyIdBool::Get( &a2dCanvasObject::GetDraggable ),
1036  a2dPropertyIdBool::Set( &a2dCanvasObject::SetDraggable ) );
1037  AddPropertyId( PROPID_Draggable );
1038 
1039  PROPID_Showshadow = new a2dPropertyIdBool( wxT( "Showshadow" ),
1040  a2dPropertyId::flag_none, false,
1041  a2dPropertyIdBool::Get( &a2dCanvasObject::GetShowshadow ),
1042  a2dPropertyIdBool::Set( &a2dCanvasObject::SetShowshadow ) );
1043  AddPropertyId( PROPID_Showshadow );
1044 
1045  PROPID_Filled = new a2dPropertyIdBool( wxT( "Filled" ),
1046  a2dPropertyId::flag_none, false,
1047  a2dPropertyIdBool::Get( &a2dCanvasObject::GetFilled ),
1048  a2dPropertyIdBool::Set( &a2dCanvasObject::SetFilled ) );
1049  AddPropertyId( PROPID_Filled );
1050 
1051  PROPID_GroupA = new a2dPropertyIdBool( wxT( "GroupA" ),
1052  a2dPropertyId::flag_none, false,
1053  a2dPropertyIdBool::Get( &a2dCanvasObject::GetGroupA ),
1054  a2dPropertyIdBool::Set( &a2dCanvasObject::SetGroupA ) );
1055  AddPropertyId( PROPID_GroupA );
1056 
1057  PROPID_GroupB = new a2dPropertyIdBool( wxT( "GroupB" ),
1058  a2dPropertyId::flag_none, false,
1059  a2dPropertyIdBool::Get( &a2dCanvasObject::GetGroupB ),
1060  a2dPropertyIdBool::Set( &a2dCanvasObject::SetGroupB ) );
1061  AddPropertyId( PROPID_GroupB );
1062 
1063  PROPID_GeneratePins = new a2dPropertyIdBool( wxT( "GeneratePins" ),
1064  a2dPropertyId::flag_none, false,
1065  a2dPropertyIdBool::Get( &a2dCanvasObject::GetGeneratePins ),
1066  a2dPropertyIdBool::Set( &a2dCanvasObject::SetGeneratePins ) );
1067  AddPropertyId( PROPID_GeneratePins );
1068 
1069  PROPID_Bin = new a2dPropertyIdBool( wxT( "Bin" ),
1070  a2dPropertyId::flag_none, false,
1071  a2dPropertyIdBool::Get( &a2dCanvasObject::GetBin ),
1072  a2dPropertyIdBool::Set( &a2dCanvasObject::SetBin ) );
1073  AddPropertyId( PROPID_Bin );
1074 
1075  PROPID_Bin2 = new a2dPropertyIdBool( wxT( "Bin2" ),
1076  a2dPropertyId::flag_none, false,
1077  a2dPropertyIdBool::Get( &a2dCanvasObject::GetBin2 ),
1078  a2dPropertyIdBool::Set( &a2dCanvasObject::SetBin2 ) );
1079  AddPropertyId( PROPID_Bin2 );
1080 
1081  PROPID_Pending = new a2dPropertyIdBool( wxT( "Pending" ),
1082  a2dPropertyId::flag_none, false,
1083  a2dPropertyIdBool::Get( &a2dCanvasObject::GetPending ),
1084  a2dPropertyIdBool::Set( &a2dCanvasObject::SetPending ) );
1085  AddPropertyId( PROPID_Pending );
1086 
1087  PROPID_Snap = new a2dPropertyIdBool( wxT( "Snap" ),
1088  a2dPropertyId::flag_none, false,
1089  a2dPropertyIdBool::Get( &a2dCanvasObject::GetSnap ),
1090  a2dPropertyIdBool::Set( &a2dCanvasObject::SetSnap ) );
1091  AddPropertyId( PROPID_Snap );
1092 
1093  PROPID_SnapTo = new a2dPropertyIdBool( wxT( "SnapTo" ),
1094  a2dPropertyId::flag_none, false,
1095  a2dPropertyIdBool::Get( &a2dCanvasObject::GetSnapTo ),
1096  a2dPropertyIdBool::Set( &a2dCanvasObject::SetSnapTo ) );
1097  AddPropertyId( PROPID_SnapTo );
1098 
1099  PROPID_Pushin = new a2dPropertyIdBool( wxT( "Pushin" ),
1100  a2dPropertyId::flag_none, false,
1101  a2dPropertyIdBool::Get( &a2dCanvasObject::GetPushin ),
1102  a2dPropertyIdBool::Set( &a2dCanvasObject::SetPushin ) );
1103  AddPropertyId( PROPID_Pushin );
1104 
1105  PROPID_Prerenderaschild = new a2dPropertyIdBool( wxT( "Prerenderaschild" ),
1106  a2dPropertyId::flag_none, false,
1107  a2dPropertyIdBool::Get( &a2dCanvasObject::GetPrerenderaschild ),
1108  a2dPropertyIdBool::Set( &a2dCanvasObject::SetPrerenderaschild ) );
1109  AddPropertyId( PROPID_Prerenderaschild );
1110 
1111  PROPID_Visiblechilds = new a2dPropertyIdBool( wxT( "Visiblechilds" ),
1112  a2dPropertyId::flag_none, false,
1113  a2dPropertyIdBool::Get( &a2dCanvasObject::GetVisiblechilds ),
1114  a2dPropertyIdBool::Set( &a2dCanvasObject::SetVisiblechilds ) );
1115  AddPropertyId( PROPID_Visiblechilds );
1116 
1117  PROPID_Editable = new a2dPropertyIdBool( wxT( "Editable" ),
1118  a2dPropertyId::flag_none, false,
1119  a2dPropertyIdBool::Get( &a2dCanvasObject::GetEditable ),
1120  a2dPropertyIdBool::Set( &a2dCanvasObject::SetEditable ) );
1121  AddPropertyId( PROPID_Editable );
1122 
1123  PROPID_Editing = new a2dPropertyIdBool( wxT( "Editing" ),
1124  a2dPropertyId::flag_none, false,
1125  a2dPropertyIdBool::Get( &a2dCanvasObject::GetEditing ),
1126  a2dPropertyIdBool::Set( &a2dCanvasObject::SetEditing ) );
1127  AddPropertyId( PROPID_Editing );
1128 
1129  PROPID_EditingRender = new a2dPropertyIdBool( wxT( "EditingRender" ),
1130  a2dPropertyId::flag_none, false,
1131  a2dPropertyIdBool::Get( &a2dCanvasObject::GetEditingRender ),
1132  a2dPropertyIdBool::Set( &a2dCanvasObject::SetEditingRender ) );
1133  AddPropertyId( PROPID_EditingRender );
1134 
1135  PROPID_ChildrenOnSameLayer = new a2dPropertyIdBool( wxT( "ChildrenOnSameLayer" ),
1136  a2dPropertyId::flag_none, false,
1137  a2dPropertyIdBool::Get( &a2dCanvasObject::GetChildrenOnSameLayer ),
1138  a2dPropertyIdBool::Set( &a2dCanvasObject::SetChildrenOnSameLayer ) );
1139  AddPropertyId( PROPID_ChildrenOnSameLayer );
1140 
1141  PROPID_DoConnect = new a2dPropertyIdBool( wxT( "DoConnect" ),
1142  a2dPropertyId::flag_none, false,
1143  a2dPropertyIdBool::Get( &a2dCanvasObject::GetDoConnect ),
1144  a2dPropertyIdBool::Set( &a2dCanvasObject::SetDoConnect ) );
1145  AddPropertyId( PROPID_DoConnect );
1146 
1147  PROPID_IsOnCorridorPath = new a2dPropertyIdBool( wxT( "IsOnCorridorPath" ),
1148  a2dPropertyId::flag_none, false,
1149  a2dPropertyIdBool::Get( &a2dCanvasObject::GetIsOnCorridorPath ),
1150  a2dPropertyIdBool::Set( &a2dCanvasObject::SetIsOnCorridorPath ) );
1151  AddPropertyId( PROPID_IsOnCorridorPath );
1152 
1153  PROPID_HasPins = new a2dPropertyIdBool( wxT( "HasPins" ),
1154  a2dPropertyId::flag_none, false,
1155  a2dPropertyIdBool::Get( &a2dCanvasObject::GetHasPins ),
1156  a2dPropertyIdBool::Set( &a2dCanvasObject::SetHasPins ) );
1157  AddPropertyId( PROPID_HasPins );
1158 
1159  PROPID_IsProperty = new a2dPropertyIdBool( wxT( "IsProperty" ),
1160  a2dPropertyId::flag_none, false,
1161  a2dPropertyIdBool::Get( &a2dCanvasObject::GetIsProperty ),
1162  a2dPropertyIdBool::Set( &a2dCanvasObject::SetIsProperty ) );
1163  AddPropertyId( PROPID_IsProperty );
1164 
1165  PROPID_MouseInObject = new a2dPropertyIdBool( wxT( "MouseInObject" ),
1166  a2dPropertyId::flag_none, false,
1167  a2dPropertyIdBool::Get( &a2dCanvasObject::GetMouseInObject ),
1168  a2dPropertyIdBool::Set( &a2dCanvasObject::SetMouseInObject ) );
1169  AddPropertyId( PROPID_MouseInObject );
1170 
1171  PROPID_HighLight = new a2dPropertyIdBool( wxT( "HighLight" ),
1173  a2dPropertyIdBool::Get( &a2dCanvasObject::GetHighLight ),
1174  a2dPropertyIdBool::Set( &a2dCanvasObject::SetHighLight ) );
1175  AddPropertyId( PROPID_HighLight );
1176 
1177  PROPID_Template = new a2dPropertyIdBool( wxT( "Template" ),
1178  a2dPropertyId::flag_none, false,
1179  a2dPropertyIdBool::Get( &a2dCanvasObject::GetTemplate ),
1180  a2dPropertyIdBool::Set( &a2dCanvasObject::SetTemplate ) );
1181  AddPropertyId( PROPID_Template );
1182 
1183  PROPID_External = new a2dPropertyIdBool( wxT( "External" ),
1184  a2dPropertyId::flag_none, false,
1185  a2dPropertyIdBool::Get( &a2dCanvasObject::GetExternal ),
1186  a2dPropertyIdBool::Set( &a2dCanvasObject::SetExternal ) );
1187  AddPropertyId( PROPID_External );
1188 
1189  PROPID_Used = new a2dPropertyIdBool( wxT( "Used" ),
1190  a2dPropertyId::flag_none, false,
1191  a2dPropertyIdBool::Get( &a2dCanvasObject::GetUsed ),
1192  a2dPropertyIdBool::Set( &a2dCanvasObject::SetUsed ) );
1193  AddPropertyId( PROPID_Used );
1194 
1195  PROPID_Release = new a2dPropertyIdBool( wxT( "Release" ),
1196  a2dPropertyId::flag_none, false,
1197  a2dPropertyIdBool::Get( &a2dCanvasObject::GetRelease ),
1198  a2dPropertyIdBool::Set( &a2dCanvasObject::SetRelease ) );
1199  AddPropertyId( PROPID_Release );
1200 
1201  PROPID_DisableFeedback = new a2dPropertyIdBool( wxT( "DisableFeedback" ),
1202  a2dPropertyId::flag_none, false );
1203  AddPropertyId( PROPID_DisableFeedback );
1204 
1205  PROPID_Allowrotation = new a2dPropertyIdBool( wxT( "Allowrotation" ),
1206  a2dPropertyId::flag_none, false );
1207  AddPropertyId( PROPID_Allowrotation );
1208 
1209  PROPID_Allowsizing = new a2dPropertyIdBool( wxT( "Allowsizing" ),
1210  a2dPropertyId::flag_none, false );
1211  AddPropertyId( PROPID_Allowsizing );
1212 
1213  PROPID_Allowskew = new a2dPropertyIdBool( wxT( "Allowskew" ),
1214  a2dPropertyId::flag_none, false );
1215  AddPropertyId( PROPID_Allowskew );
1216 
1217  PROPID_IncludeChildren = new a2dPropertyIdBool( wxT( "IncludeChildren" ),
1218  a2dPropertyId::flag_none, false );
1219  AddPropertyId( PROPID_IncludeChildren );
1220 
1221  //! set for objects that act as tool decorations, when a tool is in action.
1222  PROPID_ToolDecoration = new a2dPropertyIdBool( wxT( "ToolDecoration" ),
1223  a2dPropertyId::flag_none, false );
1224  AddPropertyId( PROPID_ToolDecoration );
1225 
1226  //! set for objects that do not have to be saved
1227  PROPID_TemporaryObject = new a2dPropertyIdBool( wxT( "TemporaryObject" ),
1228  a2dPropertyId::flag_none, false );
1229  AddPropertyId( PROPID_TemporaryObject );
1230 
1231  //! set in Startedit(), to be used to detect first (mouse)event sent to object.
1232  PROPID_FirstEventInObject = new a2dPropertyIdBool( wxT( "FirstEventInObject" ),
1233  a2dPropertyId::flag_none, false );
1234  AddPropertyId( PROPID_FirstEventInObject );
1235 
1236  PROPID_Begin = new a2dPropertyIdCanvasObject( wxT( "Begin" ),
1238  AddPropertyId( PROPID_Begin );
1239 
1240  PROPID_End = new a2dPropertyIdCanvasObject( wxT( "End" ),
1242  AddPropertyId( PROPID_End );
1243 
1244  PROPID_EndScaleX = new a2dPropertyIdDouble( wxT( "EndScaleX" ),
1246  AddPropertyId( PROPID_EndScaleX );
1247 
1248  PROPID_EndScaleY = new a2dPropertyIdDouble( wxT( "EndScaleY" ),
1250  AddPropertyId( PROPID_EndScaleY );
1251 
1252  PROPID_Spline = new a2dPropertyIdBool( wxT( "Spline" ),
1254  AddPropertyId( PROPID_Spline );
1255 
1256  PROPID_ContourWidth = new a2dPropertyIdDouble( wxT( "ContourWidth" ),
1258  a2dPropertyIdDouble::Get( &a2dCanvasObject::GetContourWidth ),
1259  a2dPropertyIdDouble::Set( &a2dCanvasObject::SetContourWidth ) );
1260  AddPropertyId( PROPID_ContourWidth );
1261 
1262  PROPID_Original = new a2dPropertyIdCanvasObject( wxT( "Original" ),
1264  AddPropertyId( PROPID_Original );
1265 
1266  PROPID_Editcopy = new a2dPropertyIdCanvasObject( wxT( "Editcopy" ),
1268  AddPropertyId( PROPID_Editcopy );
1269 
1270  PROPID_Parent = new a2dPropertyIdCanvasObject( wxT( "Parent" ),
1272  AddPropertyId( PROPID_Parent );
1273 
1274  PROPID_Objecttip = new a2dPropertyIdCanvasObject( wxT( "Objecttip" ),
1276  AddPropertyId( PROPID_Objecttip );
1277 
1278  PROPID_Controller = new a2dPropertyIdRefObjectAutoZero( wxT( "Controller" ),
1280  AddPropertyId( PROPID_Controller );
1281 
1282  PROPID_Editmode = new a2dPropertyIdUint16( wxT( "Editmode" ),
1284  AddPropertyId( PROPID_Editmode );
1285 
1286  PROPID_Editstyle = new a2dPropertyIdUint16( wxT( "Editstyle" ),
1288  AddPropertyId( PROPID_Editstyle );
1289 
1290  PROPID_Index = new a2dPropertyIdUint16( wxT( "Index" ),
1292  AddPropertyId( PROPID_Index );
1293  PROPID_Index = PROPID_Index;
1294 
1295  PROPID_RefDesCount = new a2dPropertyIdUint32( wxT( "RefDesCount" ),
1297  AddPropertyId( PROPID_RefDesCount );
1298 
1299  PROPID_RefDesNr = new a2dPropertyIdUint32( wxT( "RefDesNr" ),
1301  AddPropertyId( PROPID_RefDesNr );
1302 
1303  PROPID_Shadowstyle = new a2dPropertyIdCanvasShadowStyle( wxT( "Shadowstyle" ),
1305  AddPropertyId( PROPID_Shadowstyle );
1306 
1307  PROPID_Fill = new a2dPropertyIdFill( wxT( "Fill" ),
1309  *a2dNullFILL, static_cast < a2dPropertyIdFill::ConstGet >( &a2dCanvasObject::MX_GetFill ), static_cast < a2dPropertyIdFill::ConstSet >( &a2dCanvasObject::MX_SetFill ) );
1310  AddPropertyId( PROPID_Fill );
1311 
1312  PROPID_Stroke = new a2dPropertyIdStroke( wxT( "Stroke" ),
1314  *a2dNullSTROKE, static_cast < a2dPropertyIdStroke::ConstGet >( &a2dCanvasObject::MX_GetStroke ), static_cast < a2dPropertyIdStroke::ConstSet >( &a2dCanvasObject::MX_SetStroke ) );
1315  AddPropertyId( PROPID_Stroke );
1316 
1317  PROPID_ToolObject = new a2dPropertyIdVoidPtr( wxT( "ToolObject" ),
1319  AddPropertyId( PROPID_ToolObject );
1320 
1321  PROPID_BoundingBox = new a2dPropertyIdBoundingBox( wxT( "BoundingBox" ),
1323  AddPropertyId( PROPID_BoundingBox );
1324 
1325  PROPID_FillColour = new a2dPropertyIdColour( wxT( "FillColour" ), a2dPropertyId::flag_none, wxColour(),
1326  static_cast < a2dPropertyIdColour::Get >( &a2dCanvasObject::GetFillColour ), static_cast < a2dPropertyIdColour::ConstSet >( &a2dCanvasObject::SetFillColour ) );
1327  AddPropertyId( PROPID_FillColour );
1328 
1329  PROPID_StrokeColour = new a2dPropertyIdColour( wxT( "StrokeColour" ), a2dPropertyId::flag_none, wxColour(),
1330  static_cast < a2dPropertyIdColour::Get >( &a2dCanvasObject::GetStrokeColour ), static_cast < a2dPropertyIdColour::ConstSet >( &a2dCanvasObject::SetStrokeColour ) );
1331  AddPropertyId( PROPID_StrokeColour );
1332 
1334  AddPropertyId( PROPID_ViewSpecific );
1335 
1337  AddPropertyId( PROPID_ViewDependent );
1338 
1340  AddPropertyId( PROPID_IntViewDependTransform );
1341 
1342  PROPID_Datatype = new a2dPropertyIdUint16( wxT( "Datatype" ), a2dPropertyId::flag_none, 0 );
1343  AddPropertyId( PROPID_Datatype );
1344 
1345  PROPID_DateTime = new a2dPropertyIdDateTime( wxT( "DateTime" ),
1347  AddPropertyId( PROPID_DateTime );
1348 
1349  PROPID_ModificationDateTime = new a2dPropertyIdDateTime( wxT( "ModificationDateTime" ),
1351  AddPropertyId( PROPID_ModificationDateTime );
1352 
1353  PROPID_AccessDateTime = new a2dPropertyIdDateTime( wxT( "AccessDateTime" ),
1355  AddPropertyId( PROPID_AccessDateTime );
1356 
1358  AddPropertyId( PROPID_PopupMenu );
1359 
1361  AddPropertyId( PROPID_TipWindow );
1362 
1364  AddPropertyId( PROPID_Tags );
1365 
1366  return true;
1367 }
1368 
1371  (
1375 
1376  );
1377 
1378 IMPLEMENT_DYNAMIC_CLASS( a2dCanvasObject, a2dObject )
1379 
1380 BEGIN_EVENT_TABLE( a2dCanvasObject, a2dObject )
1381  EVT_CANVASOBJECT_MOUSE_EVENT( a2dCanvasObject::OnCanvasObjectMouseEvent )
1382  EVT_CANVASHANDLE_MOUSE_EVENT( a2dCanvasObject::OnHandleEvent )
1383  EVT_CANVASOBJECT_ENTER_EVENT( a2dCanvasObject::OnEnterObject )
1384  EVT_CANVASOBJECT_LEAVE_EVENT( a2dCanvasObject::OnLeaveObject )
1385  EVT_CANVASOBJECT_POPUPMENU_EVENT( a2dCanvasObject::OnPopUpEvent )
1386  //EVT_COM_EVENT_ID( a2dComEvent::sm_changedProperty, a2dCanvasObject::OnPropertyChanged )
1387  EVT_COM_EVENT( a2dCanvasObject::OnPropertyChanged )
1388  EVT_CHAR( a2dCanvasObject::OnChar )
1389 END_EVENT_TABLE()
1390 
1391 a2dCanvasObject::a2dCanvasObject( double x, double y )
1392 {
1393  m_lworld.Translate( x, y );
1394  //m_bflags[a2dCanvasOFlags::HasSelectedObjectsBelow]=true;
1395  //if ( m_bflags[a2dCanvasOFlags::HasSelectedObjectsBelow] )
1396  // m_childobjects = wxNullCanvasObjectList;
1397 
1398 
1399  m_childobjects = wxNullCanvasObjectList;
1400 
1401 
1402  SetHitFlags( a2dCANOBJ_EVENT_VISIBLE );
1403 
1404  m_root = NULL;
1405 
1406  m_flags = m_flagsInit;
1407 
1408  m_layer = wxLAYER_DEFAULT;
1409 
1410  //each new object is pending
1411  SetPending( true );
1412 
1413  m_worldExtend = 0;
1414  m_pixelExtend = 0;
1415 }
1416 
1418 {
1420  {
1421  delete m_childobjects;
1423  }
1424 }
1425 
1427 {
1428  return new a2dCanvasObject( *this, options, refs );
1429 }
1430 
1432  : a2dObject( other, options, refs )
1433 {
1434  m_root = other.m_root;
1435 
1436  m_flags = other.m_flags;
1437 
1438  m_hitflags = other.m_hitflags;
1439 
1440  m_flags.m_showshadow = true;
1441 
1442  m_layer = other.m_layer;
1443 
1444  m_lworld = other.m_lworld;
1445 
1447  if ( other.m_childobjects != wxNullCanvasObjectList )
1448  {
1450 
1452  {
1453  a2dCanvasObject* obj = *iter;
1454 
1455  if ( obj && !obj->GetRelease() )
1456  {
1457  if( options & clone_childs )
1458  {
1459  a2dCanvasObject* objn = obj->TClone( CloneOptions( options & ~ clone_seteditcopy ), refs );
1460  //all object having a single parent, will get this as new parent.
1461  // e.g a2dPin and a2dVisibleProperty
1462  objn->SetParent( this );
1463  m_childobjects->push_back( objn );
1464  }
1465  else
1466  {
1467  m_childobjects->push_back( obj );
1468  }
1469  }
1470  }
1471  }
1472 
1473  if( options & clone_seteditcopy )
1474  {
1475  // The copy constructor is not supposed to change the original, but with clone_seteditcopy
1476  // it will add the editcopy property, so we must use a const_cast here
1477  PROPID_Editcopy->SetPropertyToObject( const_cast<a2dCanvasObject*>( &other ), this );
1478  }
1479 
1480  if( options & clone_setoriginal )
1481  {
1482  // There are no "const" properties, so we need some const_casting here
1483  PROPID_Original->SetPropertyToObject( this, const_cast<a2dCanvasObject*>( &other ) );
1484  }
1485 
1486  m_bbox = other.m_bbox;
1487  m_bbox.SetValid( false );
1488  m_worldExtend = other.m_worldExtend;
1489  m_pixelExtend = other.m_pixelExtend;
1490 #if defined(_DEBUG) && defined (SMART_POINTER_DEBUG)
1491  //klion: it is because the CurrentSmartPointerOwner can change in property->TClone()
1492  CurrentSmartPointerOwner = this;
1493 #endif
1494 }
1495 
1496 a2dHabitat* a2dCanvasObject::GetHabitat() const
1497 {
1498  if ( m_root )
1499  return m_root->GetHabitat();
1500 
1501  //return NULL;
1502  return a2dCanvasGlobals->GetHabitat();
1503 }
1504 
1505 a2dCanvasObjectList* a2dCanvasObject::GetAsCanvasVpaths( bool WXUNUSED( transform ) ) const
1506 {
1507  return wxNullCanvasObjectList;
1508 }
1509 
1511 {
1512  bool returnIsPolygon = true;
1513  a2dVertexList* segList = GetAsVertexList( returnIsPolygon );
1514  if ( segList && returnIsPolygon )
1515  {
1516  a2dCanvasObjectList* polylist = new a2dCanvasObjectList();
1517  polylist->push_back( new a2dPolygonL( segList ) );
1518  return polylist;
1519  }
1520  else if ( segList )
1521  delete segList;
1522 
1523  a2dCanvasObjectList* polylist = NULL;
1524  a2dCanvasObjectList* vpath = GetAsCanvasVpaths( true );
1525 
1526  // now we have vector path, which we will convert to polygons and polylines.
1527  // Next only the polygons will be used for boolean operations.
1528  if ( vpath != wxNullCanvasObjectList )
1529  {
1530  a2dCanvasObjectList::iterator iter = vpath->begin();
1531  while ( iter != vpath->end() )
1532  {
1533  a2dVectorPath* obj = ( a2dVectorPath* ) ( *iter ).Get();
1534  polylist = obj->GetAsPolygons();
1535 
1536  iter = vpath->erase( iter );
1537  iter = vpath->begin();
1538  }
1539  delete vpath;
1540  return polylist;
1541  }
1542  return wxNullCanvasObjectList;
1543 }
1544 
1546 {
1547  bool returnIsPolygon = false;
1548  a2dVertexList* segList = GetAsVertexList( returnIsPolygon );
1549  if ( segList && returnIsPolygon )
1550  {
1551  a2dCanvasObjectList* polylist = new a2dCanvasObjectList();
1552  polylist->push_back( new a2dPolylineL( segList ) );
1553  return polylist;
1554  }
1555  else if ( segList )
1556  {
1557  a2dCanvasObjectList* polylist = new a2dCanvasObjectList();
1558  polylist->push_back( new a2dPolylineL( segList ) );
1559  return polylist;
1560  }
1561 
1562 
1563  a2dCanvasObjectList* polylist = NULL;
1564  a2dCanvasObjectList* vpath = GetAsCanvasVpaths( true );
1565 
1566  // now we have vector path, which we will convert to polygons and polylines.
1567  // Next only the polygons will be used for boolean operations.
1568  if ( vpath != wxNullCanvasObjectList )
1569  {
1570  a2dCanvasObjectList::iterator iter = vpath->begin();
1571  while ( iter != vpath->end() )
1572  {
1573  a2dVectorPath* obj = ( a2dVectorPath* ) ( *iter ).Get();
1574  polylist = obj->GetAsPolygons();
1575 
1576  iter = vpath->erase( iter );
1577  iter = vpath->begin();
1578  }
1579  delete vpath;
1580  }
1581 
1582  if ( !polylist )
1583  return wxNullCanvasObjectList;
1584 
1585  int i, count = polylist->size();
1586  a2dCanvasObjectList::iterator iterp = polylist->begin();
1587  for( i = 0 ; i < count ; i++ )
1588  {
1589  a2dPolygonL* poly = wxDynamicCast( ( *iterp ).Get(), a2dPolygonL );
1590  a2dPolylineL* polyline = wxDynamicCast( ( *iterp ).Get(), a2dPolylineL );
1591  if ( polyline && polyline->GetNumberOfSegments() > 2 )
1592  {
1593  iterp++;
1594  }
1595  else if ( poly && poly->GetNumberOfSegments() > 2 )
1596  {
1597  a2dPolylineL* conv = new a2dPolylineL( poly->GetSegments() );
1598  poly->SetLayer( m_layer );
1599  polylist->push_back( conv );
1600  iterp = polylist->erase( iterp );
1601  }
1602  }
1603  return polylist;
1604 }
1605 
1606 bool a2dCanvasObject::SetPosXYRestrict( double& x, double& y )
1607 {
1608  double xold = m_lworld.GetValue( 2, 0 );
1609  double yold = m_lworld.GetValue( 2, 1 );
1610  if( m_flags.m_snap )
1611  {
1612  a2dRestrictionEngine* restrictEngine = GetHabitat()->GetRestrictionEngine();
1613  if ( restrictEngine )
1614  restrictEngine->RestrictPoint( x, y );
1615  }
1616  if( xold != x || yold != y )
1617  {
1618  m_lworld.SetValue( 2, 0, x ); m_lworld.SetValue( 2, 1, y ); SetPending( true );
1619  return true;
1620  }
1621  return false;
1622 }
1623 
1624 void a2dCanvasObject::SetPosXY( double x, double y, bool restrict )
1625 {
1626  double xold = m_lworld.GetValue( 2, 0 );
1627  double yold = m_lworld.GetValue( 2, 1 );
1628 
1629  if( restrict )
1630  {
1631  SetPosXYRestrict( x, y );
1632  }
1633 
1634  if( xold != x || yold != y )
1635  {
1636  m_lworld.SetValue( 2, 0, x ); m_lworld.SetValue( 2, 1, y ); SetPending( true );
1637  }
1638 }
1639 
1640 a2dCanvasObject* a2dCanvasObject::StartEdit( a2dBaseTool* tool, wxUint16 editmode, wxEditStyle editstyle, a2dRefMap* refs )
1641 {
1642  if ( m_flags.m_editable )
1643  {
1644  a2dCanvasObjectPtr editcopy;
1645  editcopy = TClone( clone_members | clone_childs | clone_seteditcopy | clone_setoriginal, refs );
1646 
1647  editcopy->DoConnect( false );
1648  SetSnapTo( false );
1649  editcopy->SetSnapTo( false );
1650  //preserve of selection is done in a2dObjectEditTool, to improve interactive editing selection should not be visible.
1651  // But if a dialog is shown instead, it can be overuled in derived DoStartEdit()
1652  SetSelected( false );
1653  editcopy->SetSelected( false );
1654 
1655  if ( ! PROPID_Allowrotation->GetPropertyValue( this ) )
1656  PROPID_Allowrotation->SetPropertyToObject( editcopy, true );
1657  if ( ! PROPID_Allowsizing->GetPropertyValue( this ) )
1658  PROPID_Allowsizing->SetPropertyToObject( editcopy, true );
1659  if ( ! PROPID_Allowskew->GetPropertyValue( this ) )
1660  PROPID_Allowskew->SetPropertyToObject( editcopy, true );
1661  PROPID_Parent->SetPropertyToObject( editcopy, tool->GetParentObject() );
1662  editcopy->m_flags.m_editingCopy = true;
1663 
1664  editcopy->Update( updatemask_force );
1665 
1666  m_flags.m_editing = true;
1667 
1668  PROPID_Editmode->SetPropertyToObject( editcopy, editmode );
1669  PROPID_Editstyle->SetPropertyToObject( editcopy, ( wxUint16 ) editstyle );
1670 
1671  //the next maybe overruled in derived class
1672  PROPID_IncludeChildren->SetPropertyToObject( editcopy, true );
1673  PROPID_Controller->SetPropertyToObject( editcopy, tool->GetToolController() );
1675  //new start edit, so no event yet
1677 
1678  if ( !editcopy->DoStartEdit( editmode, editstyle ) )
1679  {
1680  editcopy->EndEdit();
1681  return NULL;
1682  }
1683 
1684  // Add the editcopy to the parent and set some flags
1685  tool->AddEditobject( editcopy );
1686 
1687  return editcopy;
1688  }
1689 
1690  return NULL;
1691 }
1692 
1693 void a2dCanvasObject::ReStartEdit( wxUint16 editmode )
1694 {
1695  //prevent EditEnd() from deleting the editcopy.
1696  a2dCanvasObjectPtr editcopy = this;
1697 
1698  //get the value of properties which need to be restored.
1699  a2dCanvasObject* original = PROPID_Original->GetPropertyValue( this );
1700  a2dCanvasObject* parent = PROPID_Parent->GetPropertyValue( this );
1701  a2dToolContr* controller = wxStaticCast( PROPID_Controller->GetPropertyValue( this ).Get(), a2dToolContr );
1702  wxUint16 editstyle = PROPID_Editstyle->GetPropertyValue( this );
1703 
1704  //stop editing,but the editcopy will be kept.
1705  EndEdit();
1706 
1707  //RESET the release that was flagged in endedit.
1708  m_release = false;
1709  SetVisible( true );
1710  SetIgnoreSetpending( false );
1711  SetSelected( false );
1712  PROPID_Allowrotation->SetPropertyToObject( editcopy, true );
1713  PROPID_Allowsizing->SetPropertyToObject( editcopy, true );
1714  PROPID_Allowskew->SetPropertyToObject( editcopy, true );
1715  PROPID_Original->SetPropertyToObject( editcopy, original );
1716  PROPID_Parent->SetPropertyToObject( editcopy, parent );
1717 
1718  PROPID_Editstyle->SetPropertyToObject( editcopy, editstyle );
1719 
1720  PROPID_Editcopy->SetPropertyToObject( original, editcopy );
1721 
1722  m_flags.m_editingCopy = true;
1723 
1725 
1726  original->m_flags.m_editing = true;
1727 
1728  PROPID_Editmode->SetPropertyToObject( editcopy, editmode );
1729  //the next maybe overruled in derived class
1730  PROPID_IncludeChildren->SetPropertyToObject( editcopy, true );
1731  PROPID_Controller->SetPropertyToObject( editcopy, controller );
1732 
1733 
1734  DoStartEdit( editmode , ( wxEditStyle ) editstyle );
1735 
1736  parent->Append( this );
1737 }
1738 
1739 bool a2dCanvasObject::DoStartEdit( wxUint16 WXUNUSED( editmode ), wxEditStyle WXUNUSED( editstyle ) )
1740 {
1741  if ( m_flags.m_editable )
1742  {
1743  bool allowrotation = PROPID_Allowrotation->GetPropertyValue( this );
1744  bool allowsizing = PROPID_Allowsizing->GetPropertyValue( this );
1745  bool allowskew = PROPID_Allowskew->GetPropertyValue( this );
1746 
1747  m_flags.m_visiblechilds = true;
1749 
1750  //! \todo edit of bbox ( children or not included )
1751  //add properties and handles as children in order to edit the object.
1752  //a2dBoundingBox untrans = GetUnTransformedBbox( true );
1754  if ( untrans.GetWidth() == 0 || untrans.GetWidth() == 0 )
1756 
1757  double x, y, w, h;
1758  x = untrans.GetMinX();
1759  y = untrans.GetMinY();
1760  w = untrans.GetWidth();
1761  h = untrans.GetHeight();
1762 
1763 
1764  a2dRect* around = new a2dRect( x, y, w, h );
1765  around->SetStroke( *wxRED, 0, a2dSTROKE_DOT_DASH );
1766  around->SetFill( *a2dTRANSPARENT_FILL );
1767  around->SetPreRenderAsChild( false );
1768  around->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
1769  around->SetHitFlags( a2dCANOBJ_EVENT_NON );
1770  around->SetLayer( m_layer );
1771  Append( around );
1772 
1773  a2dHandle* handle = NULL;
1774  if ( allowsizing )
1775  {
1776  Append( handle = new a2dHandle( this, x, y, wxT( "handle1" ) ) );
1777  handle->SetLayer( m_layer );
1778  Append( handle = new a2dHandle( this, x, y + h, wxT( "handle2" ) ) );
1779  handle->SetLayer( m_layer );
1780  Append( handle = new a2dHandle( this, x + w, y + h , wxT( "handle3" ) ) );
1781  handle->SetLayer( m_layer );
1782  Append( handle = new a2dHandle( this, x + w, y, wxT( "handle4" ) ) );
1783  handle->SetLayer( m_layer );
1784  Append( handle = new a2dHandle( this, x, y + h / 2 , wxT( "handle12" ) ) );
1785  handle->SetLayer( m_layer );
1786  Append( handle = new a2dHandle( this, x + w / 2, y + h, wxT( "handle23" ) ) );
1787  handle->SetLayer( m_layer );
1788  Append( handle = new a2dHandle( this, x + w, y + h / 2 , wxT( "handle34" ) ) );
1789  handle->SetLayer( m_layer );
1790  Append( handle = new a2dHandle( this, x + w / 2, y, wxT( "handle41" ) ) );
1791  }
1792 
1793  if ( allowrotation )
1794  {
1795  a2dSLine* rotline = new a2dSLine( x + w / 2, y + h / 2, x + w * 3 / 4, y + h / 2 );
1796  rotline->SetStroke( *wxRED, 0 );
1797  rotline->SetPreRenderAsChild( false );
1798  rotline->SetHitFlags( a2dCANOBJ_EVENT_NON );
1799  Append( rotline );
1800  rotline->SetLayer( m_layer );
1801 
1802  Append( handle = new a2dHandle( this, x + w * 3 / 4, y + h / 2, wxT( "rotate" ) ) );
1803  handle->SetLayer( m_layer );
1804  rotline->SetBin2( true );
1805  }
1806  if ( allowskew )
1807  {
1808  Append( handle = new a2dHandle( this, x + w * 3 / 4, y + h, wxT( "skewx" ) ) );
1809  handle->SetLayer( m_layer );
1810  Append( handle = new a2dHandle( this, x + w, y + h * 3 / 4, wxT( "skewy" ) ) );
1811  handle->SetLayer( m_layer );
1812  }
1813 
1814  m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT( "a2dHandle" ) );
1815  m_childobjects->SetSpecificFlags( true, a2dCanvasOFlags::BIN2, wxT( "a2dHandle" ) );
1816 
1817  //calculate bbox's else mouse events may take place when first idle event is not yet
1818  //processed to do this calculation.
1820  //stil set it pending to do the redraw ( in place )
1821  SetPending( true );
1822  return true;
1823  }
1824 
1825  return false;
1826 }
1827 
1829 {
1830  //! call virtual to do object specific ending
1831  DoEndEdit();
1832 
1833  SetSnapTo( true );
1834  m_flags.m_editingCopy = false;
1835 
1836  //remove properties and handles as children that were added just to edit the object.
1839 
1840  // it is not sure thata the editcopy will be deleted, e.g. when restarting,
1841  // all handles and such are removed, but re-added later in a different manner.
1842 
1843  a2dCanvasObject* original = PROPID_Original->GetPropertyValue( this );
1844 
1845  //SetSelected( m_preserve_select );
1846  RemoveProperty( PROPID_Original );
1847 
1848  RemoveProperty( PROPID_Allowrotation );
1849  RemoveProperty( PROPID_Allowsizing );
1850  RemoveProperty( PROPID_Allowskew );
1851 
1852  RemoveProperty( PROPID_Editmode );
1853  RemoveProperty( PROPID_Editstyle );
1854  RemoveProperty( PROPID_Controller );
1855  RemoveProperty( PROPID_IncludeChildren );
1856 
1857  a2dCanvasObject* parent = PROPID_Parent->GetPropertyValue( this );
1858  RemoveProperty( PROPID_Parent );
1859 
1860  SetPending( true );
1861 
1862  original->m_flags.m_editing = false;
1863  // I am not sure if this ASSERT can fail.
1864  // If it fails, think about it and then convert it to an if for RemoveProperty
1865  //wxASSERT( PROPID_Editcopy->GetPropertyValue( original ) == this );
1866  original->RemoveProperty( PROPID_Editcopy );
1867 
1868  //! set invisible, deletion is done by tool later.
1869  SetVisible( false );
1870  SetIgnoreSetpending( true );
1871  //next marks editcopy for release, it will happen in idle time.
1872  if ( parent )
1873  parent->ReleaseChild( this );
1874 }
1875 
1877 {
1878  return PROPID_Original->GetPropertyValue( this ).Get();
1879 }
1880 
1881 a2dHandle* a2dCanvasObject::SetHandlePos( wxString name, double x, double y )
1882 {
1883  a2dHandle* handle = NULL;
1884 
1886  {
1888  {
1889  handle = wxDynamicCast( ( *iter ).Get(), a2dHandle );
1890  if ( handle && handle->GetName() == name )
1891  {
1892  handle->SetPosXY( x, y );
1893  return handle;
1894  }
1895  }
1896  }
1897  return NULL;
1898 }
1899 
1900 void a2dCanvasObject::OnChar( wxKeyEvent& event )
1901 {
1903  {
1904  switch( event.GetKeyCode() )
1905  {
1906  case WXK_SPACE:
1907  {
1908  EndEdit();
1909  event.Skip();
1910  }
1911  break;
1912  default:
1913  event.Skip();
1914  }
1915  }
1916  else
1917  event.Skip();
1918 }
1919 
1921 {
1922  a2dIterC* ic = event.GetIterC();
1923 
1924  if ( HasDynamicProperties() )
1925  {
1926  const a2dMenuProperty* prop = PROPID_PopupMenu->GetPropertyListOnly( this );
1927  if ( prop )
1928  {
1929  wxWindow* win = ic->GetDrawingPart()->GetDisplayWindow();
1930  win->PopupMenu( prop->GetValue(), event.GetMouseEvent().GetX(), event.GetMouseEvent().GetY() );
1931  //wxLogDebug( wxT(" reached vertex curve with left down ") );
1932  }
1933  else
1934  event.Skip();
1935  }
1936  else
1937  event.Skip();
1938 }
1939 
1941 {
1942  a2dIterC* ic = event.GetIterC();
1943 
1944  if ( HasDynamicProperties() )
1945  {
1946  a2dCanvasObjectPtrProperty* prop = PROPID_Objecttip->GetPropertyListOnly( this );
1947  if ( prop )
1948  {
1949  prop->SetVisible( true );
1950  SetPending( true );
1951  }
1952 
1954  if ( tipProp )
1955  {
1956  wxTipWindow* tipWindow = wxDynamicCast( tipProp->GetValue(), wxTipWindow );
1957  wxWindow* win = ic->GetDrawingPart()->GetDisplayWindow();
1958  if( tipWindow )
1959  {
1960  // this happens normally in idle time, but this makes it happen for sure.
1961  tipWindow->SetTipWindowPtr( NULL );
1962  tipWindow->Close();
1963  }
1964 
1965  wxRect tipRect = tipProp->GetRect();
1966  wxPoint aWinPos( 0, 0 );
1967  aWinPos = win->ClientToScreen( aWinPos );
1968  wxRect aRect( aWinPos.x + event.GetMouseEvent().GetX() - tipRect.GetX(),
1969  aWinPos.y + event.GetMouseEvent().GetY() - tipRect.GetY(), tipRect.GetWidth(), tipRect.GetHeight() );
1970  if ( tipProp->GetUseObjRect() )
1971  {
1972  aRect = GetAbsoluteArea( *ic );
1973  wxPoint aWinPos1 = win->ClientToScreen( aRect.GetTopLeft() );
1974  wxPoint aWinPos2 = win->ClientToScreen( aRect.GetBottomRight() );
1975  aRect = wxRect( aWinPos1, aWinPos2 );
1976  }
1977  tipWindow = new wxTipWindow( win, tipProp->GetString(), 200 , ( wxTipWindow** )tipProp->GetValuePtr(), &aRect );
1978  tipProp->SetValue( tipWindow );
1979  }
1980  }
1981 
1982 #ifdef _DEBUG_REPORTHIT
1983  wxLogDebug( wxT( "%s %p" ), wxT( "enter" ), this );
1984 #endif
1985 
1986 
1987  // more object can be in editing state in case of subediting, only the one captured may change the cursor.
1989  {
1990  //if( ic->GetDrawingPart()->GetCaptured() == this )
1991  // ic->GetDrawingPart()->PushCursor( GetHabitat()->GetCursor( a2dCURSOR_HAND ) );
1992  // else
1993  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_CanvasObjectEnter ) );
1994  }
1995 }
1996 
1998 {
1999  a2dIterC* ic = event.GetIterC();
2000 
2001  if ( HasDynamicProperties() )
2002  {
2003  a2dCanvasObjectPtrProperty* prop = PROPID_Objecttip->GetPropertyListOnly( this );
2004  if ( prop )
2005  {
2006  prop->SetVisible( false );
2007  SetPending( true );
2008  }
2009  const a2dWindowProperty* tipProp = PROPID_TipWindow->GetPropertyListOnly( this );;
2010  if ( tipProp )
2011  {
2012  wxTipWindow* tipWindow = wxDynamicCast( tipProp->GetValue(), wxTipWindow );
2013  if( tipWindow )
2014  {
2015  // tipWindow->SetTipWindowPtr(NULL);
2016  // This OnLeaveObject() is called when tipWindow gets focus by SetFocus after
2017  // it was created in OnEnterObject(),
2018  // so here it is early to close the tipWindow
2019  // tipWindow->Close();
2020  }
2021 // tipProp->SetValue(NULL);
2022  }
2023  }
2024 
2025 #ifdef _DEBUG_REPORTHIT
2026  wxLogDebug( wxT( "%s %p" ), wxT( "leaf" ), this );
2027 #endif
2028 
2029  // more object can be in editing state in case of subediting, only the one captured may change the cursor.
2031  {
2032  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_CanvasObjectLeave ) );
2033  //if( ic->GetDrawingPart()->GetCaptured() == this )
2034  // ic->GetDrawingPart()->PopCursor();
2035  //else
2036  // ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Edit ) );
2037  }
2038 }
2039 
2041 {
2042  a2dCanvasObjectList::reverse_iterator iter = m_childobjects->rbegin();
2043  while( iter != m_childobjects->rend() )
2044  {
2045  a2dCanvasObject* obj = *iter;
2046  // DO NOT assume only object with mouse inside when parent was also.
2047  obj->LeaveInObjects( ic, hitEvent );
2048  if ( obj->m_flags.m_MouseInObject )
2049  {
2050  //wxLogDebug(wxT("leaveFromTop %p"), obj );
2051 
2052  obj->m_flags.m_MouseInObject = false;
2053  wxMouseEvent* mouse = wxDynamicCast( hitEvent.m_event, wxMouseEvent );
2054  a2dCanvasObjectMouseEvent leave( &ic, obj, wxEVT_CANVASOBJECT_LEAVE_EVENT, hitEvent.m_x, hitEvent.m_y, *mouse );
2055  hitEvent.SetProcessed( obj->ProcessEvent( leave ) );
2056  }
2057  iter++;
2058  }
2059 }
2060 
2062 {
2063  a2dIterC* ic = event.GetIterC();
2064 
2066  {
2067  a2dRestrictionEngine* restrictEngine = GetHabitat()->GetRestrictionEngine();
2068 
2069  a2dHandle* draghandle = event.GetCanvasHandle();
2070 
2071  //to world group coordinates to do hit test in world group coordinates
2072  double xw, yw;
2073  xw = event.GetX();
2074  yw = event.GetY();
2075 
2076  //matrix to convert from absolute world coordinates to local object coordinates,
2077  //with m_lworld included.
2078  double xwi;
2079  double ywi;
2080  ic->GetInverseTransform().TransformPoint( xw, yw, xwi, ywi );
2081 
2082  bool __includeChildren__ = PROPID_IncludeChildren->GetPropertyValue( this );
2083  a2dBoundingBox untrans;
2084  if ( __includeChildren__ )
2086  else
2088 
2089  double xmin, ymin, xmax, ymax, w, h;
2090  xmin = untrans.GetMinX();
2091  ymin = untrans.GetMinY();
2092  xmax = untrans.GetMaxX();
2093  ymax = untrans.GetMaxY();
2094  w = untrans.GetWidth();
2095  h = untrans.GetHeight();
2096 
2097  a2dAffineMatrix origworld = m_lworld;
2098  double x1, y1, x2, y2;
2099 
2100  a2dCanvasObject* original = PROPID_Original->GetPropertyValue( this );
2101 
2102  if ( event.GetMouseEvent().LeftDown() )
2103  {
2104  ic->GetDrawingPart()->PushCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_HandleLeftDown ) );
2105  if ( restrictEngine )
2106  restrictEngine->SetRestrictPoint( xw, yw );
2107  }
2108  else if ( event.GetMouseEvent().Moving() )
2109  {
2110  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_HandleMove ) );
2111  }
2112  else if ( event.GetMouseEvent().LeftUp() )
2113  {
2114  if ( m_lworld != original->GetTransformMatrix() )
2115  {
2116  m_root->GetCommandProcessor()->Submit( new a2dCommand_SetCanvasProperty( original, PROPID_TransformMatrix, m_lworld ) );
2117 
2118  a2dGeneralGlobals->RecordF( this, wxT( "setproperty __M_Transform { matrix ( %g %g %g %g %g %g ) } transform" ),
2119  m_lworld.GetValue( 0, 0 ), m_lworld.GetValue( 0, 1 ),
2120  m_lworld.GetValue( 1, 0 ), m_lworld.GetValue( 1, 1 ),
2121  m_lworld.GetValue( 2, 0 ), m_lworld.GetValue( 2, 1 ) );
2122  }
2123  }
2124  else if ( event.GetMouseEvent().Dragging() )
2125  {
2126  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_HandleDrag ) );
2127  if ( restrictEngine )
2128  restrictEngine->RestrictPoint( xw, yw );
2129  ic->GetInverseTransform().TransformPoint( xw, yw, xwi, ywi );
2130 
2131  if ( draghandle->GetName() == wxT( "handle1" ) )
2132  {
2133  //modify object
2134  double dx, dy;
2135  dx = xwi - xmin;
2136  dy = ywi - ymin;
2137 
2138  double sx;
2139  double sy;
2140  if ( w )
2141  sx = ( w - dx / 2 ) / w;
2142  else
2143  sx = 0;
2144  if ( h )
2145  sy = ( h - dy / 2 ) / h;
2146  else
2147  sy = 0;
2148 
2149  origworld.TransformPoint( xmax, ymax, x2, y2 );
2150 
2151  //reset matrix to identity
2153  Scale( sx, sy );
2154  Transform( origworld );
2155  m_lworld.TransformPoint( xmax, ymax, x1, y1 );
2156  Translate( x2 - x1, y2 - y1 );
2157  }
2158  else if ( draghandle->GetName() == wxT( "handle2" ) )
2159  {
2160  //modify object
2161  double dx, dy;
2162  dx = xwi - xmin;
2163  dy = ywi - ymax;
2164 
2165  double sx;
2166  double sy;
2167  if ( w )
2168  sx = ( w - dx / 2 ) / w;
2169  else
2170  sx = 0;
2171  if ( h )
2172  sy = ( h + dy / 2 ) / h;
2173  else
2174  sy = 0;
2175 
2176  origworld.TransformPoint( xmax, ymin, x2, y2 );
2177 
2178  //reset matrix to identity
2180  Scale( sx, sy );
2181  Transform( origworld );
2182  m_lworld.TransformPoint( xmax, ymin, x1, y1 );
2183  Translate( x2 - x1, y2 - y1 );
2184  }
2185  else if ( draghandle->GetName() == wxT( "handle3" ) )
2186  {
2187  //modify object
2188  double dx, dy;
2189  dx = xwi - xmax;
2190  dy = ywi - ymax;
2191 
2192  double sx;
2193  double sy;
2194  if ( w )
2195  sx = ( w + dx / 2 ) / w;
2196  else
2197  sx = 0;
2198  if ( h )
2199  sy = ( h + dy / 2 ) / h;
2200  else
2201  sy = 0;
2202 
2203  origworld.TransformPoint( xmin, ymin, x2, y2 );
2204 
2205  //reset matrix to identity
2207  Scale( sx, sy );
2208  Transform( origworld );
2209  m_lworld.TransformPoint( xmin, ymin, x1, y1 );
2210  Translate( x2 - x1, y2 - y1 );
2211  }
2212  else if ( draghandle->GetName() == wxT( "handle4" ) )
2213  {
2214  //modify object
2215  double dx, dy;
2216  dx = xwi - xmax;
2217  dy = ywi - ymin;
2218 
2219  double sx;
2220  double sy;
2221  if ( w )
2222  sx = ( w + dx / 2 ) / w;
2223  else
2224  sx = 0;
2225  if ( h )
2226  sy = ( h - dy / 2 ) / h;
2227  else
2228  sy = 0;
2229 
2230  origworld.TransformPoint( xmin, ymax, x2, y2 );
2231 
2232  //reset matrix to identity
2234  Scale( sx, sy );
2235  Transform( origworld );
2236  m_lworld.TransformPoint( xmin, ymax, x1, y1 );
2237  Translate( x2 - x1, y2 - y1 );
2238  }
2239  else if ( draghandle->GetName() == wxT( "rotate" ) )
2240  {
2241  double xr, yr;
2242  m_lworld.TransformPoint( xmin + w / 2, ymin + h / 2, xr, yr );
2243 
2244  //modify object
2245  double dx, dy;
2246 
2247  dx = xw - xr;
2248  dy = yw - yr;
2249  double angn;
2250  if ( !dx && !dy )
2251  angn = 0;
2252  else
2253  angn = wxRadToDeg( atan2( dy, dx ) );
2254 
2255  m_lworld = m_lworld.Rotate( angn - m_lworld.GetRotation(), xr, yr );
2256 
2257  //rotate.Translate( xr, yr);
2258  //rotate.Rotate(wxRadToDeg(-ang));
2259  //rotate.Translate( xr, yr);
2260  //Transform(rotate);
2261  }
2262  else if ( draghandle->GetName() == wxT( "skewx" ) )
2263  {
2264  //modify object
2265  double dx, dy;
2266 
2267  dx = xwi - ( xmin + w * 3 / 4 );
2268  dy = ywi - ( ymin + h / 2 );
2269 
2270  origworld.TransformPoint( xmin + w / 2, ymin + h / 2, x2, y2 );
2271 
2272  //reset matrix to identity
2274  SkewX( wxRadToDeg( atan2( dx, dy ) ) );
2275  Transform( origworld );
2276  m_lworld.TransformPoint( xmin + w / 2, ymin + h / 2, x1, y1 );
2277  Translate( x2 - x1, y2 - y1 );
2278  }
2279  else if ( draghandle->GetName() == wxT( "skewy" ) )
2280  {
2281  //modify object
2282  double dx, dy;
2283 
2284  dx = xwi - ( xmin + w / 2 );
2285  dy = ywi - ( ymin + h * 3 / 4 );
2286 
2287  origworld.TransformPoint( xmin + w / 2, ymin + h / 2, x2, y2 );
2288 
2289  //reset matrix to identity
2291  SkewY( wxRadToDeg( atan2( dy, dx ) ) );
2292  Transform( origworld );
2293  m_lworld.TransformPoint( xmin + w / 2, ymin + h / 2, x1, y1 );
2294  Translate( x2 - x1, y2 - y1 );
2295  }
2296  else if ( draghandle->GetName() == wxT( "handle12" ) )
2297  {
2298  //modify object
2299  double dx;
2300 
2301  dx = xwi - xmin;
2302 
2303  double sx;
2304  if ( w )
2305  sx = ( w - dx / 2 ) / w;
2306  else
2307  sx = 0;
2308 
2309  origworld.TransformPoint( xmax, ymax, x2, y2 );
2310 
2311  //reset matrix to identity
2313  Scale( sx, 1 );
2314  Transform( origworld );
2315  m_lworld.TransformPoint( xmax, ymax, x1, y1 );
2316  Translate( x2 - x1, y2 - y1 );
2317  }
2318  else if ( draghandle->GetName() == wxT( "handle23" ) )
2319  {
2320  //modify object
2321  double dy;
2322 
2323  dy = ywi - ymax;
2324 
2325  double sy;
2326  if ( h )
2327  sy = ( h + dy / 2 ) / h;
2328  else
2329  sy = 0;
2330 
2331  origworld.TransformPoint( xmax, ymin, x2, y2 );
2332 
2333  //reset matrix to identity
2335  Scale( 1, sy );
2336  Transform( origworld );
2337  m_lworld.TransformPoint( xmax, ymin, x1, y1 );
2338  Translate( x2 - x1, y2 - y1 );
2339  }
2340  else if ( draghandle->GetName() == wxT( "handle34" ) )
2341  {
2342  //modify object
2343  double dx;
2344 
2345  dx = xwi - xmax;
2346 
2347  double sx;
2348  if ( w )
2349  sx = ( w + dx / 2 ) / w;
2350  else
2351  sx = 0;
2352 
2353  origworld.TransformPoint( xmin, ymin, x2, y2 );
2354 
2355  //reset matrix to identity
2357  Scale( sx, 1 );
2358  Transform( origworld );
2359  m_lworld.TransformPoint( xmin, ymin, x1, y1 );
2360  Translate( x2 - x1, y2 - y1 );
2361  }
2362  else if ( draghandle->GetName() == wxT( "handle41" ) )
2363  {
2364  //modify object
2365  double dy;
2366 
2367  dy = ywi - ymin;
2368 
2369  double sy;
2370  if ( h )
2371  sy = ( h - dy / 2 ) / h;
2372  else
2373  sy = 0;
2374 
2375  origworld.TransformPoint( xmin, ymax, x2, y2 );
2376 
2377  //reset matrix to identity
2379  Scale( 1, sy );
2380  Transform( origworld );
2381  m_lworld.TransformPoint( xmin, ymax, x1, y1 );
2382  Translate( x2 - x1, y2 - y1 );
2383  }
2384  else
2385  event.Skip();
2386  SetPending( true );
2387  }
2388  }
2389 }
2390 
2392 {
2393  a2dIterC* ic = event.GetIterC();
2394  ic->SetPerLayerMode( false );
2395 
2396  if ( m_flags.m_editingCopy )
2397  ic->SetPerLayerMode( false );
2398 
2399  if ( event.GetMouseEvent().RightDown() )
2400  {
2401  //wxWindow* win = ic->GetDrawingPart()->GetDisplayWindow();
2402  //win->PopupMenu(mousemenu,event.GetX(), event.GetY());
2403  //wxLogDebug( wxT(" reached vertex curve with left down ") );
2404  a2dCanvasObjectMouseEvent popup( ic, this, wxEVT_CANVASOBJECT_POPUPMENU_EVENT, event.GetX(), event.GetY(), event.m_mouseevent );
2405  popup.SetEventObject( this );
2406 
2407  if ( !this->ProcessEvent( popup ) )
2408  event.Skip();
2409  }
2410  // editing of an object is based on the editcopy flag, which is only set at the top object of an editclone.
2411  // So the children of the object being edited does not have the flag set.
2412  else if ( m_flags.m_editingCopy && m_flags.m_editable )
2413  {
2414  a2dRestrictionEngine* restrictEngine = GetHabitat()->GetRestrictionEngine();
2415  a2dCanvasObject* original = PROPID_Original->GetPropertyValue( this );
2416  a2dCanvasObject* parent = PROPID_Parent->GetPropertyValue( this );
2417 
2418  static double xshift;
2419  static double yshift;
2420 
2421  double xw, yw;
2422  xw = event.GetX();
2423  yw = event.GetY();
2424 
2425  double xh, yh;
2426  ic->GetInverseTransform().TransformPoint( xw, yw, xh, yh );
2427 
2428  if ( event.GetMouseEvent().Moving() )///&& m_flags.m_subEditAsChild )
2429  {
2430  // all basic primitives rely on this to set cursor if no specialized move cursors (edges and such)
2431  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_CanvasObjectHit ) );
2432  event.Skip();
2433  }
2434  else if ( event.GetMouseEvent().LeftDClick() )
2435  {
2436  // double click while the object is in edit mode (m_flags.m_editingCopy)
2437  // will result in stopping the oneshot edit tool.
2438  EndEdit();
2439  }
2440  else if ( event.GetMouseEvent().LeftDown() )
2441  {
2442  // if the object is hit, we can test for sub editing of child objects.
2443  // The special case is the object called LABEL, which has priority.
2444  // Next candidate is the child hit.
2445  a2dHitEvent hitevent = a2dHitEvent( xw, yw, false );
2446  if ( IsHitWorld( *ic, hitevent ) )
2447  {
2448  if ( restrictEngine )
2449  restrictEngine->SetRestrictPoint( xw, yw );
2450 
2451  if ( 1 )
2452  {
2453  a2dCanvasObject* hit = NULL;
2454  {
2455  //labels have priority for editing
2456  a2dCanvasObject* label = original->Find( wxT( "__LABEL__" ) );
2457 
2458  if ( label )
2459  {
2460  a2dIterCU cu( *ic, original );
2461  a2dHitEvent hitevent = a2dHitEvent( xw, yw, false );
2462  hit = label->IsHitWorld( *ic, hitevent );
2463  }
2464  else if ( m_flags.m_subEdit ) // subedit allowed for other objects.
2465  {
2466  a2dHitEvent hitevent = a2dHitEvent( xw, yw, false, a2dCANOBJHITOPTION_NOROOT );
2467  hit = original->IsHitWorld( *ic, hitevent );
2468  if ( hit && !hit->m_flags.m_subEditAsChild )
2469  hit = NULL;
2470 
2471  }
2472  }
2473  if ( hit && hit->GetEditable() ) //subediting of child or labels, is we have a hit.
2474  {
2475  a2dIterCU cu( *ic, original );
2476  a2dToolContr* controller = wxStaticCast( PROPID_Controller->GetPropertyValue( this ).Get(), a2dToolContr );
2477 
2478  //editing is always a oneshot, since editing of children here is under control of the
2479  //a2dCanvasObject (can be different for derived classes). So editing tool should not take over
2480  //the decision to edit one after another child.
2481  ic->SetCorridorPath( true, NULL );
2482  controller->StartEditingObject( hit, *ic );
2483  }
2484  //subediting was not wanted or hit, therefore now start dragging the object itself
2485  //at mouse LeftDown
2486  else if ( IsDraggable() )
2487  {
2488  // Corridor is already in place, since edit tool is active.
2489  // Set corridor captured on this object, in order to drag.
2490  ic->SetCorridorPathCaptureObject( this );
2491  ic->GetDrawingPart()->PushCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Move ) );
2492 
2493  xshift = GetPosX() - xh;
2494  yshift = GetPosY() - yh;
2495  }
2496  }
2497  }
2498  // left down and no hit on this object, while the object is in edit mode (m_flags.m_editingCopy)
2499  // will result in stopping the oneshot edit tool.
2500  else
2501  {
2502  EndEdit();
2503  }
2504  }
2505  else if ( event.GetMouseEvent().LeftUp() && ic->GetDrawingPart()->GetCaptured() )
2506  {
2507  // the corridor was captured at Left Down.
2508  ic->SetCorridorPathCaptureObject( NULL );
2509  ic->GetDrawingPart()->PopCursor();
2510 
2511  if ( m_lworld != original->GetTransformMatrix() )
2512  {
2513  m_root->GetCommandProcessor()->Submit( new a2dCommand_SetCanvasProperty( original, PROPID_TransformMatrix, m_lworld ) );
2514 
2515  a2dGeneralGlobals->RecordF( this, wxT( "setproperty __M_Transform { matrix ( %g %g %g %g %g %g )} transform" ),
2516  m_lworld.GetValue( 0, 0 ), m_lworld.GetValue( 0, 1 ),
2517  m_lworld.GetValue( 1, 0 ), m_lworld.GetValue( 1, 1 ),
2518  m_lworld.GetValue( 2, 0 ), m_lworld.GetValue( 2, 1 ) );
2519  }
2520  }
2521  else if ( IsDraggable() && event.GetMouseEvent().Dragging() && ic->GetDrawingPart()->GetCaptured() )
2522  {
2523  double x, y;
2524  x = xh + xshift;
2525  y = yh + yshift;
2526 
2527  if( restrictEngine )
2528  {
2529  //temporarily restore position according to the mouse position, which is the unrestricted position.
2530  SetPosXY( x, y );
2531 
2532  a2dPoint2D point;
2533  double dx, dy; //detect restriction distance of any point.
2534  if ( restrictEngine->RestrictCanvasObjectAtVertexes( this, point, dx, dy ) )
2535  {
2536  //restrict the object drawing to that point
2537  x += dx;
2538  y += dy;
2539  }
2540  }
2541  SetPosXY( x, y );
2542  }
2543  else
2544  event.Skip();
2545  }
2546  else
2547  event.Skip();
2548 
2549 }
2550 
2552 {
2553  return m_childobjects;
2554 }
2555 
2557 {
2558  return m_childobjects;
2559 }
2560 
2562 {
2565 
2566  return m_childobjects;
2567 }
2568 
2569 
2571 {
2573  return 0;
2574  return m_childobjects->size();
2575 }
2576 
2578 {
2579  if ( m_flags.m_pushin )
2580  return this;
2581  return NULL;
2582 }
2583 
2584 
2585 void a2dCanvasObject::SetPending( bool pending )
2586 {
2587  if ( m_ignoreAllSetpending )
2588  return;
2589 
2590  m_flags.m_pending = pending;
2591 
2592  if ( pending && !m_flags.m_ignoreSetpending )
2593  {
2594  if ( m_flags.m_hasPins && !IsConnect() )
2595  {
2596  //This is not good for speed in tools.
2597  //SetConnectedPending( pending, true );
2598  }
2599  if ( m_root )
2600  m_root->SetUpdatesPending( true );
2601  }
2602 }
2603 
2604 void a2dCanvasObject::SetTransformMatrix( double xt, double yt, double scalex, double scaley, double degrees )
2605 {
2606  m_lworld = a2dAffineMatrix( xt, yt, scalex, scaley, degrees ); SetPending( true );
2607 }
2608 
2609 void a2dCanvasObject::SetRotation( double rotation )
2610 {
2611  m_lworld.SetRotation( rotation );
2612  SetPending( true );
2613 }
2614 
2615 void a2dCanvasObject::Rotate( double rotation )
2616 {
2617  m_lworld.Rotate( rotation );
2618  SetPending( true );
2619 }
2620 
2621 void a2dCanvasObject::SkewX( double angle )
2622 {
2623  m_lworld.SkewX( angle );
2624  SetPending( true );
2625 }
2626 
2627 void a2dCanvasObject::SkewY( double angle )
2628 {
2629  m_lworld.SkewY( angle );
2630  SetPending( true );
2631 }
2632 
2633 void a2dCanvasObject::Scale( double scalex, double scaley )
2634 {
2635  m_lworld.Scale( scalex, scaley, m_lworld.GetValue( 2, 0 ), m_lworld.GetValue( 2, 1 ) );
2636  SetPending( true );
2637 }
2638 
2639 void a2dCanvasObject::Mirror( bool x, bool y )
2640 {
2641  m_lworld.Mirror( x, y );
2642  SetPending( true );
2643 }
2644 
2646 {
2647  m_flags.SetSpecificFlags( setOrClear, which );
2648 }
2649 
2651 {
2652  m_flags.SetFlags( which );
2653 }
2654 
2656 {
2657  return m_flags.GetFlag( which );
2658 }
2659 
2661 {
2662  return m_flags.GetFlags();
2663 }
2664 
2666 {
2667  return m_flags.CheckMask( mask );
2668 }
2669 
2671 {
2672  m_hitflags.m_non = ( mask & a2dCANOBJ_EVENT_NON ) > 0;
2673  m_hitflags.m_fill = ( mask & a2dCANOBJ_EVENT_FILL ) > 0;
2674  m_hitflags.m_stroke = ( mask & a2dCANOBJ_EVENT_STROKE ) > 0;
2677  m_hitflags.m_visible = ( mask & a2dCANOBJ_EVENT_VISIBLE ) > 0;
2678  m_hitflags.m_all = ( mask & a2dCANOBJ_EVENT_ALL ) > 0 ;
2679 }
2680 
2682 {
2683  a2dCanvasObjectFlagsMask oflags = 0;
2684  if ( m_hitflags.m_non ) oflags = oflags | a2dCANOBJ_EVENT_NON;
2685  if ( m_hitflags.m_fill ) oflags = oflags | a2dCANOBJ_EVENT_FILL;
2686  if ( m_hitflags.m_stroke ) oflags = oflags | a2dCANOBJ_EVENT_STROKE;
2689  if ( m_hitflags.m_visible ) oflags = oflags | a2dCANOBJ_EVENT_VISIBLE;
2690  if ( m_hitflags.m_all ) oflags = oflags | a2dCANOBJ_EVENT_ALL;
2691  return oflags;
2692 }
2693 
2694 void a2dCanvasObject::foreach_f( void ( *fp ) ( a2dCanvasObject* item ) )
2695 {
2696  fp ( this );
2698  {
2700  {
2701  a2dCanvasObject* obj = *iter;
2702  if ( obj )
2703  fp ( obj );
2704  }
2705  }
2706 }
2707 
2709 {
2710  ( this->*mfp )();
2712  {
2714  {
2715  a2dCanvasObject* obj = *iter;
2716  if ( obj )
2717  ( obj->*mfp )();
2718  }
2719  }
2720 }
2721 
2722 bool a2dCanvasObject::EditProperties( const a2dPropertyId* id, bool withUndo )
2723 {
2724  a2dNamedPropertyList allprop;
2725 
2726  CollectProperties2( &allprop, id, a2dPropertyId::flag_none );
2727 
2728  bool res = false;
2729 
2730  a2dPropertyEditEvent event( this, &allprop );
2731  event.SetEventObject( this );
2732 
2733  // first try the object itself, this makes object specific property editing possible.
2734  ProcessEvent( event );
2735 
2736  if ( event.GetEdited() && !allprop.empty() )
2737  {
2738  res = true;
2739  a2dNamedPropertyList::iterator iter;
2740  for( iter = allprop.begin(); iter != allprop.end(); ++iter )
2741  {
2742  a2dNamedProperty* prop = *iter;
2743  if ( withUndo )
2744  {
2746  //\!todo
2747  //a2dGeneralGlobals->RecordF( this, wxT("setproperty ???") );
2748  }
2749  else
2750  prop->SetToObject( this );
2751  }
2752  }
2753 
2754  return res;
2755 }
2756 
2757 bool a2dCanvasObject::DoIgnoreIfNotMember( const a2dPropertyId& id )
2758 {
2759  return id.IsOnlyMember() || id.IsOnlyMemberHint();
2760 }
2761 
2763 {
2764  if ( event.GetPropertyId() && ! event.GetPropertyId()->CheckFlags( a2dPropertyId::flag_norender ) )
2765  {
2766  // we assume that the property does influence the object if its no_render flag is false
2767  SetPending( true );
2768  }
2769  // also a2dVisibleProperty showing this a2dPropertyId needs to be set pending.
2771  {
2773  {
2774  a2dVisibleProperty* visProp = wxDynamicCast( ( *iter ).Get(), a2dVisibleProperty );
2775  if ( visProp && visProp->GetPropId() == event.GetPropertyId() )
2776  visProp->ProcessEvent( event );
2777  }
2778  }
2779 }
2780 
2781 a2dText* a2dCanvasObject::SetObjectTip( const wxString& tip, double x, double y, double size, double angle, const a2dFont& font )
2782 {
2783  a2dFont lfont = font;
2784  lfont.SetSize( size );
2785  a2dText* object = new a2dText( tip, x, y, lfont, angle, true );
2786  object->SetLayer( m_layer );
2787  object->SetStroke( *a2dBLACK_STROKE );
2788  object->SetFill( *a2dTRANSPARENT_FILL );
2789  object->SetRoot( m_root );
2790  object->SetIsProperty( true );
2791  RemoveProperty( PROPID_Objecttip );
2792 
2793  a2dCanvasObjectPtrProperty prop( PROPID_Objecttip, object, false, true );
2794  PROPID_Objecttip->SetPropertyToObject( this, &prop );
2795  return object;
2796 }
2797 
2798 void a2dCanvasObject::SetTipWindow( const wxString& tip )
2799 {
2801 
2802  a2dTipWindowProperty prop( PROPID_TipWindow, NULL, tip );
2803  PROPID_TipWindow->SetPropertyToObject( this, &prop );
2804 }
2805 
2807 {
2808  if ( HasDynamicProperties() )
2809  {
2810  return PROPID_Objecttip->GetPropertyValue( this );
2811  }
2812 
2813  return 0;
2814 }
2815 
2816 void a2dCanvasObject::SetViewDependent( a2dDrawingPart* aView, bool viewdependent, bool viewspecific, bool onlyinternalarea, bool deep )
2817 {
2818  wxASSERT_MSG( !aView || aView->GetViewDependentObjects() , wxT( "a2dDrawingPart::GetViewDependentObjects() is not set" ) );
2819 
2820  if ( deep )
2821  {
2822  a2dWalker_SetViewDependent setv( aView, viewdependent, viewspecific, onlyinternalarea );
2823  setv.SetSkipNotRenderedInDrawing( true );
2824  setv.Start( this );
2825  return;
2826  }
2827 
2828  bool enPending = FALSE;
2829  if( !aView )
2830  {
2831  enPending |= RemoveProperty( PROPID_ViewSpecific );
2832  enPending |= RemoveProperty( PROPID_ViewDependent );
2834  }
2835  else
2836  {
2837  if( viewdependent )
2838  {
2839  enPending = TRUE;
2840  PROPID_ViewDependent->SetPropertyToObject( this, aView );
2841  if( onlyinternalarea )
2843  }
2844  else
2845  {
2846  a2dDrawingPart* view = wxStaticCastNull( PROPID_ViewDependent->GetPropertyValue( this ).Get(), a2dDrawingPart );
2847  if ( view == aView )
2848  {
2849  enPending |= RemoveProperty( PROPID_ViewDependent );
2851  }
2852  }
2853  if( viewspecific )
2854  {
2855  enPending = TRUE;
2856  PROPID_ViewSpecific->SetPropertyToObject( this, aView );
2857  }
2858  else
2859  {
2860  a2dDrawingPart* view = wxStaticCastNull( PROPID_ViewSpecific->GetPropertyValue( this ).Get(), a2dDrawingPart );
2861  if ( view == aView )
2862  enPending |= RemoveProperty( PROPID_ViewSpecific );
2863  }
2864  }
2865  if( enPending )
2866  SetPending( true );
2867 }
2868 
2870 {
2871  return PROPID_Shadowstyle->GetProperty( this );
2872 }
2873 
2875 {
2876  if ( !fill.IsNoFill() )
2877  PROPID_Fill->SetPropertyToObject( this, fill );
2878  else
2879  RemoveProperty( PROPID_Fill );
2880 }
2881 
2882 void a2dCanvasObject::SetFill( const wxColour& fillcolor, a2dFillStyle fillstyle )
2883 {
2884  a2dFill fill = a2dFill( fillcolor, fillstyle );
2885 
2886  PROPID_Fill->SetPropertyToObject( this, fill );
2887 }
2888 
2889 void a2dCanvasObject::SetFill( const wxColour& fillcolor, const wxColour& fillcolor2, a2dFillStyle fillstyle )
2890 {
2891  a2dFill fill = a2dFill( fillcolor, fillcolor2, fillstyle );
2892 
2893  PROPID_Fill->SetPropertyToObject( this, fill );
2894 }
2895 
2896 a2dFill a2dCanvasObject::GetFill() const
2897 {
2898  a2dFill propval = PROPID_Fill->GetPropertyValue( this );
2899  return propval;
2900 }
2901 
2903 {
2904  if ( !GetFill().IsNoFill() )
2905  return GetFill().GetColour();
2906 
2907  if ( m_flags.m_filled )
2908  {
2909  if ( m_root && m_root->GetLayerSetup() )
2910  return m_root->GetLayerSetup()->GetFill( m_layer ).GetColour();
2911  return wxColour( 0, 0, 0 );
2912  }
2913  else
2914  return a2dTRANSPARENT_FILL->GetColour();
2915 }
2916 
2917 void a2dCanvasObject::SetFillColour( const wxColour& colour )
2918 {
2919  a2dFill fill = PROPID_Fill->GetPropertyValue( this );
2920  fill.SetColour( colour );
2921  SetFill( fill );
2922 }
2923 
2924 void a2dCanvasObject::SetStroke( const wxColour& strokecolor, double width, a2dStrokeStyle strokestyle )
2925 {
2926  a2dStroke stroke = a2dStroke( strokecolor, ( float ) width, strokestyle );
2927 
2928  PROPID_Stroke->SetPropertyToObject( this, stroke );
2929 }
2930 
2931 void a2dCanvasObject::SetStroke( const wxColour& strokecolor, int width, a2dStrokeStyle strokestyle )
2932 {
2933  a2dStroke stroke = a2dStroke( strokecolor, width, strokestyle );
2934 
2935  PROPID_Stroke->SetPropertyToObject( this, stroke );
2936 }
2937 
2939 {
2940  if ( !stroke.IsNoStroke() )
2941  PROPID_Stroke->SetPropertyToObject( this, stroke );
2942  else
2943  RemoveProperty( PROPID_Stroke, true );
2944 }
2945 
2946 a2dStroke a2dCanvasObject::GetStroke() const
2947 {
2948  a2dStroke propval = PROPID_Stroke->GetPropertyValue( this );
2949  return propval;
2950 }
2951 
2953 {
2954  if ( !GetStroke().IsNoStroke() )
2955  return GetStroke().GetColour();
2956 
2957  if ( m_root && m_root->GetLayerSetup() )
2958  return m_root->GetLayerSetup()->GetStroke( m_layer ).GetColour();
2959 
2960  return wxColour( 0, 0, 0 );
2961 }
2962 
2963 void a2dCanvasObject::SetStrokeColour( const wxColour& colour )
2964 {
2965  a2dStroke stroke = PROPID_Stroke->GetPropertyValue( this );
2966  stroke.SetColour( colour );
2967  SetStroke( stroke );
2968 }
2969 
2970 const a2dFill& a2dCanvasObject::MX_GetFill() const
2971 {
2972  if ( HasDynamicProperties() )
2973  {
2974  a2dNamedPropertyList::const_iterator iter;
2975  for( iter = m_propertylist.begin(); iter != m_propertylist.end(); ++iter )
2976  {
2977  const a2dNamedProperty* prop = *iter;
2978  if ( prop->GetId() == PROPID_Fill )
2979  {
2980  a2dFillProperty* propfill = wxStaticCast( prop, a2dFillProperty );
2981  return propfill->GetValue();
2982  }
2983  }
2984  }
2985 
2986  return *a2dNullFILL;
2987 }
2988 
2989 void a2dCanvasObject::MX_SetFill( const a2dFill& value )
2990 {
2991  a2dFill fill = value;
2992  if ( !fill.IsNoFill() && fill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR )
2993  {
2994  double x1 = fill.GetStart().m_x;
2995  double y1 = fill.GetStart().m_y;
2996  double x2 = fill.GetStop().m_x;
2997  double y2 = fill.GetStop().m_y;
2998  if ( x1 == x2 && y1 == y2 )
2999  {
3000  //do a linear fill vertical
3001  a2dBoundingBox& box = GetBbox();
3002  x2 = x1 = box.GetMaxX() - box.GetMinX();
3003  y1 = box.GetMaxY();
3004  y2 = box.GetMinY();
3005 
3006  fill = a2dFill( fill.GetColour(), fill.GetColour2(), x1, y1, x2, y2 );
3007  }
3008  }
3009  else if ( !fill.IsNoFill() && fill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
3010  {
3011  double xfc = fill.GetFocal().m_x;
3012  double yfc = fill.GetFocal().m_y;
3013  double xe = fill.GetCenter().m_x;
3014  double ye = fill.GetCenter().m_y;
3015  if ( xfc == xe && yfc == ye )
3016  {
3017  //no start stop given
3018  a2dBoundingBox& box = GetBbox();
3019  xe = xfc = ( box.GetMaxX() + box.GetMinX() ) / 2;
3020  ye = yfc = ( box.GetMaxY() + box.GetMinY() ) / 2;
3021  double xr = box.GetMaxX();
3022  double yr = box.GetMaxY();
3023  double radius = wxMax( ( xe - xr ), ( ye - yr ) );
3024  fill = a2dFill( fill.GetColour(), fill.GetColour2(), xfc, yfc, xe, ye, radius / 2 );
3025  }
3026  }
3027 
3028 
3029  if ( HasDynamicProperties() )
3030  {
3031  a2dNamedPropertyList::const_iterator iter;
3032  for( iter = m_propertylist.begin(); iter != m_propertylist.end(); ++iter )
3033  {
3034  const a2dNamedProperty* prop = *iter;
3035  if ( prop->GetId() == PROPID_Fill )
3036  {
3037  a2dFillProperty* propfill = wxStaticCast( prop, a2dFillProperty );
3038  propfill->SetValue( fill );
3039  return;
3040  }
3041  }
3042  }
3043  a2dFillProperty* prop = new a2dFillProperty( PROPID_Fill, fill );
3044  AddProperty( prop );
3045 }
3046 
3047 const a2dStroke& a2dCanvasObject::MX_GetStroke() const
3048 {
3049  if ( HasDynamicProperties() )
3050  {
3051  a2dNamedPropertyList::const_iterator iter;
3052  for( iter = m_propertylist.begin(); iter != m_propertylist.end(); ++iter )
3053  {
3054  const a2dNamedProperty* prop = *iter;
3055  if ( prop->GetId() == PROPID_Stroke )
3056  {
3057  a2dStrokeProperty* propstroke = wxStaticCast( prop, a2dStrokeProperty );
3058  return propstroke->GetValue();
3059  }
3060  }
3061  }
3062 
3063  return *a2dNullSTROKE;
3064 }
3065 
3066 void a2dCanvasObject::MX_SetStroke( const a2dStroke& value )
3067 {
3068  if ( HasDynamicProperties() )
3069  {
3070  a2dNamedPropertyList::const_iterator iter;
3071  for( iter = m_propertylist.begin(); iter != m_propertylist.end(); ++iter )
3072  {
3073  const a2dNamedProperty* prop = *iter;
3074  if ( prop->GetId() == PROPID_Stroke )
3075  {
3076  a2dStrokeProperty* propstroke = wxStaticCast( prop, a2dStrokeProperty );
3077  propstroke->SetValue( value );
3078  return;
3079  }
3080  }
3081  }
3082  a2dStrokeProperty* prop = new a2dStrokeProperty( PROPID_Stroke, value );
3083  AddProperty( prop );
3084 }
3085 
3087 {
3088  a2dLayers* layers = m_root->GetLayerSetup();
3089 
3090  if ( m_flags.m_filled )
3091  {
3092  if ( style )
3093  {
3094  if ( !style->GetFill().IsNoFill() && style->GetFill().IsSameAs( *a2dINHERIT_FILL ) )
3095  {
3096  //nothing i hope
3097  }
3098  else if ( style->GetFill().IsNoFill() )
3099  {
3100  if ( layers )
3101  ic.GetDrawer2D()->SetDrawerFill( layers->GetFill( m_layer ) );
3102  else //should not be
3104  }
3105  else
3106  ic.GetDrawer2D()->SetDrawerFill( style->GetFill() );
3107 
3108  }
3109  else if ( layers )
3110  {
3111  ic.GetDrawer2D()->SetDrawerFill( layers->GetFill( m_layer ) );
3112  }
3113  }
3114  else
3115  {
3117  }
3118 
3119  if ( style )
3120  {
3121  if ( !style->GetStroke().IsNoStroke() && style->GetStroke().IsSameAs( *a2dINHERIT_STROKE ) )
3122  {
3123  //nothing i hope
3124  }
3125  else if ( style->GetStroke().IsNoStroke() )
3126  {
3127  if ( layers )
3128  ic.GetDrawer2D()->SetDrawerStroke( layers->GetStroke( m_layer ) );
3129  else //should not be
3131  }
3132  else
3133  ic.GetDrawer2D()->SetDrawerStroke( style->GetStroke() );
3134  }
3135  else if ( layers )
3136  {
3137  ic.GetDrawer2D()->SetDrawerStroke( layers->GetStroke( m_layer ) );
3138  }
3139 }
3140 
3142 {
3143  ic.SetCorridorPath( true, this );
3144 }
3145 
3147 {
3148  ic.SetCorridorPath( false );
3149 }
3150 
3152 {
3153  return ic.GetDrawingPart()->GetCaptured() == this;
3154 }
3155 
3156 bool a2dCanvasObject::GeneratePinsPossibleConnections( a2dPinClass* pinClass, a2dConnectTask task, double x, double y, double margin )
3157 {
3158  wxASSERT_MSG( pinClass->GetConnectionGenerator()
3159  , wxT( "pinclass connection generator not set" ) );
3160 
3161  return pinClass->GetConnectionGenerator()->GeneratePossibleConnections( this, pinClass, task, x, y, margin );
3162 }
3163 
3165 {
3166  return mapThis->GetConnectionGenerator()->GetConnectTemplate( this, mapThis, other, mapOther );
3167 }
3168 
3169 a2dCanvasObject* a2dCanvasObject::CreateConnectObject( a2dCanvasObject* parent, a2dPin* pinThis, a2dPin* pinOther, bool undo ) const
3170 {
3171  return pinThis->GetPinClass()->GetConnectionGenerator()->CreateConnectObject( parent, pinThis, pinOther, undo );
3172 }
3173 
3174 
3176 {
3177  // bounding boxes normally get re-calculated on the fly when an object is set pending,
3178  // or a child object was set pending.
3179  // When an object is created it is always set to pending. But calculating the boudingbox
3180  // at that moment is often useless, since it may depend on things that will be added
3181  // ( like child objects ).
3182  // This leads to the problem that sometimes one wants to have the boundingbox before it
3183  // is calculated in idle time.
3184  // So if not valid yet, we calculate it right now.
3185  // Still we set the object pending, so in the next Update cycle ( idle time ),
3186  // all objects in the parent chains will be updated also to reflect/include this objects
3187  // its boundingbox.
3188  // Doing it when a boundingbox is needed, is at the latest stage for sure, and automatic.
3189 
3190  if ( !m_bbox.GetValid() )
3191  {
3192  Update( updatemask_force ); //calculate on the fly
3193  SetPending( true );
3194  }
3195 
3196  return m_bbox;
3197 }
3198 
3199 wxRect a2dCanvasObject::GetAbsoluteArea( a2dIterC& ic, int inflate )
3200 {
3201  int x1, y1, x2, y2;
3202 
3203  a2dBoundingBox tmp = GetBbox();
3204  if ( !ic.GetTransform().IsIdentity() )
3205  tmp.MapBbox( ic.GetTransform() );
3206 
3207  //different scaling in X and Y
3208  //goes wrong IF pen is included in GetBbox().
3209  //In reality the pen width stays constant in x and y while rendering,
3210  //so we add it here.
3211  //include the pen width now
3212  tmp.Enlarge( m_worldExtend );
3213 
3214  x1 = ic.GetDrawer2D()->WorldToDeviceX( tmp.GetMinX() );
3215  y1 = ic.GetDrawer2D()->WorldToDeviceY( tmp.GetMinY() );
3216  x2 = ic.GetDrawer2D()->WorldToDeviceX( tmp.GetMaxX() );
3217  y2 = ic.GetDrawer2D()->WorldToDeviceY( tmp.GetMaxY() );
3218 
3219  if ( x1 > x2 )
3220  {
3221  int tmp = x1;
3222  x1 = x2;
3223  x2 = tmp;
3224  }
3225  if ( y1 > y2 )
3226  {
3227  int tmp = y1;
3228  y1 = y2;
3229  y2 = tmp;
3230  }
3231 
3232  wxRect tmparea;
3233  tmparea.x = x1;
3234  tmparea.y = y1;
3235 
3236  tmparea.width = x2 - x1;
3237  tmparea.height = y2 - y1;
3238  tmparea.Inflate( m_pixelExtend );
3239 
3240  //EXTREMELY IMPORTANT
3241  tmparea.Inflate( inflate ); //pixels extra on each side for the "ONE BIT BUG" ;-)
3242 
3243  return tmparea;
3244 }
3245 
3247 {
3248  //first map without extend width which is not included in the boundingbox
3249  a2dBoundingBox tmp = GetBbox();
3250  if ( !cworld.IsIdentity() )
3251  tmp.MapBbox( cworld );
3252 
3253  return tmp;
3254 }
3255 
3257 {
3258  //first map without extend width which is not included in the boundingbox
3259  a2dBoundingBox tmp = GetBbox();
3260  if ( !ic.GetTransform().IsIdentity() )
3261  tmp.MapBbox( ic.GetTransform() );
3262 
3263  if ( withExtend )
3264  {
3265  if ( m_worldExtend )
3266  tmp.Enlarge( m_worldExtend );
3267  if ( m_pixelExtend )
3269  }
3270  return tmp;
3271 }
3272 
3274 {
3275  // clipparent is either _IN or _ON ( _OUT would not get us to this point )
3276  // testing clipping of children only needed when not totaly _IN.
3277  if ( clipparent == _ON )
3278  {
3279  //get bbox at the absolute position
3280  //first map without pen width which is not included in the boundingbox
3281  a2dBoundingBox absarea = GetMappedBbox( ic, true );
3282  return ic.GetDrawer2D()->GetClippingBox().Intersect( absarea );
3283  }
3284 
3285  return clipparent;
3286 }
3287 
3288 
3289 a2dCanvasObject* a2dCanvasObject::ChildIsHitWorld( a2dIterC& ic, a2dHitEvent& hitEvent, bool filterSelectableLayers )
3290 {
3291  a2dAffineMatrix cworld;
3292  if ( !hitEvent.m_xyRelToChildren )
3293  {
3294  cworld = m_lworld;
3295  cworld.Invert();
3296  }
3297 
3298  a2dCanvasObject* res = NULL;
3299 
3300  a2dBoundingBox box; //the box hit last
3301  //------------------------------------------------------------------------
3302  // Calculate local coordinates and do a bounding box test
3303  //------------------------------------------------------------------------
3304 
3305  ic.GetInverseTransform().TransformPoint( hitEvent.m_x, hitEvent.m_y, hitEvent.m_relx, hitEvent.m_rely );
3306 
3307  //search in reverse order, last drawn on a layer, and therefore on top, will be found first for hit
3308  a2dCanvasObjectList::reverse_iterator boxiter = m_childobjects->rbegin();
3309  while( boxiter != m_childobjects->rend() )
3310  {
3311  a2dCanvasObject* obj = *boxiter;
3312 
3313  if ( obj->GetVisible() )
3314  {
3315  if ( obj->m_flags.m_ChildOnlyTranslate )
3316  {
3317  a2dAffineMatrix iworld = m_lworld;
3318  iworld.Invert();
3319  a2dIterCU cu( ic, iworld );
3320  a2dAffineMatrix transworld;
3321  transworld.Translate( GetPosX(), GetPosY() );
3322  a2dIterCU cu2( ic, transworld );
3323  }
3324 
3325  OVERLAP clipparent = ic.GetDrawer2D()->GetClippingBox().Intersect( obj->GetBbox() );
3326  // if there already was a hit, we test if the next bbox is smaller, since we want to hit on the smallest object.
3327  if ( clipparent != _OUT &&
3328  (
3329  ! box.GetValid() ||
3330  (
3331  ( obj->GetBbox().GetWidth() < box.GetWidth() || obj->GetBbox().GetHeight() < box.GetHeight() ) &&
3332  obj->GetBbox().PointInBox( hitEvent.m_relx, hitEvent.m_rely,
3334  )
3335  )
3336  )
3337  {
3338  if ( hitEvent.m_option & a2dCANOBJHITOPTION_LAYERS && GetRoot()->GetLayerSetup() )
3339  {
3340  /*
3341  ic.SetPerLayerMode( false );
3342  ic.SetObjectFilter( new a2dCanvasObjectFilterToolObjects( &a2dCanvasObject::PROPID_ToolObject, mask ) );
3343  ic.SetLayer( wxLAYER_ALL );
3344  a2dIterCU cu( ic, cworld );
3345  if ( res = IsHitWorld( ic, hitEvent ) )
3346  {
3347  ic.Reset();
3348  return res;
3349  }
3350  ic.Reset();
3351  */
3352  ic.SetPerLayerMode( true );
3353  unsigned int j;
3354  for ( j = 0; j < wxMAXLAYER; j++ )
3355  {
3356  a2dLayerInfo* layerobj;
3357  // YES here we do the opposite of when rendering, hitting the top layer first
3358  if ( ic.GetDrawingPart()->GetReverseOrder() )
3359  layerobj = GetRoot()->GetLayerSetup()->GetOrderIndex()[j];
3360  else
3361  layerobj = GetRoot()->GetLayerSetup()->GetReverseOrderIndex()[j];
3362 
3363  // non defined layers, being those that where not in the layer setup, are sorted to the end of the indexes.
3364  // So the can be skipped.
3365  if ( layerobj == wxNullLayerInfo )
3366  break;
3367 
3368  //wxLogDebug( wxT("index %d layer %d order %d"), j, layerobj->GetLayer(), layerobj->GetOrder() );
3369 
3370  //important!
3371  //if layer is visible it will be rendered
3372  //If an object on a layer is itself invisible it will not be drawn
3373  //wxLAYER_ALL is reserved and should never be part of the layersettings
3374  if ( ic.GetDrawingPart()->GetLayerRenderArray()[ layerobj->GetLayer() ].DoRenderLayer() &&
3375  layerobj->GetVisible() &&
3376  ( !filterSelectableLayers || filterSelectableLayers && layerobj->GetSelectable() )
3377  )
3378  {
3379  //wxLogDebug( "layer %d", layerobj->GetLayer() );
3380  //ic.GetDrawer2D()->ResetStyle();
3381  //ic.SetObjectFilter( new a2dCanvasObjectFilterLayerMaskNoToolNoEdit( layerobj->GetLayer(), a2dCanvasOFlags::VISIBLE ) );
3382  ic.SetObjectFilter( NULL );
3383  ic.SetLayer( layerobj->GetLayer() );
3384 
3385  a2dIterCU cu( ic, cworld );
3386  if ( obj->IsHitWorld( ic, hitEvent ) )
3387  {
3388  res = obj;
3389  box = obj->GetBbox();
3390  return res; //we found a hit on the highest layer.
3391  }
3392  ic.Reset();
3393  }
3394  }
3395  }
3396  else
3397  {
3398  a2dIterCU cu( ic, cworld );
3399  ic.SetPerLayerMode( false );
3400  if ( obj->IsHitWorld( ic, hitEvent ) )
3401  {
3402  res = obj;
3403  box = GetBbox();
3404  }
3405  ic.Reset();
3406  }
3407  }
3408  }
3409  boxiter++;
3410  }
3411 
3412  return res;
3413 }
3414 
3416 {
3418  return ( a2dCanvasObject* ) NULL;
3419  if ( hitEvent.m_option & a2dCANOBJHITOPTION_NOTSELECTED && GetSelected() )
3420  return ( a2dCanvasObject* ) NULL;
3421 
3422  if ( !ic.FilterObject( this ) ||
3423  ( ! GetIgnoreLayer() &&
3424  (
3425  !ic.GetDrawingPart()->GetLayerRenderArray()[ m_layer ].DoRenderLayer() ||
3426  ( m_root && m_root->GetLayerSetup() && !m_root->GetLayerSetup()->GetVisible( m_layer ) )
3427  )
3428  )
3429  )
3430  {
3431  ic.EndFilterObject( this );
3432  return ( a2dCanvasObject* ) NULL;
3433  }
3434 
3435  if ( ic.GetLayer() != m_layer && ic.GetLayer() != wxLAYER_ALL && !m_flags.m_ignoreLayer )
3436  {
3437  //the object itself will NOT be rendered for sure, but maybe its children still will!
3438 
3439  //object not on this layer, then children will NOT be rendered also in following cases
3441  {
3442  ic.EndFilterObject( this );
3443  return ( a2dCanvasObject* ) NULL;
3444  }
3445  if ( ic.GetLayer() != wxLAYER_ALL && m_flags.m_childrenOnSameLayer )
3446  {
3447  ic.EndFilterObject( this );
3448  return ( a2dCanvasObject* ) NULL;
3449  }
3450  }
3451 
3452  // Note: hit is not initialized to hit_nohit, because this is not wanted
3453  // with a2dCANOBJHITOPTION_ALL. This should not hurt as a a2dHit
3454  // initializes in its contructor to hit_nohit.
3455 
3456  //------------------------------------------------------------------------
3457  // Check if the object or any of its childs are visible and hittable
3458  // on the given layer
3459  //------------------------------------------------------------------------
3460 
3461  // Check if the root object can be hit, and if not, if there are childs
3462  if( hitEvent.m_option & a2dCANOBJHITOPTION_NOROOT )
3463  {
3464  //the object itself cannot be hit, but maybe its children
3465  //object cannot be hit, then children will NOT be hit also in following cases
3467  {
3468  ic.EndFilterObject( this );
3469  return ( a2dCanvasObject* ) NULL;
3470  }
3471  }
3472 
3473  //------------------------------------------------------------------------
3474  // Calculate local coordinates and do a bounding box test
3475  //------------------------------------------------------------------------
3476 
3477  ic.GetInverseTransform().TransformPoint( hitEvent.m_x, hitEvent.m_y, hitEvent.m_relx, hitEvent.m_rely );
3478 
3479  //we add the extends since they are not part of the bbox.
3480  //We could do first a hit on the plain bbox, but this does not help much in speed i think.
3481  if ( ! GetBbox().PointInBox( hitEvent.m_relx, hitEvent.m_rely, m_worldExtend + ic.GetHitMarginWorld() + ic.ExtendDeviceToWorld( m_pixelExtend ) ) )
3482  {
3483  ic.EndFilterObject( this );
3484  return ( a2dCanvasObject* ) NULL;
3485  }
3486 
3487  //------------------------------------------------------------------------
3488  // Update the iteration context
3489  //------------------------------------------------------------------------
3490  a2dIterCU cu( ic, this );
3491  // prepare relative to object coordinates for derived objects
3492  ic.GetInverseTransform().TransformPoint( hitEvent.m_x, hitEvent.m_y, hitEvent.m_relx, hitEvent.m_rely );
3493  double xrel = hitEvent.m_relx;
3494  double yrel = hitEvent.m_rely;
3495 
3496 
3497  // properties and its associated objects must be on the same layer as the object itself.
3498  // Although in there iteration on layers may happen on nested objects, the object that is directly
3499  // referred to, should be on the same layer as this object itself.
3500  // REMARK is for some reason this is not exceptable, the rendering routines should be changed also,
3501  // since the hitting test is roughly the reverse of that.
3502 
3503  //------------------------------------------------------------------------
3504  // Do a hit test for properties
3505  //------------------------------------------------------------------------
3506 
3507  if ( HasDynamicProperties() && !( hitEvent.m_option & a2dCANOBJHITOPTION_NOROOT ) )
3508  {
3509  a2dNamedPropertyList::const_iterator iter;
3510  for( iter = m_propertylist.begin(); iter != m_propertylist.end(); ++iter )
3511  {
3512  const a2dNamedProperty* prop = *iter;
3514  if ( canvasprop && canvasprop->GetCanRender() && canvasprop->GetVisible() )
3515  {
3516  a2dCanvasObject* canvasobj = canvasprop->GetCanvasObject();
3517  if( canvasobj && canvasobj->GetVisible() )
3518  {
3519  a2dCanvasObject* hit = canvasobj->IsHitWorld( ic, hitEvent );
3520  if ( hit )
3521  {
3522  if( ! ( hitEvent.m_option & a2dCANOBJHITOPTION_ALL ) )
3523  {
3524  ic.EndFilterObject( this );
3525  if( hitEvent.m_extendedWanted )
3526  {
3527  ic.Last()->m_type = hitEvent.m_how;
3528  hitEvent.m_extended.push_back( a2dExtendedResultItem(
3529  hit,
3530  ic.GetParent(),
3531  hitEvent.m_how,
3532  ic.GetLevel(),
3533  hitEvent.m_id
3534  ) );
3535  }
3536  return this;
3537  }
3538  }
3539  }
3540  }
3541  }
3542  }
3543 
3544  //------------------------------------------------------------------------
3545  // Do a hit test on child objects Pre render (of this object). It depends on the object and iteration context,
3546  // if this will be doenon one layer, or by iterating through layers.
3547  // This stage also detect if there are post render children down there.
3548  //------------------------------------------------------------------------
3549 
3550  //detect while rendering children, if certain types of objects are there,
3551  //in order to render them later.
3552  RenderChild whichchilds;
3553  whichchilds.m_prerender = false;
3554  whichchilds.m_postrender = true;
3555  whichchilds.m_property = false;
3556 
3558  {
3559  //render "postrender" objects in children
3560  a2dCanvasObject* res = NULL;
3561  if ( res = IsHitWorldChildObjects( ic, whichchilds, hitEvent ) )
3562  {
3563  ic.EndFilterObject( this );
3564  if( hitEvent.m_extendedWanted )
3565  {
3566  ic.Last()->m_type = hitEvent.m_how;
3567 
3568  hitEvent.m_extended.push_back( a2dExtendedResultItem(
3569  res,
3570  ic.GetParent(),
3571  hitEvent.m_how,
3572  ic.GetLevel(),
3573  hitEvent.m_id
3574  ) );
3575  }
3576  return res;
3577  }
3578  }
3579 
3580  //------------------------------------------------------------------------
3581  // Do a hit test for the derived object
3582  //------------------------------------------------------------------------
3583 
3584  bool isHit = false;
3585  if ( !( hitEvent.m_option & a2dCANOBJHITOPTION_NOROOT ) &&
3586  ( ic.GetLayer() == m_layer || ic.GetLayer() == wxLAYER_ALL || m_flags.m_ignoreLayer )
3587  )
3588  {
3589  double StrokeExtend = 0;
3590  a2dStroke stroke = GetStroke();
3591 
3592  if ( stroke.IsNoStroke() ) //IsNoStroke() stroke means use layer
3593  {
3594  if ( m_root && m_root->GetLayerSetup() )
3595  {
3596  a2dStroke layerpen = m_root->GetLayerSetup()->GetStroke( m_layer );
3597  if ( layerpen.GetPixelStroke() )
3598  StrokeExtend = layerpen.GetWidth() / 2;
3599  else
3600  StrokeExtend = layerpen.GetWidth() / 2;
3601  }
3602  }
3603  else if ( !stroke.IsSameAs( *a2dTRANSPARENT_STROKE ) )
3604  {
3605  if ( stroke.GetPixelStroke() )
3606  {
3607  StrokeExtend = ic.GetDrawer2D()->DeviceToWorldXRel( stroke.GetWidth() / 2 );
3608  }
3609  else
3610  StrokeExtend = stroke.GetWidth() / 2;
3611  }
3612  ic.SetStrokeWorldExtend( StrokeExtend );
3613 
3614  // Restore what might have been changed in children hits.
3615  // prepare relative to object coordinates for derived objects
3616  hitEvent.m_relx = xrel;
3617  hitEvent.m_rely = yrel;
3618 
3619  if ( DoIsHitWorld( ic, hitEvent ) )
3620  {
3621  ic.SetStrokeWorldExtend( 0 );
3622 
3624  isHit = true;
3625  else if ( m_hitflags.m_stroke && hitEvent.m_how.IsStrokeHit() )
3626  isHit = true;
3627  else if ( m_hitflags.m_fill && hitEvent.m_how.IsFillHit() )
3628  isHit = true;
3629  else if ( m_hitflags.m_fill_non_transparent && hitEvent.m_how.IsFillHit() )
3630  {
3631  if ( !GetFill().IsSameAs( *a2dTRANSPARENT_FILL ) && !GetFill().GetFilling() )
3632  isHit = true;
3633  else if ( m_root && m_root->GetLayerSetup() )
3634  {
3635  if ( !m_root->GetLayerSetup()->GetFill( m_layer ).IsSameAs( *a2dTRANSPARENT_FILL )
3636  && !m_root->GetLayerSetup()->GetFill( m_layer ).GetFilling() )
3637  isHit = true;
3638  }
3639  }
3640  else if ( m_hitflags.m_stroke_non_transparent && hitEvent.m_how.IsStrokeHit() )
3641  {
3642  if ( GetStroke().IsSameAs( *a2dTRANSPARENT_STROKE ) )
3643  isHit = true;
3644  else if ( m_root && m_root->GetLayerSetup() )
3645  {
3646  if ( !m_root->GetLayerSetup()->GetStroke( m_layer ).IsSameAs( *a2dTRANSPARENT_STROKE ) )
3647  isHit = true;
3648  }
3649  }
3650 
3651  if ( isHit )
3652  {
3653  if( hitEvent.m_extendedWanted )
3654  {
3655  ic.Last()->m_type = hitEvent.m_how;
3656 
3657  hitEvent.m_extended.push_back( a2dExtendedResultItem(
3658  this,
3659  ic.GetParent(),
3660  hitEvent.m_how,
3661  ic.GetLevel(),
3662  hitEvent.m_id
3663  ) );
3664  }
3665  if( ! ( hitEvent.m_option & a2dCANOBJHITOPTION_ALL ) )
3666  {
3667  ic.SetDeepestHit( this );
3668  ic.EndFilterObject( this );
3669  return this;
3670  }
3671  }
3672  }
3673  ic.SetStrokeWorldExtend( 0 );
3674  }
3675 
3676  //------------------------------------------------------------------------
3677  // Do a hit test on child objects Post render (of this object). It depends on the object and iteration context,
3678  // if this will be doenon one layer, or by iterating through layers.
3679  //------------------------------------------------------------------------
3680 
3682  {
3683  whichchilds.m_prerender = true;
3684  whichchilds.m_postrender = false;
3685  whichchilds.m_property = false;
3686 
3687  //render "prerender" objects in children
3688  a2dCanvasObject* res = NULL;
3689  if ( res = IsHitWorldChildObjects( ic, whichchilds, hitEvent ) )
3690  {
3691  if( hitEvent.m_extendedWanted )
3692  {
3693  ic.Last()->m_type = hitEvent.m_how;
3694  hitEvent.m_extended.push_back( a2dExtendedResultItem(
3695  res,
3696  ic.GetParent(),
3697  hitEvent.m_how,
3698  ic.GetLevel(),
3699  hitEvent.m_id
3700  ) );
3701  }
3702  ic.EndFilterObject( this );
3703  return this;
3704  }
3705  }
3706 
3707  ic.EndFilterObject( this );
3708  if( hitEvent.m_option & a2dCANOBJHITOPTION_ALL && isHit )
3709  return ( a2dCanvasObject* ) this;
3710  return ( a2dCanvasObject* ) NULL;
3711 }
3712 
3713 bool a2dCanvasObject::DoIsHitWorld( a2dIterC& WXUNUSED( ic ), a2dHitEvent& hitEvent )
3714 {
3715  return false;
3716 }
3717 
3719  a2dIterC& ic,
3720  RenderChild& whichchilds,
3721  a2dHitEvent& hitEvent
3722 )
3723 {
3725  return NULL;
3726 
3727  //------------------------------------------------------------------------
3728  // Do a layer iteration if required
3729  //------------------------------------------------------------------------
3730 
3731  // These two hit option are only valid for the first call from a2dCanvasObject::IsHitWorld()
3732  // Skipping the root object only makes sence for the first object.
3733  // Iteration on layers is only an option on root level.
3734  wxUint32 optioncurrent = hitEvent.m_option;
3736 
3737  a2dCanvasObject* foundsofar = ( a2dCanvasObject* ) NULL;
3738 
3739  //m_flags.m_childrenOnSameLayer == true means render all children at once, together with the object itself.
3740  //Therefore even if the children objects do have other layer id's, they will appear on this object its layer in the drawing.
3741  //That is why we need to test them for hit together with this object.
3743  {
3744  wxASSERT_MSG( ic.GetLayer() != wxLAYER_ALL, _T( " a2dIterC::GetPerLayerMode() can only render one layer at the time" ) );
3745 
3746  wxUint16 layer = ic.GetLayer();
3747  unsigned int j;
3748  for ( j = 0; j < wxMAXLAYER; j++ )
3749  {
3750  a2dLayerInfo* layerinfo;
3751  if ( ic.GetDrawingPart()->GetReverseOrder() )
3752  layerinfo = m_root->GetLayerSetup()->GetOrderIndex()[j];
3753  else
3754  layerinfo = m_root->GetLayerSetup()->GetReverseOrderIndex()[j];
3755 
3756  // non defined layers, being those that where not in the layer setup, are sorted to the end of the indexes.
3757  // So the can be skipped.
3758  if ( layerinfo == wxNullLayerInfo )
3759  break;
3760 
3761  //important!
3762  //if layer is visible it will be rendered
3763  //If an object on a layer is itself invisible it will not be drawn
3764  //wxLAYER_ALL is reserved and should never be part of the layersettings
3765  if ( ic.GetDrawingPart()->GetLayerRenderArray()[ layerinfo->GetLayer() ].DoRenderLayer()
3766  && layerinfo->GetVisible() )
3767  {
3768  ic.SetLayer( layerinfo->GetLayer() );
3769  a2dCanvasObject* hit = HitChildObjectsOneLayer( ic, whichchilds, hitEvent );
3770  if ( hit )
3771  {
3772  if( ! ( hitEvent.m_option & a2dCANOBJHITOPTION_ALL ) )
3773  {
3774  ic.SetLayer( layer );
3775  hitEvent.m_option = optioncurrent;
3776  return hit;
3777  }
3778  foundsofar = hit;
3779  }
3780  }
3781  ic.SetLayer( layer );
3782  }
3783  }
3784  else
3785  {
3786  //no layer iteration will be done and therefore only object on m_layer == layer will be rendered.
3787  //layer == wxLAYER_ALL is a special case, and means ignore layer order for rendering the child objects.
3788  //checking of availability and visibility of layer itself is handled in parent objects
3789  a2dCanvasObject* hit = HitChildObjectsOneLayer( ic, whichchilds, hitEvent );
3790  if ( hit )
3791  {
3792  if( ! ( hitEvent.m_option & a2dCANOBJHITOPTION_ALL ) )
3793  {
3794  hitEvent.m_option = optioncurrent;
3795  return hit;
3796  }
3797  foundsofar = hit;
3798  }
3799  }
3800  hitEvent.m_option = optioncurrent;
3801  return foundsofar;
3802 }
3803 
3805  a2dIterC& ic,
3806  RenderChild& whichchilds,
3807  a2dHitEvent& hitEvent
3808 )
3809 {
3810  a2dCanvasObject* foundsofar = ( a2dCanvasObject* ) NULL;
3811 
3812  RenderChild detectchilds;
3813  detectchilds.m_postrender = false;
3814  detectchilds.m_prerender = false;
3815  detectchilds.m_property = false;
3816 
3817  //search in reverse order, last drawn on a layer, and therefore on top, will be found first for hit
3818  a2dCanvasObjectList::reverse_iterator iter = m_childobjects->rbegin();
3819  while( iter != m_childobjects->rend() )
3820  {
3821  a2dCanvasObject* obj = *iter;
3822  int olayer = obj->GetLayer();
3823 
3824  detectchilds.m_postrender = detectchilds.m_prerender || !obj->GetPreRenderAsChild();
3825  detectchilds.m_prerender = detectchilds.m_postrender || obj->GetPreRenderAsChild();
3826  detectchilds.m_property = detectchilds.m_property || obj->GetIsProperty();
3827 
3828  //do a rough check to increase speed in common cases
3829  if ( (
3830  ( obj->GetPreRenderAsChild() && whichchilds.m_prerender && !obj->GetIsProperty() ) ||
3831  ( !obj->GetPreRenderAsChild() && whichchilds.m_postrender && !obj->GetIsProperty() ) ||
3832  ( obj->GetIsProperty() && whichchilds.m_property )
3833  )
3834  // the next does work if child is a container like e.g. a2dCanvasObjectReference
3835  // because
3836  &&
3837  ( olayer == ic.GetLayer() || ic.GetLayer() == wxLAYER_ALL || obj->GetChildObjectsCount() || obj->GetIgnoreLayer() )
3838  )
3839  {
3840  if ( obj->m_flags.m_ChildOnlyTranslate )
3841  {
3842  a2dAffineMatrix iworld = m_lworld;
3843  iworld.Invert();
3844  a2dIterCU cu( ic, iworld );
3845  a2dAffineMatrix transworld;
3846  transworld.Translate( GetPosX(), GetPosY() );
3847  a2dIterCU cu2( ic, transworld );
3848  a2dCanvasObject* hit = obj->IsHitWorld( ic, hitEvent );
3849  if( hit )
3850  {
3851  foundsofar = obj;
3852  if( obj != hit )
3853  hitEvent.m_how.m_hit = hitEvent.m_how.m_hit | a2dHit::hit_child;
3854  if( ! ( hitEvent.m_option & a2dCANOBJHITOPTION_ALL ) )
3855  break;
3856  }
3857  }
3858  else
3859  {
3860  a2dCanvasObject* hit = obj->IsHitWorld( ic, hitEvent );
3861  if( hit )
3862  {
3863  foundsofar = obj;
3864  if( obj != hit )
3865  hitEvent.m_how.m_hit = hitEvent.m_how.m_hit | a2dHit::hit_child;
3866  if( ! ( hitEvent.m_option & a2dCANOBJHITOPTION_ALL ) )
3867  break;
3868  }
3869  }
3870  }
3871  iter++;
3872  }
3873 
3874  whichchilds = detectchilds;
3875 
3876  return foundsofar; //return top opject hit
3877 }
3878 
3879 static void ReportHit( a2dCanvasObject* obj, const wxString mes, bool editflag, a2dHitEvent& hitEvent )
3880 {
3881 #ifdef _DEBUG_REPORTHIT
3882  if ( editflag )
3883  {
3884  //else not event for this object
3885  if ( hitEvent.m_isHit )
3886  wxLogDebug( wxT( "hit = %s %p" ), mes, obj );
3887  else
3888  wxLogDebug( wxT( "nohit = %s %p" ), mes, obj );
3889  }
3890 #else
3891 #endif
3892 }
3893 
3894 bool a2dCanvasObject::LocalHit( a2dIterC& ic, a2dHitEvent& hitEvent )
3895 {
3896  a2dHit how;
3897  hitEvent.m_isHit = false;
3898 
3899  //now do a proper hittest inside the derived canvas object
3900 
3901  // iteration context needs stroke extend, to be used for hittest in derived object
3902  // this extend is always in world coordinates, even if pixel pens
3903  double StrokeExtend = 0;
3904  a2dStroke stroke = GetStroke();
3905 
3906  if ( stroke.IsNoStroke() ) //IsNoStroke() stroke means use layer
3907  {
3908  if ( m_root && m_root->GetLayerSetup() )
3909  {
3910  a2dStroke layerpen = m_root->GetLayerSetup()->GetStroke( m_layer );
3911  if ( layerpen.GetPixelStroke() )
3912  StrokeExtend = layerpen.GetWidth() / 2;
3913  else
3914  StrokeExtend = layerpen.GetWidth() / 2;
3915  }
3916  }
3917  else if ( !stroke.IsSameAs( *a2dTRANSPARENT_STROKE ) )
3918  {
3919  if ( stroke.GetPixelStroke() )
3920  StrokeExtend = ic.GetDrawer2D()->DeviceToWorldXRel( stroke.GetWidth() / 2 );
3921  else
3922  StrokeExtend = stroke.GetWidth() / 2;
3923  }
3924  ic.SetStrokeWorldExtend( StrokeExtend );
3925 
3926  if ( DoIsHitWorld( ic, hitEvent ) )
3927  {
3928  //check hit mask.
3930  hitEvent.m_isHit = true;
3931  else if ( m_hitflags.m_stroke && how.IsStrokeHit() )
3932  hitEvent.m_isHit = true;
3933  else if ( m_hitflags.m_fill && how.IsFillHit() )
3934  hitEvent.m_isHit = true;
3935  else if ( m_hitflags.m_fill_non_transparent && how.IsFillHit() )
3936  {
3937  if ( !GetFill().IsSameAs( *a2dTRANSPARENT_FILL ) )
3938  hitEvent.m_isHit = true;
3939  else if ( m_root && m_root->GetLayerSetup() )
3940  {
3941  if ( !m_root->GetLayerSetup()->GetFill( m_layer ).IsSameAs( *a2dTRANSPARENT_FILL ) )
3942  hitEvent.m_isHit = true;
3943  }
3944  }
3945  else if ( m_hitflags.m_stroke_non_transparent && how.IsStrokeHit() )
3946  {
3947  if ( !GetStroke().IsSameAs( *a2dTRANSPARENT_FILL ) )
3948  hitEvent.m_isHit = true;
3949  else if ( m_root && m_root->GetLayerSetup() )
3950  {
3951  if ( !m_root->GetLayerSetup()->GetStroke( m_layer ).IsSameAs( *a2dTRANSPARENT_STROKE ) )
3952  hitEvent.m_isHit = true;
3953  }
3954  }
3955  }
3956  else
3957  {
3958  ReportHit( this, wxT( "no hit on object" ), m_flags.m_editingCopy, hitEvent );
3959  }
3960 
3961  return hitEvent.m_isHit;
3962 }
3963 
3965 {
3966  if ( ic.GetDrawingPart()->GetCaptured() == this )
3967  {
3968  wxMouseEvent* mouse = wxDynamicCast( hitEvent.m_event, wxMouseEvent );
3969  if ( mouse )
3970  {
3971  // the object is captured, so mouse events are all sent to the object, even if not hit.
3972  a2dHit how( a2dHit::hit_captured, a2dHit::stroke1_none, a2dHit::stroke2_none, 0, 0 );
3973 
3974  a2dCanvasObjectMouseEvent CanvasObjectMouseEvent( &ic, this, hitEvent.m_how, hitEvent.m_x, hitEvent.m_y, *mouse );
3975  hitEvent.SetProcessed( ProcessEvent( CanvasObjectMouseEvent ) );
3976  }
3977  else
3978  hitEvent.SetProcessed( ProcessEvent( *hitEvent.m_event ) );
3979 
3980  if ( m_flags.m_editingCopy )
3981  // first event has passed.
3983 
3984  return hitEvent.m_processed;
3985  }
3986 
3987  // If there is an event corridor path, and the end of the corridor (or the captured
3988  // object if there is one) was not yet reached, continue with just looking at the
3989  // childs.
3990  // Otherwise continue processing this object.
3991 
3992  if ( ic.GetDrawingPart()->GetEndCorridorObject() == this && !ic.GetDrawingPart()->GetCaptured() )
3993  ic.SetFoundCorridorEnd( true );
3994 
3996  {
3997  if ( !m_flags.m_isOnCorridorPath )
3998  return false;
3999  else
4000  {
4001  a2dIterCU cu( ic, this );
4002 
4003  RenderChild whichchilds;
4004  whichchilds.m_prerender = true;
4005  whichchilds.m_postrender = true;
4006  whichchilds.m_property = true;
4007 
4008  if ( ic.GetDrawingPart()->GetEndCorridorObject() == this )
4009  ic.SetFoundCorridorEnd( true );
4010 
4011  ProcessCanvasEventChild( ic, whichchilds, hitEvent );
4012 
4013  return hitEvent.m_processed;
4014  }
4015  }
4016 
4018  return ( a2dCanvasObject* ) NULL;
4019 
4020  if ( ! GetIgnoreLayer() &&
4021  (
4022  !ic.GetDrawingPart()->GetLayerRenderArray()[ m_layer ].DoRenderLayer() ||
4023  ( m_root && m_root->GetLayerSetup() && !m_root->GetLayerSetup()->GetVisible( m_layer ) )
4024  )
4025  )
4026  {
4027  return ( a2dCanvasObject* ) NULL;
4028  }
4029 
4030  if ( ic.GetLayer() != m_layer && ic.GetLayer() != wxLAYER_ALL && !m_flags.m_ignoreLayer )
4031  {
4032  //the object itself will NOT be rendered for sure, but maybe its children still will!
4033 
4034  //object not on this layer, then children will NOT be rendered also in following cases
4036  return ( a2dCanvasObject* ) NULL;
4037  if ( ic.GetLayer() != wxLAYER_ALL && m_flags.m_childrenOnSameLayer )
4038  return ( a2dCanvasObject* ) NULL;
4039  }
4040 
4041  bool sentmousevent = false;
4042  bool localsentmousevent = false;
4043  // this is used for the eventual derived object hit, to generate a proper canvasobject mouse event
4044  bool wasHit = hitEvent.m_isHit;
4045  //detect for child starting at non hit nor processed
4046  hitEvent.m_isHit = false;
4047 
4048  ic.GetInverseTransform().TransformPoint( hitEvent.m_x, hitEvent.m_y, hitEvent.m_relx, hitEvent.m_rely );
4049  //first check if within bbox + its extends in world and pixels
4050  //will only work if they are always uptodate
4051  if ( GetBbox().PointInBox( hitEvent.m_relx, hitEvent.m_rely, m_worldExtend + ic.GetHitMarginWorld() + ic.ExtendDeviceToWorld( m_pixelExtend ) ) )
4052  {
4053  a2dIterCU cu( ic, this );
4054  // prepare relative to object coordinates for derived objects
4055  ic.GetInverseTransform().TransformPoint( hitEvent.m_x, hitEvent.m_y, hitEvent.m_relx, hitEvent.m_rely );
4056 
4057  // properties using a visible canvasobject can be hit. e.g. in case of an object tip
4058  a2dNamedPropertyList::const_iterator iter;
4059  for( iter = m_propertylist.begin(); iter != m_propertylist.end(); ++iter )
4060  {
4061  const a2dNamedProperty* prop = *iter;
4063  if ( canvasprop && canvasprop->GetVisible() )
4064  {
4065  a2dCanvasObject* canvasobj = canvasprop->GetCanvasObject();
4066  if( canvasobj )
4067  {
4068  canvasobj->ProcessCanvasObjectEvent( ic, hitEvent );
4069  }
4070  }
4071  }
4072 
4073  RenderChild whichchilds;
4074  whichchilds.m_prerender = true;
4075  whichchilds.m_postrender = true;
4076  whichchilds.m_property = true;
4077 
4078  hitEvent.m_isHit = false;
4079  // next priority is to the children
4081  {
4082  ProcessCanvasEventChild( ic, whichchilds, hitEvent );
4083  }
4084 
4085  // If the event was not processed at a deeper child level, this one ( parent object ) might be interested.
4086  // So events go deep first, and if hit and processed there we are done, else it travels up to its parent objects.
4087  if ( !hitEvent.m_processed )
4088  {
4089  if ( hitEvent.m_isHit ) // Ishit in childs but not processed.
4090  {
4091  //we had a hit on this object including its children
4092  sentmousevent = true;
4093  }
4094  else if ( ic.GetLayer() == m_layer || ic.GetLayer() == wxLAYER_ALL )
4095  {
4096  localsentmousevent = LocalHit( ic, hitEvent );
4097  sentmousevent = hitEvent.m_isHit = localsentmousevent;
4098  }
4099  else
4100  ReportHit( this, wxT( "no hit or wrong layer" ), m_flags.m_editingCopy, hitEvent );
4101  }
4102  else
4103  ReportHit( this, wxT( "processed no hit" ), m_flags.m_editingCopy, hitEvent );
4104  }
4105  else
4106  ReportHit( this, wxT( "no box hit" ), m_flags.m_editingCopy, hitEvent );
4107 
4108  ic.GetInverseTransform().TransformPoint( hitEvent.m_x, hitEvent.m_y, hitEvent.m_relx, hitEvent.m_rely );
4109 
4110  // a motion event might enter an object
4111  if ( ( *hitEvent.m_event ).GetEventType() == wxEVT_MOTION )
4112  {
4113  wxMouseEvent* mouse = wxDynamicCast( hitEvent.m_event, wxMouseEvent );
4114  hitEvent.m_event->Skip( true );
4115  //there was a hit in a child or here.
4116  if ( hitEvent.m_isHit && !m_flags.m_MouseInObject )
4117  {
4118  ReportHit( this, wxT( "enter" ), m_flags.m_editingCopy, hitEvent );
4119 
4120  m_flags.m_MouseInObject = true;
4121  a2dCanvasObjectMouseEvent enter( &ic, this, wxEVT_CANVASOBJECT_ENTER_EVENT, hitEvent.m_x, hitEvent.m_y, *mouse );
4122  // it is needed for a tip window when the tip window is closed in a2dCanvasObject::OnEnterObject()
4123  // or in a2dCanvasObject::OnLeaveObject()
4124  hitEvent.SetProcessed( ProcessEvent( enter ) );
4125  // if processed, ignore that for higher level objects.
4126  hitEvent.m_event->Skip( true );
4127  hitEvent.SetProcessed( false );
4128  }
4129  }
4130 
4131  //an event is only sent if the event was not processed sofar
4132  if ( sentmousevent )
4133  {
4134  //the first object receiving an event, is the deepest hit child.
4135  if ( !ic.GetDeepestHit() )
4136  {
4137  //wxLogDebug(wxT("deepest %p"), this );
4138 
4139  ic.SetDeepestHit( this );
4140  }
4141  wxMouseEvent* mouse = wxDynamicCast( hitEvent.m_event, wxMouseEvent );
4142  if ( mouse )
4143  {
4144  a2dCanvasObjectMouseEvent CanvasObjectMouseEvent( &ic, this, hitEvent.m_how, hitEvent.m_x, hitEvent.m_y, *mouse );
4145  hitEvent.SetProcessed( ProcessEvent( CanvasObjectMouseEvent ) );
4146  }
4147  else
4148  hitEvent.SetProcessed( ProcessEvent( *hitEvent.m_event ) );
4149 
4150  if ( m_flags.m_editingCopy )
4151  // first event has passed.
4153  }
4154 
4155  // a motion event might leaf or enter an object
4156  if ( ( *hitEvent.m_event ).GetEventType() == wxEVT_MOTION )
4157  {
4158  wxMouseEvent* mouse = wxDynamicCast( hitEvent.m_event, wxMouseEvent );
4159  hitEvent.m_event->Skip( true );
4160  //there was a hit in a child or here.
4161  if ( !hitEvent.m_isHit && m_flags.m_MouseInObject )
4162  {
4163  // If child objects are on the border of a parent, they are not hittested,
4164  // because the mouse is already outside the parent its boundingbox.
4165  // No hit testing means no leave events will be generated even if a previous
4166  // mouse position was inside a child(s).
4167  // Therefore make sure all objects below are sending a leave event when mouse flag was in.
4168  LeaveInObjects( ic, hitEvent );
4169 
4170  m_flags.m_MouseInObject = false;
4171  a2dCanvasObjectMouseEvent leave( &ic, this, wxEVT_CANVASOBJECT_LEAVE_EVENT, hitEvent.m_x, hitEvent.m_y, *mouse );
4172  // it is needed for a tip window when the tip window is closed in a2dCanvasObject::OnEnterObject() or in a2dCanvasObject::OnLeaveObject()
4173  hitEvent.SetProcessed( ProcessEvent( leave ) );
4174  // if processed, ignore that for higher level objects.
4175  hitEvent.m_event->Skip( true );
4176  hitEvent.SetProcessed( false );
4177 
4178  ReportHit( this, wxT( "leaft" ), m_flags.m_editingCopy, hitEvent );
4179  }
4180  }
4181 
4182  //restore ORed result for higher level parent objects
4183  hitEvent.m_isHit |= wasHit;
4184 
4185  ic.SetStrokeWorldExtend( 0 );
4186  return hitEvent.m_processed;
4187 }
4188 
4189 bool SetPointIfCloser( const a2dPoint2D& pointToSnapTo, const a2dPoint2D& pointToSnap, a2dPoint2D& bestPointSofar, double thresHoldWorld )
4190 {
4191  double dx = pointToSnap.m_x - pointToSnapTo.m_x;
4192  double dy = pointToSnap.m_y - pointToSnapTo.m_y;
4193  double snappedDx = bestPointSofar.m_x - pointToSnapTo.m_x;
4194  double snappedDy = bestPointSofar.m_y - pointToSnapTo.m_y;
4195 
4196  if ( fabs( dx ) < thresHoldWorld && fabs( dy ) < thresHoldWorld )
4197  {
4198  if ( fabs( dx ) < fabs( snappedDx ) && fabs( dy ) < fabs( snappedDy ) )
4199  {
4200  //wxLogDebug( "closer %f %f to %f %f", pointToSnap.m_x, pointToSnap.m_y, pointToSnapTo.m_x, pointToSnapTo.m_y );
4201 
4202  bestPointSofar = pointToSnap;
4203  return true;
4204  }
4205  }
4206  return false;
4207 }
4208 
4209 bool a2dCanvasObject::RestrictToObject( a2dIterC& ic, const a2dPoint2D& pointToSnapTo, a2dPoint2D& bestPointSofar, a2dSnapToWhatMask snapToWhat, double thresHoldWorld )
4210 {
4211  // object has disabled snap?
4212  if ( !m_flags.m_snap_to )
4213  return false;
4214 
4215  bool res = false;
4216  if ( snapToWhat & a2dRestrictionEngine::snapToPins ||
4218  )
4219  {
4221  {
4223  {
4224  a2dCanvasObject* obj = *iter;
4225  a2dPin* pin = wxDynamicCast( obj, a2dPin );
4226  if ( pin && !pin->GetRelease( ) )
4227  {
4228  if ( snapToWhat & a2dRestrictionEngine::snapToPins ||
4229  ( ( snapToWhat & a2dRestrictionEngine::snapToPinsUnconnected ) && !pin->IsConnectedTo() )
4230  )
4231  {
4232  //if within the threshold, do snap to pin position.
4233  res |= SetPointIfCloser( pointToSnapTo, a2dPoint2D( pin->GetAbsX(), pin->GetAbsY() ), bestPointSofar, thresHoldWorld );
4234  }
4235  }
4236  }
4237  }
4238  }
4239  if ( snapToWhat & a2dRestrictionEngine::snapToObjectPos )
4240  {
4241  res |= SetPointIfCloser( pointToSnapTo, GetPosXY(), bestPointSofar, thresHoldWorld );
4242  }
4243 
4244  if ( snapToWhat & a2dRestrictionEngine::snapToObjectVertexes )
4245  {
4246  //a2dCanvasObjectList* vectorpaths = GetAsCanvasVpaths( true );
4247  a2dCanvasObjectList* vectorpaths = GetSnapVpath( a2dRestrictionEngine::snapToObjectVertexes );
4248  if ( vectorpaths != wxNullCanvasObjectList )
4249  {
4250  forEachIn( a2dCanvasObjectList, vectorpaths )
4251  {
4252  a2dVectorPath* obj = wxStaticCast( ( *iter ).Get(), a2dVectorPath );
4253  if ( obj->RestrictToObject( ic, pointToSnapTo, bestPointSofar, a2dRestrictionEngine::snapToObjectVertexes, thresHoldWorld ) )
4254  {
4255  res = true;
4256  }
4257  }
4258  delete vectorpaths;
4259  }
4260  }
4261 
4262  if ( snapToWhat & a2dRestrictionEngine::snapToBoundingBox )
4263  {
4265  if ( untrans.GetWidth() == 0 || untrans.GetWidth() == 0 )
4267 
4268  double x, y, w, h;
4269  x = untrans.GetMinX();
4270  y = untrans.GetMinY();
4271  w = untrans.GetWidth();
4272  h = untrans.GetHeight();
4273 
4274  double tx, ty;
4275  m_lworld.TransformPoint( x , y, tx, ty );
4276  res |= SetPointIfCloser( pointToSnapTo, a2dPoint2D( tx, ty ), bestPointSofar, thresHoldWorld );
4277  m_lworld.TransformPoint( x , y + h, tx, ty );
4278  res |= SetPointIfCloser( pointToSnapTo, a2dPoint2D( tx, ty ), bestPointSofar, thresHoldWorld );
4279  m_lworld.TransformPoint( x + w , y + h, tx, ty );
4280  res |= SetPointIfCloser( pointToSnapTo, a2dPoint2D( tx, ty ), bestPointSofar, thresHoldWorld );
4281  m_lworld.TransformPoint( x + w , y + h, tx, ty );
4282  res |= SetPointIfCloser( pointToSnapTo, a2dPoint2D( tx, ty ), bestPointSofar, thresHoldWorld );
4283  m_lworld.TransformPoint( x + w , y, tx, ty );
4284  res |= SetPointIfCloser( pointToSnapTo, a2dPoint2D( tx, ty ), bestPointSofar, thresHoldWorld );
4285  m_lworld.TransformPoint( x , y + h / 2, tx, ty );
4286  res |= SetPointIfCloser( pointToSnapTo, a2dPoint2D( tx, ty ), bestPointSofar, thresHoldWorld );
4287  m_lworld.TransformPoint( x + w / 2 , y + h, tx, ty );
4288  res |= SetPointIfCloser( pointToSnapTo, a2dPoint2D( tx, ty ), bestPointSofar, thresHoldWorld );
4289  m_lworld.TransformPoint( x + w , y + h / 2, tx, ty );
4290  res |= SetPointIfCloser( pointToSnapTo, a2dPoint2D( tx, ty ), bestPointSofar, thresHoldWorld );
4291  m_lworld.TransformPoint( x + w / 2 , y, tx, ty );
4292  res |= SetPointIfCloser( pointToSnapTo, a2dPoint2D( tx, ty ), bestPointSofar, thresHoldWorld );
4293  }
4294 
4296  {
4297  }
4299  {
4300  }
4301  if ( snapToWhat & a2dRestrictionEngine::snapToObjectSegments )
4302  {
4303  }
4304 
4305  return res;
4306 }
4307 
4309 {
4310  a2dVpath* segments = new a2dVpath();
4311  a2dVectorPath* snappath = new a2dVectorPath( segments );
4312  a2dCanvasObjectList* snappathlist = new a2dCanvasObjectList();
4313  snappathlist->push_back( snappath );
4314 
4315  if ( snapToWhat & a2dRestrictionEngine::snapToPins ||
4317  )
4318  {
4320  {
4322  {
4323  a2dCanvasObject* obj = *iter;
4324  a2dPin* pin = wxDynamicCast( obj, a2dPin );
4325  if ( pin && !pin->GetRelease( ) )
4326  {
4327  if ( snapToWhat & a2dRestrictionEngine::snapToPins ||
4328  ( snapToWhat & a2dRestrictionEngine::snapToPinsUnconnected && !pin->IsConnectedTo() )
4329  )
4330  {
4331  a2dVpathSegment* seg = new a2dVpathSegment( pin->GetAbsX(), pin->GetAbsY(), a2dPATHSEG_MOVETO );
4332  segments->Add( seg );
4333  }
4334  }
4335  }
4336  }
4337  }
4338  if ( snapToWhat & a2dRestrictionEngine::snapToObjectPos )
4339  {
4341  segments->Add( seg );
4342  }
4343 
4344  if ( snapToWhat & a2dRestrictionEngine::snapToObjectVertexes )
4345  {
4346  // if the next GetAsCanvasVpaths( true ) is to complex for snapping, derive a2dCanvasObject::GetSnapVpath() for that object.
4347  a2dCanvasObjectList* vectorpaths = GetAsCanvasVpaths( true );
4348  if ( vectorpaths != wxNullCanvasObjectList )
4349  {
4350  snappathlist->TakeOverFrom( vectorpaths );
4351  delete vectorpaths;
4352  }
4353  }
4354 
4355  if ( snapToWhat & a2dRestrictionEngine::snapToBoundingBox )
4356  {
4358  if ( untrans.GetWidth() == 0 || untrans.GetWidth() == 0 )
4360 
4361  double x, y, w, h;
4362  x = untrans.GetMinX();
4363  y = untrans.GetMinY();
4364  w = untrans.GetWidth();
4365  h = untrans.GetHeight();
4366 
4367  double tx, ty;
4368  m_lworld.TransformPoint( x , y, tx, ty );
4369  segments->Add( new a2dVpathSegment( tx, ty, a2dPATHSEG_MOVETO ) );
4370  m_lworld.TransformPoint( x , y + h, tx, ty );
4371  segments->Add( new a2dVpathSegment( tx, ty, a2dPATHSEG_MOVETO ) );
4372  m_lworld.TransformPoint( x + w , y + h, tx, ty );
4373  segments->Add( new a2dVpathSegment( tx, ty, a2dPATHSEG_MOVETO ) );
4374  m_lworld.TransformPoint( x + w , y + h, tx, ty );
4375  segments->Add( new a2dVpathSegment( tx, ty, a2dPATHSEG_MOVETO ) );
4376  m_lworld.TransformPoint( x + w , y, tx, ty );
4377  segments->Add( new a2dVpathSegment( tx, ty, a2dPATHSEG_MOVETO ) );
4378  m_lworld.TransformPoint( x , y + h / 2, tx, ty );
4379  segments->Add( new a2dVpathSegment( tx, ty, a2dPATHSEG_MOVETO ) );
4380  m_lworld.TransformPoint( x + w / 2 , y + h, tx, ty );
4381  segments->Add( new a2dVpathSegment( tx, ty, a2dPATHSEG_MOVETO ) );
4382  m_lworld.TransformPoint( x + w , y + h / 2, tx, ty );
4383  segments->Add( new a2dVpathSegment( tx, ty, a2dPATHSEG_MOVETO ) );
4384  m_lworld.TransformPoint( x + w / 2 , y, tx, ty );
4385  segments->Add( new a2dVpathSegment( tx, ty, a2dPATHSEG_MOVETO ) );
4386  }
4387 
4388  if ( snapToWhat & a2dRestrictionEngine::snapToObjectSegments )
4389  {
4390  }
4391 
4392  return snappathlist;
4393 }
4394 
4396 {
4397  a2dVertexArray* alignPoints = new a2dVertexArray();
4398  a2dBoundingBox bbox;
4399 
4400  //bbox like points
4402  {
4403  a2dBoundingBox childbox;
4404  a2dBoundingBox childboxOnlyTranslate;
4405 
4406  if ( m_flags.m_visiblechilds )
4407  {
4408  a2dAffineMatrix transworld;
4409  transworld.Translate( GetPosX(), GetPosY() );
4411  {
4412  a2dCanvasObject* obj = *iter;
4413  //calculate bbox only for visible objects
4414  a2dPin* pin = wxDynamicCast( obj, a2dPin );
4415  if ( !pin && obj && obj->GetVisible() )
4416  {
4417  if ( obj->m_flags.m_ChildOnlyTranslate )
4418  {
4419  childboxOnlyTranslate = obj->GetBbox();
4420  childboxOnlyTranslate.MapBbox( transworld );
4421  }
4422  else
4423  childbox.Expand( obj->GetBbox() );
4424  }
4425  }
4426  }
4427 
4428  if ( childboxOnlyTranslate.GetValid() ) //no child or empty child secure
4429  childbox.Expand( childboxOnlyTranslate );
4430 
4431  if ( childbox.GetValid() ) //no child or empty child secure
4432  {
4433  childbox.MapBbox( m_lworld );
4434  bbox.Expand( childbox );
4435  }
4436 
4437  if ( !m_bbox.GetValid() )
4438  {
4440  if ( m_bbox.GetValid() )
4441  {
4442  m_bbox.MapBbox( m_lworld );
4443  }
4444  }
4445  bbox.Expand( m_bbox );
4446 
4447  if ( !bbox.GetValid() )
4448  {
4449  //no objects, therefore make the bounding box the x,y of the object
4450  bbox.Expand( m_lworld.GetValue( 2, 0 ), m_lworld.GetValue( 2, 1 ) );
4451  }
4452  }
4453  else
4454  { //just bbox will do.
4455  bbox = GetBbox();
4456  }
4457 
4458  alignPoints->push_back( new a2dLineSegment( bbox.GetMinX(), bbox.GetMinY() ));
4459  alignPoints->push_back( new a2dLineSegment( bbox.GetMinX(), bbox.GetMaxY() ));
4460  alignPoints->push_back( new a2dLineSegment( bbox.GetMaxX(), bbox.GetMaxY() ));
4461  alignPoints->push_back( new a2dLineSegment( bbox.GetMaxX(), bbox.GetMinY() ));
4462 
4463  alignPoints->push_back( new a2dLineSegment( bbox.GetMinX(), bbox.GetCentre().m_y ));
4464  alignPoints->push_back( new a2dLineSegment( bbox.GetCentre().m_x, bbox.GetMaxY() ));
4465  alignPoints->push_back( new a2dLineSegment( bbox.GetMaxX(), bbox.GetCentre().m_y ));
4466  alignPoints->push_back( new a2dLineSegment( bbox.GetCentre().m_x, bbox.GetMinY() ));
4467 
4468  alignPoints->push_back( new a2dLineSegment( bbox.GetMinX(), bbox.GetCentre().m_y ));
4469 
4470  return alignPoints;
4471 }
4472 
4474 {
4475  a2dBoundingBox alignbox;
4476  a2dVertexArray* alignpoints = GetAlignmentPoints();
4477 
4478  alignbox.Expand( alignpoints->Item(0)->m_x, alignpoints->Item(0)->m_y );
4479  alignbox.Expand( alignpoints->Item(1)->m_x, alignpoints->Item(1)->m_y );
4480  alignbox.Expand( alignpoints->Item(2)->m_x, alignpoints->Item(2)->m_y );
4481  alignbox.Expand( alignpoints->Item(3)->m_x, alignpoints->Item(3)->m_y );
4482  delete alignpoints;
4483 
4484  return alignbox;
4485 }
4486 
4487 bool a2dCanvasObject::SwitchChildNamed( const wxString& objectname, a2dCanvasObject* newobject )
4488 {
4490  return m_childobjects->SwitchObjectNamed( objectname, newobject );
4491 
4492  return false;
4493 }
4494 
4496  const a2dPropertyId* id, const a2dBoundingBox& bbox ) const
4497 {
4499  {
4500  return m_childobjects->CollectObjects( total, classname, mask, id, bbox );
4501  }
4502  return 0;
4503 }
4504 
4505 a2dCanvasObject* a2dCanvasObject::Find( const wxString& objectname, const wxString& classname, a2dCanvasObjectFlagsMask mask, const a2dPropertyId* propid, const wxString& valueAsString, wxUint32 id ) const
4506 {
4508  return m_childobjects->Find( objectname, classname, mask, propid, valueAsString, id );
4509 
4510  return ( a2dCanvasObject* ) NULL;
4511 }
4512 
4514 {
4516  return m_childobjects->Find( obj );
4517  else
4518  return 0;
4519 }
4520 
4522 {
4523  bool childpending = false;
4524  {
4525  a2dIterCU cu( ic, this );
4526 
4528  {
4530  {
4531  a2dCanvasObject* obj = *iter;
4532  //no need to test clipping of bounding against ic.GetDrawer2D(),
4533  //since only pending objects are tested which is not expensive
4534  if ( obj )
4535  {
4536  childpending = ( obj->m_flags.m_pending || obj->m_release ) || childpending;
4537  obj->AddPending( ic );
4538  }
4539  }
4540  }
4541 
4542  DoAddPending( ic );
4543  }
4544 
4545  // automatically set layers available for new objects on empty layers.
4546  ic.GetDrawingPart()->GetLayerRenderArray()[ m_layer ].IncrementObjectCount();
4547  if ( m_root && m_root->GetLayerSetup() )
4548  {
4549  a2dLayerInfo* thislayer = m_root->GetLayerSetup()->GetLayerIndex()[ m_layer ];
4550  thislayer->IncrementObjectCount();
4551  }
4552 
4553  // Resize to children, requires to set it pending here, in order to add current bbox.
4554  // And in a2dCanvasObject::Update() in DoUpdate() m_flags.m_resizeToChilds must be tested by the
4555  // derived object to resize itself to its children.
4556 
4558  m_flags.m_pending |= childpending;
4559 
4560  if ( m_flags.m_pending || m_release )
4561  {
4562  // store/update or trigger the availability of layers for this a2dCanvasView.
4563  if ( m_release )
4564  {
4565  //releasing an object, may lead to a layer becoming empty.
4566  //Understand that the object can be shown on one view and not another
4567  //view.
4568  if ( ic.GetUpdateHint() & a2dCANVIEW_UPDATE_PENDING_POSTUPDATE )
4569  {
4570  //a2dLayerInfo* thislayer = m_root->GetLayerSetup()->GetLayerIndex()[ m_layer ];
4571  //thislayer->DecrementObjectCount();
4572  ic.GetDrawingPart()->GetLayerRenderArray()[ m_layer ].DecrementObjectCount();
4573  }
4574  }
4575 
4576  //first we search for bbox properties, which are taking priority above complete bbox updating
4577  bool foundMiniUpdate = false;
4578  a2dNamedPropertyList::const_iterator iter;
4579  for( iter = m_propertylist.begin(); iter != m_propertylist.end(); ++iter )
4580  {
4581  const a2dNamedProperty* prop = *iter;
4582  if ( prop->GetId() == PROPID_BoundingBox )
4583  {
4585  foundMiniUpdate = true;
4586  }
4587  }
4588 
4589  // if no bbox properties are found, we use the complete boudingbox instead.
4590  if ( !foundMiniUpdate )
4591  {
4592  //wxLogDebug( "add bbox area %p", this );
4593 
4594  wxRect absarea = GetAbsoluteArea( ic );
4595  ic.GetDrawingPart()->AddPendingUpdateArea( absarea );
4596  }
4597  }
4598 
4599 }
4600 
4602 {
4603 }
4604 
4606 {
4607  //if an object is view specific, then it is only visible on a certain view,
4608  //so also its children and all below will not be visible, therefore no need to check them.
4609  a2dDrawingPart* view = wxStaticCastNull( PROPID_ViewSpecific->GetPropertyValue( this ).Get(), a2dDrawingPart );
4610  if ( view != ic.GetDrawingPart() )
4611  return;
4612 
4613  //objects which depend on a certain view when it concerns size, can be found
4614  // at each level, so we really need to recurse always.
4615  a2dDrawingPart* view2 = wxStaticCastNull( PROPID_ViewDependent->GetPropertyValue( this ).Get(), a2dDrawingPart );
4616  if ( view2 == ic.GetDrawingPart() )
4617  {
4619  }
4620 
4621  a2dIterCU cu( ic, this );
4622 
4624 
4626  {
4628  {
4629  a2dCanvasObject* obj = *iter;
4630 // if(obj->m_childpixelsize)
4631  if ( obj )
4632  obj->UpdateViewDependentObjects( ic );
4633  }
4634  }
4635 }
4636 
4638 {
4640  if ( !propSpec )
4641  {
4642  a2dAffineMatrix tworld = ic.GetTransform();
4643 
4644  a2dAffineMatrix withoutScale( ic.GetMappingTransform() * tworld * m_lworld );
4645  withoutScale.RemoveScale();
4646  a2dAffineMatrix invertMapping( ic.GetMappingTransform() );
4647  invertMapping.Invert();
4648  a2dAffineMatrix newRelative( ic.GetInverseTransform() );
4649  newRelative *= invertMapping;
4650  newRelative *= withoutScale;
4651  m_lworld = newRelative;
4652  SetPending( true );
4653  delete propSpec;
4654  }
4655 }
4656 
4658 {
4660  if ( propSpec )
4661  {
4662  a2dMatrixProperty* propMatrix = wxStaticCast( propSpec, a2dMatrixProperty );
4663 
4664  a2dAffineMatrix tworld = ic.GetTransform();
4665  a2dAffineMatrix withoutScale( ic.GetMappingTransform() * tworld );
4666  withoutScale.RemoveScale();
4667  a2dAffineMatrix invertMapping( ic.GetMappingTransform() );
4668  invertMapping.Invert();
4669  a2dAffineMatrix newRelative( ic.GetInverseTransform() );
4670  newRelative *= invertMapping;
4671  newRelative *= withoutScale;
4672 
4673  propMatrix->SetValue( newRelative );
4674  SetPending( true );
4675  delete propSpec;
4676  }
4677 
4678 }
4679 
4681 {
4682  //the default highlight is a boundingbox, therefore if a nested child has changed also
4683  //set this object pending.
4684  a2dCanvasObject* parent = wxDynamicCast( handler->GetParent(), a2dCanvasObject );
4685  if ( parent && parent->GetHighLight() && !parent->GetPending() && GetPending() )
4686  {
4687  parent->SetPending( true );
4688  }
4689 }
4690 
4692 {
4693 }
4694 
4695 void a2dCanvasObject::DoRender( a2dIterC& ic, OVERLAP WXUNUSED( clipparent ) )
4696 {
4697  if ( m_childobjects->size() == 0 )
4698  {
4699  double x1;
4700  double y1;
4701  ic.GetTransform().TransformPoint( 0, 0, x1, y1 );
4702  int dx = ic.GetDrawer2D()->WorldToDeviceX( x1 );
4703  int dy = ic.GetDrawer2D()->WorldToDeviceY( y1 );
4704 
4706  ic.GetDrawer2D()->DrawLine( dx - 3, dy, dx + 4, dy );
4707  ic.GetDrawer2D()->DrawLine( dx, dy + 3, dx, dy - 4 );
4708  ic.GetDrawer2D()->PopTransform();
4709  }
4710 }
4711 
4713 {
4714  // Check if the object is not about to be deleted
4715  if ( m_release )
4716  return;
4717 
4718  if ( !ic.FilterObject( this ) )
4719  {
4720  ic.EndFilterObject( this );
4721  return;
4722  }
4723 
4724  //Now we will either render the object or children or both on the given layer.
4725  //OR in case layer == wxLAYER_ALL, everything will be rendered at once.
4726  //Style of objects will be according to their own style properties of using the object
4727  //m_layer id.
4728 
4729 
4730  //get bbox at the absolute position
4731  //first map without pen width which is not included in the boundingbox
4732 
4733  // if 0 in width or height, nothing will be rendered in principle.
4734  // But the stroke width is not included in bbox, so it might still be visible.
4735  if ( !m_flags.m_NoRenderCanvasObject && GetBbox().GetWidth() && GetBbox().GetHeight() )
4736  {
4737  a2dBoundingBox absarea = GetBbox();
4738  if ( !ic.GetTransform().IsIdentity() )
4739  absarea.MapBbox( ic.GetTransform() );
4740 
4741  if ( m_worldExtend )
4742  absarea.Enlarge( m_worldExtend );
4743  if ( m_pixelExtend )
4744  absarea.Enlarge( ic.GetDrawer2D()->DeviceToWorldXRel( m_pixelExtend ) );
4745 
4746  double size = wxMax( absarea.GetWidth(), absarea.GetHeight() );
4747  if ( ic.GetDrawer2D()->GetPrimitiveThreshold() != 0
4748  && size < ic.GetDrawer2D()->DeviceToWorldXRel( ic.GetDrawer2D()->GetPrimitiveThreshold() ) )
4749  {
4750  if ( ic.GetDrawer2D()->GetThresholdDrawRectangle() )
4751  {
4752  wxRect absareadev = GetAbsoluteArea( ic, 0 );
4753  ic.GetDrawer2D()->DrawRoundedRectangle( GetBbox().GetMinX(), GetBbox().GetMinY(),
4754  GetBbox().GetWidth(), GetBbox().GetHeight(), 0 );
4755 
4756  if ( m_flags.m_HighLight )
4757  DrawHighLighted( ic );
4758  }
4759  ic.EndFilterObject( this );
4760  return;
4761  }
4762  }
4763 
4764  // a2dIterCU scope ends for DrawHighLighted( ic )
4765  {
4766  //here the Drawer gets a new relative transform
4767  //Every call for drawing something on it, will use it from now on.
4768  // we go one level deeper in transform to the child level
4769  a2dIterCU cu( ic, this );
4770 
4771  //if ( m_flags.m_HighLight )
4772  // DrawHighLighted( ic );
4773 
4774 
4775  //if the propertylist NOT contains style properties,
4776  //we need to set the style according to the layer setting.
4777  bool fillset = false;
4778  bool strokeset = false;
4779  bool viewSpecific = false;
4780 
4781  a2dLayers* layers = m_root->GetLayerSetup();
4782 
4783  //investigate if there are properties which influence the rendering.
4784  //
4785  if ( HasDynamicProperties() )
4786  {
4787  bool firstclip = false;
4788 
4789  a2dNamedPropertyList::const_iterator iter;
4790  for( iter = m_propertylist.begin(); iter != m_propertylist.end(); ++iter )
4791  {
4792  const a2dNamedProperty* prop = *iter;
4793  a2dObject* obj = prop->GetRefObjectNA();
4794  if ( wxDynamicCast( prop , a2dFillProperty ) )
4795  {
4796  a2dFill fill = wxStaticCast( prop, a2dFillProperty )->GetValue();
4797  if ( m_flags.m_filled )
4798  {
4799  if ( fill.IsSameAs( *a2dINHERIT_FILL ) )
4800  fillset = true;
4801  else if ( fill.IsNoFill() )
4802  fillset = false;
4803  else
4804  {
4805  ic.GetDrawer2D()->SetDrawerFill( fill );
4806  fillset = true;
4807  }
4808  }
4809  else
4810  {
4812  fillset = true;
4813  }
4814 
4815  }
4816  else if ( wxDynamicCast( prop, a2dStrokeProperty ) )
4817  {
4818  a2dStroke stroke = wxStaticCast( prop, a2dStrokeProperty )->GetValue();
4819  if ( stroke.IsSameAs( *a2dINHERIT_STROKE ) )
4820  strokeset = true;
4821  else if ( stroke.IsNoStroke() )
4822  strokeset = false;
4823  else
4824  {
4825  strokeset = true;
4826  ic.GetDrawer2D()->SetDrawerStroke( stroke );
4827  }
4828 
4829  }
4830  else if ( !m_flags.m_editingCopy && wxDynamicCast( prop, a2dClipPathProperty ) )
4831  {
4832  //Pushing a clipping area is relative to the drawer its matrix.
4833  wxStaticCast( prop, a2dClipPathProperty )->PushClip( ic.GetDrawingPart(), firstclip ? a2dCLIP_OR : a2dCLIP_AND );
4834  firstclip = true;
4835  }
4837  {
4839  double dx = cos( shadow->GetExtrudeAngle() ) * shadow->GetExtrudeDepth();
4840  double dy = sin( shadow->GetExtrudeAngle() ) * shadow->GetExtrudeDepth();
4841 
4842  a2dAffineMatrix tworld = ic.GetTransform();
4843 
4844  SetDrawerStyle( ic, shadow );
4845  tworld.Translate( dx, dy );
4846 
4847  //here the Drawer gets a new relativetoabsolute transform
4848  //Every call for drawing something on it, will use it.
4849  ic.GetDrawer2D()->SetTransform( tworld );
4850 
4851  DoRender( ic, clipparent );
4852  tworld.Translate( -dx, -dy );
4853 
4854  //restore
4855  ic.GetDrawer2D()->SetTransform( tworld );
4856  }
4857  else if ( wxDynamicCast( prop, a2dCanvasObjectPtrProperty ) )
4858  {
4860 
4861  if (
4862  torender->GetCanRender() &&
4863  torender->GetPreRender() &&
4864  torender->GetCanvasObject() &&
4865  torender->GetVisible() &&
4866  ( !torender->GetSelectedOnly() || IsSelected() )
4867  )
4868  torender->GetCanvasObject()->Render( ic, clipparent );
4869  }
4870  else if ( prop->GetId() == PROPID_ViewSpecific && prop->GetRefObject() != ic.GetDrawingPart() )
4871  {
4872  viewSpecific = true;
4873  }
4874  }
4875  }
4876 
4877  if ( viewSpecific )
4878  {
4879  ic.EndFilterObject( this );
4880  return;
4881  }
4882 
4883  //if style not set by the properties ,do it now using the layers.
4884  if ( layers )
4885  {
4886  if ( !fillset )
4887  ic.GetDrawer2D()->SetDrawerFill( layers->GetFill( m_layer ) );
4888  if ( !strokeset )
4889  ic.GetDrawer2D()->SetDrawerStroke( layers->GetStroke( m_layer ) );
4890  }
4891  else
4892  {
4893  if ( !fillset )
4894  ic.GetDrawer2D()->SetDrawerFill( GetHabitat()->GetDefaultFill() );
4895  if ( !strokeset )
4896  ic.GetDrawer2D()->SetDrawerStroke( GetHabitat()->GetDefaultStroke() );
4897  }
4898 
4899  //save the current style state of the a2dCanvasView, in order to restore style of object when needed.
4900  a2dFill currentdrawer_fill = ic.GetDrawer2D()->GetDrawerFill();
4901  a2dStroke currentdrawer_stroke = ic.GetDrawer2D()->GetDrawerStroke();
4902 
4903  //detect while rendering children, if certain types of objects are there,
4904  //in order to render them later.
4905  RenderChild whichchilds;
4906  whichchilds.m_prerender = true;
4907  whichchilds.m_postrender = false;
4908  whichchilds.m_property = false;
4909 
4911  {
4912  //render "prerender" objects in children
4913  RenderChildObjects( ic, whichchilds, clipparent );
4914 
4915  //RenderChildObject restores style as was before calling it
4916  }
4917 
4918  //if the object has sub objects (apart from the childobjects which are handled here),
4919  //those subobjects must be rendered by iterating on layer when needed/wanted, simular to child objects.
4920  //We do not iterate here, since that is only needed if indeed there or subobjects.
4921  //This will be know in a "wxDerivedCanvasObject DoRender".
4922  //SO parent objects that call this function here, MUST:
4923  // 1- clip object against area to redraw.
4924  // 2- iterate on layers when needed.
4925  if ( ic.GetLayer() == m_layer || ic.GetLayer() == wxLAYER_ALL || m_flags.m_ignoreLayer )
4926  {
4927 
4928  // DoRender() should not change the matrix of the drawing context, or at least restore it.
4929  // To prevent taking time for this.
4930  //a2dAffineMatrix tworld = ic.GetTransform();
4931 
4932  DoRender( ic, clipparent );
4933 
4934  //restore
4935  //ic.GetDrawer2D()->SetTransform( tworld );
4936 
4937  //never know what happened in DoRender, so better restore object style
4938  ic.GetDrawer2D()->SetDrawerFill( currentdrawer_fill );
4939  ic.GetDrawer2D()->SetDrawerStroke( currentdrawer_stroke );
4940  }
4941 
4943  {
4944  whichchilds.m_prerender = false;
4945  whichchilds.m_postrender = true;
4946  whichchilds.m_property = false;
4947 
4948  //render "postrender" objects in children
4949  RenderChildObjects( ic, whichchilds, clipparent );
4950 
4951  //RenderChildObject restores style as was before calling it
4952  }
4953 
4954  //renderproperties is set true when a special a2dCanvasObject is used to display normally
4955  //invisible properties. This is indicated by the flag IsProperty()
4956  //So the objects rendering in some way a property, follow on top of all
4957  //other children.
4959  {
4960  whichchilds.m_prerender = false;
4961  whichchilds.m_postrender = false;
4962  whichchilds.m_property = true;
4963  //render post object children
4964  RenderChildObjects( ic, whichchilds, clipparent );
4965 
4966  //RenderChildObject restores style as was before calling it
4967  }
4968 
4969  // rendering object tip on top.
4970  if ( HasDynamicProperties() )
4971  {
4972 
4973  a2dNamedPropertyList::const_iterator iter;
4974  for( iter = m_propertylist.begin(); iter != m_propertylist.end(); ++iter )
4975  {
4976  const a2dNamedProperty* prop = *iter;
4977  a2dObject* obj = prop->GetRefObjectNA();
4979  {
4980  wxStaticCast( prop, a2dClipPathProperty )->PopClip( ic.GetDrawingPart() );
4981  }
4982 
4983 
4985  {
4986  //__OBJECTTIP__ can be post and prerendered
4988 
4989  if (
4990  torender->GetCanRender() &&
4991  !torender->GetPreRender() &&
4992  torender->GetCanvasObject() &&
4993  torender->GetVisible() &&
4994  ( !torender->GetSelectedOnly() || IsSelected() )
4995  )
4996  {
4997  torender->GetCanvasObject()->Render( ic, clipparent );
4998  }
4999  }
5000  // properties that have a a2dCanvasObject in some manner, can be rendered aswell.
5001  // But only if the SetCanRender is set true.
5002  // a2dClipPathProperty is an example of that.
5003  else if ( prop->GetCanRender() && obj && prop->GetVisible()
5004  )
5005  {
5006  a2dCanvasObject* canobj = wxDynamicCast( obj, a2dCanvasObject );
5007  if ( canobj )
5008  canobj->Render( ic, clipparent );
5009  }
5010  }
5011  }
5012  }
5013 
5014  if ( m_flags.m_HighLight )
5015  DrawHighLighted( ic );
5016 
5017  ic.EndFilterObject( this );
5018 }
5019 
5021 {
5022  //a2dAffineMatrix cworld = ic.GetParentTransform();
5023  //a2dAffineMatrix tworld = ic.GetTransform();
5024 
5025  ic.GetDrawer2D()->SetDrawerStroke( GetHabitat()->GetHighLightStroke() );
5026  ic.GetDrawer2D()->SetDrawerFill( GetHabitat()->GetHighLightFill() );
5027 
5029 }
5030 
5031 a2dBoundingBox a2dCanvasObject::DoGetUnTransformedBbox( a2dBboxFlags WXUNUSED( flags ) ) const
5032 {
5033  return a2dBoundingBox(); // return a non valid boundingbox ( will be expanded later on )
5034 }
5035 
5037 {
5038  a2dBoundingBox box = DoGetUnTransformedBbox( flags );
5039  if ( ( flags & a2dCANOBJ_BBOX_CHILDREN )
5042  {
5043  a2dCanvasObjectList::iterator iter;
5044  for( iter = m_childobjects->begin(); iter != m_childobjects->end(); ++iter )
5045  {
5046  a2dCanvasObject* obj = *iter;
5047  if ( obj )
5049  }
5050 
5051  for( iter = m_childobjects->begin(); iter != m_childobjects->end(); ++iter )
5052  {
5053  a2dCanvasObject* obj = *iter;
5054  // this is calculating bbox only for visible objects
5055  if( obj && obj->GetVisible() )
5056  box.Expand( obj->GetBbox() );
5057  }
5058  }
5059 
5060  //in case there is not a derived object, and there are no children,
5061  //we still like to have a boundingbox.
5062  if ( !box.GetValid() )
5063  {
5064  //no objects make the bounding box the x,y of the group
5065  //because the bouding box is untransformed, this is 0,0
5066  box.Expand( 0, 0 );
5067  }
5068 
5069  return box;
5070 }
5071 
5073 {
5075  if ( nChildLevels >= 1 && m_childobjects != wxNullCanvasObjectList && m_flags.m_visiblechilds )
5076  {
5078  {
5079  a2dCanvasObject* obj = *iter;
5080  if ( obj )
5081  box.Expand( obj->GetCalculatedBoundingBox( nChildLevels - 1 ) );
5082  }
5083  }
5084 
5085  //in case there is not a derived object, and there are no children,
5086  //we still like to have a boundingbox.
5087  if ( !box.GetValid() )
5088  {
5089  //no objects make the bounding box the x,y of the group
5090  box.Expand( 0, 0 );
5091  }
5092 
5093  box.MapBbox( m_lworld );
5094 
5095  return box;
5096 }
5097 
5098 bool a2dCanvasObject::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
5099 {
5100  if ( !m_bbox.GetValid() )
5101  {
5103  if ( m_bbox.GetValid() )
5104  {
5105  m_bbox.MapBbox( m_lworld );
5106  return true;
5107  }
5108  }
5109  return false;
5110 }
5111 
5112 
5114 {
5115  bool changed = false;
5116  a2dCanvasObjectList::iterator iter = m_childobjects->begin();
5117  while( iter != m_childobjects->end() )
5118  {
5119  a2dCanvasObjectList::value_type obj = *iter;
5120 
5121  if ( obj && obj->m_release )
5122  {
5123  obj->RemoveReleased();
5124 
5125  // There may be multiple references, if just one is to be released, the parent property should have
5126  // bin set to obj.
5127  // Search parent property in obj, to know this is the one to delete the obj child from.
5128  a2dCanvasObject* parent = PROPID_Parent->GetPropertyValue( obj );
5129  if ( ( parent == NULL ) || ( parent != NULL && parent == this ) )
5130  {
5131  if ( obj->HasPins() )
5132  obj->DisConnectWith();
5133  wxUint16 layer = obj->GetLayer();
5134  iter = m_childobjects->erase( iter );
5135  changed = true;
5136  if ( m_root && m_root->GetLayerSetup() )
5137  {
5138  a2dLayerInfo* thislayer = m_root->GetLayerSetup()->GetLayerIndex()[ layer ];
5139  thislayer->DecrementObjectCount();
5140  }
5141  }
5142  }
5143  else
5144  iter++;
5145  }
5146  return changed;
5147 }
5148 
5150 {
5151  a2dBoundingBox oldbbox = m_bbox;
5152 
5153  a2dLayers* layers = NULL;
5154  bool changed = false; //true in the end if this level or child level has changed and needs recalculation
5155  // Release all childs with m_release = true
5157  {
5158  wxString str = GetClassInfo()->GetClassName();
5159  m_flags.m_NoRenderCanvasObject = str.IsSameAs( wxT( "a2dCanvasObject" ) );
5162 
5163  changed = RemoveReleased();
5164 
5165  if ( m_childobjects->empty() && !GetIgnoreLayer() )
5166  {
5167  delete m_childobjects;
5169  }
5170  }
5171 
5172  if ( ( mode & updatemask_countObjects ) )
5173  {
5174  if ( m_root && m_root->GetLayerSetup() )
5175  {
5176  a2dLayerInfo* thislayer = m_root->GetLayerSetup()->GetLayerIndex()[ m_layer ];
5177  thislayer->IncrementObjectCount();
5178  }
5179  }
5180 
5181  // Check if the object itself needs a bbox calculation
5182  // Calculate stroke and pixel extends
5183  if ( ( mode == updatemask_force ) || m_flags.m_pending || !m_bbox.GetValid() )
5184  {
5185  // ok, the object did change and needs a calculation
5186  changed = true;
5190 
5191  m_pixelExtend = 0;
5192  m_worldExtend = 0;
5193 
5194  a2dNamedPropertyList::const_iterator iter;
5195  for( iter = m_propertylist.begin(); iter != m_propertylist.end(); ++iter )
5196  {
5197  const a2dNamedProperty* prop = *iter;
5198  a2dObject* obj = prop->GetRefObjectNA();
5199  if ( wxDynamicCast( prop , a2dStrokeProperty ) )
5200  {
5201  a2dStroke stroke = wxStaticCast( prop , a2dStrokeProperty )->GetValue();
5202 
5203  if ( stroke.IsNoStroke() ) // IsNoStroke() stroke means use layer
5204  {
5205  if ( m_root && layers )
5206  {
5207  a2dStroke layerpen = layers->GetStroke( m_layer );
5208  if ( layerpen.GetPixelStroke() )
5209  {
5210  m_pixelExtend = ( wxUint16 ) ( layerpen.GetWidth() / 2 );
5211  }
5212  else
5213  {
5214  m_worldExtend = layerpen.GetWidth() / 2;
5215  }
5216  }
5217  }
5218  else if ( !stroke.IsSameAs( *a2dTRANSPARENT_STROKE ) )
5219  {
5220  if ( stroke.GetPixelStroke() )
5221  {
5222  m_pixelExtend = ( wxUint16 ) ( stroke.GetWidth() / 2 );
5223  }
5224  else
5225  {
5226  m_worldExtend = stroke.GetWidth() / 2;
5227  }
5228  }
5229 
5230  }
5231  else if ( GetAlgoSkip() && ( prop->GetId() == a2dCanvasObject::PROPID_ToolObject ||
5233  )
5235  }
5236  }
5237 
5238  //the boundingbox consists of three parts:
5239  // derived object
5240  // child objects
5241  // properties
5242  // If one or more of those changed, all of them need to be recalculated
5243 
5244  bool childchanged = false;
5245  //check childs for change by calling its Update()
5247  {
5249  {
5250  a2dCanvasObject* obj = *iter;
5251  if ( !obj )
5252  continue;
5253 
5254  childchanged = obj->Update( mode ) || childchanged;
5257 
5258  //if childchanged has become true now, this means that down here the current child object did change and
5259  //therefore has recalculated its boundingbox already.
5260  }
5261  }
5262 
5263  bool propertychanged = false;
5264  //check properties for change
5265  if ( HasDynamicProperties() )
5266  {
5267  a2dNamedPropertyList::const_iterator iter;
5268  for( iter = m_propertylist.begin(); iter != m_propertylist.end(); ++iter )
5269  {
5270  const a2dNamedProperty* prop = *iter;
5271  a2dObject* obj = prop->GetRefObjectNA();
5272  if ( wxDynamicCast( prop, a2dShadowStyleProperty ) )
5273  {
5274  propertychanged = changed;
5275  }
5276  else if ( wxDynamicCast( obj, a2dCanvasObject ) && prop->GetCanRender() && prop->GetVisible() &&
5277  wxDynamicCast( obj, a2dCanvasObject )->GetVisible() )
5278  {
5279  propertychanged = wxStaticCast( obj, a2dCanvasObject )->Update( mode ) || propertychanged;
5280  }
5281  else if ( mode & update_includebboxprop && prop->GetId() == PROPID_BoundingBox )
5282  propertychanged = true;
5283  }
5284  }
5285 
5286  // in Update() this stores the children its boundingbox when changed.
5287  // This can be used in the DoUpdate() to e.g. resize itself to that.
5288  a2dBoundingBox childbox;
5289  // in Update() this stores the children its boundingbox when changed.
5290  // This can be used in the DoUpdate() to e.g. resize itself to that.
5291  a2dBoundingBox childboxOnlyTranslate;
5292  // in Update() this stores the properties its boundingbox when changed.
5293  // This can be used in the DoUpdate() to e.g. resize itself to that.
5294  a2dBoundingBox propbox;
5295  // holds clippingbox for current object defined by a2dClipPathProperty
5296  a2dBoundingBox clipbox;
5297  double maxworldextend = 0;
5298  double maxpixelextend = 0;
5299  a2dShadowStyleProperty* shadow = NULL;
5300 
5301  // Now if anything (this, child or properties) changed, recalculate the property and childrens boundingbox
5302  // to include all that.
5303  // If anything changed, invalidate the bounding box
5304  if ( changed || childchanged || propertychanged )
5305  {
5306  m_bbox.SetValid( false );
5307  changed = true;
5308 
5310  {
5311  a2dAffineMatrix transworld;
5312  transworld.Translate( GetPosX(), GetPosY() );
5314  {
5315  a2dCanvasObject* obj = *iter;
5316  //calculate bbox only for visible objects
5317  if( obj && obj->GetVisible() )
5318  {
5319  if ( obj->m_flags.m_ChildOnlyTranslate )
5320  {
5321  childboxOnlyTranslate = obj->GetBbox();
5322  childboxOnlyTranslate.MapBbox( transworld );
5323  }
5324  else
5325  childbox.Expand( obj->GetBbox() );
5326 
5327  maxworldextend = wxMax( obj->m_worldExtend, maxworldextend );
5328  maxpixelextend = wxMax( obj->m_pixelExtend, maxpixelextend );
5329  }
5330  }
5331 
5332  if ( childboxOnlyTranslate.GetValid() ) //no child or empty child secure
5333  {
5334  childboxOnlyTranslate.Enlarge( maxworldextend ); //enough to expand total childrens bbox with maximum stroke width
5335  }
5336 
5337  if ( childbox.GetValid() ) //no child or empty child secure
5338  {
5339  childbox.Enlarge( maxworldextend ); //enough to expand total childrens bbox with maximum stroke width
5340  }
5341  m_pixelExtend = ( wxUint16 ) wxMax( ( int ) maxpixelextend, m_pixelExtend );
5342  }
5343 
5344  if ( HasDynamicProperties() )
5345  {
5346  a2dNamedPropertyList::const_iterator iter;
5347  for( iter = m_propertylist.begin(); iter != m_propertylist.end(); ++iter )
5348  {
5349  const a2dNamedProperty* prop = *iter;
5350  a2dObject* obj = prop->GetRefObjectNA();
5351  if ( wxDynamicCast( prop, a2dClipPathProperty ) )
5352  {
5353  if ( obj )
5354  {
5355  clipbox.Expand( wxStaticCast( obj, a2dCanvasObject )->GetMappedBbox( m_lworld ) );
5356 
5357  // if the clipping object is visible, we do not only want the AND
5358  // of the clippingbox with the rest, but also clipping object itself should be in there.
5360  {
5361  propbox.Expand( wxStaticCast( obj, a2dCanvasObject )->GetMappedBbox( m_lworld ) );
5362  }
5363  }
5364  }
5365  else if ( wxDynamicCast( prop, a2dShadowStyleProperty ) )
5366  {
5367  shadow = wxStaticCast( prop, a2dShadowStyleProperty );
5368  }
5369  else if ( wxDynamicCast( obj, a2dCanvasObject ) && prop->GetCanRender() && prop->GetVisible() && wxDynamicCast( obj, a2dCanvasObject )->GetVisible() )
5370  {
5371  propbox.Expand( wxStaticCast( obj, a2dCanvasObject )->GetMappedBbox( m_lworld ) );
5372  }
5373  else if ( mode & update_includebboxprop && prop->GetId() == PROPID_BoundingBox )
5374  propbox.Expand( wxStaticCast( prop, a2dBoudingBoxProperty )->GetValue() );
5375  }
5376  }
5377  }
5378 
5379  if ( childboxOnlyTranslate.GetValid() ) //no child or empty child secure
5380  childbox.Expand( childboxOnlyTranslate );
5381 
5382  //Ask DoUpdate if it thinks anything changed.
5383  //Add derived object specific features to the boundingbox.
5384  //If the derived object has internal child objects itself, they will be Updated too.
5385  //In case those children did change, the bbox will be invalidated and recalculated.
5386  //Also when the bbox is already invalid, this will happen.
5387  //If force is true then for sure everything will be recalculated.
5388  //The return value is true if indeed something did change/ was recalculated.
5389  changed = DoUpdate( mode, childbox, clipbox, propbox ) || changed;
5390 
5391  if ( childbox.GetValid() ) //no child or empty child secure
5392  {
5393  childbox.MapBbox( m_lworld );
5394  m_bbox.Expand( childbox );
5395  }
5396 
5397  if ( shadow )
5398  {
5399  double dx = cos( shadow->GetExtrudeAngle() ) * shadow->GetExtrudeDepth();
5400  double dy = sin( shadow->GetExtrudeAngle() ) * shadow->GetExtrudeDepth();
5401 
5402  a2dBoundingBox shadowbox = m_bbox;
5403  shadowbox.Translate( dx, dy );
5404  propbox.Expand( shadowbox );
5405  }
5406  if ( propbox.GetValid() )
5407  m_bbox.Expand( propbox );
5408 
5409  if ( clipbox.GetValid() && !m_flags.m_editingCopy )
5410  m_bbox.And( &clipbox );
5411 
5412  // If the bounding box may only be expanded, extend it by the old one
5413  if( ( mode & update_save ) )
5414  {
5415  // If the old bounding box is not inside the new one,
5416  // the bounding box is added as property which lead to an extra update area in AddPending()
5417  if ( oldbbox.GetValid() && oldbbox.GetWidth() && oldbbox.GetHeight() && m_bbox.GetValid() && m_bbox.Intersect( oldbbox ) != _IN )
5418  {
5419  PROPID_BoundingBox->SetPropertyToObject( this, oldbbox );
5420  //PROPID_BoundingBox->SetPropertyToObject( this, m_bbox );
5421  SetPending( true );
5422  }
5423  }
5424 
5425  if ( !m_bbox.GetValid() )
5426  {
5427  changed = true;
5428  //no objects, therefore make the bounding box the x,y of the object
5429  m_bbox.Expand( m_lworld.GetValue( 2, 0 ), m_lworld.GetValue( 2, 1 ) );
5430  }
5431 
5432  return changed;
5433 }
5434 
5436 {
5437  return GetChildObjectsCount() != 0;
5438 }
5439 
5441 {
5444 }
5445 
5447 {
5448  if ( handler.GetUseCheck() && GetCheck() )
5449  return;
5450 
5451  handler.IncCurrentDepth();
5452 
5453  handler.WalkTask( ic, parent, this, a2dWalker_a2dCanvasObjectStart );
5454 
5455  {
5456  //go to child context
5457  a2dIterCU cu( ic, this );
5458  DoWalkerWithContext( ic, parent, handler );
5459  }
5460 
5461  handler.WalkTask( ic, parent, this, a2dWalker_a2dCanvasObjectEnd );
5462  handler.DecCurrentDepth();
5463 }
5464 
5465 void a2dCanvasObject::DoWalkerWithContext( a2dIterC& ic, wxObject* parent, a2dWalkerIOHandlerWithContext& handler )
5466 {
5467  // depthfirst means, first go to recursive object
5468  // and skipping them when iterating the other objects later on
5469  if ( handler.GetDepthFirst() && m_childobjects != wxNullCanvasObjectList && !handler.GetStopWalking() )
5470  {
5472  {
5473  a2dCanvasObject* obj = *iter;
5474  if ( obj && !obj->GetRelease() && obj->IsRecursive() )
5475  obj->WalkerWithContext( ic, this, handler );
5476  }
5477  }
5478 
5479  if ( handler.WalkTask( ic, parent, this, a2dWalker_a2dCanvasObjectPreChild ) &&
5481  {
5483  {
5484  a2dCanvasObject* obj = *iter;
5485  if ( obj && !obj->GetRelease() &&
5486  !( handler.GetDepthFirst() && obj->IsRecursive() ) )
5487  obj->WalkerWithContext( ic, this, handler );
5488  }
5489  }
5490 
5491  if ( handler.WalkTask( ic, parent, this, a2dWalker_a2dCanvasObjectPostChild ) &&
5493  {
5495  {
5496  a2dCanvasObject* obj = *iter;
5497  if ( obj && !obj->GetRelease() &&
5498  !( handler.GetDepthFirst() && obj->IsRecursive() ) )
5499  obj->WalkerWithContext( ic, this, handler );
5500  }
5501  }
5502 }
5503 
5504 void a2dCanvasObject::DoWalker( wxObject* parent, a2dWalkerIOHandler& handler )
5505 {
5506  handler.WalkTask( parent, this, a2dWalker_a2dCanvasObjectStart );
5507 
5508  a2dObject::DoWalker( parent, handler );
5509 
5510  // depthfirst means, first go to recursive object
5511  // and skipping them when iterating the other objects later on
5512  if ( handler.GetDepthFirst() && m_childobjects != wxNullCanvasObjectList && !handler.GetStopWalking() )
5513  {
5515  {
5516  a2dCanvasObject* obj = *iter;
5517  if ( obj && !obj->GetRelease() && obj->IsRecursive() )
5518  obj->Walker( this, handler );
5519  }
5520  }
5521 
5522  if ( handler.WalkTask( parent, this, a2dWalker_a2dCanvasObjectPreChild ) &&
5524  {
5525 #if defined(_DEBUG) && defined (SMART_POINTER_DEBUG)
5526  int childNum = m_childobjects->size();
5527  int childPos = 0;
5528 #endif
5530  {
5531  a2dCanvasObject* obj = *iter;
5532  if ( obj && !obj->GetRelease() &&
5533  !( handler.GetDepthFirst() && obj->IsRecursive() ) )
5534  obj->Walker( this, handler );
5535 #if defined(_DEBUG) && defined (SMART_POINTER_DEBUG)
5536  childPos++;
5537 #endif
5538  }
5539  }
5540 
5541  if ( handler.WalkTask( parent, this, a2dWalker_a2dCanvasObjectPostChild ) &&
5543  {
5545  {
5546  a2dCanvasObject* obj = *iter;
5547  if ( obj && !obj->GetRelease() &&
5548  !( handler.GetDepthFirst() && obj->IsRecursive() ) )
5549  obj->Walker( this, handler );
5550  }
5551  }
5552 
5553  handler.WalkTask( parent, this, a2dWalker_a2dCanvasObjectEnd );
5554 }
5555 
5556 #if wxART2D_USE_CVGIO
5557 
5558 void AddFlag( wxString& flags, const wxString& name, bool value, bool defval )
5559 {
5560  if ( value != defval )
5561  {
5562  if ( value )
5563  flags = flags + " " + name;
5564  else
5565  flags = flags + " " + name + "(0)";
5566  }
5567 }
5568 
5569 void a2dCanvasObject::DoSave( wxObject* WXUNUSED( parent ), a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts, a2dObjectList* towrite )
5570 {
5571  if ( xmlparts == a2dXmlSer_attrib )
5572  {
5573  a2dObject::DoSave( this, out, xmlparts, towrite );
5574 
5575  if ( wxLAYER_DEFAULT != m_layer )
5576  {
5577  out.WriteAttribute( wxT( "layer" ), m_layer );
5578  }
5579 
5580  wxString s;
5581 
5582  AddFlag( s, wxT("selected"), m_flags.m_selected, m_flagsInit.m_selected );
5583  AddFlag( s, wxT("selected2"), m_flags.m_selected2, m_flagsInit.m_selected2 );
5584 
5585  AddFlag( s, wxT("selectable"), m_flags.m_selectable ,m_flagsInit.m_selectable );
5586  AddFlag( s, wxT("subedit"), m_flags.m_subEdit ,m_flagsInit.m_subEdit );
5587  AddFlag( s, wxT("subeditaschild"), m_flags.m_subEditAsChild ,m_flagsInit.m_subEditAsChild );
5588  AddFlag( s, wxT("visible"), m_flags.m_visible ,m_flagsInit.m_visible );
5589  AddFlag( s, wxT("draggable"), m_flags.m_draggable ,m_flagsInit.m_draggable );
5590  AddFlag( s, wxT("shadow"), m_flags.m_showshadow ,m_flagsInit.m_showshadow );
5591  AddFlag( s, wxT("filled"), m_flags.m_filled ,m_flagsInit.m_filled );
5592  AddFlag( s, wxT("a"), m_flags.m_a ,m_flagsInit.m_a );
5593  AddFlag( s, wxT("b"), m_flags.m_b ,m_flagsInit.m_b );
5594  AddFlag( s, wxT("fixedStyle"), m_flags.m_fixedStyle ,m_flagsInit.m_fixedStyle );
5595  AddFlag( s, wxT("generatePins"), m_flags.m_generatePins ,m_flagsInit.m_generatePins );
5596  AddFlag( s, wxT("bin"), m_flags.m_bin ,m_flagsInit.m_bin );
5597  AddFlag( s, wxT("snap"), m_flags.m_snap ,m_flagsInit.m_snap );
5598  AddFlag( s, wxT("pushin"), m_flags.m_pushin ,m_flagsInit.m_pushin );
5599  AddFlag( s, wxT("ChildOnlyTranslate"), m_flags.m_ChildOnlyTranslate ,m_flagsInit.m_ChildOnlyTranslate );
5600 
5601  if ( !s.IsEmpty() )
5602  out.WriteAttribute( wxT( "flags" ), s );
5603 
5604  s = wxT( "" );
5605  if ( m_hitflags.m_non ) s = s + wxT( " non" ) ;
5606  if ( m_hitflags.m_fill ) s = s + wxT( " fill" ) ;
5607  if ( m_hitflags.m_stroke ) s = s + wxT( " stroke" ) ;
5608  if ( m_hitflags.m_fill_non_transparent ) s = s + wxT( " fill_non_transparent" );
5609  if ( m_hitflags.m_stroke_non_transparent ) s = s + wxT( " stroke_non_transparent" );
5610  if ( m_hitflags.m_visible ) s = s + wxT( " visible" ) ;
5611  if ( m_hitflags.m_all ) s = s + wxT( " all" ) ;
5612 
5614  out.WriteAttribute( wxT( "hitflags" ), s );
5615 
5616  if ( !m_lworld.IsIdentity() )
5617  {
5618  out.WriteNewLine();
5619  s.Printf ( wxT( "matrix( %g %g %g %g %g %g )" ),
5620  m_lworld.GetValue( 0, 0 ) * out.GetScale(), m_lworld.GetValue( 0, 1 ) * out.GetScale(),
5621  m_lworld.GetValue( 1, 0 ) * out.GetScale(), m_lworld.GetValue( 1, 1 ) * out.GetScale(),
5622  m_lworld.GetValue( 2, 0 ) * out.GetScale(), m_lworld.GetValue( 2, 1 ) * out.GetScale()
5623  );
5624  out.WriteAttribute( wxT( "transform" ), s );
5625  out.WriteNewLine();
5626  }
5627 
5628  if ( GetFill().IsSameAs( *a2dINHERIT_FILL ) )
5629  {
5630  out.WriteAttribute( wxT( "fill" ), wxT( "inherit" ) );
5631  }
5632  if ( GetStroke().IsSameAs( *a2dINHERIT_STROKE ) )
5633  {
5634  out.WriteAttribute( wxT( "stroke" ), wxT( "inherit" ) );
5635  }
5636  }
5637  else
5638  {
5639  a2dObject::DoSave( this, out, xmlparts, towrite );
5640 
5642  {
5644  {
5645  a2dCanvasObject* obj = *iter;
5646  if ( obj )
5647  obj->Save( this, out, towrite );
5648  //out.WriteNewLine();
5649  }
5650  }
5651  }
5652 }
5653 
5655 {
5656  wxString str = parser.GetAttributeValue( wxT( "transform" ) );
5657  wxString error;
5658  if ( !str.IsEmpty() && !::ParseCvgTransForm( result, str, error ) )
5659  {
5660  a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _( "CVG : invalid transform %s at line %d" ), str.c_str(), parser.GetCurrentLineNumber() );
5661  return true; //just a warning, still continue
5662  }
5663 
5664  result.SetValue( 2, 0, result.GetValue( 2, 0 ) * parser.GetScale() );
5665  result.SetValue( 2, 1, result.GetValue( 2, 1 ) * parser.GetScale() );
5666 
5667  return true;
5668 }
5669 
5670 bool ParseFlag( wxString& str, wxString& flagname, bool& flagvalue, wxString& error )
5671 {
5672  if ( str == wxT( "" ) )
5673  return false;
5674 
5675  wxString numstr;
5676  size_t i;
5677  for ( i = 0; i < str.Len(); i++ )
5678  {
5679  //skip space
5680  while ( wxIsspace( str[i] ) ) i++;
5681 
5682  flagname.Clear();
5683  while ( i < str.Len() && isalnum ( str[i] ) )
5684  {
5685  flagname += str.GetChar( i );
5686  i++;
5687  }
5688 
5689  //skip space
5690  while ( i < str.Len() && wxIsspace( str[i] ) ) i++;
5691 
5692  if ( i == str.Len() )
5693  {
5694  flagvalue = true;
5695  return true;
5696  }
5697 
5698  if ( str[i] != wxT( '(' ) )
5699  {
5700  error = _( "CVG parsing error: missing" );
5701  return false;
5702  }
5703  i++;
5704 
5705  while ( i < str.Len() && wxIsspace( str[i] ) ) i++;
5706 
5707  while ( i < str.Len() && str[i] != wxT( ')' ) )
5708  {
5709  numstr.Clear();
5710  if ( isdigit( str[i] ) )
5711  {
5712  numstr = str.GetChar( i );
5713  }
5714  i++;
5715  }
5716 
5717  if ( i == str.Len() || str[i] != wxT( ')' ) )
5718  {
5719  error = _( "CVG parsing error: missing" );
5720  return false;
5721  }
5722  flagvalue = numstr != "0";
5723  return true;
5724  }
5725  return false;
5726 }
5727 
5728 void a2dCanvasObject::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
5729 {
5730 
5731  if ( xmlparts == a2dXmlSer_attrib )
5732  {
5733  a2dObject::DoLoad( parent, parser, xmlparts );
5734 
5735  ParseCvgTransForm( m_lworld, parser );
5736 
5737  m_layer = parser.GetAttributeValueUint16( wxT( "layer" ), 0 );
5738 
5739  wxString flags = parser.GetAttributeValue( wxT( "flags" ) );
5740  wxStringTokenizer tkz( flags );
5741 
5742  while ( tkz.HasMoreTokens() )
5743  {
5744  wxString token = tkz.GetNextToken();
5745  wxString flagname, error;
5746  bool flagvalue = false;
5747 
5748  if ( !ParseFlag( token, flagname, flagvalue, error ) )
5749  a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _( "could not parse %s, %s, will be skipped line %d" ),
5750  token.c_str(), error.c_str(), parser.GetCurrentLineNumber() );
5751  else
5752  {
5753  if ( flagname == wxT( "selected" ) )
5754  m_flags.m_selected = flagvalue;
5755  if ( flagname == wxT( "selected2" ) )
5756  m_flags.m_selected2 = flagvalue;
5757  else if ( flagname == wxT( "selectable" ) )
5758  m_flags.m_selectable = flagvalue;
5759  else if ( flagname == wxT( "subedit" ) )
5760  m_flags.m_subEdit = flagvalue;
5761  else if ( flagname == wxT( "subeditaschild" ) )
5762  m_flags.m_subEditAsChild = flagvalue;
5763  else if ( flagname == wxT( "visible" ) )
5764  m_flags.m_visible = flagvalue;
5765  else if ( flagname == wxT( "draggable" ) )
5766  m_flags.m_draggable = flagvalue;
5767  else if ( flagname == wxT( "showshadow" ) )
5768  m_flags.m_showshadow = flagvalue;
5769  else if ( flagname == wxT( "filled" ) )
5770  m_flags.m_filled = flagvalue;
5771  else if ( flagname == wxT( "a" ) )
5772  m_flags.m_a = flagvalue;
5773  else if ( flagname == wxT( "b" ) )
5774  m_flags.m_b = flagvalue;
5775  else if ( flagname == wxT( "fixedStyle" ) )
5776  m_flags.m_fixedStyle = flagvalue;
5777  else if ( flagname == wxT( "generatePins" ) )
5778  m_flags.m_generatePins = flagvalue;
5779  else if ( flagname == wxT( "bin" ) )
5780  m_flags.m_bin = flagvalue;
5781  else if ( flagname == wxT( "snap" ) )
5782  m_flags.m_snap = flagvalue;
5783  else if ( flagname == wxT( "snap_to" ) )
5784  m_flags.m_snap_to = flagvalue;
5785  else if ( flagname == wxT( "pushin" ) )
5786  m_flags.m_pushin = flagvalue;
5787  else if ( flagname == wxT( "ChildOnlyTranslate" ) )
5788  m_flags.m_ChildOnlyTranslate = flagvalue;
5789  }
5790  }
5791 
5792 
5793  // not hitflags, assume visible hitflag
5794  if ( parser.HasAttribute( wxT( "hitflags" ) ) )
5795  {
5796  wxString hitflags = parser.GetAttributeValue( wxT( "hitflags" ) );
5797  m_hitflags.m_non = hitflags.Find( wxT( "non" ) ) != -1;
5798  m_hitflags.m_fill = hitflags.Find( wxT( "fill" ) ) != -1;
5799  m_hitflags.m_stroke = hitflags.Find( wxT( "stroke" ) ) != -1;
5800  m_hitflags.m_fill_non_transparent = hitflags.Find( wxT( "fill_non_transparent" ) ) != -1;
5801  m_hitflags.m_stroke_non_transparent = hitflags.Find( wxT( "stroke_non_transparent" ) ) != -1;
5802  m_hitflags.m_visible = hitflags.Find( wxT( "visible" ) ) != -1;
5803  m_hitflags.m_all = hitflags.Find( wxT( "all" ) ) != -1;
5804  }
5805  else
5806  m_hitflags.m_visible = true;
5807  }
5808  else
5809  {
5810  //! todo ignore until this down here is fully converted.
5811  //a2dObject::DoLoad( parent, parser, xmlparts );
5812 
5813  if ( parser.GetTagName() == wxT( "properties" ) )
5814  {
5815  parser.Next();
5816  while( parser.GetTagName() == wxT( "o" ) )
5817  {
5818  wxString classname = parser.GetAttributeValue( wxT( "classname" ) );
5819  wxObject* obj = parser.CreateObject( classname );
5821  if ( property )
5822  {
5823  property->Load( this, parser );
5824  if ( parser.GetLastError() == a2dError_NoError )
5825  property->SetToObject( this );
5826  }
5827  else if( wxDynamicCast( obj, a2dFill ) )
5828  {
5829  // This is for compatitbility
5830  wxStaticCast( obj, a2dFill )->Load( this, parser );
5831  a2dCanvasObject::PROPID_Fill->SetPropertyToObject( this, *wxStaticCast( obj, a2dFill ) );
5832  delete obj;
5833  }
5834  else if( wxDynamicCast( obj, a2dStroke ) )
5835  {
5836  // This is for compatitbility
5837  wxStaticCast( obj, a2dStroke )->Load( this, parser );
5838  a2dCanvasObject::PROPID_Stroke->SetPropertyToObject( this, *wxStaticCast( obj, a2dStroke ) );
5839  delete obj;
5840  }
5841  else
5842  {
5843  a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _( "could not create a2dNamedProperty %s, will be skipped line %d" ),
5844  classname.c_str(), parser.GetCurrentLineNumber() );
5845  parser.SkipSubTree();
5846  parser.Require( END_TAG, wxT( "o" ) );
5847  parser.Next();
5848  }
5849  }
5850 
5851  parser.Require( END_TAG, wxT( "properties" ) );
5852  parser.Next();
5853  }
5854 
5855  while( parser.GetEventType() == START_TAG && parser.GetTagName() == wxT( "o" ) )
5856  {
5857  // The refid attribute is used in a2dObject::Load() to point to other objects as a reference.
5858  // Meaning it will be a smart pointer to an object already load or still to be loaded later on.
5859  // We do not need to construct the real object just to load that. We just Create the most simple
5860  // a2dCanvasObject pointer here to hold/load it.
5861  if ( parser.HasAttribute( wxT( "refid" ) ) )
5862  {
5863  a2dCanvasObjectPtr object = new a2dCanvasObject();
5864  Append( object );
5865  object->Load( this, parser );
5867  parser.ResolveOrAdd( obj );
5868  }
5869  else
5870  {
5871  wxString classname = parser.GetAttributeValue( wxT( "classname" ) );
5872  a2dCanvasObject* object = wxDynamicCast( parser.CreateObject( classname ), a2dCanvasObject );
5873  if ( !object )
5874  {
5875  a2dGeneralGlobals->ReportErrorF( a2dError_XMLparse, _( "could not create a2dCanvasObject %s, will be skipped line %d" ),
5876  classname.c_str(), parser.GetCurrentLineNumber() );
5877  parser.SkipSubTree();
5878  parser.Require( END_TAG, wxT( "o" ) );
5879  parser.Next();
5880  }
5881  else
5882  {
5883  Append( object );
5884  object->Load( this, parser );
5885  // if the object just load is a pure reference ( only has a refid attribute ),
5886  // we can resolve here if the referenced object itself was already read.
5887  // This is a speed issue, and if not resolved now, meaning object is still to be read, we will resolve it later.
5888  // See a2dObject::Load() too.
5890  parser.ResolveOrAdd( obj );
5891  }
5892  }
5893  }
5894  }
5895 }
5896 
5897 #endif //wxART2D_USE_CVGIO
5898 
5900 {
5901  a2dBoundingBox bbox;
5902  if ( HasDynamicProperties() )
5903  {
5904  a2dNamedPropertyList::const_iterator iter;
5905  for( iter = m_propertylist.begin(); iter != m_propertylist.end(); ++iter )
5906  {
5907  const a2dNamedProperty* prop = *iter;
5909  if ( clipprop )
5910  {
5911  a2dBoundingBox tmp;
5912  tmp.Expand( clipprop->GetClipObject()->GetMappedBbox( m_lworld ) );
5913  bbox.Expand( tmp );
5914  }
5915  }
5916  }
5917  return bbox;
5918 }
5919 
5920 void a2dCanvasObject::SetLayer( wxUint16 layer )
5921 {
5922  wxASSERT_MSG( wxMAXLAYER > layer , wxT( " layer > wxMAXLAYER, index to high" ) );
5923 
5924  SetPending( true );
5925  m_layer = layer;
5926  if ( m_root && m_root->GetLayerSetup() )
5927  {
5928  wxASSERT_MSG( m_root->GetLayerSetup()->GetLayerIndex()[m_layer] != wxNullLayerInfo,
5929  wxT( "layer not defined in layer table" ) );
5930  }
5931 };
5932 
5933 void a2dCanvasObject::SetRoot( a2dDrawing* root, bool recurse )
5934 {
5935  m_root = root;
5936  /*
5937  if (m_root && m_root->GetLayerSetup() )
5938  {
5939  wxASSERT_MSG( wxNullLayerInfo != m_root->GetLayerSetup()->GetLayerIndex()[m_layer],
5940  wxT("layer not defined in layer table") );
5941  }
5942  */
5943  if ( recurse )
5944  {
5945  a2dWalker_SetRoot setRecursive( root );
5946  setRecursive.SetSkipNotRenderedInDrawing( true );
5947  setRecursive.Start( this );
5948  }
5949 }
5950 
5952 {
5954  return;
5955 
5956  a2dCanvasObjectList::iterator iter = m_childobjects->begin();
5957 
5958  //iterate over layers if the children are meant to be drawn on a given layer at once
5959  //OR we do NOT render per layer from a parent object.
5961  {
5962  wxASSERT_MSG( ic.GetLayer() != wxLAYER_ALL, _T( " a2dIterC::GetPerLayerMode() can only render one layer at the time" ) );
5963 
5964  unsigned int j;
5965  for ( j = 0; j < wxMAXLAYER; j++ )
5966  {
5967  a2dLayerInfo* layerinfo;
5968  // YES here we do the opposite of when rendering, hitting the top layer first
5969  if ( ic.GetDrawingPart()->GetReverseOrder() )
5970  layerinfo = GetRoot()->GetLayerSetup()->GetReverseOrderIndex()[j];
5971  else
5972  layerinfo = GetRoot()->GetLayerSetup()->GetOrderIndex()[j];
5973 
5974  // non defined layers, being those that where not in the layer setup, are sorted to the end of the indexes.
5975  // So the can be skipped.
5976  if ( layerinfo == wxNullLayerInfo )
5977  break;
5978 
5979  //important!
5980  //if layer is visible it will be rendered
5981  //If an object on a layer is itself invisible it will not be drawn
5982  if ( ic.GetLayer() == wxLAYER_ALL ||
5983  ( ic.GetDrawingPart()->GetLayerRenderArray()[ layerinfo->GetLayer() ].DoRenderLayer()
5984  && layerinfo->GetVisible()
5985  )
5986  )
5987  {
5988  RenderChildObjectsOneLayer( ic, whichchilds, clipparent );
5989  }
5990  }
5991  }
5992  else
5993  {
5994  //no layer iteration will be done and therefore only object on m_layer == layer will be rendered.
5995  //layer == wxLAYER_ALL is a special case, and means ignore layer order for rendering the child objects.
5996  //checking of availability and visibility of layer itself is handled in parent objects
5997  RenderChildObjectsOneLayer( ic, whichchilds, clipparent );
5998  }
5999  //restore not needed, all object do restore themselfs the transform in the end
6000  //ic.GetDrawer2D()->SetRelativeTransform( *tworld );
6001 }
6002 
6004 {
6006  return;
6007 
6008  RenderChild detectchilds;
6009  detectchilds.m_postrender = false;
6010  detectchilds.m_prerender = false;
6011  detectchilds.m_property = false;
6012 
6013  //save the current style state of the a2dCanvasView, in order to inherit and restore style of object
6014  a2dFill currentdrawer_fill = ic.GetDrawer2D()->GetDrawerFill();
6015  a2dStroke currentdrawer_stroke = ic.GetDrawer2D()->GetDrawerStroke();
6016 
6018  {
6019  a2dCanvasObject* obj = *iter;
6020  if ( !obj )
6021  continue;
6022 
6023  int olayer = obj->GetLayer();
6024 
6025  //! detect specific objects, to prevent extra rendering calls for child objects, if they do not exist.
6026  detectchilds.m_postrender = detectchilds.m_postrender || !obj->GetPreRenderAsChild();
6027  detectchilds.m_prerender = detectchilds.m_prerender || obj->GetPreRenderAsChild();
6028  detectchilds.m_property = detectchilds.m_property || obj->GetIsProperty();
6029 
6030  //do a rough check to increase speed in common cases
6031  if ( (
6032  ( obj->GetPreRenderAsChild() && whichchilds.m_prerender && !obj->GetIsProperty() ) ||
6033  ( !obj->GetPreRenderAsChild() && whichchilds.m_postrender && !obj->GetIsProperty() ) ||
6034  ( obj->GetIsProperty() && whichchilds.m_property )
6035  )
6036  // the next does work if child is a container like e.g. a2dCanvasObjectReference
6037  // because they have a flags GetIgnoreLayer() set.
6038  &&
6039  ( olayer == ic.GetLayer() || ic.GetLayer() == wxLAYER_ALL || obj->GetChildObjectsCount() || obj->GetIgnoreLayer() )
6040  )
6041  {
6042  /*LEAVE IN
6043  //test bbox per object like this!!
6044  ic.GetDrawer2D()->SetDrawerStroke( a2dBLACK_STROKE );
6045  ic.GetDrawer2D()->SetDrawerFill( a2dTRANSPARENT_FILL );
6046  wxRect absareadev = obj->GetAbsoluteArea( ic );
6047  ic.GetDrawer2D()->DevDrawRectangle( absareadev.x, absareadev.y, absareadev.width, absareadev.height);
6048  ic.GetDrawer2D()->SetDrawerStroke( currentdrawer_stroke );
6049  ic.GetDrawer2D()->SetDrawerFill( currentdrawer_fill );
6050  */
6051 
6052  // clipparent is either _IN or _ON ( _OUT would not get us to this point )
6053  // testing clipping of children only needed when not totaly _IN.
6054 
6055  OVERLAP childclip = _IN;
6056  if ( clipparent != _IN )
6057  childclip = obj->GetClipStatus( ic, clipparent );
6058 
6059  if ( childclip != _OUT ) //if a child is _OUT, no need to render it.
6060  {
6061  //optimization only when inheritance is used for child, we need to make sure the
6062  //current style is right.
6063  //else it will be set to another value anyway, therefore no need to
6064  //restore style that (maybe) was modified in previous rendered object of this group
6065  //The end effect of this is that objects with same style do not result in
6066  //unnecessary stroke and fill changes, which for certain (wxDC) a2dCanvasView types
6067  //takes a lot of time.
6068 
6069  if ( obj->HasDynamicProperties() )
6070  {
6071  if ( !obj->GetFill().IsNoFill() && obj->GetFill().IsSameAs( *a2dINHERIT_FILL ) )
6072  ic.GetDrawer2D()->SetDrawerFill( currentdrawer_fill );
6073  //if ( !obj->GetStroke()->IsNoStroke() && obj->GetStroke() == a2dINHERIT_STROKE )
6074  // ic.GetDrawer2D()->SetDrawerStroke( currentdrawer_stroke );
6075  }
6076 
6077  if ( obj->m_flags.m_ChildOnlyTranslate )
6078  {
6079  a2dAffineMatrix iworld = m_lworld;
6080  iworld.Invert();
6081  a2dIterCU cu( ic, iworld );
6082  a2dAffineMatrix transworld;
6083  transworld.Translate( GetPosX(), GetPosY() );
6084  a2dIterCU cu2( ic, transworld );
6085  obj->Render( ic, childclip );
6086  }
6087  else
6088  obj->Render( ic, childclip );
6089  }
6090 
6091  }
6092  }
6093 
6094  ic.GetDrawer2D()->SetDrawerFill( currentdrawer_fill );
6095  ic.GetDrawer2D()->SetDrawerStroke( currentdrawer_stroke );
6096 
6097  whichchilds = detectchilds;
6098 }
6099 
6101 {
6102  a2dCanvasObject* group = 0; //only make a group if there are object with the right mask
6103 
6106 
6107  a2dCanvasObjectList::iterator iter = m_childobjects->begin();
6108  while( iter != m_childobjects->end() )
6109  {
6110  a2dCanvasObjectList::value_type obj = *iter;
6111  if ( obj && obj->CheckMask( mask ) )
6112  {
6113  if ( !group )
6114  group = new a2dCanvasObject();
6115 
6116  iter = m_childobjects->erase( iter );
6117  group->Append( obj );
6118  }
6119  else
6120  iter++;
6121  }
6122 
6123  if ( !group )
6124  return group;
6125 
6126  group->SetRoot( m_root );
6127  group->SetIgnoreLayer( true );
6128  //parent boxes don't change
6129  group->Update( updatemask_force );
6130 
6131  //let the bounding be the position
6132  double dx, dy;
6133  dx = group->GetBbox().GetMinX();
6134  dy = group->GetBbox().GetMinY();
6135 
6136  //translate the objects within the group in opposite direction
6137  for( iter = group->m_childobjects->begin(); iter != group->m_childobjects->end(); ++iter )
6138  {
6139  a2dCanvasObject* obj = *iter;
6140  if ( obj )
6141  obj->Translate( -dx, -dy );
6142  }
6143 
6144  if ( createref )
6145  {
6146  a2dCanvasObjectReference* ref = new a2dCanvasObjectReference( dx, dy, group );
6147  ref->SetRoot( m_root );
6148  Append( ref );
6149  }
6150  else
6151  {
6152  group->SetPosXY( dx, dy );
6153  Append( group );
6154  }
6155 
6157  return group;
6158 }
6159 
6161 {
6163  {
6164  a2dCanvasObjectList::iterator iter = m_childobjects->begin();
6165  while( iter != m_childobjects->end() )
6166  {
6167  a2dCanvasObjectList::value_type directChild = *iter;
6168 
6169  if ( directChild && directChild->m_childobjects != wxNullCanvasObjectList )
6170  {
6171  a2dCanvasObjectList::iterator subiter = directChild->m_childobjects->begin();
6172  while( subiter != directChild->m_childobjects->end() )
6173  {
6174  a2dCanvasObjectList::value_type subchild = *subiter;
6175 
6176  if ( subchild && !subchild->GetRelease() )
6177  {
6178  subchild->Transform( directChild->GetTransformMatrix() );
6179  m_childobjects->push_front( subchild );
6180  subiter = directChild->m_childobjects->erase( subiter );
6181  }
6182  else
6183  subiter++;
6184  }
6185  }
6186  iter++;
6187  }
6188  }
6189 }
6190 
6192 {
6194  {
6195  m_lworld.Identity();
6196  return true;
6197  }
6198 
6200  {
6201  a2dCanvasObject* obj = *iter;
6202  if ( obj )
6203  obj->Transform( m_lworld );
6204  }
6205  m_lworld.Identity();
6206  return true;
6207 }
6208 
6210 {
6211  //very slow
6212  //wxASSERT_MSG( wxNOT_F OUND == IndexOf(obj) , wxT("object is already a child, use a reference") );
6213 
6214  if ( m_root )
6215  obj->SetRoot( m_root, true ); //do recurse here. ( Think like pins do get set).
6216 
6219 
6220  m_childobjects->push_front( obj );
6221  obj->SetPending( true );
6222 }
6223 
6225 {
6226  //very slow
6227  //wxASSERT_MSG( wxNOT_FOUND == IndexOf(obj) , wxT("object is already a child, use a reference") );
6228 
6229  if ( m_root )
6230  {
6231  obj->SetRoot( m_root, true ); //do recurse here. ( Things like pins do get set).
6232 
6233  // to slow if many
6234  // a2dComEvent changedlayer( this, obj->GetLayer(), a2dCanvasDocument::sm_changedLayer );
6235  // m_root->ProcessEvent( changedlayer );
6236  }
6237 
6240 
6241  m_childobjects->push_back( obj );
6242  obj->SetPending( true );
6243  obj->SetParent( this ); //if pin haspins will be set.
6244 }
6245 
6246 void a2dCanvasObject::Insert( size_t before, a2dCanvasObject* obj, bool ignoreReleased )
6247 {
6248  //very slow
6249  //wxASSERT_MSG( wxNOT_FOUND == IndexOf(obj) , wxT("object is already a child, use a reference") );
6250 
6251  if ( m_root )
6252  obj->SetRoot( m_root, true ); //do recurse here. ( Think like pins do get set).
6253 
6256 
6257  m_childobjects->Insert( before, obj, ignoreReleased );
6258 }
6259 
6260 int a2dCanvasObject::ReleaseChild( a2dCanvasObject* obj, bool backwards, bool all, bool now, bool undoCommands )
6261 {
6262  if ( obj == 0 )
6263  return 0;
6265  return 0;
6266 
6267  int totalreleased = 0;
6268  {
6269  // keep the object alive until we are done
6270  a2dCanvasObjectPtr keepAlive = obj;
6271 
6272  totalreleased = m_childobjects->Release( obj, backwards, all, now );
6273  if ( totalreleased )
6274  {
6275  if ( obj->HasPins() )
6276  obj->DisConnectWith( NULL, wxT( "" ), undoCommands );
6277  }
6278  }
6279 
6280  if ( now )
6281  {
6282  SetPending( true ); //yes parent! to do a proper update, since the real object is gone.
6283  }
6284 
6285  //delete when no more children, this is better since temporary editing childs handles should
6286  //not lead to always having a childlist
6288  {
6289  delete m_childobjects;
6291  }
6292 
6293  return totalreleased;
6294 }
6295 
6297 {
6299  return false;
6300 
6301  bool did = false;
6302 
6303  if ( m_childobjects->size() && m_childobjects->Release( mask ) )
6304  {
6305  SetPending( true );
6306  did = true;
6307  }
6308 
6309  //delete when no more children, this is better since temporary editing childs handles should
6310  //not lead to always having a childlist
6312  {
6313  delete m_childobjects;
6315  }
6316 
6317  return did;
6318 }
6319 
6321 {
6323  return -1;
6324 
6325  return m_childobjects->IndexOf( obj );
6326 }
6327 
6328 
6329 
6330 void a2dCanvasObject::SetTemplate( bool b )
6331 {
6332  m_flags.m_template = b;
6333 }
6334 
6335 
6336 void a2dCanvasObject::SetExternal( bool b )
6337 {
6338  m_flags.m_external = b;
6339 }
6340 
6341 
6342 void a2dCanvasObject::SetUsed( bool b )
6343 {
6344  m_flags.m_used = b;
6345 }
6346 
6347 
6348 bool a2dCanvasObject::GetTemplate() const
6349 {
6350  return m_flags.m_template;
6351 }
6352 
6353 
6354 bool a2dCanvasObject::GetExternal() const
6355 {
6356  return m_flags.m_external;
6357 }
6358 
6359 
6360 bool a2dCanvasObject::GetUsed() const
6361 {
6362  return m_flags.m_used;
6363 }
6364 
6366 {
6368  return true;
6369 
6370  // Objects belonging to the tool definitely shouldn't be saved.
6371  if( HasProperty( a2dCanvasObject::PROPID_ToolObject ) )
6372  return true;
6373 
6374  if( m_flags.m_editingCopy )
6375  return true;
6376 
6377  return false;
6378 }
6379 
6380 void a2dCanvasObject::ShowPins( bool onoff )
6381 {
6383  return;
6384 
6386  {
6387  a2dCanvasObject* obj = *iter;
6388  a2dPin* pin = wxDynamicCast( obj, a2dPin );
6389  if ( pin )
6390  pin->SetVisible( onoff );
6391  }
6392 }
6393 
6395 {
6397  return;
6398 
6400  {
6401  a2dCanvasObject* obj = *iter;
6402  a2dPin* pin = wxDynamicCast( obj, a2dPin );
6403  if ( pin )
6404  pin->SetRenderConnected( onoff );
6405  }
6406 }
6407 
6409 {
6410  if (HasPins() )
6411  DisConnectWith( NULL, wxT( "" ), withundo );
6412 }
6413 
6414 bool a2dCanvasObject::HasPins( bool realcheck )
6415 {
6417  return false;
6418 
6419  if ( !realcheck )
6420  return m_flags.m_hasPins;
6421 
6423  {
6424  a2dCanvasObject* obj = *iter;
6425  a2dPin* pin = wxDynamicCast( obj, a2dPin );
6426  if ( pin && !pin->GetRelease( ) )
6427  {
6428  m_flags.m_hasPins = true;
6429  return true;
6430  }
6431  }
6432  m_flags.m_hasPins = false;
6433  return false;
6434 }
6435 
6436 a2dPin* a2dCanvasObject::HasPinNamed( const wxString pinName, bool NotConnected )
6437 {
6439  return NULL;
6440 
6442  {
6443  a2dCanvasObject* obj = *iter;
6444  a2dPin* pin = wxDynamicCast( obj, a2dPin );
6445  if ( pin && !pin->GetRelease( ) &&
6446  pin->GetName().Matches( pinName ) &&
6447  ( !NotConnected || !pin->IsConnectedTo() ) )
6448  {
6449  return pin;
6450  }
6451  }
6452  return NULL;
6453 }
6454 
6456 {
6458  return 0;
6459 
6460  int nrpins = 0;
6461 
6463  {
6464  a2dCanvasObject* obj = *iter;
6465  if ( !obj )
6466  continue;
6467  a2dPin* pin = wxDynamicCast( obj, a2dPin );
6468  if ( pin && !pin->GetRelease( ) )
6469  nrpins++;
6470  }
6471  return nrpins;
6472 }
6473 
6474 a2dPin* a2dCanvasObject::AddPin( const wxString name, double x, double y, wxUint32 a2dpinFlags, a2dPinClass* pinClass, bool undo )
6475 {
6476  //wxASSERT_MSG( !HasPinNamed( name ) , wxT("this pin is already in the object, name must be unique") );
6477 
6478  wxASSERT_MSG( pinClass , wxT( "pinClass may not be NULL" ) );
6479 
6480  a2dPin* newPin = wxStaticCast( pinClass->GetPin()->Clone( clone_deep ), a2dPin );
6481 
6482  newPin->SetName( name );
6483  newPin->SetParent( this );
6484  newPin->SetPinClass( pinClass );
6485  newPin->SetPosXY( x, y );
6486  newPin->SetDynamicPin( ( a2dpinFlags & a2dPin::dynamic ) > 0 );
6487  newPin->SetTemporaryPin( ( a2dpinFlags & a2dPin::temporary ) > 0 );
6488  newPin->SetObjectPin( ( a2dpinFlags & a2dPin::objectPin ) > 0 );
6489 
6490  //and now there are pins.
6491  m_flags.m_hasPins = true;
6492 
6493  if ( undo )
6494  {
6496  cmp->Submit( new a2dCommand_AddObject( this, newPin ) );
6497  }
6498  else
6499  Append( newPin );
6500 
6501  return newPin;
6502 }
6503 
6504 void a2dCanvasObject::RemovePins( bool NotConnected, bool onlyTemporary, bool now )
6505 {
6507  return;
6508 
6509  bool all = true; //when allpins are removed
6510 
6511  a2dCanvasObjectList::iterator iter = m_childobjects->begin();
6512  while( iter != m_childobjects->end() )
6513  {
6514  a2dCanvasObjectList::value_type obj = *iter;
6515  a2dPin* pin = wxDynamicCast( obj.Get(), a2dPin );
6516  if ( pin )
6517  {
6518  // remove not connected pins if told to do so.
6519  // remove temporary pins if told so, but only if the mouse is not inside it.
6520  // This keeps pins a life until the mouse leafs the pin.
6521  if (
6522  ( !NotConnected || !pin->IsConnectedTo() ) &&
6523  ( !onlyTemporary || pin->IsTemporaryPin() ) //&& !pin->GetMouseInObject() ) //some tools depend on removing pins, even if mouse is on them.
6524  )
6525  {
6526  if ( now )
6527  {
6528  iter = m_childobjects->erase( iter );
6529  }
6530  else
6531  {
6532  pin->SetRelease( true );
6533  pin->SetPending( true );
6534  iter++;
6535  }
6536  }
6537  else
6538  {
6539  all = false;
6540  iter++;
6541  }
6542  }
6543  else
6544  iter++;
6545  }
6546  if ( all )
6547  m_flags.m_hasPins = false;
6548 }
6549 
6550 bool a2dCanvasObject::IsConnected( bool needsupdate, a2dCanvasObject* toConnect )
6551 {
6552  bool res = false;
6553 
6555  return false;
6556 
6558  {
6559  a2dCanvasObject* obj = *iter;
6560  a2dPin* pin = wxDynamicCast( obj, a2dPin );
6561  if ( pin && !pin->GetRelease( ) )
6562  {
6563  a2dPinList::const_iterator iter;
6564  for ( iter = pin->GetConnectedPins().begin( ) ; iter != pin->GetConnectedPins().end( ) ; iter++ )
6565  {
6566  a2dPin* otherpin = *iter;
6567  if ( !otherpin || otherpin->GetRelease() )
6568  continue;
6569  if ( !toConnect || toConnect == otherpin->GetParent() )
6570  {
6571  if ( needsupdate )
6572  {
6573  if ( otherpin->GetParent()->NeedsUpdateWhenConnected() )
6574  return true;
6575  }
6576  else
6577  return true;
6578  }
6579  }
6580  }
6581  }
6582 
6583  return res;
6584 }
6585 
6586 bool a2dCanvasObject::FindConnectedPins( a2dCanvasObjectList& result, a2dPin* pin, bool walkWires, a2dPinClass* searchPinClass, a2dCanvasObject* isConnectedTo )
6587 {
6589  return false;
6590 
6591  bool hasConnectedPins = false;
6592 
6594  {
6595  a2dCanvasObject* obj = *iter;
6596  a2dPin* pinc = wxDynamicCast( obj, a2dPin );
6597  if ( !pinc || pinc->GetRelease( ) )
6598  continue;
6599  if ( !pinc->GetBin() && ( !pin || ( pinc == pin ) )
6600  //&&
6601  //std::find( result.begin(), result.end(), pinc ) == result.end()
6602  )
6603  {
6604  pinc->SetBin( true );
6605  a2dPinList::const_iterator iter;
6606  for ( iter = pinc->GetConnectedPins().begin( ) ; iter != pinc->GetConnectedPins().end( ) ; iter++ )
6607  {
6608  a2dPin* pincother = *iter;
6609 
6610  if ( !pincother || pincother->GetBin() || pincother->GetRelease() )
6611  continue;
6612 
6613  wxASSERT_MSG(
6614  pincother->IsConnectedTo( pinc )
6615  , _( "connected pinc not reflected in connected pin" ) );
6616 
6617  // recurse into a connected bin if we want to walk accross wires to
6618  // connected objects.
6619  if ( ( pincother->GetParent()->IsConnect() || pincother->GetParent()->IsVirtConnect() ) &&
6620  walkWires )
6621  {
6622  // search recursive on all pins of wire/connect object.
6623  hasConnectedPins |= pincother->GetParent()->FindConnectedPins( result, NULL, walkWires, searchPinClass, isConnectedTo );
6624  }
6625  else
6626  {
6627  // search recursive on the connected pin for other wires and objects.
6628  hasConnectedPins |= pincother->GetParent()->FindConnectedPins( result, pincother, walkWires, searchPinClass, isConnectedTo );
6629  if (
6630  ( !searchPinClass || searchPinClass == pincother->GetPinClass() ) &&
6631  ( !isConnectedTo || isConnectedTo == pincother->GetParent() )
6632  )
6633  {
6634  hasConnectedPins = true;
6635  result.push_back( pincother ); //non wires pin which is connected to some other object.
6636  }
6637  }
6638  }
6639  }
6640  }
6641  return hasConnectedPins;
6642 }
6643 
6644 bool a2dCanvasObject::FindConnectedWires( a2dCanvasObjectList& result, a2dPin* pin, bool walkWires, bool selectedEnds, bool stopAtSelectedWire, bool addToResult )
6645 {
6647  return false;
6648 
6649  //if one or all branches from this wire down are oke
6650  bool branchesOke = false;
6651  bool allBranchesOke = true;
6652 
6653  a2dCanvasObjectList wiresFromThis;
6654  SetBin( true ); //start object, or recursive wires we walk on
6655 
6656  // when trying to find wire in between selected objects, we do not want wires returning to the start object.
6657  if ( selectedEnds && !addToResult )
6658  {
6660  {
6661  a2dCanvasObject* obj = *iter;
6662  a2dPin* pinc = wxDynamicCast( obj, a2dPin );
6663  if ( !pinc || pinc->GetRelease( ) )
6664  continue;
6665 
6666  pinc->SetBin( true ); //don't go here again.
6667  }
6668  }
6670  {
6671  a2dCanvasObject* obj = *iter;
6672  a2dPin* pinc = wxDynamicCast( obj, a2dPin );
6673  if ( !pinc || pinc->GetRelease( ) )
6674  continue;
6675 
6676  if ( !pin || ( pinc == pin ) )
6677  {
6678  pinc->SetBin( true ); //don't go here again.
6679  //we are on he pin asked for, or we pass all pins, and no go onto branches from this wire.
6680  a2dPinList::const_iterator iterconp;
6681  if ( pinc->GetConnectedPins().empty() && !selectedEnds )
6682  branchesOke = true;
6683 
6684  for ( iterconp = pinc->GetConnectedPins().begin( ) ; iterconp != pinc->GetConnectedPins().end( ) ; iterconp++ )
6685  {
6686  a2dPin* pincother = *iterconp;
6687  // the bin flag on pin prevent going back where we came from, or continuing to an already passed object.
6688  if ( pincother && ( pincother->GetRelease() || pincother->GetBin() ) )
6689  continue;
6690 
6691  if ( pincother )
6692  {
6693  wxASSERT_MSG(
6694  pincother->IsConnectedTo( pinc )
6695  , _( "connected pinc not reflected in connected pin" ) );
6696  a2dCanvasObject* parentOther = pincother->GetParent();
6697  if ( !parentOther->GetBin() )
6698  {
6699  // recurse into a connected pin if we want to walk accross wires to
6700  // connected objects.
6701  if ( parentOther->IsConnect() )
6702  {
6703  if ( walkWires && ( !stopAtSelectedWire || stopAtSelectedWire && !parentOther->IsSelected() ) )
6704  {
6705  bool downHereOke = parentOther->FindConnectedWires( result, NULL, walkWires, selectedEnds, false, true );
6706  branchesOke |= downHereOke; //one branch oke, we already want this wire, leading to that branch.
6707  allBranchesOke &= downHereOke;
6708  }
6709  }
6710  else
6711  {
6712  if ( !selectedEnds || selectedEnds && parentOther->IsSelected() )
6713  {
6714  branchesOke = true;
6715  }
6716  else
6717  allBranchesOke = false;
6718  }
6719  }
6720  else
6721  {
6722  // connected object with bin flag set
6723  if ( parentOther->IsConnect() )
6724  {
6725  //maybe needs also check if in result, to make it oke.
6726  //if ( std::find( result.begin(), result.end(), parentOther ) != result.end() )
6727  if ( !selectedEnds || selectedEnds && parentOther->IsSelected() )
6728  branchesOke = true;
6729  }
6730  else
6731  {
6732  if ( !selectedEnds || selectedEnds && parentOther->IsSelected() )
6733  {
6734  branchesOke = true;
6735  }
6736  else
6737  allBranchesOke = false;
6738  }
6739  }
6740  }
6741  else
6742  {
6743  //non connected pin (loose end ), for wanting all wires (non selected) we want this one too.
6744  if ( !selectedEnds )
6745  branchesOke = true;
6746  }
6747  }
6748  }
6749  }
6750 
6751  if ( addToResult && branchesOke ) //&& std::find( result.begin(), result.end(), this ) == result.end() )
6752  result.push_back( this );
6753 
6754  return branchesOke;
6755 }
6756 
6757 bool a2dCanvasObject::GetConnected( a2dCanvasObjectList* connected, bool needsupdate )
6758 {
6759  bool res = false;
6761  {
6762  a2dCanvasObject* obj = *iter;
6763  a2dPin* pinc = wxDynamicCast( obj, a2dPin );
6764  if ( !pinc )
6765  continue;
6766  a2dPinList::const_iterator iterconp;
6767  for ( iterconp = pinc->GetConnectedPins().begin( ) ; iterconp != pinc->GetConnectedPins().end( ) ; iterconp++ )
6768  {
6769  a2dPin* pincother = *iterconp;
6770  if ( !pincother || pincother->GetRelease() )
6771  continue;
6772  if ( needsupdate )
6773  {
6774  if ( pincother->GetParent()->NeedsUpdateWhenConnected() )
6775  {
6776  res = true;
6777  connected->push_back( pincother->GetParent() );
6778  }
6779  }
6780  else
6781  {
6782  res = true;
6783  connected->push_back( pincother->GetParent() );
6784  }
6785  }
6786  }
6787  return res;
6788 }
6789 
6790 bool a2dCanvasObject::CanConnectWith( a2dIterC& ic, a2dCanvasObject* toConnect, bool autocreate )
6791 {
6793  return false;
6794 
6795  bool done = false;
6796 
6798  {
6799  a2dCanvasObject* obj = *iter;
6800  a2dPin* pinc = wxDynamicCast( obj, a2dPin );
6801  if ( pinc && pinc->IsVisible() && !pinc->GetRelease( ) )
6802  {
6803  //search pins at same position in object to connect
6804 
6805  a2dPin* connect = toConnect->CanConnectWith( ic, pinc, ic.GetHitMarginWorld(), autocreate );
6806  if ( connect && !connect->IsConnectedTo( pinc ) && !pinc->GetBin() )
6807  {
6808  pinc->SetBin( true );
6809  done = true;
6810  }
6811  }
6812  }
6813 
6814  return done;
6815 }
6816 
6817 bool a2dCanvasObject::DoCanConnectWith( a2dIterC& ic, a2dPin* pin, double margin, bool autocreate )
6818 {
6819  if ( autocreate )
6820  {
6821  //first remove autogenerated pins, which were (possible) not for a specific pinClass.
6822  RemovePins( true, true );
6823  a2dHitEvent hitevent = a2dHitEvent( pin->GetAbsX(), pin->GetAbsY(), false );
6824  a2dCanvasObject* hit = IsHitWorld( ic, hitevent );
6825  if( hit )
6826  {
6827  bool found = false;
6828  // generate pins which can connect this pin
6829  found = GeneratePinsPossibleConnections( pin->GetPinClass(), a2d_GeneratePinsForPinClass, pin->GetPosX(), pin->GetPosY(), margin ) || found;
6830  return found;
6831  }
6832  }
6833  return false;
6834 }
6835 
6836 a2dPin* a2dCanvasObject::CanConnectWith( a2dIterC& ic, a2dPin* pin, double margin, bool autocreate )
6837 {
6838  if ( !m_flags.m_doConnect || !pin->IsVisible() )
6839  return ( a2dPin* ) NULL;
6840 
6841  DoCanConnectWith( ic, pin, margin, autocreate );
6842 
6844  return ( a2dPin* ) NULL;
6845 
6847  {
6848  a2dCanvasObject* obj = *iter;
6849  a2dPin* pinc = wxDynamicCast( obj, a2dPin );
6850  if ( pinc && pinc->IsVisible() && !pinc->GetRelease( ) )
6851  {
6852  if ( fabs( pin->GetAbsX() - pinc->GetAbsX() ) < margin &&
6853  fabs( pin->GetAbsY() - pinc->GetAbsY() ) < margin &&
6854  pin->MayConnectTo( pinc ) )
6855  {
6856  return pinc;
6857  }
6858  }
6859  }
6860 
6861  return ( a2dPin* )NULL;
6862 }
6863 
6864 bool a2dCanvasObject::ConnectWith( a2dCanvasObject* parent, a2dPin* pin, double margin, bool undo )
6865 {
6866  a2dIterC ic;
6867  a2dPin* pinfound = CanConnectWith( ic, pin, margin, true );
6868  if ( pinfound && pinfound->IsTemporaryPin() ) //those pins are generated without commands, not good for undo.
6869  {
6870  pinfound = wxStaticCast( pinfound->Clone( clone_deep ), a2dPin );
6871  pinfound->SetTemporaryPin( false );
6872  if ( undo )
6873  m_root->GetCommandProcessor()->Submit( new a2dCommand_AddObject( pinfound->GetParent(), pinfound ), true ); //this makes it save
6874  else
6875  pinfound->GetParent()->Append( pinfound );
6876  return true;
6877  }
6878  if ( pinfound )
6879  {
6880  ConnectPins( parent, pinfound, pin, undo );
6881  return true;
6882  }
6883  return false;
6884 }
6885 
6886 bool a2dCanvasObject::ConnectWith( a2dCanvasObject* parent, a2dCanvasObject* toConnect, const wxString& pinname, double margin, bool undo )
6887 {
6888  if ( m_childobjects == wxNullCanvasObjectList || !m_flags.m_doConnect || toConnect == this )
6889  return false;
6890 
6891  bool done = false;
6893  {
6894  a2dCanvasObject* obj = *iter;
6895  a2dPin* pinc = wxDynamicCast( obj, a2dPin );
6896  if ( pinc && pinc->IsVisible() && !pinc->GetRelease( ) )
6897  {
6898  if ( pinname.IsEmpty() )
6899  {
6900  //search pins at same position in object to connect
6901 
6902  for( a2dCanvasObjectList::iterator itero = toConnect->m_childobjects->begin(); itero != toConnect->m_childobjects->end(); ++itero )
6903  {
6904  a2dCanvasObject* obj = *itero;
6905  if ( !obj )
6906  continue;
6907  a2dPin* pinother = wxDynamicCast( obj, a2dPin );
6908  if ( pinother && pinother->IsVisible() && !pinother->GetRelease( ) )
6909  {
6910  bool fits = false;
6911  if ( fabs( pinother->GetAbsX() - pinc->GetAbsX() ) < margin &&
6912  fabs( pinother->GetAbsY() - pinc->GetAbsY() ) < margin )
6913  fits = true;
6914 
6915  if ( fits &&
6916  ( !pinother->IsConnectedTo( pinc ) && //are NOT already connected?
6917  pinother->MayConnectTo( pinc ) ) //is allowed?
6918  )
6919  {
6920  /*todo
6921 
6922  //now we have two pins on top of eachother, and they are not connected with eachother,
6923  //but connection is allowed, and also they may be already connected to others.
6924 
6925  //if this object is already connected to the other object via a pin at this point,
6926  //we do not connect to a second one.
6927  //The reason for this situation becomes clear when all pins are placed at the same position.
6928  //e.g. after a scaling action.
6929  //I call this (zero wire or zero Length object)
6930  if (
6931  ( pinother->ConnectedTo() && pinother->ConnectedTo()->GetParent() == this ) ||
6932  ( pinother->GetParent()->IsConnected( false, this ) )
6933  ) //toConnect object already connected to this object?
6934  {
6935  if ( pinother->GetParent()->IsConnect() ) // is a wire?
6936  {
6937  //zero wire, do not connect again.
6938  }
6939  else
6940  {
6941  //zero object do not connect again.
6942  }
6943  }
6944  //if poth pins are connected to a third object at both pins (at same position),
6945  //currently they will not be connected.
6946  else
6947  */
6948  if (
6949  pinc->IsConnectedTo() && pinother->IsConnectedTo() //both connected?
6950  //todo pinc->ConnectedTo()->GetParent() == pinother->ConnectedTo()->GetParent() //same connect object?
6951  )
6952  {
6953  //zero wire or zero object
6954  //TODO remove zero wires, and make a one to one connection between the pins ???
6955  }
6956  else
6957  {
6958  ConnectPins( parent, pinc, pinother, undo );
6959  }
6960  done = true;
6961  }
6962  }
6963  }
6964  }
6965  else
6966  {
6967  //search pin with pinname in object to connect ( should only be one! )
6968  for( a2dCanvasObjectList::iterator itero = toConnect->m_childobjects->begin(); itero != toConnect->m_childobjects->end(); ++itero )
6969  {
6970  a2dCanvasObject* obj = *itero;
6971  if ( !obj )
6972  continue;
6973  a2dPin* pinother = wxDynamicCast( obj, a2dPin );
6974  if ( pinother && pinother->IsVisible() && !pinother->GetRelease( ) && pinname == pinother->GetName() )
6975  {
6976  if ( fabs( pinother->GetAbsX() - pinc->GetAbsX() ) < margin &&
6977  fabs( pinother->GetAbsY() - pinc->GetAbsY() ) < margin &&
6978  pinother->MayConnectTo( pinc )
6979  )
6980  {
6981  if ( !pinother->IsConnectedTo( pinc ) )
6982  ConnectPins( parent, pinc, pinother, undo );
6983  return true;
6984  }
6985  else
6986  {
6987  CreateConnectObject( parent, pinc, pinother, undo );
6988  return true;
6989  }
6990  }
6991  }
6992  }
6993  }
6994  }
6995 
6996  return done;
6997 }
6998 
7000 {
7001  bool did = false;
7002 
7003  for( a2dCanvasObjectList::iterator iter = m_childobjects->begin(); iter != m_childobjects->end(); ++iter )
7004  {
7005  a2dCanvasObject* obj = *iter;
7006  if ( obj && obj->IsConnect() && obj->CheckMask( mask ) )
7007  {
7009  {
7010  a2dCanvasObject* objd = *iter;
7011  a2dPinPtr pin = wxDynamicCast( objd, a2dPin );
7012  if ( pin && !pin->GetRelease() )
7013  {
7014  a2dPinList::const_iterator iterconp;
7015  for ( iterconp = pin->GetConnectedPins().begin( ) ; iterconp != pin->GetConnectedPins().end( ) ; iterconp++ )
7016  {
7017  a2dPin* pincother = *iterconp;
7018  if ( !pincother || pincother->GetRelease() || !pincother->GetParent()->IsConnect() )
7019  continue;
7020 
7021  wxASSERT_MSG(
7022  pincother->IsConnectedTo( pin )
7023  , _( "connected pinc not reflected in connected pin" ) );
7024 
7025  if ( pin->GetParent()->GetClassInfo()->IsKindOf( pincother->GetParent()->GetClassInfo() ) )
7026  {
7027  did = true;
7028  }
7029  }
7030  }
7031  }
7032  }
7033  }
7034  return did;
7035 }
7036 
7037 void a2dCanvasObject::ConnectPins( a2dCanvasObject* WXUNUSED( parent ), a2dPin* pinc, a2dPin* pinother, bool undo )
7038 {
7039  wxASSERT_MSG( fabs( pinc->GetAbsX() - pinother->GetAbsX() ) < GetHabitat()->ACCUR() &&
7040  fabs( pinc->GetAbsY() - pinother->GetAbsY() ) < GetHabitat()->ACCUR()
7041  , _( "two pins are not at same position" ) );
7042 
7043  if ( undo )
7044  {
7045  m_root->GetCommandProcessor()->Submit( new a2dCommand_ConnectPins( pinc, pinother ), true );
7046  }
7047  else
7048  {
7049  pinc->ConnectTo( pinother );
7050  }
7051 }
7052 
7053 void a2dCanvasObject::ConnectPinsCreateConnect( a2dCanvasObject* parent, a2dPin* pinc, a2dPin* pinother, bool undo )
7054 {
7055  if ( pinother->IsConnectedTo( pinc ) && pinc->IsConnectedTo( pinother ) )//already connected at this pin.
7056  {
7057  if ( fabs( pinc->GetAbsX() - pinother->GetAbsX() ) < GetHabitat()->ACCUR() &&
7058  fabs( pinc->GetAbsY() - pinother->GetAbsY() ) < GetHabitat()->ACCUR() )
7059  {
7060  //exactly the same position, no need to create a wire.
7061  return;
7062  }
7063  else
7064  {
7065  //disconnect in order to create wire.
7066  ConnectPins( parent, NULL, NULL, undo );
7067  }
7068  }
7069 
7070  if ( fabs( pinc->GetAbsX() - pinother->GetAbsX() ) < GetHabitat()->ACCUR() &&
7071  fabs( pinc->GetAbsY() - pinother->GetAbsY() ) < GetHabitat()->ACCUR() )
7072  {
7073  ConnectPins( parent, pinc, pinother, undo );
7074  }
7075  else
7076  {
7077  CreateConnectObject( parent, pinc, pinother, undo );
7078  }
7079 }
7080 
7081 bool a2dCanvasObject::DisConnectWith( a2dCanvasObject* toDisConnect, const wxString& pinname, bool undo )
7082 {
7084  return false;
7085 
7086  bool done = false;
7088  {
7089  a2dCanvasObject* obj = *iter;
7090  a2dPin* pinc = wxDynamicCast( obj, a2dPin );
7091  if ( pinc )
7092  {
7093  if ( toDisConnect )
7094  {
7095  for( a2dCanvasObjectList::iterator itero = toDisConnect->m_childobjects->begin(); itero != toDisConnect->m_childobjects->end(); ++itero )
7096  {
7097  a2dCanvasObject* obj = *itero;
7098  a2dPin* pinother = wxDynamicCast( obj, a2dPin );
7099  if ( pinother && pinother->IsConnectedTo( pinc ) ) //connected pin?
7100  {
7101  if ( pinname.IsEmpty() || pinname == pinc->GetName() )
7102  {
7103  if ( undo )
7104  m_root->GetCommandProcessor()->Submit( new a2dCommand_DisConnectPins( pinc, pinother ), true );
7105  else
7106  pinc->Disconnect( pinother );
7107  done = true;
7108  }
7109  }
7110  }
7111  }
7112  else
7113  {
7114  if ( undo )
7115  {
7116  a2dPinList::const_iterator iterconp;
7117  for ( iterconp = pinc->GetConnectedPins().begin( ) ; iterconp != pinc->GetConnectedPins().end( ) ; iterconp++ )
7118  {
7119  a2dPin* pinother = *iterconp;
7120  if ( !pinother || pinother->GetRelease() )
7121  continue;
7122  m_root->GetCommandProcessor()->Submit( new a2dCommand_DisConnectPins( pinc, pinother ), true );
7123  done = true;
7124  }
7125  }
7126  else
7127  pinc->Disconnect( NULL );
7128  }
7129  }
7130  }
7131  return done;
7132 }
7133 
7134 bool a2dCanvasObject::DisConnectAt( a2dPin* toDisConnect, bool undo )
7135 {
7137  return false;
7138 
7139  bool done = false;
7141  {
7142  a2dCanvasObject* obj = *iter;
7143  a2dPin* pinc = wxDynamicCast( obj, a2dPin );
7144  if ( pinc && ( pinc == toDisConnect || !toDisConnect ) )
7145  {
7146  a2dPinList::const_iterator iterconp;
7147  for ( iterconp = pinc->GetConnectedPins().begin( ) ; iterconp != pinc->GetConnectedPins().end( ) ; iterconp++ )
7148  {
7149  a2dPin* pinother = *iterconp;
7150  if ( !pinother || pinother->GetRelease() )
7151  continue;
7152  if ( undo )
7153  m_root->GetCommandProcessor()->Submit( new a2dCommand_DisConnectPins( pinc, pinother ), true );
7154  else
7155  pinc->Disconnect( pinother );
7156  done = true;
7157  }
7158  }
7159  }
7160  return done;
7161 }
7162 
7164 {
7165  if ( parent && HasPins() && !IsConnect() )
7166  {
7167  //connect if hit on pin of other object
7168  if ( DoConnect() )
7169  {
7170  a2dCanvasObjectList allpinobjects;
7171  parent->CollectObjects( &allpinobjects, wxT( "" ), a2dCanvasOFlags::HasPins | a2dCanvasOFlags::VISIBLE );
7172  for( a2dCanvasObjectList::const_iterator iter = allpinobjects.begin(); iter != allpinobjects.end(); ++iter )
7173  {
7174  a2dCanvasObject* obj = *iter;
7175  if ( obj != this && !obj->m_flags.m_editingCopy && !obj->IsConnect() && obj->DoConnect() )
7176  {
7177  //connect this object with the other if possible.
7178  // New wires will be added to the parent of objects.
7179  ConnectWith( parent, obj , wxT( "" ), GetHabitat()->ACCUR(), undo );
7180  }
7181  }
7182  }
7183  }
7184 }
7185 
7186 bool a2dCanvasObject::CreateWiresOnPins( a2dCanvasObject* parent, bool undo, bool onlyNonSelected )
7187 {
7189  return false;
7190 
7191  if ( HasPins() )//&& !IsConnect() && DoConnect() )
7192  {
7193  bool done = false;
7195  {
7196  a2dCanvasObject* obj = *iter;
7197  a2dPin* pinc = wxDynamicCast( obj, a2dPin );
7198  if ( pinc && pinc->IsVisible() && !pinc->GetRelease() )
7199  {
7200  a2dPinList::const_iterator iterconp;
7201  for ( iterconp = pinc->GetConnectedPins().begin( ) ; iterconp != pinc->GetConnectedPins().end( ) ; iterconp++ )
7202  {
7203  a2dPin* other = *iterconp;
7204  if ( !other || other->GetRelease() )
7205  continue;
7206 
7207  //if already connected at this pin create a connect if needed.
7208  if ( other && other->IsVisible() &&
7209  ( !onlyNonSelected || onlyNonSelected && !other->GetParent()->IsSelected() )
7210  )
7211  {
7212  a2dCanvasObject* otherobj = other->GetParent();
7213  if ( otherobj->IsConnect() )
7214  {
7215  a2dWirePolylineL* wire = wxStaticCast( otherobj, a2dWirePolylineL );
7216  // if connected object is already a wire, it can be reused in general.
7217  if ( (wire->FindBeginPin() != other && wire->FindEndPin() != other)
7218  || ( wire->GetPinCount() > 2 && wire->GetNumberOfSegments() <= 2 )
7219  )
7220  {
7221  pinc->Disconnect();
7222  CreateConnectObject( parent, pinc, other, undo );
7223  done = true;
7224  }
7225  }
7226  else
7227  {
7228  pinc->Disconnect();
7229  CreateConnectObject( parent, pinc, other, undo );
7230  done = true;
7231  }
7232  }
7233  }
7234  }
7235  }
7236  return done;
7237  }
7238  return false;
7239 }
7240 
7241 bool a2dCanvasObject::SetConnectedPending( bool WXUNUSED( onoff ), bool needsupdateonly )
7242 {
7243  bool res = false;
7245  {
7246  a2dCanvasObject* obj = *iter;
7247  a2dPin* pinc = wxDynamicCast( obj, a2dPin );
7248  if ( pinc && !pinc->GetRelease( ) )
7249  {
7250  a2dPinList::const_iterator iterconp;
7251  for ( iterconp = pinc->GetConnectedPins().begin( ) ; iterconp != pinc->GetConnectedPins().end( ) ; iterconp++ )
7252  {
7253  a2dPin* pincother = *iterconp;
7254 
7255  if ( !pincother || pincother->GetRelease() )
7256  continue;
7257 
7258  a2dCanvasObject* conparent = pincother->GetParent();
7259  if ( conparent && !conparent->GetRelease() )
7260  {
7261  if ( needsupdateonly )
7262  {
7263  if ( conparent->NeedsUpdateWhenConnected() )
7264  {
7265  res = true;
7266  conparent->SetPending( true );
7267  }
7268  }
7269  else
7270  {
7271  res = true;
7272  conparent->SetPending( true );
7273  }
7274  }
7275  }
7276  }
7277  }
7278  return res;
7279 }
7280 
7281 bool a2dCanvasObject::ProcessCanvasEventChild( a2dIterC& ic, RenderChild& whichchilds, a2dHitEvent& hitEvent )
7282 {
7284  return false;
7285 
7286  a2dCanvasObjectList::iterator iter = m_childobjects->begin();
7287 
7288  if ( iter != m_childobjects->end() )
7289  {
7290  //iterate over layers if the children are meant to be drawn on a given layer at once
7291  //OR we do NOT render per layer from a parent object.
7293  {
7294  wxASSERT_MSG( ic.GetLayer() != wxLAYER_ALL, _T( " a2dIterC::GetPerLayerMode() can only hit one layer at the time" ) );
7295 
7296  wxUint16 layer = ic.GetLayer();
7297  unsigned int j;
7298  for ( j = 0; j < wxMAXLAYER; j++ )
7299  {
7300  a2dLayerInfo* layerinfo;
7301  // YES here we do the opposite of when rendering, hitting the top layer first
7302  if ( ic.GetDrawingPart()->GetReverseOrder() )
7303  layerinfo = GetRoot()->GetLayerSetup()->GetOrderIndex()[j];
7304  else
7305  layerinfo = GetRoot()->GetLayerSetup()->GetReverseOrderIndex()[j];
7306 
7307  // non defined layers, being those that where not in the layer setup, are sorted to the end of the indexes.
7308  // So the can be skipped.
7309  if ( layerinfo == wxNullLayerInfo )
7310  break;
7311 
7312  //important!
7313  //if layer is visible it will be rendered
7314  //If an object on a layer is itself invisible it will not be drawn
7315  //wxLAYER_ALL is reserved and should never be part of the layersettings
7316  if ( ic.GetDrawingPart()->GetLayerRenderArray()[ layerinfo->GetLayer() ].DoRenderLayer()
7317  && layerinfo->GetVisible() )
7318  {
7319  ic.SetLayer( layerinfo->GetLayer() );
7320  ProcessCanvasEventChildOneLayer( ic, whichchilds, hitEvent );
7321  }
7322  }
7323  ic.SetLayer( layer );
7324  }
7325  else
7326  {
7327  //no layer iteration will be done and therefore only object on m_layer == layer will be rendered.
7328  //layer == wxLAYER_ALL is a special case, and means ignore layer order for rendering the child objects.
7329  //checking of availability and visibility of layer itself is handled in parent objects
7330  ProcessCanvasEventChildOneLayer( ic, whichchilds, hitEvent );
7331  }
7332  }
7333  return hitEvent.m_processed;
7334 }
7335 
7336 bool a2dCanvasObject::ProcessCanvasEventChildOneLayer( a2dIterC& ic, RenderChild& whichchilds, a2dHitEvent& hitEvent )
7337 {
7338  RenderChild detectchilds;
7339  detectchilds.m_postrender = false;
7340  detectchilds.m_prerender = false;
7341  detectchilds.m_property = false;
7342 
7343  //search in reverse order, last drawn on a layer, and therefore on top, will be found first for hit
7344 
7345  a2dCanvasObjectList::reverse_iterator iter = m_childobjects->rbegin();
7346  while( iter != m_childobjects->rend() )
7347  {
7348  a2dCanvasObject* obj = *iter;
7349  if ( !obj )
7350  {
7351  iter++;
7352  continue;
7353  }
7354  int olayer = obj->GetLayer();
7355 
7356  detectchilds.m_postrender = detectchilds.m_prerender || !obj->GetPreRenderAsChild();
7357  detectchilds.m_prerender = detectchilds.m_postrender || obj->GetPreRenderAsChild();
7358  detectchilds.m_property = detectchilds.m_property || obj->GetIsProperty();
7359 
7360  iter++;
7361 
7362  //do a rough check to increase speed in common cases
7363  if ( (
7364  ( obj->GetPreRenderAsChild() && whichchilds.m_prerender && !obj->GetIsProperty() ) ||
7365  ( !obj->GetPreRenderAsChild() && whichchilds.m_postrender && !obj->GetIsProperty() ) ||
7366  ( obj->GetIsProperty() && whichchilds.m_property )
7367  )
7368  // the next does work if child is a container like e.g. a2dCanvasObjectReference
7369  // because
7370  &&
7371  ( olayer == ic.GetLayer() || ic.GetLayer() == wxLAYER_ALL || obj->GetChildObjectsCount() || obj->GetIgnoreLayer() )
7372  )
7373  {
7374  obj->ProcessCanvasObjectEvent( ic, hitEvent );
7375  }
7376  }
7377 
7378  whichchilds = detectchilds;
7379 
7380  return hitEvent.m_processed; //return
7381 }
7382 
7383 #ifdef _DEBUG
7384 
7385 void a2dCanvasObject::Dump( int indent )
7386 {
7387  wxString line( wxT( ' ' ), indent );
7388 
7389  line += wxString::Format( wxT( "a ((%s*)0x%p), x=%lg, y=%lg" ), GetClassInfo()->GetClassName(), this, GetPosX(), GetPosY() );
7390 
7391  DoDump( indent, &line );
7392 
7393  wxLogDebug( line );
7394 
7396  {
7397  a2dCanvasObject* obj = *iter;
7398  obj->Dump( indent + 2 );
7399  }
7400 }
7401 
7402 void a2dCanvasObject::DoDump( int WXUNUSED( indent ), wxString* line )
7403 {
7405  *line += wxT( " pTO" );
7407  *line += wxT( " pTD" );
7408  if( HasProperty( PROPID_Editcopy ) )
7409  *line += wxT( " pEC" );
7410  if( HasProperty( PROPID_Original ) )
7411  *line += wxT( " pOR" );
7412  if( m_flags.m_editingCopy )
7413  *line += wxT( " fEC" );
7414  if( m_flags.m_editing )
7415  *line += wxT( " fED" );
7416 }
7417 
7418 #endif
a2dHit m_how
return in which way the object was hit (stroke, fill, ...)
Definition: canobj.h:301
Display Part of a a2dDrawing, in which a2dCanvasObjects are shown.
Definition: drawer.h:470
bool m_processed
set if event was processed sofar
Definition: canobj.h:311
void PushCursor(const wxCursor &cursor)
push a cursor on the cursor stack, and set display cursor to new back being cursor.
Definition: drawer.cpp:1052
virtual void EndFilter(a2dIterC &ic, a2dCanvasObject *canvasObject)
called from a2dCanvasObject to reset filtering feature when filtered object goes out of context...
Definition: canobj.h:2771
virtual void MakeReferencesUnique()
All direct a2dCanvasObject which are part of this one are made unique.
Definition: canobj.cpp:5440
virtual bool ProcessCanvasObjectEvent(a2dIterC &ic, a2dHitEvent &hitEvent)
Hit objects will receive the event.
Definition: canobj.cpp:3964
perform snapping to boundingbox of objects
Definition: restrict.h:137
wxPoint2DDouble a2dPoint2D
this to define if coordinate numbers are integer or doubles
Definition: artglob.h:47
bool IsStrokeHit() const
true if this is a stroke hit (parent or child/member stroke)
Definition: polyver.h:109
void OnHandleEvent(a2dHandleMouseEvent &event)
called if a mouse event occured on a child object, that is a handle
Definition: canobj.cpp:2061
bool GetFilled() const
Definition: canobj.h:1476
double m_relx
(world coordinates) hit point x relative to the canvas object its parent object(s) ...
Definition: canobj.h:289
a2dPropertyIdTyped< wxMenu *, a2dMenuProperty > a2dPropertyIdMenu
property of this type
Definition: id.h:671
a2dAffineMatrix & Mirror(bool y=true, bool x=false)
mirror a matrix in x, y
Definition: afmatrix.cpp:396
double GetHeight() const
returns height of the boundingbox
Definition: bbox.cpp:334
virtual void ConnectPinsCreateConnect(a2dCanvasObject *parent, a2dPin *pinc, a2dPin *pinother, bool undo=false)
connect two pins
Definition: canobj.cpp:7053
bool GetSnap() const
is snap flag set?
Definition: canobj.h:1686
virtual void Render(a2dIterC &ic, OVERLAP clipparent)
Render this object to the active a2dDrawingPart.
Definition: canobj.cpp:4712
(In) Visible property that can be added to Docview Objects.
Definition: gen.h:1785
double GetAbsY() const
get absolute Y position of the pin ( after applying the parent&#39;s matrix and its own matrix ) ...
Definition: canpin.cpp:966
virtual bool DisConnectWith(a2dCanvasObject *toDisConnect=NULL, const wxString &pinname=wxT(""), bool undo=false)
Do Disconnect from another a2dCanvasObject by pin name.
Definition: canobj.cpp:7081
bool m_all
all events
Definition: canobj.h:187
bool SetSpecificFlags(bool setOrClear, a2dCanvasObjectFlagsMask which, const wxString &classname=wxT(""), a2dCanvasObjectFlagsMask whichobjects=a2dCanvasOFlags::ALL, const a2dBoundingBox &bbox=wxNonValidBbox, const a2dAffineMatrix &tworld=a2dIDENTITY_MATRIX)
set all given bit flags at once recursive for all objects in given boundingbox
Definition: objlist.cpp:519
bool m_objectLevel
indicates type of constructor used.
Definition: canobj.h:3041
#define wxDynamicCast(obj, className)
Define wxDynamicCast so that it will give a compiler error for unrelated types.
Definition: gen.h:75
Base class for all types of strokes, understood by a2dDrawer2D classes.
Definition: stylebase.h:378
void SetRoot(a2dDrawing *root, bool recurse=true)
Sets this object to a a2dCanvasDocument.
Definition: canobj.cpp:5933
virtual void SetTransform(const a2dAffineMatrix &userToWorld)
set user-to-world transform matrix.
Definition: drawer2d.cpp:446
virtual bool DoIsHitWorld(a2dIterC &ic, a2dHitEvent &hitEvent)
Does hit test on the object (exclusif child objects)
Definition: canobj.cpp:3713
a2dPoint2D GetCentre() const
get centre
Definition: bbox.cpp:277
hit if visible
Definition: canobj.h:165
virtual bool RestrictToObject(a2dIterC &ic, const a2dPoint2D &pointToSnapTo, a2dPoint2D &bestPointSofar, a2dSnapToWhatMask snapToWhat, double thresHoldWorld)
called from an a2dRestrictionEngine, to restrict vertexes, lines, object to this object.
Definition: vpath.cpp:82
bool IsNoStroke() const
Definition: stylebase.h:510
bool GetGeneratePins() const
get the GeneratePins flag
Definition: canobj.h:2289
a2dCanvasObjectList * CreateChildObjectList()
create and get the list where the child objects are stored in.
Definition: canobj.cpp:2561
a2dCanvasObjectReference is a reference to any a2dCanvasObject derived class.
Definition: recur.h:53
virtual bool GetVisible() const
some derived properties can be visible or not and override this
Definition: gen.h:1908
void OnEnterObject(a2dCanvasObjectMouseEvent &event)
called when the mouse enters the object
Definition: canobj.cpp:1940
void SetGeneratePins(bool value)
set the GeneratePins flag
Definition: canobj.h:2295
bool m_stroke_non_transparent
only when non transparent stroke
Definition: canobj.h:183
bool HasAttribute(const wxString &attrib)
Does the current tag have this attribute?
Definition: genxmlpars.cpp:560
virtual bool IsVirtConnect() const
object is a virtual connection (connects invisible with other objects without using wires ) ...
Definition: canobj.h:1834
property to hold a a2dAffineMatrix
Definition: afmatrix.h:410
virtual void SetParent(a2dCanvasObject *parent)
set parent object of the pin or some other objects that needs a parent
Definition: canobj.h:2122
void AddPending(a2dIterC &ic)
search objects ( if nested recursive ) that have the pending flag Set
Definition: canobj.cpp:4521
a2dHandle is used inside editing versions of a certain objects.
Definition: canpin.h:30
bool RemoveScale()
Remove Scale:
Definition: afmatrix.cpp:290
virtual bool IsTemporary_DontSave() const
Check if this is a temporary object, which should not be saved.
Definition: canobj.cpp:6365
bool GetEditable() const
get if the object may be edited
Definition: canobj.h:1584
The a2dBaseTool is used to derive tools from that are controlled by.
Definition: tools.h:379
virtual bool HasProperty(const a2dPropertyId *id, const wxString &stringvalue=wxEmptyString) const
Check if the object has a property with given id and string representation.
Definition: gen.cpp:1621
bool CanConnectWith(a2dIterC &ic, a2dCanvasObject *toConnect, bool autocreate)
check connect to other object
Definition: canobj.cpp:6790
mouse event sent from a2dCanvasObject to itself
Definition: canglob.h:223
~a2dExtendedResult()
Destructor.
Definition: canobj.cpp:832
void ClearCorridorPath(bool uncapture)
Reset all corridor paths and uncapture object.
Definition: drawer.cpp:1549
a2dConnectTask
flags for searching a connecting a2dpinClass, for the connecting task at hand.
Definition: connectgen.h:40
void SetRotation(double rotation)
Sets a rotation of this object.
Definition: canobj.cpp:2609
static const a2dCanvasObjectFlagsMask HasPins
Definition: candefs.h:205
bool GetConnected(a2dCanvasObjectList *connected, bool needsupdate)
get connected objects that are connected to this object via its pins.
Definition: canobj.cpp:6757
int WorldToDeviceY(double y) const
convert y from world to device coordinates
Definition: drawer2d.h:455
const a2dStroke * a2dBLACK_STROKE
global a2dStroke stock object for BLACK stroking
a2dAffineMatrix m_relativetransform
the accumulated transforms up to and including m_object-&gt;m_lworld
Definition: canobj.h:3035
const a2dAffineMatrix & GetParentTransform() const
Get the accumulated transform up to but NOT including m_lworld of the current obejct.
Definition: canobj.cpp:709
bool ParseCvgTransForm(a2dAffineMatrix &result, a2dIOHandlerXmlSerIn &parser)
parse Cvg transform of object
Definition: canobj.cpp:5654
void SetFoundCorridorEnd(bool foundCorridorEnd)
when there is a corridorPath set, this is used internal to set this flag to indicate that the end of ...
Definition: canobj.h:3392
bool m_selected2
object is selected2
Definition: candefs.h:238
virtual void PopTransform(void)
Recall the previously saved user-to-world transform off the matrix stack.
Definition: drawer2d.cpp:480
const a2dAffineMatrix & GetTransformMatrix() const
get the matrix used to position the object
Definition: canobj.h:500
void SetRelease(bool value)
set release flag
Definition: gen.h:1346
bool m_fill_non_transparent
only when non transparent fill
Definition: canobj.h:181
virtual a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
Clone this object and return a pointer to the new object.
Definition: canobj.cpp:1426
XMLeventType Next()
Walks to next element and returns event type.
Definition: genxmlpars.cpp:422
bool m_editing
true if the object is currently being edited
Definition: candefs.h:301
if set, set in the clone the PROPID_Original property to the copied object
Definition: gen.h:1212
a2dPoint2D GetStop() const
Get stop for gradient fill colour change.
Definition: stylebase.cpp:4733
void OnCanvasObjectMouseEvent(a2dCanvasObjectMouseEvent &event)
default handler for mouse events, sent to the object from the a2dDrawingPart.
Definition: canobj.cpp:2391
const a2dFill * a2dINHERIT_FILL
global a2dFill stock object for INHERTED from parent object filling
a2dCanvasObjectHitFlags
event mask flags for a2dCanvasObject hit
Definition: canobj.h:158
bool ResolveOrAdd(a2dSmrtPtr< a2dObject > *storedHere, const wxString &id=wxT(""))
try to resolve the object that is in storedHere when it is a reference.
Definition: gen.cpp:4760
a2dPropertyIdTyped< wxUint32, a2dUint32Property > a2dPropertyIdUint32
property of this type
Definition: id.h:653
class to map references to objects stored in XML, in order to make the connection later on...
Definition: gen.h:3462
virtual a2dCanvasObject * StartEdit(a2dBaseTool *tool, wxUint16 editmode, wxEditStyle editstyle=wxEDITSTYLE_COPY, a2dRefMap *refs=NULL)
create an editcopy and initialize editing of the editcopy
Definition: canobj.cpp:1640
a2dPin * FindEndPin()
Get the end pin from the childs.
Definition: polygon.cpp:3035
Creates a shadow behind a a2dCanvasObject when added as property.
Definition: canprop.h:157
wxColour GetColour2() const
return colour 2
Definition: stylebase.cpp:4969
bool RemoveReleased()
child objects which have relesed flag set, are removed as child, called recursive on rleased child ob...
Definition: canobj.cpp:5113
a2dDrawing * m_root
root group for rendering and accessing the canvas&#39;s also contains layer settings
Definition: canobj.h:2525
virtual wxString GetName() const
Get the ids print and serialization name.
Definition: id.h:245
see a2dCommandProcessorEvent
Definition: comevt.h:649
void DecCurrentDepth()
Decrement recursion depth.
Definition: gen.h:3940
transfer this property via a command processor
Definition: id.h:169
a2dCanvasObject * GetDeepestHit() const
get deepest object that was hit during event processing down the hierarchy.
Definition: canobj.h:3442
this is a hint for DoIgnoreIfNotMember in derived classes
Definition: id.h:179
a2dCanvasOFlags m_flags
holds flags for objects
Definition: canobj.h:2528
unsigned int GetChildObjectsCount() const
get number of child objects
Definition: canobj.cpp:2570
void SetDrawerStyle(a2dIterC &ic, a2dStyleProperty *style)
sets fill and stroke of object to a2dDrawingPart
Definition: canobj.cpp:3086
virtual void SetVisible(bool visible)
the object is visible or not.
Definition: canprop.h:232
const a2dAffineMatrix & GetInverseTransform() const
Inverse of GetTransform()
Definition: canobj.cpp:699
static const a2dCanvasObjectFlagsMask BIN2
Definition: candefs.h:193
#define EVT_CANVASOBJECT_ENTER_EVENT(func)
static event table macro for a2dCanvasObject mouse enter event
Definition: canglob.h:314
void SetValid(bool)
Definition: bbox.cpp:364
const wxRect & GetRect() const
get rect which keep tip visible
Definition: gen.h:2894
a2dError GetLastError() const
get last error encountered
Definition: gen.h:3538
OVERLAP Intersect(const a2dBoundingBox &, double Marge=0) const
Definition: bbox.cpp:205
a2dPin is used in a2dCanvasObject to add pins to it.
Definition: canpin.h:233
This is a class/type description for a2dPin&#39;s.
Definition: canpin.h:628
polygon defined with list of points.
Definition: polygon.h:45
static a2dCanvasOFlags m_flagsInit
holds value for flags to initialize m_flags
Definition: canobj.h:2533
static a2dPropertyIdVoidPtr * PROPID_ToolObject
set for objects that act as tool object, when a tool is in action.
Definition: canobj.h:2678
virtual void DoWalker(wxObject *parent, a2dWalkerIOHandler &handler)
iterate over this object and its children
Definition: gen.cpp:1488
Ref Counted base object.
Definition: gen.h:1045
bool GetPending() const
is this object pending for update?
Definition: canobj.h:1162
a2dCanvasObjectList * GetAsPolygons()
convert to a list of a2dPolygonL and a2dPolylineL
Definition: vpath.cpp:116
void OnChar(wxKeyEvent &event)
default handler for character events
Definition: canobj.cpp:1900
void SetTransformMatrix(const a2dAffineMatrix &mat=a2dIDENTITY_MATRIX)
Returns the matrix used to position the object.
Definition: canobj.h:509
bool Rotate(double angle)
Rotate clockwise by the given number of degrees:
Definition: afmatrix.cpp:432
snap segments of other objects in a2dCanvasObject::RestrictToObject()
Definition: restrict.h:120
a2dDrawing * GetRoot() const
get a2dCanvasDocument of the object.
Definition: canobj.h:952
void Enlarge(const double Marge)
enlarge with the given amount
Definition: bbox.cpp:162
proptype * GetPropertyListOnly(const a2dObject *obj) const
Get the property from the list in obj ( no members, not cloned )
Definition: id.inl:318
a2dLayerViewList & GetLayerRenderArray()
get the layer render array
Definition: drawer.h:564
Flags
Flags for property ids.
Definition: id.h:158
bool SwitchChildNamed(const wxString &objectname, a2dCanvasObject *newobject)
the object with the given name is released and switched in place to newobject
Definition: canobj.cpp:4487
virtual void SetContourWidth(double width)
set the Contour width of the shape
Definition: canobj.h:1408
a2dCanvasObject * GetCaptured() const
are events redirected to a captured corridor? if so return the captured object in it...
Definition: drawer.h:641
const a2dError a2dError_NoError
When cloning, and this flag is set, the property is cloned deep, else not.
Definition: id.h:196
double GetHitMarginWorld() const
Get HitMargin used to extend a hittest in world units.
Definition: drawer.cpp:739
bool SetConnectedPending(bool onoff, bool needsupdateonly)
set connected pending or not pending
Definition: canobj.cpp:7241
a2dObject * Clone(CloneOptions options, a2dRefMap *refs=NULL) const
create an exact copy of this property
Definition: gen.cpp:1199
bool m_pending
set when a2dCanvasObject needs an update (redraw).
Definition: candefs.h:277
wxUint16 GetLayer()
get the layer that is to be rendered
Definition: canobj.h:3282
a2dCanvasOHitFlags m_hitflags
allow hits on basis of those flags
Definition: canobj.h:2536
virtual void EndFilter(a2dIterC &ic, a2dCanvasObject *canvasObject)
called from a2dCanvasObject to reset filtering feature when filtered object goes out of context...
Definition: canobj.cpp:153
This template class is for property ids meant for properties that do not encapsulate another type...
Definition: id.h:397
bool SwitchObjectNamed(const wxString &objectname, a2dCanvasObject *newobject)
If object with the given name is found, it is switched to newobject.
Definition: objlist.cpp:588
a2dDrawingPart * GetDrawingPart()
Access to the tool controllers drawer.
Definition: tools.h:632
virtual bool Update(UpdateMode mode)
Update the state of the object according to its current position etc.
Definition: canobj.cpp:5149
bool GetDepthFirst()
What is the current recursion depth.
Definition: gen.h:3949
virtual void DependencyPending(a2dWalkerIOHandler *handler)
called by to check if this object becomes pending as a result of other objects
Definition: canobj.cpp:4680
static const a2dCanvasObjectFlagsMask PUSHIN
Definition: candefs.h:197
used to connect two pins
Definition: drawing.h:2411
virtual bool RestrictCanvasObjectAtVertexes(a2dCanvasObject *object, a2dPoint2D &point, double &dx, double &dy, wxUint32 sourceRequired=snapToAll, bool ignoreEngine=false)
return the clossest vertex which can be snapped if any.
Definition: restrict.cpp:685
bool m_fill
only when over filled area of object
Definition: canobj.h:177
virtual int GetCurrentLineNumber()
where in the input was line the current tag
Definition: genxmlpars.cpp:349
bool GetCanRender() const
return true if the object can be rendered.
Definition: canprop.h:242
static const a2dAffineMatrix & GetIdentityMatrix()
Return a static identity matrix as reference.
Definition: afmatrix.h:141
#define EVT_CANVASHANDLE_MOUSE_EVENT(func)
static event table macro for a2dHandle mouse event
Definition: canglob.h:318
void IncCurrentDepth()
Increment recursion depth.
Definition: gen.h:3937
virtual bool GeneratePinsPossibleConnections(a2dPinClass *pinClass, a2dConnectTask task, double x, double y, double margin=0)
generates pins on all possible locations where the object can be connected.
Definition: canobj.cpp:3156
void SetDrawerStroke(const a2dStroke &stroke)
Used to set the current stroke.
Definition: drawer2d.cpp:565
bool IsIdentity(void) const
Is the matrix the identity matrix?
Definition: afmatrix.h:147
a2dBoundingBox GetCalculatedBoundingBox(int nChildLevels)
Like GetBbox, but it always calculcates the bounding box from scratch.
Definition: canobj.cpp:5072
virtual void RemoveHierarchy()
move childs of childs and members which have hierarchy one level up to this object its child list...
Definition: canobj.cpp:6160
Defines a font to be set to a2dDrawer2D or stored in a2dCanvsObject etc.
Definition: stylebase.h:779
bool GetReverseOrder() const
Get Setting for draw layers in reverse order.
Definition: drawer.h:589
Input and output handler for the XmlSer format.
Definition: genxmlpars.h:819
proptype * GetProperty(a2dObject *obj) const
Get the property in obj (not cloned)
Definition: id.inl:121
a2dNamedPropertyList m_propertylist
properties
Definition: gen.h:1561
UpdateMode
Various mode flags for Update.
Definition: canobj.h:1091
wxColour GetStrokeColour() const
get first colour of stroke
Definition: canobj.cpp:2952
double GetScale()
See GetScale()
Definition: genxmlpars.h:784
snap to pins in other objects when not connected
Definition: restrict.h:112
void SetStrokeWorldExtend(double worldStrokeExtend)
Set strokeworld extend of last added object, used in a2dCanvasObject::DoIsHitWorld() ...
Definition: canobj.h:3400
if set, clone childs, otherwise ref-copy them
Definition: gen.h:1207
bool GetPixelStroke() const
if the width is pixels or not.
Definition: stylebase.cpp:6335
double GetValue(int col, int row) const
get the value in the matrix at col,row
Definition: afmatrix.cpp:106
a command processor specially designed to work with a a2dCanvasDocument
Definition: drawing.h:1046
void SetSelectable(bool selectable)
Allows to select this object.
Definition: canobj.h:1664
virtual void SetPending(bool pending)
set this object pending for update
Definition: canobj.cpp:2585
OVERLAP
Result of a a2dBoundingBox intersection or hittest.
Definition: bbox.h:24
bool m_visiblechilds
child objects are visible or not
Definition: candefs.h:292
virtual a2dVertexArray * GetAlignmentPoints()
Return a list of points to align object with others.
Definition: canobj.cpp:4395
bool IsNoFill() const
Definition: stylebase.h:273
a2dCanvasObjectPtr m_object
the canvas object at the current level of iteration
Definition: canobj.h:3030
bool GetThresholdDrawRectangle() const
underneath the threshold draw a rectangle instead of the real object.
Definition: drawer2d.h:217
object hit should not have select flag set
Definition: canobj.h:90
virtual bool Filter(a2dIterC &ic, a2dCanvasObject *canvasObject)
called from a2dCanvasObject to filter objects for rendering
Definition: canobj.cpp:82
a2dPropertyIdTyped< bool, a2dBoolProperty > a2dPropertyIdBool
property of this type
Definition: id.h:655
virtual bool Filter(a2dIterC &ic, a2dCanvasObject *canvasObject)
called from a2dCanvasObject to filter objects for rendering
Definition: canobj.cpp:256
a2dPin * IsConnectedTo(a2dPin *pin=a2dAnyPin) const
Return the pin to which this pin is connected.
Definition: canpin.cpp:751
a2dToolContr * GetToolController()
to get the tool controller to which this tool is attached.
Definition: tools.h:627
a2dNamedProperty * GetProperty(const a2dPropertyId *propertyId, a2dPropertyId::Flags flags=a2dPropertyId::flag_none) const
get property on this object
Definition: gen.cpp:1590
virtual bool Filter(a2dIterC &ic, a2dCanvasObject *canvasObject)
called from a2dCanvasObject to filter objects for rendering
Definition: canobj.cpp:293
static const a2dCanvasObjectFlagsMask FILLED
Definition: candefs.h:189
A2DGENERALDLLEXP a2dWalkEvent a2dWalker_a2dCanvasObjectPreChild
id for a2dWalkEvent issued from within a2dWalkerIOHandler
bool m_hasPins
true if this object does have a2dPin&#39;s as children
Definition: candefs.h:323
The base class for all drawable objects in a a2dCanvasDocument.
double GetTransformedHitMargin()
transformed to object its coordinate system
Definition: canobj.cpp:616
void SetViewDependent(a2dDrawingPart *aView, bool viewdependent, bool viewspecific=false, bool onlyinternalarea=false, bool deep=false)
set the object view dependent and maybe process all children to set these flags
Definition: canobj.cpp:2816
This is one hit result from a2dExtendedResult.
Definition: canobj.h:192
set the a2dCanvasObject&#39;s view dependent
Definition: algos.h:682
static const a2dCanvasObjectFlagsMask generatePins
Definition: candefs.h:216
list of a2dNamedProperty objects
Definition: gen.h:804
see wx/general/smrtptr.h
bool SkewX(double degrees)
Skew Xaxis:
Definition: afmatrix.cpp:441
void foreach_mf(void(a2dCanvasObject::*mfp)())
call fp for each object
Definition: canobj.cpp:2708
wxUint16 GetPrimitiveThreshold() const
get drawing threshold
Definition: drawer2d.h:214
virtual ~a2dCanvasObject()
destructor called by derived objects
Definition: canobj.cpp:1417
bool GetFlag(const a2dCanvasObjectFlagsMask which) const
get specific bitflag value
Definition: canobj.cpp:2655
virtual bool GetCanRender() const
some derived properties can be renderable or not and override this
Definition: gen.h:1916
wxUint16 m_layer
layer of object, default wxLAYER_DEFAULT
Definition: canobj.h:2556
bool CreateWiresOnPins(a2dCanvasObject *parent, bool undo, bool onlyNonSelected=false)
create wires on pins which do not have wires, but directly are connected to other objects...
Definition: canobj.cpp:7186
virtual void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
load object specific CVG data
Definition: canobj.cpp:5728
Search the list before searching members.
Definition: id.h:184
OVERLAP GetClipStatus(a2dIterC &ic, OVERLAP clipparent)
used for deciding if the object needs to be rendered against the current clipping area of the active ...
Definition: canobj.cpp:3273
vertex array of line and arc segments.
Definition: polyver.h:494
a2dCanvasObjectFlagsMask GetFlags() const
get bitflags as an integer
Definition: canobj.cpp:2660
property to hold a window type variable (for example wxTipWindow) to be associated with a a2dObject ...
Definition: gen.h:2806
a2dPropertyIdTyped< a2dSmrtPtr< a2dObject >, a2dProperty > a2dPropertyIdRefObject
property of this type
Definition: id.h:681
a2dCanvasObject is the base class for Canvas Objects.
Definition: canobj.h:371
a2dCanvasObject * GetObject() const
the object where the iterative context is currently
Definition: canobj.cpp:655
wxColour GetColour() const
return colour 1
Definition: stylebase.cpp:6131
std::vector< a2dLayerInfoPtr > & GetLayerIndex()
return array index on Layer
Definition: layerinf.cpp:555
void SetSize(double size)
Set the font size.
Definition: stylebase.cpp:2909
a2dAffineMatrix a2dIDENTITY_MATRIX
global a2dAffineMatrix to set/pass the identity matrix.
Definition: afmatrix.cpp:51
virtual void EndFilter(a2dIterC &ic, a2dCanvasObject *canvasObject)
called from a2dCanvasObject to reset filtering feature when filtered object goes out of context...
Definition: canobj.cpp:382
a2dHit m_type
type of the hit
Definition: canobj.h:3047
OVERLAP GetClipStatus() const
what is the clipping withing the current view for the last added object in context ...
Definition: canobj.cpp:671
a2dCanvasObject * CreateHierarchy(a2dCanvasObjectFlagsMask mask, bool createref=true)
object with the same given mask are made into a group.
Definition: canobj.cpp:6100
no special flags set
Definition: id.h:161
virtual bool GeneratePossibleConnections(a2dCanvasObject *object, a2dPinClass *pinClass, a2dConnectTask task, double x, double y, double margin) const
generate temporary pins to which objects can connect
bool And(a2dBoundingBox *, double Marge=0)
intersect the boundingbox with another, return true if the result is non zero
Definition: bbox.cpp:56
virtual void SetParent(a2dCanvasObject *parent)
set parent object of the pin
Definition: canpin.cpp:932
bool SetPointIfCloser(const a2dPoint2D &pointToSnapTo, const a2dPoint2D &pointToSnap, a2dPoint2D &bestPointSofar, double thresHoldWorld)
Definition: canobj.cpp:4189
bool m_used
GDSII format flag.
Definition: candefs.h:345
a2dCanvasObject * GetObject()
Get the current object.
Definition: canobj.h:3016
virtual a2dObject * GetRefObject() const
when a2dProperty, return its value else assert
Definition: gen.cpp:1976
void ReStartEdit(wxUint16 editmode)
to restart editing in a different mode
Definition: canobj.cpp:1693
a2dLayers * GetLayerSetup()
Get the layersettings for the canvas.
Definition: drawing.h:506
void SetEditable(bool editable)
Sets if this object may be edited.
Definition: canobj.h:1581
a2dCanvasObjectList * GetChildObjectList()
get the list where the child objects are stored in.
Definition: canobj.cpp:2551
a2dCanvas uses a2dCanvasView for displaying a view on a a2dCanvasDocument.
vertex list of line and arc segments.
Definition: polyver.h:600
virtual wxObject * CreateObject(const wxString &symbolicName)
Creates an specific object by name.
Definition: gen.cpp:4937
void TransformPoint(double x, double y, double &tx, double &ty) const
Transform a point.
Definition: afmatrix.cpp:559
void SetObjectFilter(a2dCanvasObjectFilter *filter)
set object filter class.
Definition: canobj.h:3418
OVERLAP m_clip
how far this object in the view being rendered
Definition: canobj.h:3044
bool m_snap_to
snapping of other objects to this when in place
Definition: candefs.h:283
bool GetUseObjRect() const
is the tip based on a2dCanvasObject boundingbox
Definition: gen.h:2897
double GetRotation() const
return rotation
Definition: afmatrix.cpp:799
wxString GetName() const
get the name given to the handle.
Definition: canpin.h:56
virtual void EndEdit()
cleanup an editcopy object
Definition: canobj.cpp:1828
virtual void DoRender(a2dIterC &ic, OVERLAP clipparent)
render derived object
Definition: canobj.cpp:4695
~a2dIterCU()
Restore the iteration context.
Definition: canobj.cpp:408
double TransformDistance(double distance) const
Transform a distance.
Definition: afmatrix.cpp:616
bool GetSelected() const
is the object selected flag set
Definition: canobj.h:1603
return to contain edit bbox, suitable for editing matrix of object
Definition: canobj.h:666
void SetFlags(a2dCanvasObjectFlagsMask newmask)
set bit flags of object (true or false) to given newmask values
Definition: canobj.cpp:2650
void SetSelected(bool selected)
Set the object selected flag if allowed.
Definition: canobj.h:1620
bool GetVisible()
is the layer visible
Definition: layerinf.cpp:341
a2dAffineMatrix m_inverseRelativetransform
inverse of m_relativetransform
Definition: canobj.h:3038
virtual bool RestrictToObject(a2dIterC &ic, const a2dPoint2D &pointToSnapTo, a2dPoint2D &bestPointSofar, a2dSnapToWhatMask snapToWhat, double thresHoldWorld)
called from an a2dRestrictionEngine, to restrict vertexes, lines, object to this object.
Definition: canobj.cpp:4209
void SetHitMarginWorld(double world)
used to extend a hittest with the given margin in world coordinates.
Definition: canobj.cpp:601
bool m_external
GDSII format flag.
Definition: candefs.h:342
bool m_selected
object is selected
Definition: candefs.h:235
double GetHitMarginWorld() const
hit marging in world units.
Definition: canglob.h:618
void SetBin(bool bin)
general flag use at will.
Definition: canobj.h:2259
void ReWireConnected(a2dCanvasObject *parent, bool undo=false)
rewire the object to keep connection or to make connection with other objects
Definition: canobj.cpp:7163
bool m_release
when set object is treated as being deleted, and wil be deleted in idle time.
Definition: gen.h:1570
bool IsVisible() const
get visibility (rendering depends on layer settings also)
Definition: canobj.h:1316
void EndFilterObject(a2dCanvasObject *canvasObject)
called when filter ends
Definition: canobj.cpp:817
bool GetPreRender() const
returns the current prerender setting.
Definition: canprop.h:251
int ReleaseChild(a2dCanvasObject *obj, bool backwards=false, bool all=false, bool now=false, bool undoCommands=false)
remove the given object from the childobjects
Definition: canobj.cpp:6260
static a2dPropertyIdBool * PROPID_FirstEventInObject
set in Startedit(), to be used to detect first (mouse)event sent to object.
Definition: canobj.h:2694
float m_worldExtend
world extend in world coordinates.
Definition: canobj.h:2545
A2DGENERALDLLEXP a2dWalkEvent a2dWalker_a2dCanvasObjectPostChild
id for a2dWalkEvent issued from within a2dWalkerIOHandler
a2dAffineMatrix m_lworld
used for positioning the object (x,y,ang,scale etc.)
Definition: canobj.h:2559
static a2dPropertyIdRefObject * PROPID_ViewSpecific
Definition: canobj.h:2691
The point hits a child of the object.
Definition: polyver.h:58
wxUint64 a2dCanvasObjectFlagsMask
mask flags for a2dCanvasObject
Definition: candefs.h:152
void SetDrawerFill(const a2dFill &fill)
Used to set the current fill.
Definition: drawer2d.cpp:621
bool m_generatePins
generate pins if true
Definition: candefs.h:268
Io handler to iterate through a a2dDocument.
Definition: gen.h:3911
bool GetGroupA() const
get the groupA flag
Definition: canobj.h:2267
bool SetPosXYRestrict(double &x, double &y)
set position to x,y but restricted, returns new values
Definition: canobj.cpp:1606
a2dFillStyle
Filling styles for a2dFill.
Definition: stylebase.h:91
bool m_b
group B flag (e.g boolean operations)
Definition: candefs.h:265
void OnPropertyChanged(a2dComEvent &event)
Definition: canobj.cpp:2762
a2dWirePolylineL is a polyline that adjusts itself when the objects it connects move ...
Definition: wire.h:42
wxMouseEvent & GetMouseEvent()
return the original mouse event that was redirected to the a2dHandle
Definition: canglob.h:290
bool GetCheck() const
general flag use at will.
Definition: gen.h:1342
#define EVT_CANVASOBJECT_POPUPMENU_EVENT(func)
static event table macro for a2dCanvasObject mouse Right Down event
Definition: canglob.h:324
void Transform(const a2dAffineMatrix &tworld, const wxString &type=wxT(""), a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::ALL, const a2dPropertyId *id=NULL)
Transform objects fitting the given filter.
Definition: objlist.cpp:625
void SetGroupA(bool value)
set the groupA flag
Definition: canobj.h:2273
snap to other objects its vertexes, which are decided in a2dCanvasObject::RestrictToObject() ...
Definition: restrict.h:116
bool m_xyRelToChildren
is set, m_x and m_y are supplied relative to the child objects ( object matrix m_world already applie...
Definition: canobj.h:297
a2dObject * GetObjectTip()
quickly get first property with name OBJECTTIP
Definition: canobj.cpp:2806
bool Disconnect(a2dPin *pin=a2dAnyPin, bool forceErase=false)
Definition: canpin.cpp:789
wxUint32 m_option
the way to hit/traverse the document.
Definition: canobj.h:299
bool m_draggable
can be dragged
Definition: candefs.h:253
void WriteNewLine()
Writes a new line and takes care of indentation.
Definition: genxmlpars.cpp:890
virtual void PushTransform()
Save the current user-to-world transform on the affine stack.
Definition: drawer2d.cpp:452
bool Start(a2dCanvasObject *object)
start setting the root object from here
Definition: algos.cpp:931
void SetIgnoreSetpending(bool value=true)
set IgnoreSetpending flag
Definition: canobj.h:2299
bool CleanWires(a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::ALL)
pins one wires to the same kind of wire are removed.
Definition: canobj.cpp:6999
bool GetPreRenderAsChild() const
Returns if this object should be rendered before other children objects.
Definition: canobj.h:1472
void ConnectPins(a2dCanvasObject *parent, a2dPin *pinc, a2dPin *pinother, bool undo=false)
connect two pins which must be unconnected and at the same position
Definition: canobj.cpp:7037
a2dText is an abstract base class.
Definition: cantext.h:93
a2dPin * GetPin()
get default pin for graph like structure
Definition: canpin.cpp:528
a2dCanvasObjectList * wxNullCanvasObjectList
define a NON a2dCanvasObjectList
Definition: objlist.cpp:53
a2dPropertyIdTyped< wxDateTime, a2dDateTimeProperty > a2dPropertyIdDateTime
property of this type
Definition: id.h:669
used to change a property on objects
Definition: drawing.h:2244
double ExtendDeviceToWorld(int extend)
Transform a pixel extend from device to world units.
Definition: canobj.cpp:611
void Mirror(bool x=true, bool y=false)
Mirrors this object in x or y orientation.
Definition: canobj.cpp:2639
void SetTemporaryPin(bool temporaryPin)
Definition: canpin.h:437
void ConnectTo(a2dPin *connectto)
connect this pin to the given pin
Definition: canpin.cpp:918
bool m_isOnCorridorPath
This object is on the corridor path to a captured object or to a corridored object.
Definition: candefs.h:320
bool GetSelectable()
can objects on this layer be selected
Definition: layerinf.cpp:346
void IncrementObjectCount()
increment currently counted number of objects on this layer inside a document.
Definition: layerinf.h:200
bool GetValid() const
returns true if boundingbox is calculated properly and therefore its valid flag is set...
Definition: bbox.cpp:299
void Expand(const a2dPoint2D &, const a2dPoint2D &)
expand boundingbox width two points
Definition: bbox.cpp:155
const a2dBoundingBox & Translate(a2dPoint2D &)
translate with given vector
Definition: bbox.cpp:370
virtual a2dBoundingBox GetUnTransformedBbox(a2dBboxFlags flags=a2dCANOBJ_BBOX_CHILDREN) const
Get boundingbox without the affine matrix transform included.
Definition: canobj.cpp:5036
double GetMinX() const
get minimum X of the boundingbox
Definition: bbox.cpp:304
bool GetSelectedOnly() const
returns the current only selected setting.
Definition: canprop.h:260
virtual void DrawRoundedRectangle(double x, double y, double width, double height, double radius, bool pixelsize=false)
Draw RoundedRectangle in world coordinates.
Definition: drawer2d.cpp:2048
bool CheckFlags(Flags flags) const
check a flag mask (all given flags must be set)
Definition: id.h:282
virtual bool Filter(a2dIterC &ic, a2dCanvasObject *canvasObject)
called from a2dCanvasObject to filter objects for rendering
Definition: canobj.cpp:139
a2dCanvasObjectList * m_childobjects
holds child objects
Definition: canobj.h:2562
virtual bool Filter(a2dIterC &ic, a2dCanvasObject *canvasObject)
called from a2dCanvasObject to filter objects for rendering
Definition: canobj.cpp:352
bool m_selectable
can select object
Definition: candefs.h:241
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 Transform(const a2dAffineMatrix &tworld)
transform the object using the given matrix
Definition: canobj.h:577
void SetColour(const wxColour &col)
set colour used for gradient and wxSTROKE_MASK_OPAQUE filling.
Definition: stylebase.cpp:6112
bool m_visible
is the object visible (overruled by paranet object in some cases during rendering ...
Definition: candefs.h:250
#define forEachIn(listtype, list)
easy iteration for a2dlist
Definition: a2dlist.h:111
a2dExtendedResult m_extended
extended result information with e.g path to lead to the nested object hit
Definition: canobj.h:303
class draws nothing, still can be used as a drawing context.
Definition: drawer2d.h:1245
void SkipSubTree()
Skips all child elements / tags of current element / tag.
Definition: genxmlpars.cpp:652
bool m_NoRenderCanvasObject
true is the object is a a2dCanvasObject (or derived ) without rendering something if there or now chi...
Definition: candefs.h:351
virtual void DoUpdateViewDependentObjects(a2dIterC &ic)
update derived objects
Definition: canobj.cpp:4657
polyline defined with list of points.
Definition: polygon.h:332
void OnPopUpEvent(a2dCanvasObjectMouseEvent &event)
called on Right Down by default.
Definition: canobj.cpp:1920
virtual void RenderChildObjectsOneLayer(a2dIterC &ic, RenderChild &whichchilds, OVERLAP clipparent)
to render the child objects
Definition: canobj.cpp:6003
virtual void EndFilter(a2dIterC &ic, a2dCanvasObject *canvasObject)
called from a2dCanvasObject to reset filtering feature when filtered object goes out of context...
Definition: canobj.cpp:242
void SetPropertyToObject(a2dObject *obj, const basetype &value, SetFlags setflags=set_none) const
Set the property in obj to value.
Definition: id.inl:238
a2dHitOption
Enum for hit test options.
Definition: canobj.h:76
virtual void EndFilter(a2dIterC &ic, a2dCanvasObject *canvasObject)
called from a2dCanvasObject to reset filtering feature when filtered object goes out of context...
Definition: canobj.cpp:131
void ReleaseMouse(a2dIterC &ic)
release the mouse capture for this object
Definition: canobj.cpp:3146
void Walker(wxObject *parent, a2dWalkerIOHandler &handler)
This is used to recursively walk through an object tree.
Definition: gen.cpp:1473
virtual a2dCanvasObjectList * GetAsCanvasVpaths(bool transform=true) const
when implemented the object without its children, is converted to
Definition: canobj.cpp:1505
bool GetSnapTo() const
is snap_to flag set?
Definition: canobj.h:1707
double GetPosX() const
get x position from affine matrix
Definition: canobj.h:527
virtual bool Filter(a2dIterC &ic, a2dCanvasObject *canvasObject)
called from a2dCanvasObject to filter objects for rendering
Definition: canobj.cpp:124
void Insert(size_t before, a2dCanvasObject *obj, bool ignoreReleased)
insert at index, taking into account released objects if needed.
Definition: objlist.cpp:742
static const a2dCanvasObjectFlagsMask SELECTABLE
Definition: candefs.h:182
property to hold a Menu type variable to be associated with a a2dObject
Definition: gen.h:2764
a2dPropertyIdTyped< wxUint16, a2dUint16Property > a2dPropertyIdUint16
property of this type
Definition: id.h:651
void SetHitMarginDevice(int pixels)
used to extend a hittest with the number of pixels.
Definition: canobj.cpp:596
#define EVT_COM_EVENT(func)
static wxEvtHandler for communication event
Definition: gen.h:564
bool m_stroke
only when over stroked area of object
Definition: canobj.h:179
void SkewY(double angle)
Skew in Y.
Definition: canobj.cpp:2627
virtual bool WalkTask(a2dIterC &ic, wxObject *parent, wxObject *object, a2dWalkEvent event)=0
called from within a2dCanvasDocument
(In)Visible property that can be added to Canvas Objects.
Definition: canprop.h:396
const a2dError a2dError_XMLparse
a2dPoint2D GetStart() const
Get start for gradient fill colour change.
Definition: stylebase.cpp:4727
Definition: bbox.h:26
~a2dIterPP()
Restore the iteration context.
Definition: canobj.cpp:479
a2dDrawer2D * GetDrawer2D() const
get current a2dDrawer2D
Definition: canobj.cpp:636
Normal straight line segment in a2dVpath.
Definition: polyver.h:878
#define wxStaticCast(obj, className)
The wxWindows 2.4.2 wxStaticCast is buggy. It evaluates its argument twice.
Definition: gen.h:123
a2dPoint2D GetCenter() const
Get start for gradient fill colour change.
Definition: stylebase.cpp:4753
virtual void EndFilter(a2dIterC &ic, a2dCanvasObject *canvasObject)
called from a2dCanvasObject to reset filtering feature when filtered object goes out of context...
Definition: canobj.cpp:183
wxColour GetFillColour() const
get first colour of fill
Definition: canobj.cpp:2902
hit if filled
Definition: canobj.h:161
a2dVertexListPtr GetSegments()
Get the list of points ( this is not a copy! )
Definition: polygon.h:219
Drawing context abstraction.
Definition: drawer2d.h:177
snap to intersections in other objects
Definition: restrict.h:114
void SetStrokeColour(const wxColour &colour)
set first colour of stroke
Definition: canobj.cpp:2963
static a2dPropertyIdBool * PROPID_TemporaryObject
set for objects that do not have to be saved
Definition: canobj.h:2681
void SetCorridorPathCaptureObject(a2dCanvasObject *captureObject)
Definition: canobj.cpp:799
virtual void DoEndEdit()
only used for editable objects and under control of a editing tool.
Definition: canobj.h:2601
bool m_editable
object can be edited
Definition: candefs.h:295
a2dCanvasObject * GetShowObject() const
return pointer of then currently shown object on the drawer.
Definition: drawer.h:680
a2dExtendedResult()
Default constructor.
Definition: canobj.cpp:828
void SetDisableDrawing(bool disableDrawing)
when set, all drawing functions return immediately.
Definition: drawer2d.h:716
double wxRadToDeg(double rad)
conversion from radians to degrees
Definition: artglob.cpp:31
Normal straight line segment in a2dVertexList and a2dVertexArray.
Definition: polyver.h:163
virtual a2dPolygonL * GetClipObject() const
return a2dPolygonL that is used for clipping
Definition: canprop.h:337
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
Save settings.
Definition: gen.cpp:1657
void SkewX(double angle)
Skew in X.
Definition: canobj.cpp:2621
void SetSpecificFlags(bool setOrClear, a2dCanvasObjectFlagsMask which)
set all bit flags in object that or true in mask to true or false
Definition: canobj.cpp:2645
#define EVT_CANVASOBJECT_MOUSE_EVENT(func)
static event table macro for a2dCanvasObject mouse event
Definition: canglob.h:312
virtual void SetPending(bool pending)
set this object pending for update
Definition: canpin.cpp:945
a2dSLine
Definition: canprim.h:987
a2dCanvasObject * HitChildObjectsOneLayer(a2dIterC &ic, RenderChild &whichchilds, a2dHitEvent &hitEvent)
This is an internal function used by IsHitWorldChildObjects(). Don&#39;t use it directly.
Definition: canobj.cpp:3804
Definition: bbox.h:27
void SetPerLayerMode(bool value)
if set the rendering is done layers by layer from the top
Definition: canobj.h:3427
A2DGENERALDLLEXP a2dSmrtPtr< a2dGeneralGlobal > a2dGeneralGlobals
a global pointer to get to global instance of important classes.
Definition: comevt.cpp:1148
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
write object specific CVGL data
Definition: canobj.cpp:5569
const a2dAffineMatrix & GetUserToDeviceTransform() const
get matrix which transforms directly from relative world coordinates to device
Definition: canobj.cpp:626
void SetDeepestHit(a2dCanvasObject *canvasObject)
set during event processing down the hierarchy, to the deepest object that was hit ...
Definition: canobj.h:3439
void Translate(double x, double y)
relative translate the object to position x,y in world coordinates
Definition: canobj.h:569
void SetUpdatesPending(bool onoff)
Tells the document that an object has changed.
Definition: drawing.cpp:405
virtual bool DisConnectAt(a2dPin *pin, bool undo=false)
Do Disconnect from another a2dCanvasObject by pin pointer.
Definition: canobj.cpp:7134
general event sent from a2dHandle to its parent a2dCanvasObject
Definition: canglob.h:273
used to disconnect two pins
Definition: drawing.h:2439
int Release(a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::ALL, const wxString &classname=wxT(""), const a2dPropertyId *id=NULL, const wxString &name=wxT(""), bool now=true)
release only objects with the given mask and classname and has property named propertyname and object...
Definition: objlist.cpp:306
bool m_extendedWanted
fill m_extended or not
Definition: canobj.h:305
void Add(a2dVpathSegment *seg)
add a segment
Definition: polyver.h:1240
Restriction engine for editing restrictions like snapping.
Definition: restrict.h:88
bool m_isHit
in the end if there was a hit (even if not processed event)
Definition: canobj.h:315
bool SkewY(double degrees)
Skew Yaxis:
Definition: afmatrix.cpp:460
const a2dPropertyId * GetId() const
Get the a2dPropertyId object identifying this property.
Definition: gen.h:1858
wxUint16 GetLayer() const
Returns the layer index where this object is drawn upon.
Definition: canobj.h:2368
bool m_childrenOnSameLayer
Definition: candefs.h:311
const a2dFill & GetFill() const
Definition: canprop.h:76
int CollectObjects(a2dCanvasObjectList *total, const wxString &type=wxT(""), a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::ALL, const a2dPropertyId *id=NULL, const a2dBoundingBox &bbox=wxNonValidBbox)
Copy objects fitting the given filter to the total list.
Definition: objlist.cpp:663
void SetColour(const wxColour &col)
set colour used for gradient and wxSTIPPLE_MASK_OPAQUE filling.
Definition: stylebase.cpp:4988
bool FindConnectedWires(a2dCanvasObjectList &result, a2dPin *pin, bool walkWires=true, bool selectedEnds=false, bool stopAtSelectedWire=false, bool addToResult=false)
find wires on pins of this objects.
Definition: canobj.cpp:6644
void OnLeaveObject(a2dCanvasObjectMouseEvent &event)
called when the mouse leaves the object
Definition: canobj.cpp:1997
int WorldToDeviceX(double x) const
convert x from world to device coordinates
Definition: drawer2d.h:453
a2dDrawer2D * GetDrawer2D()
get the internal m_drawer2D that is used for rendering the document
Definition: drawer.h:1125
bool m_visible
only when visible
Definition: canobj.h:185
bool HasPins(bool realcheck=false)
are there a2dPin derived children
Definition: canobj.cpp:6414
void Prepend(a2dCanvasObject *obj)
prepend a a2dCanvasObject to the childobjects
Definition: canobj.cpp:6209
contains the layer properties for one layer,
Definition: layerinf.h:41
virtual void DrawLine(double x1, double y1, double x2, double y2)
Draw line in world coordinates.
Definition: drawer2d.cpp:2167
const a2dStroke * a2dINHERIT_STROKE
global a2dStroke stock object for INHERTED from parent object stroking
Input and output handler for the XmlSer format.
Definition: genxmlpars.h:862
bool CheckMask(a2dCanvasObjectFlagsMask mask) const
Compares all flags in object to the given mask and return true is the same.
Definition: canobj.cpp:2665
if set, respect layer order, hit testing is done per layer from the top.
Definition: canobj.h:82
bool IsSelected() const
Is the object selected flag set.
Definition: canobj.h:1610
bool GetBin() const
general flag use at will.
Definition: canobj.h:2262
Invisible Style property that can be added to Canvas Objects.
Definition: canprop.h:55
const wxString & GetString(void)
when a2dStringProperty, return its value else assert
Definition: gen.h:2888
a2dPin * AddPin(const wxString name, double x, double y, wxUint32 a2dpinFlags, a2dPinClass *pinClass, bool undo=false)
add a a2dPin as child
Definition: canobj.cpp:6474
virtual a2dCanvasObject * GetConnectTemplate(const a2dCanvasObject *object, a2dPinClass *thisPinClass, const a2dCanvasObject *other, a2dPinClass *otherPinClass) const
create connection object based on two pin classes, which (may) need to be connected.
bool IsConnected(bool needsupdate, a2dCanvasObject *toConnect=0)
Is the object connected ( Optinal to specific object ) ?
Definition: canobj.cpp:6550
a2dPin * FindBeginPin()
Get the begin pin from the childs.
Definition: polygon.cpp:3030
void RemovePins(bool NotConnected=false, bool onlyTemporary=false, bool now=false)
Remove all a2dPin children.
Definition: canobj.cpp:6504
bool m_subEditAsChild
allow subedit on this object when child of other object
Definition: candefs.h:247
bool m_ignoreLayer
when this is set DoRender() is called even if layer of the object is not the layer to be rendered...
Definition: candefs.h:336
a2dPoint2D GetFocal() const
Get start for gradient fill colour change.
Definition: stylebase.cpp:4759
Search the list only for this dynamic property.
Definition: id.h:201
bool GetEdited()
when properties where edited, this must become true
Definition: comevt.h:665
void SetFilled(bool filled)
set the filled flag to render only outlines
Definition: canobj.h:1483
const a2dFill * a2dNullFILL
global a2dFill stock object for defining NO filling
a2dCanvasObject(double x=0, double y=0)
constructor called by derived objects
Definition: canobj.cpp:1391
void SetObjectPin(bool objectPin)
set when pin is an object pin
Definition: canpin.h:450
the property is temporary and never saved
Definition: id.h:163
a2dCanvasObject flags as a structure
Definition: candefs.h:164
Contains a2dDrawing Class to hold a drawing.
bool Identity(void)
Make into identity matrix.
Definition: afmatrix.cpp:256
int GetLevel() const
number of levels deep we are inside a document as seen from the m_top
Definition: canobj.h:3353
wxUint32 a2dSnapToWhatMask
mask for a2dSnapToWhat flags
Definition: restrict.h:26
bool PointInBox(const a2dPoint2D &, double Marge=0) const
is the point within the boundingbox
Definition: bbox.cpp:256
int IndexOf(a2dCanvasObject *obj) const
returns index of the given a2dCanvasObject in this childobjects
Definition: canobj.cpp:6320
virtual a2dCanvasObject * CreateConnectObject(a2dCanvasObject *parent, a2dPin *pinThis, a2dPin *pinOther, bool undo=false) const
generates a connection object with pins and all.
Definition: canobj.cpp:3169
no hit will be reported
Definition: canobj.h:160
a2dHandle * SetHandlePos(wxString name, double x, double y)
set a2dHandle position with the given name
Definition: canobj.cpp:1881
A2DGENERALDLLEXP a2dWalkEvent a2dWalker_a2dCanvasObjectStart
id for a2dWalkEvent issued from within a2dWalkerIOHandler
virtual bool Submit(a2dCommand *command, bool storeIt=true)
next to the base class submit, it sets a2DocumentCommandProcessor for a2dCommand
Definition: comevt.cpp:842
bool m_resizeToChilds
when true, the wxEVT_CANVASOBJECT_RESIZE_EVENT is sent to this object, if the child box did change...
Definition: candefs.h:357
used to add object to a a2dCanvasDocument in the current parent
Definition: drawing.h:1403
property to hold a tip window type variable to be associated with a a2dObject
Definition: gen.h:2850
virtual void EndFilter(a2dIterC &ic, a2dCanvasObject *canvasObject)
called from a2dCanvasObject to reset filtering feature when filtered object goes out of context...
Definition: canobj.cpp:279
bool m_snap
snapping of editable object or when moving
Definition: candefs.h:280
defines common settinsg for a habitat for a set of a2dCameleons.
Definition: canglob.h:439
virtual a2dCanvasObjectList * GetSnapVpath(a2dSnapToWhatMask snapToWhat)
return a vectorpath indicating on which point/segments the object likes to be snapped.
Definition: canobj.cpp:4308
a2dCanvasObject * ChildIsHitWorld(a2dIterC &ic, a2dHitEvent &hitEvent, bool filterSelectableLayers=false)
Do hittest on children.
Definition: canobj.cpp:3289
bool GetUseCheck()
see SetUseCheck
Definition: gen.h:3955
a2dCanvasObject * GetEndCorridorObject() const
return the corridor object if set else NULL
Definition: drawer.h:654
void SetVisible(bool visible)
set if this object will visible (be rendered or not)
Definition: canobj.h:1303
virtual bool DoStartEdit(wxUint16 editmode, wxEditStyle editstyle)
only used for editable objects and under control of a editing tool.
Definition: canobj.cpp:1739
bool IsTemporaryPin() const
return true if this pin is a temporary pin
Definition: canpin.h:433
void SetFillColour(const wxColour &colour)
set first colour of fill
Definition: canobj.cpp:2917
void SetSnapTo(bool snap)
Sets snap_to flag.
Definition: canobj.h:1704
A 2x3 affine matrix class for 2D transformations.
Definition: afmatrix.h:53
void MakeUnique()
all with reference count &gt; 1 are cloned.
Definition: objlist.cpp:143
virtual a2dObject * GetRefObjectNA() const
when a2dProperty, return its value else return NULL
Definition: gen.cpp:1982
static a2dPropertyIdMatrix * PROPID_IntViewDependTransform
used for objects with* PROPID_viewDependent but only for internal area
Definition: canobj.h:2705
a2dPoint2D GetPosXY() const
get position of object
Definition: canobj.h:533
wxMouseEvent & GetMouseEvent()
return the original mouse event that was redirected to the a2dCanvasObject
Definition: canglob.h:243
a2dStroke GetDrawerStroke() const
get the current stroke
Definition: drawer2d.h:548
int GetPinCount()
How many a2dPin derived children are there.
Definition: canobj.cpp:6455
const a2dStroke * a2dNullSTROKE
global a2dStroke stock object for NO stroking
A2DGENERALDLLEXP a2dWalkEvent a2dWalker_a2dCanvasObjectEnd
id for a2dWalkEvent issued from within a2dWalkerIOHandler
static a2dPropertyIdWindow * PROPID_TipWindow
when set used for tip window by default in OnCanvasMouseEvent()
Definition: canobj.h:2718
wxUint16 m_pixelExtend
Pixel extend.
Definition: canobj.h:2553
if set, don&#39;t hit test the root object or object for which IsHitWorld is called
Definition: canobj.h:87
a2dPinClass * GetPinClass() const
return the pin class of this pin
Definition: canpin.h:356
double GetMaxX() const
get maximum X of the boundingbox
Definition: bbox.cpp:316
static const a2dCanvasObjectFlagsMask DRAGGABLE
Definition: candefs.h:187
a2dPropertyIdTyped< a2dAutoZeroPtr< a2dObject >, a2dAutoZeroProperty > a2dPropertyIdRefObjectAutoZero
property of this type
Definition: id.h:683
const a2dPropertyId * GetPropId()
get the id of the property displayed by this object
Definition: canprop.h:427
bool DoConnect()
if return true, connection with other object on this object its pins is allowed.
Definition: canobj.h:1845
bool IsCapturedMouse(a2dIterC &ic) const
is the mouse captured for this object
Definition: canobj.cpp:3151
const a2dAffineMatrix & GetInverseParentTransform() const
inverse of GetParentTransform()
Definition: canobj.cpp:723
a2dPin * HasPinNamed(const wxString pinName, bool NotConnected=false)
are there a2dPin derived children which matches the given pin name?
Definition: canobj.cpp:6436
if set, set in the clone the PROPID_editcopy property to the original object
Definition: gen.h:1215
double GetPosY() const
get y position from affine matrix
Definition: canobj.h:530
bool GetFilling() const
if true, filling is on else filling is transparent.
Definition: stylebase.cpp:5069
virtual void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
Load settings.
Definition: gen.cpp:1699
wxUint16 GetAttributeValueUint16(const wxString &attrib, wxUint16 defaultv=0)
cast to wxUint16 of GetAttributeValueInt()
Definition: genxmlpars.h:462
virtual void ClearAllPinConnections(bool withundo=true)
Remove all pin connections by issuing a2dCommand_DisConnectPins commands.
Definition: canobj.cpp:6408
virtual double GetContourWidth() const
get the Contour width of the shape
Definition: canobj.h:1411
while iterating a a2dCanvasDocument, this holds the context.
Definition: canobj.h:3212
snap segments middle of other objects in a2dCanvasObject::RestrictToObject()
Definition: restrict.h:118
void UpdateViewDependentObjects(a2dIterC &ic)
update the transform matrix for objects with property &#39;PROPID_viewDependent&#39;
Definition: canobj.cpp:4605
double m_x
x endpoint of line
Definition: polyver.h:232
struct for how a single object on one layer was hit
Definition: polyver.h:38
a2dIterPP(a2dIterC &ic, a2dCanvasObject *object, OVERLAP clip=_IN, a2dHit type=a2dHit())
Update iteration context.
Definition: canobj.cpp:454
double m_x
(world coordinates) hit point x as in a2dDrawingPart or any other top level
Definition: canobj.h:293
a2dWalker based algorithms
bool GetPerLayerMode()
if set the rendering is done layers by layer from the top
Definition: canobj.h:3430
a2dCanvasObject * GetOriginal()
if this is an editcopy, return the orginal else NULL
Definition: canobj.cpp:1876
All updates of these modes force an update (e.g. update non-pending valid bounding boxes) ...
Definition: canobj.h:1107
a2dBoundingBox GetClipBox(a2dIterC &ic)
returns boundingbox clipping object if clipping property is set
Definition: canobj.cpp:5899
static const a2dCanvasObjectFlagsMask NON
Flags for a2dCanvasObject.
Definition: candefs.h:179
virtual void DependentCommands(a2dCanvasObject *parent, a2dCommand *command)
call this when a a2dCommands should result in extra commands, to become part of a parent a2dCommandGr...
Definition: canobj.cpp:4691
void SetSnap(bool snap)
Sets snap flag.
Definition: canobj.h:1695
void MapBbox(const a2dAffineMatrix &matrix)
Definition: bbox.cpp:445
Definition: bbox.h:28
virtual void DrawHighLighted(a2dIterC &ic)
called by Render() if m_flags.m_HighLight is set
Definition: canobj.cpp:5020
a2dlist< a2dDumbPtr< a2dPin > > & GetConnectedPins()
Return list fo connected pins.
Definition: canpin.h:462
a2dCommandProcessor * GetCommandProcessor() const
Returns a pointer to the command processor associated with this document.
Definition: drawing.h:549
bool ReleaseChildObjects(a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::ALL)
removes and release only from the childobjects the objects with the given mask
Definition: canobj.cpp:6296
static a2dPropertyIdMenu * PROPID_PopupMenu
when set used for popup menu by default in OnPopUpEvent()
Definition: canobj.h:2715
void CaptureMouse(a2dIterC &ic)
redirect all mouse events for the canvas to this object
Definition: canobj.cpp:3141
#define EVT_CANVASOBJECT_LEAVE_EVENT(func)
static event table macro for a2dCanvasObject mouse leave event
Definition: canglob.h:316
virtual a2dVertexList * GetAsVertexList(bool &returnIsPolygon) const
convert to a polygon.
Definition: canobj.h:2491
a2dBoundingBox GetMappedBbox(a2dIterC &ic, bool withExtend=true)
first translate boundingbox with cworld and recalculate at new position
Definition: canobj.cpp:3256
void DecrementObjectCount()
decrement currently counted number of objects on this layer inside a document.
Definition: layerinf.h:203
double m_y
y endpoint of line
Definition: polyver.h:235
virtual bool Submit(a2dCommand *command, bool storeIt=true)
Definition: drawing.cpp:5966
~a2dIterC()
destructor
Definition: canobj.cpp:538
bool m_doConnect
in case of pins on the object is it currely allowed for other object to connect to it...
Definition: candefs.h:314
void SetStroke(const wxColour &strokecolor, double width=0, a2dStrokeStyle style=a2dSTROKE_SOLID)
Set a stroke for the object which will be used instead of the layer stroke.
Definition: canobj.cpp:2924
void SetChildrenOnSameLayer(bool samelayer)
if set children are rendered on the same layer as this object.
Definition: canobj.h:1429
bool GetViewDependentObjects() const
see SetViewDependentObjects()
Definition: drawer.h:561
std::vector< a2dLayerInfoPtr > & GetReverseOrderIndex()
return array index on ReverseOrder
Definition: layerinf.cpp:569
int TakeOverFrom(a2dCanvasObjectList *total, const wxString &type=wxT(""), a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::ALL, const a2dPropertyId *id=NULL)
Move objects fitting the given filter from the total list to this list.
Definition: objlist.cpp:724
void Scale(double scalex, double scaley)
Scale in x and y ( &gt; zero)
Definition: canobj.cpp:2633
int m_id
application specific use
Definition: canobj.h:317
bool m_subEdit
allow subedit of children within this object
Definition: candefs.h:244
static const a2dCanvasObjectFlagsMask VISIBLE
Definition: candefs.h:186
Clipping Path property that can be added to a2dCanvasObject&#39;s.
Definition: canprop.h:322
wxString GetName() const
get the name given to the pin.
Definition: canpin.h:322
wxString GetAttributeValue(const wxString &attrib, const wxString &defaultv=wxT(""))
Returns the value of an attribute.
Definition: genxmlpars.cpp:450
a2dIterCU(a2dIterC &ic, a2dCanvasObject *object, OVERLAP clip=_IN)
Update iteration context.
Definition: canobj.cpp:402
void SetRenderConnected(bool RenderConnected)
flag to render connected pin
Definition: canpin.h:284
a2dRestrictionEngine * GetRestrictionEngine()
Get restriction engine (grid snapping)
Definition: canglob.cpp:934
bool GetFoundCorridorEnd()
when there is a corridor path set, this return if end has bin found while iterating.
Definition: canobj.h:3389
virtual bool EditProperties(const a2dPropertyId *id, bool withUndo)
edit properties of the object
Definition: canobj.cpp:2722
static const a2dCanvasObjectFlagsMask SNAP_TO
Definition: candefs.h:196
void AddEditobject(a2dCanvasObject *object)
Add an editcopy object to the tool/document.
Definition: tools.cpp:916
bool GetGroupB() const
get the groupA flag
Definition: canobj.h:2278
a2dText * SetObjectTip(const wxString &tip, double x, double y, double size=30, double angle=0, const a2dFont &font=*a2dDEFAULT_CANVASFONT)
quickly set a property name OBJECTTIP
Definition: canobj.cpp:2781
property to hold a a2dStroke type variable to be associated with a a2dObject
Definition: styleprop.h:98
a2dConnectionGenerator * GetConnectionGenerator() const
Get class for generating new connection objects between object and pins.
Definition: canpin.h:723
virtual bool DoCanConnectWith(a2dIterC &ic, a2dPin *pin, double margin, bool autocreate)
prepare an object for being connected to a given pin
Definition: canobj.cpp:6817
wxObject * GetParent()
Definition: gen.h:3972
bool GetRelease() const
get release flag
Definition: gen.h:1350
a2dCanvasCommandProcessor * GetCanvasCommandProcessor()
get a pointer to the command processor
Definition: drawing.cpp:375
void SetGroupB(bool value)
set the groupA flag
Definition: canobj.h:2284
wire classes for connecting objects.
a2dCanvasObject * GetParent() const
when traversing tree this the object one level higher.
Definition: canobj.cpp:641
bool m_HasSelectedObjectsBelow
selected objects detected below
Definition: candefs.h:354
virtual bool Filter(a2dIterC &ic, a2dCanvasObject *canvasObject)
called from a2dCanvasObject to filter objects for rendering
Definition: canobj.h:2768
bool IsDraggable() const
get if the object can be dragged
Definition: canobj.h:1683
virtual bool AddProperty(a2dNamedProperty *property)
This function is called by a2dPropertyId to add a property to the list.
Definition: gen.cpp:1541
double GetHitMarginWorld()
Get HitMargin in World units.
Definition: canobj.cpp:606
virtual bool GetVisible() const
return true if the object is visible.
Definition: canprop.h:234
This is the base class for all kinds of property id&#39;s for a2dObject.
Definition: id.h:154
double GetMaxY() const
get maximum Y of the boundingbox
Definition: bbox.cpp:322
double GetWidth() const
returns width of the boundingbox
Definition: bbox.cpp:328
a2dCanvasObject * GetParentObject()
parent object relative to which the actions take place.
Definition: tools.h:684
An object of this class will update a a2dIterC with the required information.
Definition: canobj.h:3123
hit if stroked
Definition: canobj.h:162
XMLeventType GetEventType()
Returns the type of current event.
Definition: genxmlpars.cpp:606
void Require(const XMLeventType &type, wxString name)
Forces a special tag.
Definition: genxmlpars.cpp:390
bool HasDynamicProperties() const
test if there are dynamic properties in the m_propertylist
Definition: gen.h:1513
void foreach_f(void(*fp)(a2dCanvasObject *item))
call fp for each object
Definition: canobj.cpp:2694
void SetIsProperty(bool IsProperty)
Definition: canobj.h:2152
a2dBoundingBox GetAlignmentBbox()
calls GetAlignmentPoints()
Definition: canobj.cpp:4473
virtual a2dCanvasObject * CreateConnectObject(a2dCanvasObject *parent, a2dPin *pinThis, a2dPin *pinOther, bool undo=false) const
create connection object based on two pins which need to be connected.
if set, don&#39;t stop at the first hit, but test child/sibling objects anyway
Definition: canobj.h:97
virtual a2dCanvasObject * GetConnectTemplate(a2dPinClass *mapThis, a2dCanvasObject *other, a2dPinClass *mapOther) const
based on the a2dPinClass&#39;s of eventually a2dPin&#39;s wanted in both objects, a
Definition: canobj.cpp:3164
wxString GetTagName()
Returns name of the current XML tag.
Definition: genxmlpars.cpp:565
return to contain children bbox
Definition: canobj.h:667
static const a2dCanvasObjectFlagsMask VISIBLECHILDS
Definition: candefs.h:199
void SetLayer(wxUint16 layer)
set the layer that is to be rendered
Definition: canobj.h:3288
wxColour GetColour() const
return colour
Definition: stylebase.cpp:5012
void SetDraggable(bool draggable)
Sets if this object may be dragged.
Definition: canobj.h:1673
void SetClipStatus(OVERLAP status)
set the clipping withing the current view for the last added object in context
Definition: canobj.cpp:693
void SetPosXY(double x, double y, bool restrict=false)
set position to x,y
Definition: canobj.cpp:1624
bool Scale(double scale)
Scale by scale (isotropic scaling i.e. the same in x and y):
Definition: afmatrix.cpp:270
bool m_HasToolObjectsBelow
special tool object detected below
Definition: candefs.h:348
bool Translate(double x, double y)
Translate by dx, dy:
Definition: afmatrix.cpp:420
property to hold a a2dCanvasObject pointer type variable to be associated with a canvasobject ...
Definition: canprop.h:202
virtual bool Filter(a2dIterC &ic, a2dCanvasObject *canvasObject)
called from a2dCanvasObject to filter objects for rendering
Definition: canobj.cpp:197
const a2dStroke & GetStroke() const
Definition: canprop.h:80
void SetToObject(a2dObject *obj, a2dPropertyId::SetFlags setflags=a2dPropertyId::set_none)
Set this property to an object.
Definition: gen.h:1851
virtual bool Filter(a2dIterC &ic, a2dCanvasObject *canvasObject)
called from a2dCanvasObject to filter objects for rendering
Definition: canobj.cpp:162
const a2dStroke * a2dTRANSPARENT_STROKE
global a2dStroke stock object for TRANSPARENT stroking
A list class for reference counted objects.
Definition: smrtptr.h:653
void SetTipWindow(const wxString &tip)
quickly set a property a2dTipWindowProperty
Definition: canobj.cpp:2798
hit if stroke is not transparent
Definition: canobj.h:164
always hit
Definition: canobj.h:166
bool m_editingCopy
true if the object needs to be rendered in edit mode.
Definition: candefs.h:304
virtual bool EliminateMatrix()
reduce matrix to identity
Definition: canobj.cpp:6191
bool m_template
GDSII format flag.
Definition: candefs.h:339
void SetPinClass(a2dPinClass *pinClass)
Set the pin class.
Definition: canpin.h:359
static const a2dCanvasObjectFlagsMask DoConnect
Definition: candefs.h:203
a2dFill GetDrawerFill() const
get the current fill
Definition: drawer2d.h:557
virtual void DoAddPending(a2dIterC &ic)
called by addPending
Definition: canobj.cpp:4601
if set, clone members (e.g. line end styles), otherwise ref-copy them
Definition: gen.h:1203
see a2dComEvent
Definition: gen.h:371
bool m_a
group A flag (e.g boolean operations)
Definition: candefs.h:262
a2dCanvasObject * Find(a2dCanvasObject *obj) const
return the object if it is part of the list
Definition: objlist.cpp:553
void SetEndCorridorObject(a2dCanvasObject *endCorridorObject)
use in combination with the a2dIterC class to set a corridor path for events.
Definition: drawer.cpp:1041
bool GetVisible() const
get visibility (rendering depends on layer settings also)
Definition: canobj.h:1309
virtual bool ConnectWith(a2dCanvasObject *parent, a2dCanvasObject *toconnect, const wxString &pinname=wxT(""), double margin=1, bool undo=false)
Do connect with another a2dCanvasObject by pinname.
Definition: canobj.cpp:6886
bool GetSelectable() const
is the object selectable flag set
Definition: canobj.h:1648
void ShowPins(bool onoff)
Set a2dPin children visible or not.
Definition: canobj.cpp:6380
a2dRect
Definition: canprim.h:440
base classes for tools and controller on top of the tools.
a2dCanvasObject * IsHitWorld(a2dIterC &ic, a2dHitEvent &hitEvent)
If the position (x,y) is within the object return this.
Definition: canobj.cpp:3415
Allow adding a specific property with ID more than once to a list.
Definition: id.h:188
used to tell which child object to render and to detect the need for it.
Definition: canobj.h:381
virtual void DoUpdateViewDependentTransform(a2dIterC &ic)
update transform matrix klion: I&#39;m not sure that this function necessary as virtual ...
Definition: canobj.cpp:4637
The a2dBoundingBox class stores one a2dBoundingBox of a a2dCanvasObject.
Definition: bbox.h:39
bool GetChildrenOnSameLayer() const
are children rendered on the same layer as this object?
Definition: canobj.h:1432
std::vector< a2dLayerInfoPtr > & GetOrderIndex()
return array index on Order
Definition: layerinf.cpp:562
bool Invert(void)
Invert matrix.
Definition: afmatrix.cpp:197
virtual bool FindConnectedPins(a2dCanvasObjectList &result, a2dPin *pin=NULL, bool walkWires=true, a2dPinClass *searchPinClass=NULL, a2dCanvasObject *isConnectedTo=NULL)
Find pins in other object which are connected to this object.
Definition: canobj.cpp:6586
void SetDynamicPin(bool dynamicPin)
set when pin is a dynamic pin
Definition: canpin.h:421
void Rotate(double rotation)
Rotates this object clockwise.
Definition: canobj.cpp:2615
static a2dPropertyIdDateTime * PROPID_DateTime
some time property which a user wants to store
Definition: canobj.h:2708
virtual bool MayConnectTo(a2dPin *connectto)
Is given pin allowed to connect to this pin.
Definition: canpin.cpp:997
virtual a2dBoundingBox DoGetUnTransformedBbox(a2dBboxFlags flags=a2dCANOBJ_BBOX_NON) const
In derived object this should be overriden to calculate the boundingbox of the object without its chi...
Definition: canobj.cpp:5031
virtual bool RemoveProperty(const a2dPropertyId *id, bool all=true)
This function is called by a2dPropertyId to remove a property from the list.
Definition: gen.cpp:1573
bool GetHasToolObjectsBelow() const
tool object itself or one of its recursive children
Definition: canobj.h:1767
virtual a2dCanvasObject * PushInto(a2dCanvasObject *parent)
when wanting to traverse hierarchy what level is down here.
Definition: canobj.cpp:2577
when set this type of property has no influence on rendering
Definition: id.h:204
void SetValue(int col, int row, double value)
set the value in the matrix at col,row
Definition: afmatrix.cpp:114
virtual bool WalkTask(wxObject *parent, wxObject *object, a2dWalkEvent event)
called from within a2dObject&#39;s and derived classes
Definition: gen.cpp:5265
double GetMinY() const
get minimum Y of the boundingbox
Definition: bbox.cpp:310
static a2dPropertyIdBoundingBox * PROPID_BoundingBox
used to store state ( redraw area) of the object as it was before a change
Definition: canobj.h:2684
float GetWidth() const
Definition: stylebase.cpp:6281
the a2dDrawingPart is a a2dView specially designed for displaying parts of a a2dDrawing. It uses a a2dDrawer2D to actually redraw things from the document, by giving that a2dDrawer2D as drawing context to the document, and telling the document to redraw a certain rectangular area. At that last is what this class is for. It optimizes the areas to be redrawn after object in the document were changed. To do that it combines redraw areas to a minimal set of redrawing areas. All the administration for this and the way things will be redrawn is from this view.
void SetPosXyPoint(const a2dPoint2D &pos)
set position to x,y
Definition: canobj.h:547
bool FilterObject(a2dCanvasObject *canvasObject)
apply object filter
Definition: canobj.cpp:809
void SetCaptured(a2dCanvasObject *captured)
set the object that is captured for events in the a2dDrawing.
Definition: drawer.h:638
void LeaveInObjects(a2dIterC &ic, a2dHitEvent &hitEvent)
Definition: canobj.cpp:2040
basetype GetPropertyValue(const a2dObject *obj) const
Get the property value in obj.
Definition: id.inl:325
bool GetSelected2() const
is the object selected2 flag set
Definition: canobj.h:1629
bool m_bin
general flag ( used for temporarely marking object )
Definition: candefs.h:271
a2dCanvasGlobal * a2dCanvasGlobals
global a2dCanvasGlobal to have easy access to global settings
Definition: canglob.cpp:1234
virtual bool NeedsUpdateWhenConnected() const
used in case of flexible canvas objects (wires).
Definition: canobj.h:1841
virtual void Save(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dObjectList *towrite)
write all needed to an XML type of file called the CVG format
Definition: gen.cpp:1343
static a2dPropertyIdBool * PROPID_ToolDecoration
set for objects that act as tool decorations, when a tool is in action.
Definition: canobj.h:2675
virtual a2dNamedProperty * FindProperty(const a2dPropertyId *id, a2dPropertyId::Flags flags=a2dPropertyId::flag_none)
Find a dynamic property with given id in the property list.
Definition: gen.cpp:1547
a2dCanvasObject for a Vector Path
Definition: vpath.h:55
virtual bool DoUpdate(UpdateMode mode, const a2dBoundingBox &childbox, const a2dBoundingBox &clipbox, const a2dBoundingBox &propbox)
Update derived Object specific things ( mainly boundingbox)
Definition: canobj.cpp:5098
virtual bool StartEditingObject(a2dCanvasObject *objectToEdit)
start editing object using existing corridor to object
Definition: tools.cpp:425
size_t GetNumberOfSegments()
get the number of points in the pointlist
Definition: polygon.h:229
static const a2dCanvasObjectFlagsMask SNAP
Definition: candefs.h:195
const a2dShadowStyleProperty * GetShadowStyle() const
quick way to get the style property containing Shadow property
Definition: canobj.cpp:2869
The a2dToolContr is the base class for Tool controller classes.
Definition: tools.h:87
bool m_non
no events
Definition: canobj.h:175
bool GetStopWalking()
check for stop
Definition: gen.h:3934
void SetRenderConnectedPins(bool onoff)
Calls a2dPin::SetRenderConnected() for all pins.
Definition: canobj.cpp:6394
set the a2dCanvasObject&#39;s a2dDrawing root recursive
Definition: algos.h:723
a2dDrawingPart * GetDrawingPart() const
get current a2dDrawingPart
Definition: canobj.cpp:631
virtual a2dCanvasObjectList * GetAsPolygons(bool transform=true) const
convert to a list of polygons.
Definition: canobj.cpp:1510
This template class is for property ids with a known data type.
Definition: id.h:477
property to hold a a2dBoundingBox type variable to be associated with a canvasobject ...
Definition: canprop.h:470
double GetScale()
See GetScale()
Definition: genxmlpars.h:545
virtual void EndFilter(a2dIterC &ic, a2dCanvasObject *canvasObject)
called from a2dCanvasObject to reset filtering feature when filtered object goes out of context...
Definition: canobj.cpp:338
a2dBoundingBox m_bbox
boundingbox in world coordinates
Definition: canobj.h:2539
Vector Path.
Definition: polyver.h:1211
Walker taking iterative context into account.
Definition: algos.h:1208
static a2dPropertyIdTagVec * PROPID_Tags
used in tool when grouping using tags
Definition: canobj.h:2721
hit if filling is not transparent
Definition: canobj.h:163
virtual a2dCanvasObjectList * GetAsPolylines(bool transform=true) const
convert to a list of polylines.
Definition: canobj.cpp:1545
void Reset()
Reset this object for beeing reused. It will keep the drawer but NULL object infos.
Definition: canobj.cpp:588
bool CheckCollect(const a2dPropertyId *id, Flags flags) const
check a property id and flags to see if the property shall be collected
Definition: id.h:284
wxRect GetAbsoluteArea(a2dIterC &ic, int inflate=2)
Get absolute occupied area in the device coordinates.
Definition: canobj.cpp:3199
virtual void RenderChildObjects(a2dIterC &ic, RenderChild &whichchilds, OVERLAP clipparent)
render only the child objects
Definition: canobj.cpp:5951
void SetRotation(double rotation)
set rotation
Definition: afmatrix.cpp:815
a2dCanvasObject * Find(const wxString &objectname, const wxString &classname=wxT(""), a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::ALL, const a2dPropertyId *propid=NULL, const wxString &valueAsString=wxT(""), wxUint32 id=0) const
return the object which fits the filter.
Definition: canobj.cpp:4505
a2dIterC()
constructor used when drawer is not known
Definition: canobj.cpp:495
int CollectObjects(a2dCanvasObjectList *total, const wxString &classname=wxT(""), a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::ALL, const a2dPropertyId *id=0, const a2dBoundingBox &bbox=wxNonValidBbox) const
Copy objects with the right conditions to the total list.
Definition: canobj.cpp:4495
void Insert(size_t before, a2dCanvasObject *obj, bool ignoreReleased=true)
insert a a2dCanvasObject to the childobjects
Definition: canobj.cpp:6246
double GetAbsX() const
get absolute X position of the pin ( after applying the parent&#39;s matrix and its own matrix ) ...
Definition: canpin.cpp:959
static const a2dCanvasObjectFlagsMask SHOWSHADOW
Definition: candefs.h:188
If a property with this id has changed its parent/holder will be notified.
Definition: id.h:213
a2dCanvasObjectFlagsMask GetHitFlags() const
return hitflags as mask
Definition: canobj.cpp:2681
bool IsFillHit() const
true if this is a fill hit (parent or child/member fill)
Definition: polyver.h:111
bool GetIsProperty() const
Definition: canobj.h:2156
void Append(a2dCanvasObject *obj)
append a a2dCanvasObject to the childobjects
Definition: canobj.cpp:6224
a2dStrokeStyle
stroke styles for a2dStroke
Definition: stylebase.h:298
void SetName(const wxString &name)
set the name of the pin (must be unique)
Definition: canpin.h:325
static const a2dCanvasObjectFlagsMask EDITABLE
Definition: candefs.h:200
a2dCanvasObject * GetParent() const
get parent object of the pin
Definition: canpin.h:295
const a2dAffineMatrix & GetTransform() const
Get the accumulated transform up to and including m_lworld of the current object. ...
Definition: canobj.cpp:663
a2dPropertyIdTyped< wxWindow *, a2dWindowProperty > a2dPropertyIdWindow
property of this type
Definition: id.h:675
void PopCursor()
pop a cursor from the cursor stack, and set display cursor to back
Definition: drawer.cpp:1059
static a2dPropertyIdUint16 * PROPID_Datatype
used in GDSII and KEY format to specify the DATATYPE of elements
Definition: canobj.h:2700
virtual void SetLayer(wxUint16 layer)
set layer index where this object is drawn upon.
Definition: canobj.cpp:5920
property to hold a a2dFill type variable to be associated with a a2dObject
Definition: styleprop.h:44
a2dCanvasObject * IsHitWorldChildObjects(a2dIterC &ic, RenderChild &whichchilds, a2dHitEvent &hitEvent)
This is an internal function used by IsHitWorld(). Don&#39;t use it directly.
Definition: canobj.cpp:3718
virtual bool IsConnect() const
return true, if this object is used to connect other object&#39;s using rubberband like structures...
Definition: canobj.h:1831
const a2dAffineMatrix & GetMappingTransform() const
get the mapping matrix
Definition: canobj.cpp:621
wxEvent * m_event
event to process in case of event processing call
Definition: canobj.h:309
const a2dAffineMatrix & GetMappingMatrix()
get the world-to-device (aka mapping) matrix
Definition: drawer2d.h:478
list of a2dObject&#39;s
Definition: gen.h:3157
double m_rely
(world coordinates) hit point y relative to the canvas object its parent object(s) ...
Definition: canobj.h:291
void SetRestrictPoint(double xSnap, double ySnap)
sets the point for snapping to
Definition: restrict.h:337
double m_y
(world coordinates) hit point y as in a2dDrawingPart or any other top level
Definition: canobj.h:295
OVERLAP GetParentClipStatus() const
what is the clipping withing the current view for the second last added object in context ...
Definition: canobj.cpp:679
CloneOptions
options for cloning
Definition: gen.h:1200
double DeviceToWorldXRel(double x) const
convert x relative from device to world coordinates
Definition: drawer2d.h:444
void SetHitFlags(a2dCanvasObjectHitFlags mask)
set hit flags
Definition: canobj.cpp:2670
bool m_ignoreSetpending
ignore this object in a2dCanvasObject::SetPending()
Definition: candefs.h:307
const a2dAffineMatrix & GetUserToDeviceTransform() const
get matrix which transforms directly from user coordinates to device
Definition: drawer2d.h:503
bool GetDraggable() const
get if the object can be dragged
Definition: canobj.h:1676
static a2dPropertyIdRefObject * PROPID_ViewDependent
used for objects that depend on &#39;aView&#39; view when it comes to size.
Definition: canobj.h:2703
void SetCorridorPath(bool OnOff, a2dCanvasObject *captureObject=NULL)
to set corridor path ( also to captured object), its a2dCanvasOFlags::IsOnCorridorPath flag is set on...
Definition: canobj.cpp:739
void WalkerWithContext(a2dIterC &ic, wxObject *parent, a2dWalkerIOHandlerWithContext &handler)
This is used to recursively walk through an object tree.
Definition: canobj.cpp:5446
void SetPreRenderAsChild(bool prerender)
If set, this object has a higher priority in rendering than other children objects.
Definition: canobj.h:1469
virtual bool IsRecursive()
returns if this object does have nested objects
Definition: canobj.cpp:5435
a2dBoundingBox & GetBbox()
get boundingbox in world coordinates exclusive stroke width relative to its parent ...
Definition: canobj.cpp:3175
structure to give as parameter to member functions of a2dCanvasObject
Definition: canobj.h:252
Contain one drawing as hierarchical tree of a2dCanvasObject&#39;s.
Definition: drawing.h:434
bool m_pushin
is push into allowed
Definition: candefs.h:286
virtual bool RestrictPoint(double &x, double &y, wxUint32 sourceRequired=snapToAll, bool ignoreEngine=false)
Restrict a single point of a line or polyline.
Definition: restrict.cpp:227
static bool m_ignoreAllSetpending
when set all SetPending() calss are supressed.
Definition: canobj.h:2601
void SetFill(const a2dFill &fill)
Set a fill for the object which will be used instead of the layer fill.
Definition: canobj.cpp:2874
virtual void PushIdentityTransform()
push no transform, to draw directly in device coordinates
Definition: drawer2d.cpp:469
a2dPropertyIdTyped< double, a2dDoubleProperty > a2dPropertyIdDouble
property of this type
Definition: id.h:657
snap to pins in other objects
Definition: restrict.h:111
virtual void DoWalker(wxObject *parent, a2dWalkerIOHandler &handler)
iterate over this object and its children
Definition: canobj.cpp:5504
bool m_filled
use fill to fill if set
Definition: candefs.h:259
const a2dFill * a2dTRANSPARENT_FILL
global a2dFill stock object for TRANSPARENT filling
static const a2dCanvasObjectFlagsMask PRERENDERASCHILD
Definition: candefs.h:198
general canvas module declarations and classes
wxEditStyle
Definition: canobj.h:109
int IndexOf(T *object) const
Find the index of a specific object.
Definition: smrtptr.inl:103
bool m_fixedStyle
if set fixed style (stroke and fill )is assumed. Can be used in tools to detect if style should be ch...
Definition: candefs.h:298
a2dPropertyIdTyped< void *, a2dVoidPtrProperty > a2dPropertyIdVoidPtr
property of this type
Definition: id.h:661
a base command for the a2dCommandProcessor
Definition: comevt.h:140
void GetClippingBox(double &x, double &y, double &w, double &h) const
what is the current clipping region in world coordinates
Definition: drawer2d.cpp:3006
bool m_showshadow
show shadow object if true and shadow property is available
Definition: candefs.h:256
canobj.cpp Source File -- Sun Oct 12 2014 17:04:14 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation