wxArt2D
connectgen.cpp
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/canvas/canobj.h"
22 #include "wx/canvas/tools.h"
23 #include "wx/canvas/sttool.h"
24 #include "wx/canvas/drawing.h"
25 #include "wx/canvas/drawer.h"
26 #include "wx/canvas/connectgen.h"
27 #include "wx/canvas/wire.h"
28 #include "wx/canvas/canglob.h"
29 #include "wx/canvas/algos.h"
30 #include <float.h>
31 
32 #include <algorithm>
33 
34 #if defined(__WXMSW__) && defined(__MEMDEBUG__)
35 #include <wx/msw/msvcrt.h>
36 #endif
37 
38 //----------------------------------------------------------------------------
39 // a2dConnectionGenerator
40 //----------------------------------------------------------------------------
41 
43 {
45 
46  m_anypinclass = NULL;
47  m_returnPinClass = NULL;
48  m_returnConnect = NULL;
49  a2dWirePolylineL* wirestandard = new a2dWirePolylineL();
50  wirestandard->SetStroke( a2dStroke( wxColour( 170, 0, 170 ), 2, a2dSTROKE_SOLID ) );
51  wirestandard->SetStartPinClass( a2dPinClass::Standard );
52  wirestandard->SetEndPinClass( a2dPinClass::Standard );
53  m_tmplObject = wirestandard;
54  m_wiresEditCopies = new a2dCanvasObjectList();
55  m_wires = new a2dCanvasObjectList();
56  m_routeWhenDrag = true;
57  //m_routeWhenDrag = false;
58  m_routeMethod = StraightEndSegment;//StraightSegment;//GridRouting;
59  m_routeMethod = GridRouting;
60  m_allowredirect = true;
61  m_generatePins = true;
62  m_routedata = NULL;
63  m_offset = 100;
64 
65  m_noEditCopy = false;
66 }
67 
69 {
70  delete m_wiresEditCopies;
71  delete m_wires;
72 }
73 
75 {
76  if ( m_routeMethod == StraightEndSegment )
77  m_routeMethod = StraightEndSegmentUnlessPins;
78  else if ( m_routeMethod == StraightEndSegmentUnlessPins )
79  m_routeMethod = StraightSegment;
80  else if ( m_routeMethod == StraightSegment )
81  m_routeMethod = StraightSegmentUnlessPins;
82  else if ( m_routeMethod == StraightSegmentUnlessPins )
83  m_routeMethod = ManhattanSegments;
84  else if ( m_routeMethod == ManhattanSegments )
85  m_routeMethod = ManhattanEndSegments;
86  else if ( m_routeMethod == ManhattanEndSegments )
87  m_routeMethod = ManhattanEndSegmentsStay;
88  else if ( m_routeMethod == ManhattanEndSegmentsStay )
89  m_routeMethod = ManhattanEndSegmentsConvertAndStay;
90  else if ( m_routeMethod == ManhattanEndSegmentsConvertAndStay )
91  m_routeMethod = GridRouting;
92  else
93  m_routeMethod = StraightEndSegment;
94 }
95 
96 wxString a2dConnectionGenerator::GetRouteMethodAsString()
97 {
98  if ( m_routeMethod == StraightEndSegment )
99  return "StraightEndSegment";
100  else if ( m_routeMethod == StraightEndSegmentUnlessPins )
101  return "StraightEndSegmentUnlessPins";
102  else if ( m_routeMethod == StraightSegment )
103  return "StraightSegment";
104  else if ( m_routeMethod == StraightSegmentUnlessPins )
105  return "StraightSegmentUnlessPins";
106  else if ( m_routeMethod == ManhattanSegments )
107  return "ManhattanSegments";
108  else if ( m_routeMethod == ManhattanEndSegments )
109  return "ManhattanEndSegments";
110  else if ( m_routeMethod == ManhattanEndSegmentsStay )
111  return "ManhattanEndSegmentsStay";
112  else if ( m_routeMethod == ManhattanEndSegmentsConvertAndStay )
113  return "ManhattanEndSegmentsConvertAndStay";
114  else
115  return "GridRouting";
116 }
117 
118 void a2dConnectionGenerator::PrepareForRewire( a2dCanvasObject* parent, a2dCanvasObjectList& dragList, bool walkWires, bool selected, bool stopAtSelectedWire, bool CreateExtraWires, a2dBaseTool* tool, a2dRefMap* refs )
119 {
120  bool onlyNonSelected = true;
121 
122  m_parent = parent;
123 
124  //drag is comming so first create wires where there are non.
125  if ( CreateExtraWires )
126  CreateWiresOnPins( m_parent, dragList, true, onlyNonSelected );
127 
128  //find all wires going to this object.
130  setflags.SetSkipNotRenderedInDrawing( true );
131  setflags.Start( m_parent, false );
132  // find all wires which do go to the objects, and are to be rerouted.
133  a2dCanvasObjectList connectedwires;
134 
135  a2dCanvasObjectList::iterator iter;
136  for( iter = dragList.begin(); iter != dragList.end(); ++iter )
137  {
138  a2dCanvasObject* original = *iter;
139  original->SetBin( true );
140  original->FindConnectedWires( connectedwires, NULL, walkWires, selected, stopAtSelectedWire );
141  }
142 
143  iter = connectedwires.begin();
144  while( iter != connectedwires.end() )
145  {
146  a2dCanvasObjectList::value_type wire = *iter;
147  if ( std::find( dragList.begin(), dragList.end(), wire ) != dragList.end() )
148  iter = connectedwires.erase( iter );
149  else
150  {
151  wire->SetBin( false );
152  wire->EliminateMatrix();
153  iter++;
154  }
155  }
156  // All non selected wires found connected to m_objects found!
157  AddRerouteWires( &connectedwires, m_parent );
158  OptimizeRerouteWires();
159  PrepareForRerouteWires( tool, refs );
160  setflags.Start( m_parent, false );
161 }
162 
163 void a2dConnectionGenerator::CreateWiresOnPins( a2dCanvasObject* parent, const a2dCanvasObjectList& objectsToDrag, bool undo, bool onlyNonSelected )
164 {
166 
167  for( a2dCanvasObjectList::const_iterator iterdrags = objectsToDrag.begin(); iterdrags != objectsToDrag.end(); ++iterdrags )
168  {
169  a2dCanvasObjectPtr original = *iterdrags;
170 
171  if ( !original->GetChildObjectsCount() )
172  continue;
173 
174  if ( original->HasPins() )
175  {
176  bool done = false;
178  {
179  a2dCanvasObject* obj = *iter;
180  a2dPin* pinc = wxDynamicCast( obj, a2dPin );
181  if ( pinc && !pinc->GetRelease() )
182  {
183  a2dPinList::const_iterator iterconp;
184  for ( iterconp = pinc->GetConnectedPins().begin( ) ; iterconp != pinc->GetConnectedPins().end( ) ; iterconp++ )
185  {
186  a2dPin* other = *iterconp;
187  if ( !other || other->GetRelease() )
188  continue;
189 
190  //if already connected at this pin create a connect if needed.
191  if ( !onlyNonSelected || onlyNonSelected && !other->GetParent()->IsSelected() )
192  {
193  a2dConnectionGenerator* pinConnectGen = pinc->GetPinClass()->GetConnectionGenerator();
194  wxASSERT_MSG( pinConnectGen == other->GetPinClass()->GetConnectionGenerator(), wxT( "incompatible connection generator on connected pins" ) );
195  if ( !pinConnectGen )
196  pinConnectGen = this;
197 
198  a2dCanvasObject* otherobj = other->GetParent();
199  if ( otherobj->IsConnect() )
200  {
201  switch ( m_routeMethod )
202  {
203  case GridRouting:
204  {
205  a2dWirePolylineL* wire = wxStaticCast( otherobj, a2dWirePolylineL );
206  // if connected object is already a wire, it can be reused in general.
207  // If the end or begin pin is connected to the object to drag, we can reuse.
208  // But if both end and begin are connected to the drag objects, we prefer an extra wire also.
209  if (
210  ( wire->FindBeginPin() != other && wire->FindEndPin() != other ) ||
211  ( wire->FindBeginPin()->IsConnectedTo( pinc ) && wire->FindEndPin()->IsConnectedTo( pinc ) )
212  )
213  {
214  if ( undo )
215  cmdh->Submit( new a2dCommand_DisConnectPins( pinc, other ), true );
216  else
217  pinc->Disconnect( other );
218  a2dCanvasObject* newwire = pinConnectGen->CreateConnectObject( parent, pinc, other, undo );
219  newwire->SetStroke( wire->GetStroke() );
220  }
221  }
222  break;
223  case StraightSegment:
224  case StraightEndSegment:
227  {
228  a2dWirePolylineL* wire = wxStaticCast( otherobj, a2dWirePolylineL );
229  // if connected object is already a wire, it can be reused in general.
230  // If the end or begin pin is connected to the object to drag, we can reuse.
231  // But if both end and begin are connected to the drag objects, we prefer an extra wire also.
232  if (
233  ( wire->FindBeginPin() != other && wire->FindEndPin() != other ) ||
234  ( wire->FindBeginPin()->IsConnectedTo( pinc ) && wire->FindEndPin()->IsConnectedTo( pinc ) )
235  )
236  {
237  if ( undo )
238  cmdh->Submit( new a2dCommand_DisConnectPins( pinc, other ), true );
239  else
240  pinc->Disconnect( other );
241  a2dCanvasObject* newwire = pinConnectGen->CreateConnectObject( parent, pinc, other, undo );
242  newwire->SetStroke( wire->GetStroke() );
243  }
244  else if ( wire->GetPinCount() > 2 &&
245  ( m_routeMethod == StraightEndSegmentUnlessPins || m_routeMethod == StraightSegmentUnlessPins )
246  )
247  {
248  a2dVertexList* newpoints = wire->GetSegments();
249  //its the begin or end pin
250  // The other pins are somewhere on the wire.
251  // For a two point wire, just add a segment.
252  if ( wire->GetNumberOfSegments() <= 2 )
253  {
254  if( other->GetName() == wxT( "begin" ) )
255  {
256  newpoints->push_front( new a2dLineSegment( other->GetAbsXY() ) );
257  }
258  else if( other->GetName() == wxT( "end" ) )
259  {
260  newpoints->push_back( new a2dLineSegment( other->GetAbsXY() ) );
261  }
262  if ( cmdh && undo )
263  {
264  wire->GetRoot()->GetCommandProcessor()->Submit( new a2dCommand_SetSegments( wire, newpoints, true ), true );
265  }
266  else
267  wire->SetSegments( newpoints );
268  }
269  // For a more than 2 segment wire, check if pin is on the segment to be rerouted.
270  else
271  {
272  for( a2dCanvasObjectList::iterator iterpins = wire->GetChildObjectList()->begin(); iterpins != wire->GetChildObjectList()->end(); ++iterpins )
273  {
274  a2dPin* pin = wxDynamicCast( iterpins->Get(), a2dPin );
275  if( !pin ) continue;
276  if( !pin->IsConnectedTo( pinc ) ) continue;
277  if( pin->GetName() != wxT( "begin" ) && pin->GetName() != wxT( "end" ) )
278  {
279  int index = wire->FindPinSegmentIndex( pin );
280  if ( index == 0 && other->GetName() == wxT( "begin" ) )
281  newpoints->push_front( new a2dLineSegment( other->GetAbsXY() ) );
282  else if ( index == wire->GetNumberOfSegments()-2 && other->GetName() == wxT( "end" ) )
283  newpoints->push_back( new a2dLineSegment( other->GetAbsXY() ) );
284  if ( cmdh && undo )
285  {
286  wire->GetRoot()->GetCommandProcessor()->Submit( new a2dCommand_SetSegments( wire, newpoints, true ), true );
287  }
288  else
289  wire->SetSegments( newpoints );
290  }
291  }
292  }
293  }
294  }
295  break;
296  default:
297  break;
298  }
299  }
300  else
301  { // a connection on a pin straight to a second object which is not a wire.
302  if ( undo )
303  cmdh->Submit( new a2dCommand_DisConnectPins( pinc, other ), true );
304  else
305  pinc->Disconnect( other );
306 
307  //sometimes an object gets connected to itself, which is at least disconnected above, no need for wire.
308  if ( pinc != other )
309  {
311  if ( original->IsConnect() )
312  {
313  a2dWirePolylineL* wire = wxDynamicCast( original.Get(), a2dWirePolylineL );
314  a2dStroke preserve = wire->GetStroke();
315  a2dCanvasObject* newwire = pinConnectGen->CreateConnectObject( parent, pinc, other, undo );
316  newwire->SetStroke( wire->GetStroke() );
317  }
318  else
319  pinConnectGen->CreateConnectObject( parent, pinc, other, undo );
320  }
321  }
322  }
323  }
324  }
325  }
326  }
327  }
328 }
329 
330 void a2dConnectionGenerator::OptimizeRerouteWires( bool removeZero )
331 {
332  wxASSERT_MSG( m_parent, wxT( "parent object must be set" ) );
333 
335 
336  //first remove all unconnected pins (not begin or end), since that looks better.
337  a2dCanvasObjectList::iterator iter;
338  for( iter = m_wires->begin(); iter != m_wires->end(); ++iter )
339  {
340  a2dCanvasObject* connect = *iter;
341 
342  if ( !connect->GetRelease() && connect->IsConnect() )
343  {
344  a2dWirePolylineL* wire = wxStaticCast( connect, a2dWirePolylineL );
345  a2dPin* begin = wire->FindBeginPin();
346  a2dPin* end = wire->FindEndPin();
347  for( a2dCanvasObjectList::iterator iterpins = wire->GetChildObjectList()->begin(); iterpins != wire->GetChildObjectList()->end(); ++iterpins )
348  {
349  a2dPin* pin = wxDynamicCast( iterpins->Get(), a2dPin );
350  if( !pin || pin->GetRelease( ) )
351  continue;
352 
353  if ( begin != pin && end != pin )
354  {
355  if( !pin->IsConnectedTo() )
356  {
357  // cleanup unconnected pins when not at ends
358  cmdh->Submit( new a2dCommand_ReleaseObject( wire, pin ) );
359  }
360  continue;
361  }
362  }
363  }
364  }
365 
366  if ( removeZero )
367  {
368  for( iter = m_wires->begin(); iter != m_wires->end(); ++iter )
369  {
370  a2dCanvasObject* connect = *iter;
371 
372  if ( !connect->GetRelease() && connect->IsConnect() )
373  {
374  a2dWirePolylineL* wire = wxStaticCast( connect, a2dWirePolylineL );
375  if ( wire->GetSegments()->Length() < a2dACCUR )
376  {
377  a2dPin* begin = wire->FindBeginPin();
378  a2dPin* end = wire->FindEndPin();
379  if ( begin->GetConnectedPinsNr() == 1 && end->GetConnectedPinsNr() == 1 )
380  // merge pins into one, and remove this wire.
381  cmdh->Submit( new a2dCommand_RemoveZeroWire( m_parent, wire ) );
382  }
383  }
384  }
385  }
386 
387  for( iter = m_wires->begin(); iter != m_wires->end(); ++iter )
388  {
389  a2dCanvasObject* connect = *iter;
390 
391  if ( !connect->GetRelease() && connect->IsConnect() )
392  {
393  a2dWirePolylineL* wire = wxStaticCast( connect, a2dWirePolylineL );
394  if ( wire->GetSegments()->Length() < a2dACCUR )
395  continue;
396 
397  wire->OptimizeRerouteWires( m_parent, true, m_allowredirect );
398  }
399  }
400 
401  iter = m_wires->begin();
402  while( iter != m_wires->end() )
403  {
404  a2dWirePolylineL* wire = wxStaticCast( iter->Get(), a2dWirePolylineL );
405  if ( !wire->GetRelease() )
406  {
407  wire->EliminateMatrix();
408  iter++;
409  }
410  else
411  iter = m_wires->erase( iter );
412  }
413 
414 
415  // cleanup all that happened above
416  iter = m_wires->begin();
417  while( iter != m_wires->end() )
418  {
419  a2dWirePolylineL* wire = wxStaticCast( iter->Get(), a2dWirePolylineL );
420  if ( !wire->GetRelease() )
421  {
422 /*
423  a2dPin* begin = wire->FindBeginPin();
424  a2dPin* end = wire->FindEndPin();
425  a2dCanvasObjectList::iterator iterconpins = wire->GetChildObjectList()->begin();
426  while( iterconpins != wire->GetChildObjectList()->end() )
427  {
428  a2dPin* pinc = wxDynamicCast( iterconpins->Get(), a2dPin );
429  if( !pinc || pinc->GetRelease() )
430  {
431  // update redraw?? iterconpins = wire->GetChildObjectList()->erase( iterconpins );
432  iterconpins++;
433  }
434  else if( !pinc->IsConnectedTo() )
435  {
436  if ( begin != pinc && end != pinc )
437  // cleanup unconnected pins when not at ends
438  pinc->SetRelease( false );
439  iterconpins++;
440  }
441  else
442  iterconpins++;
443  }
444 */
445  wire->EliminateMatrix();
446  iter++;
447  }
448  }
449 }
450 
451 void a2dConnectionGenerator::AddRerouteWires( a2dCanvasObjectList* wires, a2dCanvasObject* parentOfWires )
452 {
453  m_parent = parentOfWires;
454  m_wires->TakeOverFrom( wires );
455 }
456 
457 void a2dConnectionGenerator::AddRerouteWire( a2dCanvasObject* wire, a2dCanvasObject* parentOfWires )
458 {
459  m_parent = parentOfWires;
460  if ( wire->IsConnect() )
461  m_wires->push_back( wire );
462 }
463 
464 bool PrioritySorter ( const a2dCanvasObjectPtr& a, const a2dCanvasObjectPtr& b )
465 {
468 
469  int pa = aw? aw->GetPriority() : 0;
470  int pb = bw? bw->GetPriority() : 0;
471  return pa < pb;
472 }
473 
474 
475 //remove references on pin which do not point to the pin notThis.
476 void RemoveRefsNotThis( a2dRefMap* refs, a2dPin* pin, a2dPin* notThis )
477 {
478  a2dPinList::const_iterator iterconp;
479  for ( iterconp = pin->GetConnectedPins().begin( ) ; iterconp != pin->GetConnectedPins().end( ) ; iterconp++ )
480  {
481  a2dPin* connectedPin = *iterconp;
482  if( !connectedPin )
483  continue;
484  if ( connectedPin != notThis )
485  {
486  int id = connectedPin->GetUniqueSerializationId();
487  wxASSERT( id != 0 );
488  wxString resolveKey;
489  resolveKey << id;
490  refs->RemoveReference( resolveKey );
491  }
492  }
493 }
494 
496 {
497  wxASSERT_MSG( m_parent, wxT( "parent object must be set" ) );
498 
499  if ( m_noEditCopy )
500  {
501  for( a2dCanvasObjectList::iterator iter = m_wires->begin(); iter != m_wires->end(); ++iter )
502  {
503  a2dCanvasObject* connect = *iter;
504  if ( connect->IsConnect() )
505  {
506  a2dCanvasObject *wirecopy = connect;
507  m_wiresEditCopies->push_back( wirecopy );
508  for( a2dCanvasObjectList::iterator iterpins = connect->GetChildObjectList()->begin(); iterpins != connect->GetChildObjectList()->end(); ++iterpins )
509  {
510  a2dPin* pin = wxDynamicCast( iterpins->Get(), a2dPin );
511  if( !pin || pin->GetRelease( ) )
512  continue;
513  }
514 
515  }
516  }
517  }
518  else
519  {
520  for( a2dCanvasObjectList::iterator iter = m_wires->begin(); iter != m_wires->end(); ++iter )
521  {
522  a2dCanvasObject* connect = *iter;
523 
524  if ( connect->IsConnect() )
525  {
526  a2dCanvasObject *wirecopy = connect->TClone( clone_childs | clone_seteditcopy | clone_setoriginal, refs );
527  m_wiresEditCopies->push_back( wirecopy );
528  // this makes the wire visible as editcopy like objects
530  // and this makes sure those editcopy wire are not treated as editable.
531  // The main edit copy object to which those wires are connected is of course editable.
532  wirecopy->SetEditable( false );
533 
534  for( a2dCanvasObjectList::iterator iterpins = connect->GetChildObjectList()->begin(); iterpins != connect->GetChildObjectList()->end(); ++iterpins )
535  {
536  a2dPin* pin = wxDynamicCast( iterpins->Get(), a2dPin );
537  if( !pin || pin->GetRelease( ) )
538  continue;
539 
540  a2dPinList::const_iterator iterconp;
541  for ( iterconp = pin->GetConnectedPins().begin( ) ; iterconp != pin->GetConnectedPins().end( ) ; iterconp++ )
542  {
543  a2dPin* otherpin = *iterconp;
544  if( !otherpin )
545  continue;
546 
547  a2dCanvasObject* connectedobj = otherpin->GetParent();
548  if ( !connectedobj->IsConnect() && !connectedobj->GetBin() ) //objects dragged have bin set.
549  {
550  if ( 1 )
551  {
552  //all object that are not connects and are at the end of (in)directly connected wires
553  // to the first object, are terminated with a special object in order to recognize
554  // the type of connected objects/pins when rerouting.
555  a2dCanvasObject* endWire = new a2dWireEnd( pin->GetPosX(), pin->GetPosY() );
556  a2dPin* endpin = wxStaticCast( otherpin->TClone( clone_setoriginal, refs ) , a2dPin );
557  endpin->SetInternal( true ); //prevents adding it as occupied in Rerouting.
558  endpin->SetPosXY( 0, 0 );
559  endWire->Append( endpin );
560  // above also pins in otherpin which are not connected to pin where added as not resolved.
561  // We remove them here, since the are not part of the wires to reroute, and can not be resolved within that cloned group.
562  RemoveRefsNotThis( refs, otherpin, pin );
563  a2dCanvasObject::PROPID_Original->SetPropertyToObject( endWire, connectedobj );
564  //NOT the following because of filtering in routing initializing, also not needed here.
565  //PROPID_Editcopy->SetPropertyToObject( connectobj, endWire );
567  m_wiresEditCopies->push_back( endWire );
568  }
569  }
570  }
571  }
572  }
573  }
574  }
575 
576  if ( !m_noEditCopy && m_routeWhenDrag && tool )
577  {
578  for( a2dCanvasObjectList::iterator iter = m_wiresEditCopies->begin(); iter != m_wiresEditCopies->end(); ++iter )
579  {
580  tool->AddEditobject( ( *iter ) );
581  ( *iter )->SetVisible( true );
582  }
583  }
584  else
585  {
586  m_wires->SetSpecificFlags( true, a2dCanvasOFlags::VISIBLE );
587  }
588 
589  switch ( m_routeMethod )
590  {
591  case GridRouting:
592  {
593  PrepareGridRoute();
594  }
595  }
596 
597 /*
598  switch ( m_routeMethod )
599  {
600  case GridRouting:
601  {
602  }
603  break;
604  case StraightEndSegmentUnlessPins:
605  case StraightSegmentUnlessPins:
606  case StraightEndSegment:
607  {
608  for( a2dCanvasObjectList::iterator iter = m_wiresEditCopies->begin(); iter != m_wiresEditCopies->end(); ++iter )
609  {
610  if ( (*iter)->IsConnect() )
611  {
612  a2dWirePolylineL* wire = wxStaticCast( (*iter).Get(), a2dWirePolylineL );
613  for( a2dCanvasObjectList::iterator iterpins = wire->GetChildObjectList()->begin(); iterpins != wire->GetChildObjectList()->end(); ++iterpins )
614  {
615  a2dPin* pin = wxDynamicCast( iterpins->Get(), a2dPin );
616  if( !pin ) continue;
617  if( !pin->ConnectedTo() ) continue;
618  a2dPin* otherPin = pin->ConnectedTo();
619 
620  a2dVertexList* newpoints = wire->GetSegments();
621  if ( (wire->FindBeginPin() != otherPin && wire->FindEndPin() != otherPin )
622  || ( wire->GetPinCount() > 2 && wire->GetNumberOfSegments() <= 2 )
623  )
624  {
625  if( pin->GetName() == wxT( "begin" ) )
626  {
627  newpoints->push_front( new a2dLineSegment( pin->ConnectedTo()->GetAbsXY() ) );
628  }
629  else if( pin->GetName() == wxT( "end" ) )
630  {
631  newpoints->push_back( new a2dLineSegment( pin->ConnectedTo()->GetAbsXY() ) );
632  }
633  else
634  {
635  }
636  }
637  wire->SetSegments( newpoints );
638 
639  }
640  }
641  }
642  }
643  break;
644  default:
645  break;
646  }
647 */
648 }
649 
650 void a2dConnectionGenerator::ResetPositionsToOrignals()
651 {
652  wxASSERT_MSG( m_parent, wxT( "parent object must be set" ) );
653 
654  for( a2dCanvasObjectList::iterator iter = m_wiresEditCopies->begin(); iter != m_wiresEditCopies->end(); ++iter )
655  {
656  if ( !(*iter)->IsConnect() )
657  continue;
658  a2dWirePolylineL* wire = wxStaticCast( (*iter).Get(), a2dWirePolylineL );
659  if ( wire )
660  {
661  a2dWirePolylineL* target = wire;
662 
663  // Check if there is an original property, that indicates we do want it,
664  // because only editcopies have this property.
665  a2dWirePolylineL* original = wxStaticCastNull( a2dCanvasObject::PROPID_Original->GetPropertyValue( wire ), a2dWirePolylineL );
666  // Only do this for editcopy wires
667  if( !original )
668  continue;
669 
670  // Reassign the original location to the point list of the editcopy
671  {
672  a2dVertexList* newpoints = new a2dVertexList;
673  *newpoints = *original->GetSegments();
674  target->SetSegments( newpoints );
675  }
676 
677  // Reassign the pin positions
678  for( a2dCanvasObjectList::iterator iterpins = target->GetChildObjectList()->begin(); iterpins != target->GetChildObjectList()->end(); ++iterpins )
679  {
680  a2dCanvasObject* obj = *iterpins;
681  a2dPin* pin = wxDynamicCast( obj, a2dPin );
682  if( !pin ) continue;
683 
684  //every pin also has the PROPID_Original property set, to get to the equivalent pin in the original.
685  a2dPin* pinori = wxStaticCast( a2dCanvasObject::PROPID_Original->GetPropertyValue( pin ).Get(), a2dPin );
686 
687  pin->SetTransformMatrix( pinori->GetTransformMatrix() );
688  }
689 
690  // One Adjust at the beginning also shouldn't hurt
691  // In draging modes this shouldn't do anything, because the wires don't change
692  // So this will only have an effect for wire editing tools
693  target->AdjustAfterChange( false );
694  }
695  }
696 }
697 
698 void a2dConnectionGenerator::PrepareGridRoute()
699 {
700  wxASSERT_MSG( m_parent, wxT( "parent object must be set" ) );
701 
702  s_a2dCanvasObjectSorter = &PrioritySorter;
703  m_wiresEditCopies->sort();
704 
705  // In phase 1, the routing order of wires is determined
706  // First all wires that connect objects with objects are routed
707  // A wire that is connected to another wire at end or begin, is routed after that wire.
708  // The idea is that wires further away from object get routed latest.
709  bool again = true;
710  while ( again )
711  {
712  again = false;
713  for( a2dCanvasObjectList::iterator iter = m_wiresEditCopies->begin(); iter != m_wiresEditCopies->end(); ++iter )
714  {
715  if ( !(*iter)->IsConnect() )
716  continue;
717  a2dWirePolylineL* wire = wxStaticCast( (*iter).Get(), a2dWirePolylineL );
718  if ( wire )
719  {
720  a2dWirePolylineL* target = wire;
721 
722 /* They are only edit copies anyway.
723  // Check if there is an original property, that indicates we do want it,
724  // because only editcopies have this property.
725  a2dWirePolylineL* original = wxStaticCastNull( a2dCanvasObject::PROPID_Original->GetPropertyValue( wire ), a2dWirePolylineL );
726  // Only do this for editcopy wires
727  if( !original )
728  continue;
729 */
730  int oldpriority = target->GetPriority();
731  int priority = 0;
732 
733  // Go through all pins and adjust priority to connected wires
734  for( a2dCanvasObjectList::iterator iterpins = target->GetChildObjectList()->begin(); iterpins != target->GetChildObjectList()->end(); ++iterpins )
735  {
736  a2dCanvasObject* obj = *iterpins;
737  a2dPin* pin = wxDynamicCast( obj, a2dPin );
738  if( !pin || pin->GetRelease() ) continue;
739 
740  // Only begin or end pins
741  if( pin->GetName() != wxT( "begin" ) && pin->GetName() != wxT( "end" ) )
742  continue;
743 
744  a2dPinList::const_iterator iterconp;
745  for ( iterconp = pin->GetConnectedPins().begin( ) ; iterconp != pin->GetConnectedPins().end( ) ; iterconp++ )
746  {
747  a2dPin* otherpin = *iterconp;
748  if( !otherpin )
749  continue;
750 
751  // Only pins connected to a wire can delay routing
752  if( !otherpin->GetParent()->IsConnect() )
753  continue;
754 
755  if( otherpin->GetName() == wxT( "begin" ) || otherpin->GetName() == wxT( "end" ) )
756  continue;
757 
758  a2dWirePolylineL* wireconnected = wxDynamicCast( otherpin->GetParent(), a2dWirePolylineL );
759  int minpriority = 1 + (wireconnected? wireconnected->GetPriority() : 0);
760  if( minpriority > priority && minpriority < 255 ) //limit at some value else sometimes infinite loop
761  priority = minpriority;
762  }
763  }
764 
765  target->SetPriority( priority );
766  target->SetReroute( true );
767 
768  if( oldpriority != priority )
769  // redo this, because the priority of other wires could depend on us
770  again = true;
771  }
772  }
773  }
774  s_a2dCanvasObjectSorter = &PrioritySorter;
775  m_wiresEditCopies->sort();
776 
777  //if ( !a2dCanvasGlobals->GetHabitat()->GetRouteOneLine() )
778  if ( !m_wiresEditCopies->empty() )
779  {
780  m_routedata = NULL;
781  m_routedata = new a2dRouteData( m_parent, false );
782  }
783 }
784 
785 void a2dConnectionGenerator::RerouteWire( a2dWirePolylineL* wire, bool& again )
786 {
787  bool oneLine = a2dCanvasGlobals->GetHabitat()->GetRouteOneLine();
788 
789  // In phase 3, the wires will be rerouted
790  // Check if any pin got dislocated
791  // Note: target is zero for dynamically created wires
792  if ( wire->GetReroute() )
793  {
794  wire->SetPriority( 0 );
795  wire->SetReroute( false );
796 
797  for( a2dCanvasObjectList::iterator iter = wire->GetChildObjectList()->begin(); iter != wire->GetChildObjectList()->end(); ++iter )
798  {
799  a2dCanvasObject* obj = *iter;
800  a2dPin* pin = wxDynamicCast( obj, a2dPin );
801  if( !pin || pin->GetRelease() ) continue;
802 
803  a2dPin* otherPin = pin->IsDislocated();
804  if( otherPin )
805  {
806  // only connected pins can be dislocated
807  if( pin->IsDynamicPin() )
808  {
809  // often a dynamic pin is connected to end of begin of another wire, but with draging selections,
810  // it becomes possible that a dynamic pin is dislocated, but its connected wire is selected and will not be rerouted.
811  // In such a situation an extra wire should have bin created in CreateWiresOnPins()
812  a2dPoint2D otherPos = otherPin->GetAbsXY();
813  }
814  else
815  {
816  if( pin->GetName() == wxT( "begin" ) )
817  {
818  if ( oneLine || wire->GetRouteOneLine() )
819  {
820  a2dPoint2D otherEnd = wire->FindEndPin()->GetAbsXY();
821  a2dVertexList* newpoints = new a2dVertexList;
822  newpoints->push_back( new a2dLineSegment( otherPin->GetAbsXY() ) );
823  newpoints->push_back( new a2dLineSegment( otherEnd ) );
824  // Adjust the existing vertex list to the new vertex list
825  wire->SetSegments( newpoints );
826  wire->SetPending( true );
827  wire->SetRerouteAdded( true );
828  }
829  else
830  {
831  // Reroute wire
832  m_routedata->RerouteWire( wire, pin, wire->FindEndPin(), false, false );
833  // target->SetEndPoint( 0, 1, otherPos.m_x, otherPos.m_y, data->m_final );
834  }
835 
836  // This could dislocates other pins, so repeat routing.
837  // Dynamic pins on the wire are moved towards new segments.
838  if( wire->AdjustAfterChange( false ) )
839  again = true;
840  }
841  else if( pin->GetName() == wxT( "end" ) )
842  {
843  if ( oneLine || wire->GetRouteOneLine() )
844  {
845  a2dPoint2D otherEnd = wire->FindBeginPin()->GetAbsXY();
846  a2dVertexList* newpoints = new a2dVertexList;
847  newpoints->push_back( new a2dLineSegment( otherEnd ) );
848  newpoints->push_back( new a2dLineSegment( otherPin->GetAbsXY() ) );
849  // Adjust the existing vertex list to the new vertex list
850  wire->SetSegments( newpoints );
851  wire->SetPending( true );
852  wire->SetRerouteAdded( true );
853  }
854  else
855  {
856  // Reroute wire
857  m_routedata->RerouteWire( wire, pin, wire->FindBeginPin(), true, false );
858  // wire->SetEndPoint( GetNumberOfSegments()-1, GetNumberOfSegments()-2, otherPos.m_x, otherPos.m_y, data->m_final );
859  }
860 
861  // This could dislocates other dynamic pins also, so repeat routing if so.
862  // Dynamic pins on the wire are moved towards new segments.
863  if( wire->AdjustAfterChange( false ) )
864  again = true;
865  }
866  else
867  {
868  wxASSERT_MSG( 0, wxT( "Unknown pin type in wire" ) );
869  }
870  }
871  }
872  }
873  //Rerouting was done, dynamic pins on wire were moved with it.
874  //Pins on wires connected to those dynamic pins are now dislocated,
875  // and will be rerouted.
876 
877 /* try removing segments that are on
878  for( a2dCanvasObjectList::iterator iter = wire->GetChildObjectList()->begin(); iter != wire->GetChildObjectList()->end(); ++iter )
879  {
880  a2dCanvasObject* obj = *iter;
881  a2dPin* pin = wxDynamicCast( obj, a2dPin );
882  if( !pin || pin->GetRelease() ) continue;
883 
884  if( pin->GetName() == wxT( "begin" ) )
885  {
886  a2dPinList::const_iterator iterconp;
887  for ( iterconp = pin->GetConnectedPins().begin( ) ; iterconp != pin->GetConnectedPins().end( ) ; iterconp++ )
888  {
889  a2dPin* otherPin = *iterconp;
890  if( !otherPin || otherPin->GetRelease() )
891  continue;
892 
893  if( otherPin->IsDynamicPin() && otherPin->GetParent()->IsConnect() )
894  {
895  a2dWirePolylineL* wireconnected = wxStaticCast( otherPin->GetParent(), a2dWirePolylineL );
896  if ( wireconnected )
897  {
898  a2dPoint2D beginPos = pin->GetAbsXY();
899  a2dHit result = wireconnected->GetSegments()->HitTestPolyline( beginPos, a2dCanvasGlobals->GetHabitat()->GetCoordinateEpsilon() );
900  while( result.IsHit() && wire->GetSegments()->size() > 2 )
901  {
902  //remove begin segment on wire, and move pin there.
903  if ( wire->GetFirstPoint()->GetPoint() == beginPos )
904  {
905  wire->GetSegments()->pop_front();
906  beginPos = wire->GetFirstPoint()->GetPoint();
907  }
908  else
909  {
910  wire->GetSegments()->pop_back();
911  beginPos = wire->GetLastPoint()->GetPoint();
912  }
913  result = wireconnected->GetSegments()->HitTestPolyline( beginPos, a2dCanvasGlobals->GetHabitat()->GetCoordinateEpsilon() );
914  }
915  pin->SetPosXY( beginPos.m_x, beginPos.m_y );
916  }
917 
918  wire->SetPending( true );
919  wire->SetRerouteAdded( true );
920  // This could dislocates other pins, so repeat routing.
921  // Dynamic pins on the wire are moved towards new segments.
922  if( wire->AdjustAfterChange( false ) )
923  again = true;
924 
925  }
926  }
927  }
928  }
929 */
930  }
931 }
932 
933 void a2dConnectionGenerator::AutoConnect( a2dWirePolylineL* wire, bool allowreconnectbegin, bool allowreconnectend )
934 {
935  for( a2dCanvasObjectList::iterator iter = wire->GetChildObjectList()->begin(); iter != wire->GetChildObjectList()->end(); ++iter )
936  {
937  a2dCanvasObject* obj = *iter;
938  a2dPin* pin = wxDynamicCast( obj, a2dPin );
939  if( !pin ) continue;
940 
941  if( pin->GetName() == wxT( "begin" ) )
942  {
943  if( allowreconnectbegin )
944  {
945  pin->AutoConnect( m_parent, 1.0 );
946  }
947  }
948  else if( pin->GetName() == wxT( "end" ) )
949  {
950  if( allowreconnectend )
951  {
952  pin->AutoConnect( m_parent, 1.0 );
953  }
954  }
955  }
956 }
957 
958 void a2dConnectionGenerator::RerouteWires( bool final, bool fromOriginal )
959 {
960  wxASSERT_MSG( m_parent, wxT( "parent object must be set" ) );
961  double offset = m_offset;
962 
963  if ( m_routeWhenDrag || ( !m_routeWhenDrag && final ) )
964  {
965  switch ( m_routeMethod )
966  {
967  case StraightSegment:
969  {
970  // keep re-adjusting wires, until no more pin is dislocated
971  bool displaced = true;
972  int i = 0;
973  while ( displaced && i < 1000 )
974  {
975  i++;
976  displaced = false; // unless more displaced pins are found.
977  for( a2dCanvasObjectList::iterator iter = m_wiresEditCopies->begin(); iter != m_wiresEditCopies->end(); ++iter )
978  {
979  if ( !(*iter)->IsConnect() )
980  continue;
981  a2dWirePolylineL* wire = wxStaticCast( (*iter).Get(), a2dWirePolylineL );
982  for( a2dCanvasObjectList::iterator iterpins = wire->GetChildObjectList()->begin(); iterpins != wire->GetChildObjectList()->end(); ++iterpins )
983  {
984  a2dPin* pin = wxDynamicCast( iterpins->Get(), a2dPin );
985  if( !pin || pin->GetRelease() ) continue;
986 
987  // if a pin on a dragged object is not the same position as wire pin, the wire needs rerouting.
988  // Pins on the wires are adjusted to the new situation. And only when final the editcopy wires are transfered to the originals.
989  a2dPin* otherPin = pin->IsDislocated();
990  if( otherPin )
991  {
992  if( pin->IsDynamicPin() )
993  {
994  a2dPoint2D otherPos = otherPin->GetAbsXY();
995  if( wire->MoveDynamicPinCloseTo( pin, otherPos, false ) )
996  {
997  displaced = true;
998  }
999  }
1000  else
1001  {
1002  a2dVertexList* newpoints = wire->GetSegments();
1003  if ( m_routeMethod != StraightSegmentUnlessPins )//wire->GetNumberOfSegments() == 2 )
1004  {
1005  newpoints = new a2dVertexList;
1006  if( pin->GetName() == wxT( "begin" ) )
1007  {
1008  a2dPoint2D otherEnd = wire->FindEndPin()->GetAbsXY();
1009  newpoints->push_back( new a2dLineSegment( otherPin->GetAbsXY() ) );
1010  newpoints->push_back( new a2dLineSegment( otherEnd ) );
1011  }
1012  else if( pin->GetName() == wxT( "end" ) )
1013  {
1014  a2dPoint2D otherEnd = wire->FindBeginPin()->GetAbsXY();
1015  newpoints->push_back( new a2dLineSegment( otherEnd ) );
1016  newpoints->push_back( new a2dLineSegment( otherPin->GetAbsXY() ) );
1017  }
1018  else
1019  {
1020  }
1021  }
1022  else
1023  {
1024  {
1025  if( pin->GetName() == wxT( "begin" ) )
1026  {
1027  a2dLineSegment* seg = newpoints->front();
1028  seg->SetPoint( otherPin->GetAbsXY() );
1029  }
1030  else if( pin->GetName() == wxT( "end" ) )
1031  {
1032  a2dLineSegment* seg = newpoints->back();
1033  seg->SetPoint( otherPin->GetAbsXY() );
1034  }
1035  else
1036  {
1037  //newpoints->push_back( new a2dLineSegment( pin->ConnectedTo()->GetAbsXY() ) );
1038  }
1039  }
1040  }
1041 
1042 
1043  // Adjust the existing vertex list to the new vertex list
1044  wire->SetSegments( newpoints );
1045  if( wire->AdjustAfterChange( false ) )
1046  displaced = true;
1047  wire->SetPending( true );
1048  }
1049  }
1050  }
1051  }
1052  }
1053  }
1054  break;
1055  case ManhattanSegments:
1056  {
1057  // keep re-adjusting wires, until no more pin is dislocated
1058  bool displaced = true;
1059  int i = 0;
1060  while ( displaced && i < 1000 )
1061  {
1062  i++;
1063  displaced = false; // unless more displaced pins are found.
1064  for( a2dCanvasObjectList::iterator iter = m_wiresEditCopies->begin(); iter != m_wiresEditCopies->end(); ++iter )
1065  {
1066  if ( !(*iter)->IsConnect() )
1067  continue;
1068  a2dWirePolylineL* wire = wxStaticCast( (*iter).Get(), a2dWirePolylineL );
1069  for( a2dCanvasObjectList::iterator iterpins = wire->GetChildObjectList()->begin(); iterpins != wire->GetChildObjectList()->end(); ++iterpins )
1070  {
1071  a2dPin* pin = wxDynamicCast( iterpins->Get(), a2dPin );
1072  if( !pin || pin->GetRelease() ) continue;
1073 
1074  // if a pin on a dragged object is not the same position as wire pin, the wire needs rerouting.
1075  // Pins on the wires are adjusted to the new situation. And only when final the editcopy wires are transfered to the originals.
1076  a2dPin* otherPin = pin->IsDislocated();
1077  if( otherPin )
1078  {
1079  if( pin->IsDynamicPin() )
1080  {
1081  a2dPoint2D otherPos = otherPin->GetAbsXY();
1082  if( wire->MoveDynamicPinCloseTo( pin, otherPos, false ) )
1083  {
1084  displaced = true;
1085  }
1086  }
1087  else
1088  {
1089  a2dVertexList* newpoints = wire->GetSegments();
1090  newpoints = new a2dVertexList;
1091  if( pin->GetName() == wxT( "begin" ) )
1092  {
1093  a2dSingleRoute routeWire( offset, 400 );
1094  a2dPin* otherEndpin = wire->FindEndPin()->IsConnectedTo();
1095  if ( !otherEndpin )
1096  {
1097  wire->AdjustBeginEndPinAngle();
1098  otherEndpin = wire->FindEndPin();
1099  routeWire.ComputeConToWireVertex( otherPin, otherEndpin->GetAbsX(), otherEndpin->GetAbsY(), otherEndpin->GetAbsAngle() - 180 );
1100  }
1101  else
1102  routeWire.ComputeCon ( otherPin, otherEndpin );
1103 
1104  for ( int v = 0; v < routeWire.m_pnr; v++ )
1105  {
1106  newpoints->push_back( new a2dLineSegment( routeWire.m_p[v][0], routeWire.m_p[v][1] ) );
1107  }
1108  offset += m_offset;
1109  }
1110  else if( pin->GetName() == wxT( "end" ) )
1111  {
1112  a2dSingleRoute routeWire( offset, 400 );
1113  a2dPin* otherEndpin = wire->FindBeginPin()->IsConnectedTo();
1114  if ( !otherEndpin )
1115  {
1116  wire->AdjustBeginEndPinAngle();
1117  otherEndpin = wire->FindBeginPin();
1118  routeWire.ComputeConToWireVertex( otherPin, otherEndpin->GetAbsX(), otherEndpin->GetAbsY(), otherEndpin->GetAbsAngle() - 180 );
1119  }
1120  else
1121  routeWire.ComputeCon ( otherPin, otherEndpin );
1122 
1123  for ( int v = 0; v < routeWire.m_pnr; v++ )
1124  {
1125  newpoints->push_front( new a2dLineSegment( routeWire.m_p[v][0], routeWire.m_p[v][1] ) );
1126  }
1127  offset += m_offset;
1128  }
1129  else
1130  {
1131  }
1132  // Adjust the existing vertex list to the new vertex list
1133  wire->SetSegments( newpoints );
1134  if( wire->AdjustAfterChange( false ) )
1135  displaced = true;
1136  wire->SetPending( true );
1137  }
1138  }
1139  }
1140  }
1141  }
1142  }
1143  break;
1144  case ManhattanEndSegments:
1145  {
1146  bool displaced = true;
1147  unsigned int trials = 0;
1148  while ( displaced && trials < 10 )
1149  {
1150  trials++;
1151  displaced = false; // unless more displaced pins are found.
1152  for( a2dCanvasObjectList::iterator iter = m_wiresEditCopies->begin(); iter != m_wiresEditCopies->end(); ++iter )
1153  {
1154  a2dCanvasObject* obj = *iter;
1155  if ( !obj->IsConnect() )
1156  continue;
1158 
1159  for( a2dCanvasObjectList::iterator iterpins = wire->GetChildObjectList()->begin(); iterpins != wire->GetChildObjectList()->end(); ++iterpins )
1160  {
1161  a2dPin* pin = wxDynamicCast( iterpins->Get(), a2dPin );
1162  if( !pin || pin->GetRelease() ) continue;
1163 
1164  // if a pin on a dragged object is not the same position as wire pin, the wire needs rerouting.
1165  // Pins on the wires are adjusted to the new situation. And only when final the editcopy wires are transfered to the originals.
1166  a2dPin* otherPin = pin->IsDislocated();
1167  if( otherPin )
1168  {
1169  bool hasbins = false;
1170  a2dVertexList* newpoints = wire->GetSegments();
1171  a2dVertexList::iterator iter = newpoints->begin();
1172  while ( iter != newpoints->end() )
1173  {
1174  if ( (*iter)->GetBin() && newpoints->size() > 1 )
1175  {
1176  iter = newpoints->erase( iter );
1177  hasbins = true;
1178  }
1179  else
1180  iter++;
1181  }
1182  wire->AdjustAfterChange( false );
1183 
1184  if( pin->IsDynamicPin() )
1185  {
1186  a2dPoint2D otherPos = otherPin->GetAbsXY();
1187  if( wire->MoveDynamicPinCloseTo( pin, otherPos, false ) )
1188  {
1189  displaced = true;
1190  }
1191  }
1192  else
1193  {
1194  if( pin->GetName() == wxT( "begin" ) )
1195  {
1196  if ( !hasbins )
1197  {
1198  if ( newpoints->size() > 1 )
1199  newpoints->pop_front();
1200  if ( newpoints->size() > 1 )
1201  newpoints->pop_front();
1202  wire->AdjustAfterChange( false );
1203  }
1204  wire->AdjustBeginEndPinAngle();
1205 
1206  if ( newpoints->size() <= 2 )
1207  {
1208  newpoints->clear();
1209  a2dPin* otherEndpin = wire->FindEndPin()->IsConnectedTo();
1210  a2dSingleRoute routeWire( offset, 400 );
1211  if ( !otherEndpin )
1212  {
1213  otherEndpin = wire->FindEndPin();
1214  routeWire.ComputeConToWireVertex( otherPin, otherEndpin->GetAbsX(), otherEndpin->GetAbsY(), otherEndpin->GetAbsAngle() - 180 );
1215  }
1216  else
1217  routeWire.ComputeCon ( otherPin, otherEndpin );
1218 
1219  for ( int v = 0; v < routeWire.m_pnr; v++ )
1220  {
1221  a2dLineSegment* seg = new a2dLineSegment( routeWire.m_p[v][0], routeWire.m_p[v][1] );
1222  seg->SetBin( true );
1223  newpoints->push_front( seg );
1224  }
1225  }
1226  else
1227  {
1228  a2dSingleRoute routeWire( 0, 400 );
1229  routeWire.ComputeCon ( pin, otherPin );
1230 
1231  for ( int v = 1; v < routeWire.m_pnr; v++ )
1232  {
1233  a2dLineSegment* seg = new a2dLineSegment( routeWire.m_p[v][0], routeWire.m_p[v][1] );
1234  seg->SetBin( true );
1235  newpoints->push_front( seg );
1236  }
1237  }
1238  offset += m_offset;
1239  }
1240  else if( pin->GetName() == wxT( "end" ) )
1241  {
1242  if ( !hasbins )
1243  {
1244  if ( newpoints->size() > 1 )
1245  newpoints->pop_back();
1246  if ( newpoints->size() > 1 )
1247  newpoints->pop_back();
1248  wire->AdjustAfterChange( false );
1249  }
1250  wire->AdjustBeginEndPinAngle();
1251 
1252  if ( newpoints->size() <= 2 )
1253  {
1254  newpoints->clear();
1255  a2dPin* otherEndpin = wire->FindBeginPin()->IsConnectedTo();
1256  a2dSingleRoute routeWire( offset, 400 );
1257  if ( !otherEndpin )
1258  {
1259  otherEndpin = wire->FindBeginPin();
1260  routeWire.ComputeConToWireVertex( otherPin, otherEndpin->GetAbsX(), otherEndpin->GetAbsY(), otherEndpin->GetAbsAngle() - 180 );
1261  }
1262  else
1263  routeWire.ComputeCon ( otherPin, otherEndpin );
1264 
1265  for ( int v = 0; v < routeWire.m_pnr; v++ )
1266  {
1267  a2dLineSegment* seg = new a2dLineSegment( routeWire.m_p[v][0], routeWire.m_p[v][1] );
1268  seg->SetBin( true );
1269  newpoints->push_front( seg );
1270  }
1271  }
1272  else
1273  {
1274  a2dSingleRoute routeWire( 0, 400 );
1275  routeWire.ComputeCon ( pin, otherPin );
1276 
1277  for ( int v = 1; v < routeWire.m_pnr; v++ )
1278  {
1279  a2dLineSegment* seg = new a2dLineSegment( routeWire.m_p[v][0], routeWire.m_p[v][1] );
1280  seg->SetBin( true );
1281  newpoints->push_back( seg );
1282  }
1283  }
1284  offset += m_offset;
1285  }
1286  else
1287  {
1288  }
1289  // Adjust the existing vertex list to the new vertex list
1290  wire->SetSegments( newpoints );
1291  if( wire->AdjustAfterChange( false ) )
1292  displaced = true;
1293  wire->SetPending( true );
1294  }
1295  }
1296  }
1297  }
1298  }
1299  }
1300  break;
1303  {
1304  bool displaced = true;
1305  unsigned int trials = 0;
1306  while ( displaced && trials < 10 )
1307  {
1308  trials++;
1309  displaced = false; // unless more displaced pins are found.
1310  for( a2dCanvasObjectList::iterator iter = m_wiresEditCopies->begin(); iter != m_wiresEditCopies->end(); ++iter )
1311  {
1312  a2dCanvasObject* obj = *iter;
1313  if ( !obj->IsConnect() )
1314  continue;
1316 
1317  for( a2dCanvasObjectList::iterator iterpins = wire->GetChildObjectList()->begin(); iterpins != wire->GetChildObjectList()->end(); ++iterpins )
1318  {
1319  a2dPin* pin = wxDynamicCast( iterpins->Get(), a2dPin );
1320  if( !pin || pin->GetRelease() ) continue;
1321 
1322  // if a pin on a dragged object is not the same position as wire pin, the wire needs rerouting.
1323  // Pins on the wires are adjusted to the new situation. And only when final the editcopy wires are transfered to the originals.
1324  a2dPin* otherPin = pin->IsDislocated();
1325  if( otherPin )
1326  {
1327  a2dVertexList* newpoints = wire->GetSegments();
1328 
1329  if( pin->IsDynamicPin() )
1330  {
1331  a2dPoint2D otherPos = otherPin->GetAbsXY();
1332  if( wire->MoveDynamicPinCloseTo( pin, otherPos, false ) )
1333  {
1334  displaced = true;
1335  }
1336  }
1337  else
1338  {
1339  if( pin->GetName() == wxT( "begin" ) )
1340  {
1341  a2dPin* otherEndpin = wire->FindEndPin()->IsConnectedTo();
1342  if ( !otherEndpin )
1343  {
1344  a2dLineSegment* seg = newpoints->front();
1345  seg->SetPoint( otherPin->GetAbsXY() );
1346  }
1347  else if ( newpoints->size() > 2 )
1348  {
1349  a2dVertexList::iterator iter = newpoints->begin();
1350  a2dLineSegment* seg, *seg2, *seg3;
1351  if ( iter != newpoints->end() )
1352  seg = *iter;
1353  iter++;
1354  if ( iter != newpoints->end() )
1355  seg2 = *iter;
1356  iter++;
1357  if ( iter != newpoints->end() )
1358  seg3 = *iter;
1359 
1360  EndManhattanRoute( otherPin, seg, seg2, seg3, newpoints, false );
1361  }
1362  else
1363  {
1364  a2dVertexList::iterator iter = newpoints->begin();
1365  a2dLineSegment* seg, *seg2;
1366  seg = seg2 = NULL;
1367  if ( iter != newpoints->end() )
1368  seg = *iter;
1369  iter++;
1370  if ( iter != newpoints->end() )
1371  seg2 = *iter;
1372  if ( seg2 && m_routeMethod == ManhattanEndSegmentsConvertAndStay )
1373  { //convert straight endsegment to a manhattan pair of segments
1374  newpoints->push_front( new a2dLineSegment( otherPin->GetAbsXY() ) );
1375  seg->SetPoint( a2dPoint2D( seg2->m_x, otherPin->GetAbsY() ) );
1376  }
1377  else //if ( m_routeMethod == ManhattanEndSegmentsStay )
1378  {
1379  seg->SetPoint( otherPin->GetAbsXY() );
1380  }
1381  }
1382  }
1383  else if( pin->GetName() == wxT( "end" ) )
1384  {
1385  a2dPin* otherEndpin = wire->FindBeginPin()->IsConnectedTo();
1386  if ( !otherEndpin )
1387  {
1388  a2dLineSegment* seg = newpoints->back();
1389  seg->SetPoint( otherPin->GetAbsXY() );
1390  }
1391  else if ( newpoints->size() > 2 )
1392  {
1393  a2dVertexList::reverse_iterator iter = newpoints->rbegin();
1394  a2dLineSegment* seg, *seg2, *seg3;
1395  if ( iter != newpoints->rend() )
1396  seg = *iter;
1397  iter++;
1398  if ( iter != newpoints->rend() )
1399  seg2 = *iter;
1400  iter++;
1401  if ( iter != newpoints->rend() )
1402  seg3 = *iter;
1403 
1404  EndManhattanRoute( otherPin, seg, seg2, seg3, newpoints, true );
1405  }
1406  else
1407  {
1408  a2dVertexList::reverse_iterator iter = newpoints->rbegin();
1409  a2dLineSegment* seg, *seg2;
1410  seg = seg2 = NULL;
1411  if ( iter != newpoints->rend() )
1412  seg = *iter;
1413  iter++;
1414  if ( iter != newpoints->rend() )
1415  seg2 = *iter;
1416  if ( seg2 && m_routeMethod == ManhattanEndSegmentsConvertAndStay )
1417  { //convert straight endsegment to a manhattan pair of segments
1418  newpoints->push_back( new a2dLineSegment( otherPin->GetAbsXY() ) );
1419  seg->SetPoint( a2dPoint2D( seg2->m_x, otherPin->GetAbsY() ) );
1420  }
1421  else //if ( m_routeMethod == ManhattanEndSegmentsStay )
1422  {
1423  seg->SetPoint( otherPin->GetAbsXY() );
1424  }
1425  }
1426  }
1427  else
1428  {
1429  }
1430  wire->Remove180DegPoints( NULL, false );
1431  // Adjust the existing vertex list to the new vertex list
1432  wire->SetSegments( newpoints );
1433  if( wire->AdjustAfterChange( false ) )
1434  displaced = true;
1435  wire->SetPending( true );
1436  }
1437  }
1438  }
1439  }
1440  }
1441  }
1442  break;
1443  case GridRouting:
1444  {
1445  if ( fromOriginal )
1446  ResetPositionsToOrignals();
1447  PrepareGridRoute();
1448 
1449  bool again = true;
1450  while ( again )
1451  {
1452  again = false;
1453  for( a2dCanvasObjectList::iterator iter = m_wiresEditCopies->begin(); iter != m_wiresEditCopies->end(); ++iter )
1454  {
1455  if ( !(*iter)->IsConnect() )
1456  continue;
1457  a2dWirePolylineL* wire = wxStaticCast( (*iter).Get(), a2dWirePolylineL );
1458  if ( wire )
1459  {
1460 
1461 /* No need to do this, since we have only edit copy wires.
1462  // Check if there is an original property, that indicates we do want it,
1463  // because only editcopies have this property.
1464  a2dWirePolylineL* original = wxStaticCastNull( a2dCanvasObject::PROPID_Original->GetPropertyValue( wire ), a2dWirePolylineL );
1465  a2dWirePolylineL* target = wire;
1466 
1467  // Only do this for editcopy wires
1468  if( !original )
1469  continue;
1470 */
1471  RerouteWire( wire, again );
1472  }
1473  }
1474  }
1475  if ( final )
1476  m_routedata = NULL;
1477  }
1478  break;
1479  case StraightEndSegment:
1481  {
1482  bool displaced = true;
1483  unsigned int trials = 0;
1484  while ( displaced && trials < 10000 )
1485  {
1486  trials++;
1487  displaced = false; // unless more displaced pins are found.
1488  for( a2dCanvasObjectList::iterator iter = m_wiresEditCopies->begin(); iter != m_wiresEditCopies->end(); ++iter )
1489  {
1490  a2dCanvasObject* obj = *iter;
1491  if ( !obj->IsConnect() )
1492  continue;
1494 
1495  for( a2dCanvasObjectList::iterator iterpins = wire->GetChildObjectList()->begin(); iterpins != wire->GetChildObjectList()->end(); ++iterpins )
1496  {
1497  a2dPin* pin = wxDynamicCast( iterpins->Get(), a2dPin );
1498  if( !pin || pin->GetRelease() ) continue;
1499 
1500  // if a pin on a dragged object is not the same position as wire pin, the wire needs rerouting.
1501  // Pins on the wires are adjusted to the new situation. And only when final the editcopy wires are transfered to the originals.
1502  a2dPin* otherPin = pin->IsDislocated();
1503  if( otherPin )
1504  {
1505  if( pin->IsDynamicPin() )
1506  {
1507  a2dPoint2D otherPos = otherPin->GetAbsXY();
1508  if( wire->MoveDynamicPinCloseTo( pin, otherPos, false ) )
1509  {
1510  displaced = true;
1511  }
1512  }
1513  else
1514  {
1515  a2dVertexList* newpoints = wire->GetSegments();
1516  {
1517  if( pin->GetName() == wxT( "begin" ) )
1518  {
1519  a2dLineSegment* seg = newpoints->front();
1520  seg->SetPoint( otherPin->GetAbsXY() );
1521  }
1522  else if( pin->GetName() == wxT( "end" ) )
1523  {
1524  a2dLineSegment* seg = newpoints->back();
1525  seg->SetPoint( otherPin->GetAbsXY() );
1526  }
1527  else
1528  {
1529  //newpoints->push_back( new a2dLineSegment( pin->ConnectedTo()->GetAbsXY() ) );
1530  }
1531  }
1532 
1533  wire->SetSegments( newpoints );
1534  if( wire->AdjustAfterChange( false ) )
1535  displaced = true;
1536  wire->SetPending( true );
1537  }
1538  }
1539  }
1540  }
1541  }
1542  }
1543  break;
1544  default:
1545  break;
1546  }
1547 
1548  }
1549 
1550  // but all information back to the originals.
1551  if ( final )
1552  {
1553 /* Check for dislocated pins in editcopies.
1554  for( a2dCanvasObjectList::iterator iter = m_wiresEditCopies->begin(); iter != m_wiresEditCopies->end(); ++iter )
1555  {
1556  a2dWirePolylineL* wire = wxStaticCast( (*iter).Get(), a2dWirePolylineL );
1557  for( a2dCanvasObjectList::iterator iterpins = wire->GetChildObjectList()->begin(); iterpins != wire->GetChildObjectList()->end(); ++iterpins )
1558  {
1559  a2dPin* pin = wxDynamicCast( iterpins->Get(), a2dPin );
1560  if( !pin ) continue;
1561  if( !pin->ConnectedTo() ) continue;
1562 
1563  // if a pin on a dragged object is not the same position as wire pin, the wire needs rerouting.
1564  // Pins on the wires are adjusted to the new situation. And only when final the editcopy wires are transfered to the originals.
1565  if( pin->IsDislocated() )
1566  {
1567  wxLogDebug(wxT("route x=%12.6lf, y=%12.6lf"), pin->GetAbsX() , pin->GetAbsY() );
1568  wxLogDebug(wxT(" xo=%12.6lf, y=o%12.6lf"), pin->ConnectedTo()->GetAbsX() , pin->ConnectedTo()->GetAbsY() );
1569  }
1570  }
1571  }
1572 */
1573  for( a2dCanvasObjectList::iterator iter = m_wiresEditCopies->begin(); iter != m_wiresEditCopies->end(); ++iter )
1574  {
1575  a2dCanvasObject* obj = *iter;
1576  if ( !obj->IsConnect() )
1577  continue;
1578 
1581  a2dWirePolylineL* target = wire;
1582  if ( !m_noEditCopy )
1583  target = wxStaticCastNull( a2dCanvasObject::PROPID_Original->GetPropertyValue( wire ).Get(), a2dWirePolylineL );
1584  a2dVertexList* newpoints = wire->GetSegments();
1585  if ( cmd )
1586  cmd->Submit( new a2dCommand_SetSegments( target, newpoints, true ), final );
1587  else
1588  target->SetSegments( newpoints );
1589  for( a2dCanvasObjectList::iterator iterpins = wire->GetChildObjectList()->begin(); iterpins != wire->GetChildObjectList()->end(); ++iterpins )
1590  {
1591  a2dPin* pin = wxDynamicCast( iterpins->Get(), a2dPin );
1592  if( !pin ) continue;
1593  if( !pin->IsConnectedTo() ) continue;
1594 
1595  a2dPin* targetPin = pin;
1596  if ( !m_noEditCopy )
1597  targetPin = wxStaticCastNull( a2dCanvasObject::PROPID_Original->GetPropertyValue( pin ).Get(), a2dPin );
1598  if ( cmd )
1599  cmd->Submit( new a2dCommand_SetCanvasProperty( targetPin, a2dCanvasObject::PROPID_Position, pin->GetPosXY(), -1, false ), final );
1600  else
1601  targetPin->SetPosXyPoint( pin->GetPosXY() );
1602  }
1603  //AutoConnect( target, true, true );//allowreconnectbegin, allowreconnectend );
1604  }
1605 
1606 /* Check for dislocated pins in originals
1607  for( a2dCanvasObjectList::iterator iter = m_wires->begin(); iter != m_wires->end(); ++iter )
1608  {
1609  a2dWirePolylineL* wire = wxStaticCast( (*iter).Get(), a2dWirePolylineL );
1610  for( a2dCanvasObjectList::iterator iterpins = wire->GetChildObjectList()->begin(); iterpins != wire->GetChildObjectList()->end(); ++iterpins )
1611  {
1612  a2dPin* pin = wxDynamicCast( iterpins->Get(), a2dPin );
1613  if( !pin ) continue;
1614  if( !pin->ConnectedTo() ) continue;
1615 
1616  // if a pin on a dragged object is not the same position as wire pin, the wire needs rerouting.
1617  // Pins on the wires are adjusted to the new situation. And only when final the editcopy wires are transfered to the originals.
1618  if( pin->IsDislocated() )
1619  {
1620  wxLogDebug(wxT("after x=%12.6lf, y=%12.6lf"), pin->GetAbsX() , pin->GetAbsY() );
1621  wxLogDebug(wxT(" xo=%12.6lf, y=o%12.6lf"), pin->ConnectedTo()->GetAbsX() , pin->ConnectedTo()->GetAbsY() );
1622  }
1623  }
1624  }
1625 */
1626  m_wiresEditCopies->clear();
1627  for( a2dCanvasObjectList::iterator iter = m_wires->begin(); iter != m_wires->end(); ++iter )
1628  {
1629  a2dWalker_RemovePropertyCandoc setp( a2dCanvasObject::PROPID_Editcopy );
1630  setp.SetSkipNotRenderedInDrawing( true );
1631  setp.Start( *iter );
1632  a2dWirePolylineL* wire = wxStaticCast( (*iter).Get(), a2dWirePolylineL );
1633  wire->EliminateMatrix();
1634  wire->SetVisible( true );
1635  }
1636 
1637  OptimizeRerouteWires( true );
1638  m_wires->clear();
1639  }
1640 }
1641 
1642 void a2dConnectionGenerator::EndManhattanRoute( a2dPin* pin, a2dLineSegment* seg1, a2dLineSegment* seg2, a2dLineSegment* seg3, a2dVertexList* points, bool reverse )
1643 {
1644  double seg1seg2Slope = 0;
1645  double seg2seg3Slope = 0;
1646  bool seg1seg2Same = false;
1647  bool seg2seg3Same = false;
1648 
1649  if ( seg1->m_x == seg2->m_x )
1650  {
1651  if ( seg1->m_y == seg2->m_y )
1652  {
1653  seg1seg2Same = true;
1654  //point seg1 and seg2 same, use pinangle
1655  double pinangle = pin->GetAbsAngle();
1656  if ( pinangle == 0 || pinangle == 180 )
1657  seg1seg2Slope = 0;
1658  else
1659  seg1seg2Slope = DBL_MAX;
1660  }
1661  else
1662  seg1seg2Slope = DBL_MAX;
1663  }
1664  else
1665  seg1seg2Slope = ( seg1->m_y - seg2->m_y ) / ( seg1->m_x - seg2->m_x );
1666 
1667  if ( seg2->m_x == seg3->m_x )
1668  {
1669  if ( seg2->m_y == seg3->m_y )
1670  {
1671  seg2seg3Same = true;
1672  seg2seg3Slope = 0;
1673  if ( seg1seg2Same )
1674  seg2seg3Slope = seg1seg2Slope;
1675  }
1676  else
1677  seg2seg3Slope = DBL_MAX;
1678  }
1679  else
1680  seg2seg3Slope = ( seg2->m_y - seg3->m_y ) / ( seg2->m_x - seg3->m_x );
1681 
1682  //axis aligned straight angles
1683  // If bin flag for segment is set, it mean there was a straight segment, at an angle at the start.
1684  // In that case when m_routeMethod == ManhattanEndSegmentsStay, the segement will stay straight.
1685  if ( !seg1->GetBin() &&
1686  (
1687  ( seg1seg2Slope == 0 && seg2seg3Slope == 0 )||
1688  ( seg1seg2Slope == DBL_MAX && seg2seg3Slope == DBL_MAX ) ||
1689  ( seg1seg2Slope == 0 && seg2seg3Slope == DBL_MAX ) ||
1690  ( seg1seg2Slope == DBL_MAX && seg2seg3Slope == 0 )
1691  )
1692  )
1693  {
1694  //wxLogDebug( wxString::Format("MS %p", seg1 ) );
1695 
1696  seg1->SetPoint( pin->GetAbsXY() );
1697 
1698  if ( seg1seg2Slope == 0 && seg2seg3Slope == 0 )
1699  {
1700  if ( seg1seg2Same && seg2seg3Same )
1701  seg2->SetPoint( a2dPoint2D( seg2->m_x, pin->GetAbsY() ) );
1702  else if ( seg2seg3Same )
1703  seg2->SetPoint( a2dPoint2D( seg2->m_x, pin->GetAbsY() ) );
1704  else
1705  {
1706  if ( reverse )
1707  points->push_back( new a2dLineSegment( pin->GetAbsXY() ) );
1708  else
1709  points->push_front( new a2dLineSegment( pin->GetAbsXY() ) );
1710  seg1->SetPoint( a2dPoint2D( seg2->m_x, pin->GetAbsY() ) );
1711  }
1712  }
1713  else if ( seg1seg2Slope == DBL_MAX && seg2seg3Slope == DBL_MAX )
1714  {
1715  if ( seg1seg2Same && seg2seg3Same )
1716  seg2->SetPoint( a2dPoint2D( seg2->m_x, pin->GetAbsY() ) );
1717  else if ( seg2seg3Same )
1718  seg2->SetPoint( a2dPoint2D( seg2->m_x, pin->GetAbsY() ) );
1719  else
1720  {
1721  if ( reverse )
1722  points->push_back( new a2dLineSegment( pin->GetAbsXY() ) );
1723  else
1724  points->push_front( new a2dLineSegment( pin->GetAbsXY() ) );
1725  seg1->SetPoint( a2dPoint2D( seg2->m_x, pin->GetAbsY() ) );
1726  }
1727  }
1728  else if ( seg1seg2Slope == 0 && seg2seg3Slope == DBL_MAX )
1729  seg2->SetPoint( a2dPoint2D( seg2->m_x, pin->GetAbsY() ) );
1730  else if ( seg1seg2Slope == DBL_MAX && seg2seg3Slope == 0 )
1731  seg2->SetPoint( a2dPoint2D( pin->GetAbsX(), seg2->m_y ) );
1732  }
1733  else
1734  {
1735  if ( m_routeMethod == ManhattanEndSegmentsStay )
1736  {
1737  //wxLogDebug( wxString::Format("S %p", seg1 ) );
1738  seg1->SetBin( true );
1739  seg1->SetPoint( pin->GetAbsXY() );
1740  }
1741  else if ( m_routeMethod == ManhattanEndSegmentsConvertAndStay )
1742  { //convert straight endsegment to a manhattan pair of segments
1743  if ( reverse )
1744  points->push_back( new a2dLineSegment( pin->GetAbsXY() ) );
1745  else
1746  points->push_front( new a2dLineSegment( pin->GetAbsXY() ) );
1747  seg1->SetPoint( a2dPoint2D( seg2->m_x, pin->GetAbsY() ) );
1748  }
1749  else
1750  { // not written yet method
1751  seg1->SetPoint( pin->GetAbsXY() );
1752  }
1753  }
1754 }
1755 
1757 {
1758  m_tmplObject = tmplObject;
1759 }
1760 
1762 {
1763  return m_tmplObject;
1764 }
1765 
1767 {
1768  a2dPinClass* thisPinClass = NULL;
1769  a2dPinClass* otherPinClass = NULL;
1770  a2dPinClass* wirePinClassThis = NULL;
1771  a2dPinClass* wirePinClassOther = NULL;
1772  a2dWirePolylineL* wire = NULL;
1773  a2dCanvasObject* connect = NULL;
1774  m_reverseCreate = false;
1775 
1776  wire = wxStaticCast( m_tmplObject.Get(), a2dWirePolylineL );
1777  if ( wire )
1778  {
1779  wirePinClassThis = wire->GetStartPinClass();
1780  wirePinClassOther = wire->GetEndPinClass();
1781  if ( pinThis && pinOther )
1782  {
1783  thisPinClass = pinThis->GetPinClass();
1784  otherPinClass = pinOther->GetPinClass();
1785 
1786  if ( thisPinClass->CanConnectTo( wire->GetStartPinClass() ) && otherPinClass->CanConnectTo( wire->GetEndPinClass() ) )
1787  {
1788  m_reverseCreate = false;
1789  }
1790  else if ( otherPinClass->CanConnectTo( wire->GetStartPinClass() ) && thisPinClass->CanConnectTo( wire->GetEndPinClass() ) )
1791  {
1792  m_reverseCreate = true;
1793  }
1794  else
1795  {
1796  wire = NULL;
1797  }
1798  }
1799  else if ( pinThis )
1800  {
1801  thisPinClass = pinThis->GetPinClass();
1802  if ( thisPinClass->CanConnectTo( wire->GetStartPinClass() ) )
1803  {
1804  m_reverseCreate = false;
1805  }
1806  else if ( thisPinClass->CanConnectTo( wire->GetEndPinClass() ) )
1807  {
1808  m_reverseCreate = true;
1809  }
1810  else
1811  {
1812  wire = NULL;
1813  }
1814  }
1815  else if ( pinOther )
1816  {
1817  otherPinClass = pinOther->GetPinClass();
1818  if ( otherPinClass->CanConnectTo( wire->GetEndPinClass() ) )
1819  {
1820  m_reverseCreate = false;
1821  }
1822  else if ( otherPinClass->CanConnectTo( wire->GetStartPinClass() ) )
1823  {
1824  m_reverseCreate = true;
1825  }
1826  else
1827  {
1828  wire = NULL;
1829  }
1830  }
1831 
1832  connect = wire;
1833  }
1834  else
1835  {
1836  connect = m_tmplObject;
1837  wirePinClassThis = a2dPinClass::Standard;
1838  wirePinClassOther = a2dPinClass::Standard;
1839  }
1840 
1841  // make wires always from pinThis to pinOther
1842  // So begin pin is connected at pinThis
1843  // So end pin is connected at pinOther
1844  if ( m_reverseCreate )
1845  {
1846  a2dPinPtr swappin = pinThis;
1847  pinThis = pinOther;
1848  pinOther = swappin;
1849  a2dPinClass* swapPinClass = thisPinClass;
1850  thisPinClass = otherPinClass;
1851  otherPinClass = swapPinClass;
1852  }
1853 
1854  if ( connect )
1855  {
1856  connect = wxStaticCast( connect->Clone( clone_deep ), a2dCanvasObject );
1857  wire = wxStaticCast( connect, a2dWirePolylineL );
1858 
1859  if ( !undo )
1860  {
1861  parent->Append( connect );
1862  if ( pinThis )
1863  {
1864  if (wire )
1865  wire->AddPoint( pinThis->GetAbsX(), pinThis->GetAbsY(), -1 , true );
1866  a2dPin* begin = wire->AddPin( wxT( "begin" ), pinThis->GetAbsX(), pinThis->GetAbsY(), a2dPin::NON,
1867  wirePinClassThis );
1868  connect->ConnectPins( parent, pinThis, begin, undo );
1869  }
1870  else
1871  connect->AddPin( wxT( "begin" ), pinOther->GetAbsX(), pinOther->GetAbsY(), a2dPin::NON,
1872  wirePinClassThis );
1873 
1874  if ( pinOther )
1875  {
1876  if (wire )
1877  wire->AddPoint( pinOther->GetAbsX(), pinOther->GetAbsY(), -1 , true );
1878  a2dPin* end = connect->AddPin( wxT( "end" ), pinOther->GetAbsX(), pinOther->GetAbsY(), a2dPin::NON,
1879  wirePinClassOther );
1880  connect->ConnectPins( parent, pinOther, end, undo );
1881  }
1882  else
1883  connect->AddPin( wxT( "end" ), pinThis->GetAbsX(), pinThis->GetAbsY(), a2dPin::NON,
1884  wirePinClassOther );
1885  }
1886  else
1887  {
1889  cmp->Submit( new a2dCommand_AddObject( parent, wire ) );
1890  if ( pinThis )
1891  {
1892  if (wire )
1893  cmp->Submit( new a2dCommand_AddPoint( wire, pinThis->GetAbsX(), pinThis->GetAbsY(), -1 ) );
1894  a2dPin* begin = connect->AddPin( wxT( "begin" ), pinThis->GetAbsX(), pinThis->GetAbsY(), a2dPin::NON,
1895  wirePinClassThis, true );
1896 
1897  //cmp->Submit( new a2dCommand_AddObject( wire, begin ), true );
1898  cmp->Submit( new a2dCommand_ConnectPins( pinThis, begin ), true );
1899  }
1900  else
1901  connect->AddPin( wxT( "begin" ), pinOther->GetAbsX(), pinOther->GetAbsY(), a2dPin::NON,
1902  wirePinClassThis, true );
1903 
1904  if ( pinOther )
1905  {
1906  if (wire )
1907  cmp->Submit( new a2dCommand_AddPoint( wire, pinOther->GetAbsX(), pinOther->GetAbsY(), -1 ) );
1908  a2dPin* end = connect->AddPin( wxT( "end" ), pinOther->GetAbsX(), pinOther->GetAbsY(), a2dPin::NON,
1909  wirePinClassOther, true );
1910 
1911  //cmp->Submit( new a2dCommand_AddObject( wire, end ), true );
1912  cmp->Submit( new a2dCommand_ConnectPins( pinOther, end ), true );
1913  }
1914  else
1915  connect->AddPin( wxT( "end" ), pinThis->GetAbsX(), pinThis->GetAbsY(), a2dPin::NON,
1916  wirePinClassOther, true );
1917  }
1918 
1919  if (wire )
1920  wire->SetConnectionInfo( true, thisPinClass, otherPinClass );
1921  return wire;
1922  }
1923  return NULL;
1924 }
1925 
1926 a2dCanvasObject* a2dConnectionGenerator::GetConnectTemplate( const a2dCanvasObject* object, a2dPinClass* thisPinClass, const a2dCanvasObject* other, a2dPinClass* otherPinClass ) const
1927 {
1928  a2dWirePolylineL* wire = NULL;
1929  a2dCanvasObject* connect = NULL;
1930  wire = wxStaticCast( m_tmplObject.Get(), a2dWirePolylineL );
1931  if ( wire )
1932  {
1933  if ( thisPinClass && otherPinClass )
1934  {
1935  if ( thisPinClass->CanConnectTo( wire->GetStartPinClass() ) && otherPinClass->CanConnectTo( wire->GetEndPinClass() ) )
1936  {
1937  m_reverseCreate = false;
1938  }
1939  else if ( otherPinClass->CanConnectTo( wire->GetStartPinClass() ) && thisPinClass->CanConnectTo( wire->GetEndPinClass() ) )
1940  {
1941  m_reverseCreate = true;
1942  }
1943  else
1944  {
1945  wire = NULL;
1946  }
1947  }
1948  else if ( thisPinClass )
1949  {
1950  if ( thisPinClass->CanConnectTo( wire->GetStartPinClass() ) )
1951  {
1952  m_reverseCreate = false;
1953  }
1954  else if ( thisPinClass->CanConnectTo( wire->GetEndPinClass() ) )
1955  {
1956  m_reverseCreate = true;
1957  }
1958  else
1959  {
1960  wire = NULL;
1961  }
1962  }
1963  else if ( otherPinClass )
1964  {
1965  if ( otherPinClass->CanConnectTo( wire->GetEndPinClass() ) )
1966  {
1967  m_reverseCreate = false;
1968  }
1969  else if ( otherPinClass->CanConnectTo( wire->GetStartPinClass() ) )
1970  {
1971  m_reverseCreate = true;
1972  }
1973  else
1974  {
1975  wire = NULL;
1976  }
1977  }
1978  connect = wire;
1979  }
1980  else
1981  {
1982  connect = m_tmplObject;
1983  }
1984 
1985  return connect;
1986 }
1987 
1988 
1989 bool a2dConnectionGenerator::GeneratePossibleConnections( a2dCanvasObject* object, a2dPinClass* pinClass, a2dConnectTask task, double x, double y, double margin ) const
1990 {
1991  if ( !m_generatePins )
1992  {
1993  if ( ! wxDynamicCast( object, a2dWirePolylineL ) ) // this object should always deliver pins
1994  return false;
1995  }
1996 
1997  assert( pinClass );
1998  bool found = object->GeneratePins( pinClass, task, x, y, margin );
1999  return found;
2000 }
2001 
2003 {
2004  wxASSERT_MSG( pinClass, wxT( "pinClass cannot be NULL, maybe use a2dPinClass::Any?" ) );
2005 /*
2006  // no pinclass, only happens when trying to start a new wire on an object/wire, without knowing start pinclass.
2007  if ( pinClassTo == a2dPinClass::Any )
2008  {
2009  if ( obj && obj->GetRoot() && obj->GetRoot()->GetLayerSetup() )
2010  {
2011  a2dLayerInfo* info = obj->GetRoot()->GetLayerSetup()->GetLayerIndex()[ obj->GetLayer() ];
2012  if ( info != wxNullLayerInfo )
2013  return info->GetPinClass();
2014 
2015  }
2016 
2017  a2dPinClass* objectPinClassStart = pinClass->CanConnectToAsObject();
2018  if ( objectPinClassStart )
2019  return objectPinClassStart;
2020 
2021  if ( obj->IsConnect() )
2022  return m_anypinclass;
2023  else
2024  return m_anypinclass;
2025  }
2026 */
2027 
2028  switch ( task )
2029  {
2030  case a2d_StartWire:
2031  {
2032  return pinClass;
2033  }
2034  break;
2035  case a2d_FinishWire:
2036  {
2037  return pinClassTo;
2038  }
2039  break;
2040 
2042  {
2043  a2dPinClass* PinClass = pinClass->CanConnectTo( NULL );
2044  return PinClass;
2045  }
2046 
2048  {
2049  a2dPinClass* PinClass = pinClass->CanConnectTo( NULL );
2050  return PinClass;
2051  }
2052  break;
2053 
2055  {
2056  a2dPinClass* PinClass = pinClass->CanConnectTo( NULL );
2057  return PinClass;
2058  }
2059  break;
2060 
2061  default:
2062 
2063  break;
2064  }
2065 
2066  return NULL;
2067 }
2068 
2069 bool a2dConnectionGenerator::GeneratePinsToConnect( a2dDrawingPart* part, a2dCanvasObject* root, a2dPinClass* pinClassToConnectTo, a2dConnectTask task, double xpin, double ypin, a2dCanvasObjectFlagsMask mask )
2070 {
2071  double x = xpin;
2072  double y = ypin;
2073 
2074  a2dIterC ic( part );
2075  if ( a2dPin::GetWorldBased() )
2076  ic.SetHitMarginWorld( 0 );//a2dCanvasGlobals->GetHabitat()->GetPinSize()/2.0 );
2077  else
2078  ic.SetHitMarginDevice( 0 );// a2dCanvasGlobals->GetHabitat()->GetPinSize()/2.0 );
2079 
2080  //double m = ic.GetHitMarginWorld();
2081  double m = a2dCanvasGlobals->GetHabitat()->GetPinSize()/2.0;
2082 
2083  //we still want to do this, else even wires will not have generated pins.
2084  //if ( !m_generatePins )
2085  // return false;
2086 
2087  a2dWalker_GeneratePinsToConnect generateconnectpins( mask, pinClassToConnectTo, task, xpin, ypin );
2088  if ( root == part->GetShowObject() )
2089  {
2090  ic.SetLayer( wxLAYER_ALL ); //generate pins not layer specific (all generates pins)
2091 
2092  generateconnectpins.SetBoundingBoxCondition( _ON | _IN );
2093  generateconnectpins.SetBoundingBox( a2dBoundingBox( x - m , y - m , x + m , y + m ) );
2094  //Try Generate pins on all objects hit.
2095  a2dAffineMatrix cworld = root->GetTransformMatrix();
2096  cworld.Invert();
2097 
2098  a2dIterCU cu( ic, cworld );
2099  return generateconnectpins.Start( ic, root );
2100  }
2101  else
2102  {
2103  ic.SetLayer( wxLAYER_ALL ); //generate pins does not need to be layer specific in one object
2104  // Generate pins only on a specific object.
2105  return generateconnectpins.Start( ic, root, false );
2106  }
2107 }
2108 
2109 a2dPin* a2dConnectionGenerator::SearchPinForFinishWire( a2dCanvasObject* root, a2dPin* pinToConnectTo, a2dPinClass* pinClassToConnectTo, double margin, a2dCanvasObjectFlagsMask mask )
2110 {
2111  double x = pinToConnectTo->GetAbsX();
2112  double y = pinToConnectTo->GetAbsY();
2113 
2114  double m = margin;
2115 
2116  a2dWalker_FindPinsToConnectToPin findconnectpins( mask, pinToConnectTo, a2d_FinishWire, margin );
2117  findconnectpins.SetBoundingBox( a2dBoundingBox( x - m , y - m , x + m , y + m ) );
2118  findconnectpins.SetBoundingBoxCondition( _ON | _IN );
2119  findconnectpins.StopAtFirst( true );
2120  findconnectpins.Start( root );
2121 
2122  if ( findconnectpins.m_found.size() )
2123  return wxDynamicCast( findconnectpins.m_found.front().Get(), a2dPin );
2124  return NULL;
2125 }
2126 
2127 a2dPin* a2dConnectionGenerator::SearchPinForStartWire( a2dCanvasObject* root, double xpin, double ypin, a2dPinClass* pinClassToConnectTo, double margin, a2dCanvasObjectFlagsMask mask )
2128 {
2129  /* MIGHT BE INTERESTING extended testing hits all pins, so can decide what it wants as hit.
2130 
2131  a2dHitEvent hitinfo( xw, yw, false, a2dCANOBJHITOPTION_NONE, true );
2132  a2dCanvasObject* hit = GetCanvasView()->IsHitWorld( hitinfo, wxLAYER_ALL );
2133 
2134  a2dPin *pin = 0;
2135  {
2136  //First try to find object pins which are not of connection/wire objects
2137  int i;
2138  float minDist = FLT_MAX;
2139  for( i=0; i< hitinfo.m_extended.size(); i++ )
2140  {
2141  a2dPin *pin2 = wxDynamicCast( hitinfo.m_extended[i].GetObject(), a2dPin );
2142  if(
2143  pin2 &&
2144  !pin2->ConnectedTo() &&
2145  pin2->GetPinClass() && pin2->GetPinClass()->IsObjectPin() &&
2146  hitinfo.m_extended[i].GetHitType().m_distance < minDist
2147  )
2148  {
2149  pin = pin2;
2150  how2 = hitinfo.m_extended[i].GetHitType();
2151  minDist = how2.m_distance;
2152  }
2153  }
2154  if ( !pin )
2155  //Now try to find object pins which are of connection/wire objects
2156  for( i=0; i< hitinfo.m_extended.size(); i++ )
2157  {
2158  a2dPin *pin2 = wxDynamicCast( hitinfo.m_extended[i].GetObject(), a2dPin );
2159  if(
2160  pin2 &&
2161  !pin2->ConnectedTo() &&
2162  pin2->GetPinClass() && !pin2->GetPinClass()->IsObjectPin() ) &&
2163  hitinfo.m_extended[i].GetHitType().m_distance < minDist
2164  )
2165  {
2166  pin = pin2;
2167  how2 = hitinfo.m_extended[i].GetHitType();
2168  minDist = how2.m_distance;
2169  }
2170  }
2171  }
2172  */
2173 
2174  double m = margin;
2175  a2dWalker_FindPinsToConnect findconnectpins( mask, pinClassToConnectTo, a2d_StartWire, xpin, ypin, margin );
2176  findconnectpins.SetBoundingBox( a2dBoundingBox( xpin - m , ypin - m , xpin + m , ypin + m ) );
2177  findconnectpins.SetBoundingBoxCondition( _ON | _IN );
2178  findconnectpins.StopAtFirst( true );
2179  findconnectpins.Start( root );
2180 
2181  m_returnPinClass = findconnectpins.m_returnPinclass;
2182  m_returnConnect = NULL;
2183 
2184  if ( findconnectpins.m_found.size() )
2185  return wxDynamicCast( findconnectpins.m_found.front().Get(), a2dPin );
2186  return NULL;
2187 }
2188 
2190 {
2191  a2dAffineMatrix cworld = root->GetTransformMatrix();
2192  cworld.Invert();
2193 
2194  a2dBoundingBox mapped = root->GetMappedBbox( cworld );
2195 
2196  a2dWalker_SetPinsToBeginState resetpins( mask );
2197  resetpins.SetBoundingBox( mapped );
2198  resetpins.SetBoundingBoxCondition( _ON | _IN );
2199  resetpins.Start( root );
2200 }
2201 
2203 {
2204  a2dWalker_SetPinsToEndState endstate( mask );
2205  endstate.Start( root );
2206 }
2207 
2209 {
2210  if ( !m_generatePins )
2211  {
2212  if ( ! wxDynamicCast( connectObject, a2dWirePolylineL ) ) // this object should always deliver pins
2213  return false;
2214  }
2215 
2216  a2dIterC ic( part );
2217  if ( a2dPin::GetWorldBased() )
2218  ic.SetHitMarginWorld( a2dCanvasGlobals->GetHabitat()->GetPinSize()/2.0 );
2219  else
2220  ic.SetHitMarginDevice( a2dCanvasGlobals->GetHabitat()->GetPinSize()/2.0 );
2221 
2222  double m = ic.GetHitMarginWorld();
2223 
2224  a2dWalker_GeneratePinsToConnectObject feedbconnections( mask, connectObject, a2d_GeneratePinsForPinClass );
2225  feedbconnections.Start( ic, root );
2226  return true;
2227 }
2228 
2229 bool a2dConnectionGenerator::ConnectToPinsObject( a2dCanvasObject* root, a2dCanvasObject* connectObject, double margin, a2dPinClass* pinClassToConnectTo, a2dCanvasObjectFlagsMask mask )
2230 {
2231  a2dWalker_ConnectToPinsObject connectWherePossible( mask, connectObject, a2d_GeneratePinsForPinClass, margin );
2232  connectWherePossible.Start( root, true );
2233  return true;
2234 }
2235 
2236 //----------------------------------------------------------------------------
2237 // a2dConnectionGeneratorInOut
2238 //----------------------------------------------------------------------------
2239 
2242 
2245 {
2246  m_anypinclass = NULL;
2247 
2248  //Input <=> Output
2249 
2250  Input = new a2dPinClass( wxT( "input" ) );
2251  Output->SetAngleLine( false );
2252  Output = new a2dPinClass( wxT( "output" ) );
2253  Input->SetAngleLine( false );
2254  Input->SetConnectionGenerator( this );
2255  Output->SetConnectionGenerator( this );
2256  Input->AddConnect( Output );
2257  Output->AddConnect( Input );
2258  a2dPinClass::m_allPinClasses.push_back( Input );
2259  a2dPinClass::m_allPinClasses.push_back( Output );
2260 
2261  //Setup a wire/pin to define which pins can connect, and with which wire
2262  a2dWirePolylineL* wireio = new a2dWirePolylineL();
2263  a2dStroke wirestroke = a2dStroke( wxColour( 0, 50, 0 ), 2, a2dSTROKE_LONG_DASH );
2264  wireio->SetStroke( wirestroke );
2265  wireio->SetStartPinClass( Input );
2266  wireio->SetEndPinClass( Output );
2267  a2dArrow* arrow2 = new a2dArrow( 0, 0, 4, 0, 2 );
2268  arrow2->SetStroke( wirestroke );
2269  wireio->SetEnd( arrow2 );
2270  SetConnectObject( wireio );
2271 }
2272 
2274 {
2275 }
2276 
2278 {
2279  switch ( task )
2280  {
2281  case a2d_StartWire:
2282  {
2283  if ( pinClass == Input )
2284  return Output;
2285 
2286  if ( pinClass == Output )
2287  return Input;
2288  }
2289  break;
2290  case a2d_FinishWire:
2291  {
2292  if ( pinClass == Input )
2293  return Output;
2294 
2295  if ( pinClass == Output )
2296  return Input;
2297  }
2298  break;
2299 
2301  {
2302  a2dPinClass* PinClass = pinClass->CanConnectTo( NULL );
2303  return PinClass;
2304  }
2305  break;
2306 
2308  {
2309  a2dPinClass* PinClass = pinClass->CanConnectTo( NULL );
2310  return PinClass;
2311  }
2312  break;
2313 
2315  {
2316  a2dPinClass* PinClass = pinClass->CanConnectTo( NULL );
2317  return PinClass;
2318  }
2319  break;
2320 
2321  default:
2322 
2323  break;
2324  }
2325 
2326  return NULL;
2327 }
2328 
2329 //----------------------------------------------------------------------------
2330 // a2dConnectionGeneratorObjectWire
2331 //----------------------------------------------------------------------------
2332 
2335 
2336 
2339 {
2340  m_anypinclass = NULL;
2341 
2342  //Object <=> Wire
2343  Object = new a2dPinClass( wxT( "object" ) );
2344  Object->SetConnectionGenerator( this );
2345  Object->SetAngleLine( false );
2346  Wire = new a2dPinClass( wxT( "wire" ) );
2347  Wire->SetConnectionGenerator( this );
2348  Wire->SetAngleLine( false );
2349 
2350  Object->AddConnect( Wire );
2351  Object->AddConnect( Object );
2352  Wire->AddConnect( Object );
2353  Wire->AddConnect( Wire );
2354 
2355  //Setup a wire/pin to define which pins can connect, and with which wire
2356  a2dWirePolylineL* wireio = new a2dWirePolylineL();
2357  a2dStroke wirestroke = a2dStroke( wxColour( 100, 250, 100 ), 2, a2dSTROKE_LONG_DASH );
2358  wireio->SetStroke( wirestroke );
2359  wireio->SetStartPinClass( Wire );
2360  wireio->SetEndPinClass( Wire );
2361  a2dPinClass::m_allPinClasses.push_back( Object );
2362  a2dPinClass::m_allPinClasses.push_back( Wire );
2363 
2364  a2dArrow* arrow2 = new a2dArrow( 0, 0, 4, 0, 2 );
2365  arrow2->SetStroke( wirestroke );
2366  wireio->SetEnd( arrow2 );
2367  SetConnectObject( wireio );
2368 }
2369 
2371 {
2372 }
2373 
2375 {
2376  switch ( task )
2377  {
2378  case a2d_StartWire:
2379  {
2380  if ( pinClass == Object )
2381  return Wire;
2382 
2383  if ( pinClass == Wire )
2384  return Object;
2385  }
2386  break;
2387  case a2d_FinishWire:
2388  {
2389  if ( pinClass == Object )
2390  return Wire;
2391 
2392  if ( pinClass == Wire )
2393  return Object;
2394  }
2395  break;
2396 
2398  {
2399  a2dPinClass* PinClass = pinClass->CanConnectTo( NULL );
2400  return PinClass;
2401  }
2402 
2404  {
2405  a2dPinClass* PinClass = pinClass->CanConnectTo( NULL );
2406  return PinClass;
2407  }
2408  break;
2409 
2411  {
2412  a2dPinClass* PinClass = pinClass->CanConnectTo( NULL );
2413  return PinClass;
2414  }
2415  break;
2416 
2417  default:
2418 
2419  break;
2420  }
2421 
2422  return NULL;
2423 }
2424 
2425 //----------------------------------------------------------------------------
2426 // a2dConnectionGeneratorDirectedFlow
2427 //----------------------------------------------------------------------------
2428 
2433 
2436 {
2437  m_anypinclass = NULL;
2438 
2439  // ObjectInput <=> ObjectOutput
2440 
2441  ObjectInput = new a2dPinClass( wxT( "objectinput" ) );
2442  ObjectOutput = new a2dPinClass( wxT( "objectoutput" ) );
2443  WireInput = new a2dPinClass( wxT( "wireinput" ) );
2444  WireOutput = new a2dPinClass( wxT( "wireoutput" ) );
2445  ObjectInput->SetAngleLine( false );
2446  ObjectOutput->SetAngleLine( false );
2447  WireInput->SetAngleLine( false );
2448  WireOutput->SetAngleLine( false );
2449 
2454 
2463 
2468 
2469  //Setup a wire/pin to define which pins can connect, and with which wire
2470  a2dWirePolylineL* wireio = new a2dWirePolylineL();
2471  a2dStroke wirestroke = a2dStroke( wxColour( 55, 250, 250 ), 2, a2dSTROKE_LONG_DASH );
2472  wireio->SetStroke( wirestroke );
2473  wireio->SetStartPinClass( WireInput );
2474  wireio->SetEndPinClass( WireOutput );
2475  a2dArrow* arrow2 = new a2dArrow( 0, 0, 4, 0, 2 );
2476  arrow2->SetStroke( wirestroke );
2477  wireio->SetEnd( arrow2 );
2478 
2479  SetConnectObject( wireio );
2480 
2481 }
2482 
2484 {
2485 }
2486 
2488 {
2489 /*
2490  if ( pinClass == a2dPinClass::Any )
2491  {
2492  if ( obj->IsConnect() )
2493  {
2494  if ( wxDynamicCast( obj, a2dWirePolylineL )->GetStartPinClass() == a2dPinClass::WireInput )
2495  return a2dPinClass::WireOutput;
2496  if ( wxDynamicCast( obj, a2dWirePolylineL )->GetStartPinClass() == a2dPinClass::WireOutput )
2497  return a2dPinClass::WireInput;
2498  else
2499  return NULL;
2500  }
2501  else
2502  {
2503  return a2dPinClass::Object;
2504  }
2505  }
2506 */
2507 
2508  switch ( task )
2509  {
2510  case a2d_StartWire:
2511  {
2512  if ( pinClass == ObjectInput )
2513  return WireOutput;
2514 
2515  if ( pinClass == ObjectOutput )
2516  return WireInput;
2517 
2518  if ( pinClass == WireInput )
2519  return ObjectOutput;
2520 
2521  if ( pinClass == WireOutput )
2522  return ObjectInput;
2523  }
2524  break;
2525  case a2d_FinishWire:
2526  {
2527  if ( pinClass == ObjectInput )
2528  return WireOutput;
2529 
2530  if ( pinClass == ObjectOutput )
2531  return WireInput;
2532 
2533  if ( pinClass == WireInput )
2534  return ObjectOutput;
2535 
2536  if ( pinClass == WireOutput )
2537  return ObjectInput;
2538  }
2539  break;
2540 
2542  {
2543  a2dPinClass* PinClass = pinClass->CanConnectTo( NULL );
2544  return PinClass;
2545  }
2546 
2548  {
2549  a2dPinClass* PinClass = pinClass->CanConnectTo( NULL );
2550  return PinClass;
2551  }
2552  break;
2553 
2555  {
2556  a2dPinClass* PinClass = pinClass->CanConnectTo( NULL );
2557  return PinClass;
2558  }
2559  break;
2560 
2561  default:
2562 
2563  break;
2564  }
2565 
2566  return NULL;
2567 }
2568 
2569 //----------------------------------------------------------------------------
2570 // a2dConnectionGeneratorTwoFlow
2571 //----------------------------------------------------------------------------
2572 
2581 
2582 
2585 {
2586  m_anypinclass = NULL;
2587 
2588  //FLOWA
2589 
2590  FlowAInput = new a2dPinClass( wxT( "FlowAinput" ) );
2591  FlowAOutput = new a2dPinClass( wxT( "FlowAoutput" ) );
2592  FlowAWireInput = new a2dPinClass( wxT( "FlowAwireinput" ) );
2593  FlowAWireOutput = new a2dPinClass( wxT( "FlowAwireoutput" ) );
2594 
2599 
2606 
2609 
2614 
2615  //Setup a wire/pin to define which pins can connect, and with which wire
2616  a2dWirePolylineL* wireio = new a2dWirePolylineL();
2617  a2dStroke wirestroke = a2dStroke( wxColour( 5, 250, 250 ), 2, a2dSTROKE_LONG_DASH );
2618  wireio->SetStroke( wirestroke );
2619  wireio->SetStartPinClass( FlowAWireInput );
2620  wireio->SetEndPinClass( FlowAWireOutput );
2621  a2dArrow* arrow2 = new a2dArrow( 0, 0, 4, 0, 2 );
2622  arrow2->SetStroke( wirestroke );
2623  wireio->SetEnd( arrow2 );
2624  SetConnectObject( wireio );
2625 
2626  FlowAInput->SetAngleLine( false );
2627  FlowAWireInput->SetAngleLine( false );
2628  FlowAWireOutput->SetAngleLine( false );
2629  FlowAInput->SetAngleLine( false );
2630  FlowAOutput->SetAngleLine( false );
2631 
2632 
2633  //FLOWB
2634 
2635  FlowBInput = new a2dPinClass( wxT( "FlowBinput" ) );
2636  FlowBOutput = new a2dPinClass( wxT( "FlowBoutput" ) );
2637  FlowBWireInput = new a2dPinClass( wxT( "FlowBwireinput" ) );
2638  FlowBWireOutput = new a2dPinClass( wxT( "FlowBwireoutput" ) );
2639 
2644 
2651 
2654 
2659 
2660  //Setup a wire/pin to define which pins can connect, and with which wire
2661  a2dWirePolylineL* wireiob = new a2dWirePolylineL();
2662  a2dStroke wirestrokeb = a2dStroke( wxColour( 25, 0, 25 ), 1, a2dSTROKE_SOLID );
2663  wireiob->SetStroke( wirestrokeb );
2664  wireiob->SetStartPinClass( FlowBWireInput );
2665  wireiob->SetEndPinClass( FlowBWireOutput );
2666  a2dArrow* arrow2b = new a2dArrow( 0, 0, 4, 0, 2 );
2667  arrow2b->SetStroke( wirestrokeb );
2668  wireiob->SetEnd( arrow2b );
2669  SetConnectObjectFlowB( wireiob );
2670 
2671  FlowBInput->SetAngleLine( false );
2672  FlowBWireInput->SetAngleLine( false );
2673  FlowBWireOutput->SetAngleLine( false );
2674  FlowBInput->SetAngleLine( false );
2675  FlowBOutput->SetAngleLine( false );
2676 
2677 }
2678 
2680 {
2681 }
2682 
2684 {
2685  m_tmplObjectFlowB = tmplObject;
2686 }
2687 
2689 {
2690  return m_tmplObjectFlowB;
2691 }
2692 
2694 {
2695  switch ( task )
2696  {
2697  case a2d_StartWire:
2698  {
2699  if ( pinClass == FlowAInput )
2700  return FlowAWireOutput;
2701 
2702  if ( pinClass == FlowAOutput )
2703  return FlowAWireInput;
2704 
2705  if ( pinClass == FlowAWireInput )
2706  return FlowAOutput;
2707 
2708  if ( pinClass == FlowAWireOutput )
2709  return FlowAInput;
2710 
2711  if ( pinClass == FlowBInput )
2712  return FlowBWireOutput;
2713 
2714  if ( pinClass == FlowBOutput )
2715  return FlowBWireInput;
2716 
2717  if ( pinClass == FlowAWireInput )
2718  return FlowBOutput;
2719 
2720  if ( pinClass == FlowBWireOutput )
2721  return FlowBInput;
2722  }
2723  break;
2724  case a2d_FinishWire:
2725  {
2726  if ( pinClass == FlowAInput )
2727  return FlowAWireOutput;
2728 
2729  if ( pinClass == FlowAOutput )
2730  return FlowAWireInput;
2731 
2732  if ( pinClass == FlowAWireInput )
2733  return FlowAOutput;
2734 
2735  if ( pinClass == FlowAWireOutput )
2736  return FlowAInput;
2737 
2738  if ( pinClass == FlowBInput )
2739  return FlowBWireOutput;
2740 
2741  if ( pinClass == FlowBOutput )
2742  return FlowBWireInput;
2743 
2744  if ( pinClass == FlowBWireInput )
2745  return FlowBOutput;
2746 
2747  if ( pinClass == FlowBWireOutput )
2748  return FlowBInput;
2749  }
2750  break;
2751 
2753  {
2754  a2dPinClass* PinClass = pinClass->CanConnectTo( NULL );
2755  return PinClass;
2756  }
2757 
2759  {
2760  a2dPinClass* PinClass = pinClass->CanConnectTo( NULL );
2761  return PinClass;
2762  }
2763  break;
2764 
2766  {
2767  a2dPinClass* PinClass = pinClass->CanConnectTo( NULL );
2768  return PinClass;
2769  }
2770  break;
2771 
2772  default:
2773 
2774  break;
2775  }
2776 
2777  return NULL;
2778 }
2779 
2781 {
2782  a2dPinClass* thisPinClass = NULL;
2783  a2dPinClass* otherPinClass = NULL;
2784  if ( pinThis )
2785  thisPinClass = pinThis->GetPinClass();
2786  if ( pinOther )
2787  otherPinClass = pinOther->GetPinClass();
2788 
2789  if (
2790  pinThis &&
2791  ( thisPinClass == FlowAInput || thisPinClass == FlowAOutput || thisPinClass == FlowAWireInput || thisPinClass == FlowAWireOutput )
2792  )
2793  return a2dConnectionGenerator::CreateConnectObject( parent, pinThis, pinOther, undo );
2794  if (
2795  pinOther &&
2796  ( otherPinClass == FlowAInput || otherPinClass == FlowAOutput || otherPinClass == FlowAWireInput || otherPinClass == FlowAWireOutput )
2797  )
2798  return a2dConnectionGenerator::CreateConnectObject( parent, pinThis, pinOther, undo );
2799 
2800  // assume flow B
2801 
2804  a2dCanvasObject* ret = a2dConnectionGenerator::CreateConnectObject( parent, pinThis, pinOther, undo );
2805  m_tmplObject = save;
2806  return ret;
2807 }
Display Part of a a2dDrawing, in which a2dCanvasObjects are shown.
Definition: drawer.h:470
wxPoint2DDouble a2dPoint2D
this to define if coordinate numbers are integer or doubles
Definition: artglob.h:47
a2dPin * IsDislocated() const
Definition: canpin.cpp:1089
void SetConnectionGenerator(a2dConnectionGenerator *connectionGenerator)
Set class for generating new connection objects between object and pins.
Definition: canpin.h:720
static const a2dCanvasObjectFlagsMask BIN
Definition: candefs.h:192
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
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
Temporary object used in editing connected objects.
Definition: wire.h:202
#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
virtual bool GeneratePinsToConnectObject(a2dDrawingPart *part, a2dCanvasObject *root, a2dCanvasObject *connectObject, a2dPinClass *pinClassToConnectTo=NULL, a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::VISIBLE)
Generate pins on objects, and test which can connect to the given object.
a2dConnectionGeneratorInOut()
constructor
Generate pins on objects, which can connect to the given pinclass.
Definition: algos.h:1375
a2dCanvasObject * GetConnectObjectFlowB() const
return connect object.
The a2dBaseTool is used to derive tools from that are controlled by.
Definition: tools.h:379
a2dConnectTask
flags for searching a connecting a2dpinClass, for the connecting task at hand.
Definition: connectgen.h:40
static a2dPinClass * WireOutput
Pins of this class can only connect to ObjectOutput pins.
Definition: connectgen.h:519
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.
#define a2dACCUR
accuracy used to have some limit to calculation like hittesting
Definition: artglob.h:41
~a2dConnectionGeneratorTwoFlow()
destructor
const a2dAffineMatrix & GetTransformMatrix() const
get the matrix used to position the object
Definition: canobj.h:500
if set, set in the clone the PROPID_Original property to the copied object
Definition: gen.h:1212
a2dCanvasObjectPtr m_tmplObjectFlowB
Template for created object which represents a connection. e.g a2dWirePolylineL.
Definition: connectgen.h:585
Remove original and replace with one straight segment, dynamic pins move with segment.
Definition: connectgen.h:161
generate pins, given Connect/wire pinclass
Definition: connectgen.h:49
class to map references to objects stored in XML, in order to make the connection later on...
Definition: gen.h:3462
a2dPin * FindEndPin()
Get the end pin from the childs.
Definition: polygon.cpp:3035
virtual a2dPin * SearchPinForFinishWire(a2dCanvasObject *root, a2dPin *pinToConnectTo, a2dPinClass *pinClassToConnectTo, double margin, a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::VISIBLE)
static a2dPinClass * Output
Pins of this class can only connect to Input pins.
Definition: connectgen.h:444
unsigned int GetChildObjectsCount() const
get number of child objects
Definition: canobj.cpp:2570
~a2dConnectionGeneratorInOut()
destructor
a2dCanvasObjectList m_found
pins found
Definition: algos.h:1317
Add manhattan lines to end.
Definition: connectgen.h:167
Find pins in view, which can connect to the given pinclass.
Definition: algos.h:1264
void SetAnyPinClass(a2dPinClass *pinClass)
see GetAnyPinClass()
Definition: connectgen.h:242
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
used to add points to polygon objects
Definition: drawing.h:1959
virtual a2dPinClass * GetPinClassForTask(a2dPinClass *pinClass, a2dConnectTask task, a2dCanvasObject *obj=NULL, a2dPinClass *pinClassTo=NULL, a2dPin *pinFrom=NULL) const
return a a2dPinClass which should be used to connect to the input a2dPinClass.
void SetTransformMatrix(const a2dAffineMatrix &mat=a2dIDENTITY_MATRIX)
Returns the matrix used to position the object.
Definition: canobj.h:509
a2dDrawing * GetRoot() const
get a2dCanvasDocument of the object.
Definition: canobj.h:952
a2dConnectionGeneratorObjectWire()
constructor
void AddConnect(a2dPinClass *pinClass)
add a connection pinclass, to which this pin can connect
Definition: canpin.h:651
virtual a2dPinClass * GetPinClassForTask(a2dPinClass *pinClass, a2dConnectTask task, a2dCanvasObject *obj=NULL, a2dPinClass *pinClassTo=NULL, a2dPin *pinFrom=NULL) const
return a a2dPinClass which should be used to connect to the input a2dPinClass.
a2dObject * Clone(CloneOptions options, a2dRefMap *refs=NULL) const
create an exact copy of this property
Definition: gen.cpp:1199
~a2dConnectionGeneratorDirectedFlow()
destructor
static a2dPinClass * Input
Pins of this class can only connect to Output pins.
Definition: connectgen.h:442
generate pins, given Connect/wire pinclass
Definition: connectgen.h:48
used to connect two pins
Definition: drawing.h:2411
static a2dPinClass * Object
Pins of this class can only connect to Wire pins.
Definition: connectgen.h:477
if set, clone childs, otherwise ref-copy them
Definition: gen.h:1207
void OptimizeRerouteWires(a2dCanvasObject *parent, bool removeZero=true, bool allowredirect=true)
Definition: wire.cpp:1202
a command processor specially designed to work with a a2dCanvasDocument
Definition: drawing.h:1046
virtual void SetPending(bool pending)
set this object pending for update
Definition: canobj.cpp:2585
a2dPin * IsConnectedTo(a2dPin *pin=a2dAnyPin) const
Return the pin to which this pin is connected.
Definition: canpin.cpp:751
The base class for all drawable objects in a a2dCanvasDocument.
void SetReroute(bool onOff)
indicated if the wire still needs to be rerouted, used in routing algorithms of wire between objects...
Definition: wire.h:71
static a2dPinClass * FlowAWireInput
Pins of this class can only connect to FlowAWireOutput and FlowAOutput pins.
Definition: connectgen.h:560
Remove original and replace with manhattan lines.
Definition: connectgen.h:166
a2dPoint2D GetAbsXY() const
get absolute position of the pin ( after applying the parent&#39;s matrix and its own matrix ) ...
Definition: canpin.cpp:952
a2dCanvasObject is the base class for Canvas Objects.
Definition: canobj.h:371
~a2dConnectionGenerator()
destructor
Definition: connectgen.cpp:68
wxUint32 GetConnectedPinsNr() const
Get the number of connected pins.
Definition: canpin.cpp:738
bool RemoveReference(const wxString &idToRemove)
remove given reference if from reference map.
Definition: gen.cpp:4844
virtual a2dPinClass * GetPinClassForTask(a2dPinClass *pinClass, a2dConnectTask task, a2dCanvasObject *obj=NULL, a2dPinClass *pinClassTo=NULL, a2dPin *pinFrom=NULL) const
return a a2dPinClass which should be used to connect to the input a2dPinClass.
virtual bool GeneratePossibleConnections(a2dCanvasObject *object, a2dPinClass *pinClass, a2dConnectTask task, double x, double y, double margin) const
generate temporary pins to which objects can connect
a2dCanvasObjectList m_found
pins found
Definition: algos.h:1288
a2dPinClass * CanConnectTo(a2dPinClass *other=NULL) const
searches in the connection list for a given pin class
Definition: canpin.cpp:499
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
vertex list of line and arc segments.
Definition: polyver.h:600
virtual void SetPinsToEndState(a2dCanvasObject *root, a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::VISIBLE)
set end state of pins after tool is finsihed
a2dCanvasObject * GetConnectObject() const
return connect object.
void SetHitMarginWorld(double world)
used to extend a hittest with the given margin in world coordinates.
Definition: canobj.cpp:601
base command processor
Definition: comevt.h:829
static a2dPinClass * ObjectInput
Pins of this class can only connect to WireInput pins.
Definition: connectgen.h:513
static a2dPinClass * FlowBWireInput
Pins of this class can only connect to FlowBWireOutput and FlowBOutput pins.
Definition: connectgen.h:569
a2dConnectionGenerator()
constructor
Definition: connectgen.cpp:42
void SetBin(bool bin)
general flag use at will.
Definition: canobj.h:2259
static a2dPinClass * FlowBWireOutput
Pins of this class can only connect to FlowBInput and FlowBWireInput pins.
Definition: connectgen.h:571
void RotateRouteMethod()
cycle through routing methods
Definition: connectgen.cpp:74
int FindPinSegmentIndex(a2dPin *pinToFind, double margin=a2dACCUR)
find the index of the segment where the pin is on.
Definition: polygon.cpp:3074
~a2dConnectionGeneratorObjectWire()
destructor
find wire/connect pinclass, given start pinclass of start pin
Definition: connectgen.h:43
void CreateWiresOnPins(a2dCanvasObject *parent, const a2dCanvasObjectList &objectsToDrag, bool undo, bool onlyNonSelected=false)
create wires on pins which do not have wires, but directly are connected to other objects...
Definition: connectgen.cpp:163
wxUint64 a2dCanvasObjectFlagsMask
mask flags for a2dCanvasObject
Definition: candefs.h:152
bool MoveDynamicPinCloseTo(a2dPin *pin, const a2dPoint2D &point, bool final)
Move the given dynamic pin close to the given absolute point.
Definition: polygon.cpp:2993
a2dWirePolylineL is a polyline that adjusts itself when the objects it connects move ...
Definition: wire.h:42
bool Disconnect(a2dPin *pin=a2dAnyPin, bool forceErase=false)
Definition: canpin.cpp:789
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
used to change a property on objects
Definition: drawing.h:2244
a2dConnectionGeneratorTwoFlow()
constructor
void SetConnectObject(a2dCanvasObject *tmplObject)
the template object is used as a template for creating new wires between pins.
void SetPriority(wxUint8 priority)
used to set order of rerouting in a set of lines.
Definition: wire.h:83
#define forEachIn(listtype, list)
easy iteration for a2dlist
Definition: a2dlist.h:111
a2dCanvasObjectPtr m_tmplObject
Template for created object which represents a connection. e.g a2dWirePolylineL.
Definition: connectgen.h:382
void SetPropertyToObject(a2dObject *obj, const basetype &value, SetFlags setflags=set_none) const
Set the property in obj to value.
Definition: id.inl:238
void AdjustBeginEndPinAngle()
adjust pin angles to the last segment at end and begin of wire.
Definition: wire.cpp:406
double GetPosX() const
get x position from affine matrix
Definition: canobj.h:527
void SetHitMarginDevice(int pixels)
used to extend a hittest with the number of pixels.
Definition: canobj.cpp:596
void SetSegments(a2dVertexList *points)
Set the list of points ( the old list is NOT DELETED !!! )
Definition: polygon.cpp:830
Definition: bbox.h:26
bool GetRouteOneLine() const
see SetRouteOneLine()
Definition: canglob.h:649
#define wxStaticCast(obj, className)
The wxWindows 2.4.2 wxStaticCast is buggy. It evaluates its argument twice.
Definition: gen.h:123
a2dVertexListPtr GetSegments()
Get the list of points ( this is not a copy! )
Definition: polygon.h:219
bool Start(a2dCanvasObject *object)
Start traversing at object, returns true.
Definition: algos.cpp:2657
a2dCanvasObject * GetShowObject() const
return pointer of then currently shown object on the drawer.
Definition: drawer.h:680
Normal straight line segment in a2dVertexList and a2dVertexArray.
Definition: polyver.h:163
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
Definition: bbox.h:27
virtual a2dPin * SearchPinForStartWire(a2dCanvasObject *root, double xpin, double ypin, a2dPinClass *pinClassToConnectTo, double margin, a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::VISIBLE)
Class for rerouting wires.
Definition: route.h:51
used to disconnect two pins
Definition: drawing.h:2439
static std::list< a2dPinClass * > m_allPinClasses
a linked lists of all a2dPinClass&#39;es, so that one can get a class by name
Definition: canpin.h:757
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
bool HasPins(bool realcheck=false)
are there a2dPin derived children
Definition: canobj.cpp:6414
static a2dPinClass * FlowAInput
Pins of this class can only connect to FlowAWireOutput and FlowAOutput pins.
Definition: connectgen.h:556
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
static const a2dCanvasObjectFlagsMask EditingCopy
Definition: candefs.h:207
void SetBoundingBoxCondition(wxUint16 intersectionCondition)
if boundingbox is set, the object is testen against this condition, default _IN
Definition: algos.h:288
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.
a2dPin * FindBeginPin()
Get the begin pin from the childs.
Definition: polygon.cpp:3030
Remove from property in a hierarchy of a canvas document.
Definition: algos.h:188
Contains a2dDrawing Class to hold a drawing.
used to set the complete Segment list/array of polygons
Definition: drawing.h:2102
static a2dPinClass * FlowBOutput
Pins of this class can only connect to FlowBWireInput and FlowBInput pins.
Definition: connectgen.h:567
a2dArrow is used for having line begin and ends on specific objects.
Definition: canprim.h:198
set a2dCanvasObjects flags in a hierarchy of a a2dCanvasDocument
Definition: algos.h:486
virtual bool Submit(a2dCommand *command, bool storeIt=true)
next to the base class submit, it sets a2DocumentCommandProcessor for a2dCommand
Definition: comevt.cpp:842
used to add object to a a2dCanvasDocument in the current parent
Definition: drawing.h:1403
Keep manhattan lines at end intact.
Definition: connectgen.h:168
void SetVisible(bool visible)
set if this object will visible (be rendered or not)
Definition: canobj.h:1303
virtual a2dPinClass * GetPinClassForTask(a2dPinClass *pinClass, a2dConnectTask task, a2dCanvasObject *obj=NULL, a2dPinClass *pinClassTo=NULL, a2dPin *pinFrom=NULL) const
return a a2dPinClass which should be used to connect to the input a2dPinClass.
A 2x3 affine matrix class for 2D transformations.
Definition: afmatrix.h:53
a2dPoint2D GetPosXY() const
get position of object
Definition: canobj.h:533
Same as StraightSegment, unless there are dynamic pins on segment.
Definition: connectgen.h:165
int GetPinCount()
How many a2dPin derived children are there.
Definition: canobj.cpp:6455
static a2dPinClass * FlowAWireOutput
Pins of this class can only connect to FlowAInput and FlowAWireInput pins.
Definition: connectgen.h:562
bool IsDynamicPin() const
return true if this pin is a dynamic pin
Definition: canpin.h:418
a2dPinClass * GetPinClass() const
return the pin class of this pin
Definition: canpin.h:356
void AutoConnect(a2dCanvasObject *root, double margin)
Try to connect this pin to another pin at the same location.
Definition: canpin.cpp:1072
bool m_reverseCreate
how to create a connection
Definition: connectgen.h:392
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
while iterating a a2dCanvasDocument, this holds the context.
Definition: canobj.h:3212
double m_x
x endpoint of line
Definition: polyver.h:232
a2dWalker based algorithms
void Remove180DegPoints(a2dCanvasObject *sendCommandsTo=NULL, bool removeZeroFirst=true)
remove segments which are opposite direction overlapping.
Definition: polygon.cpp:2136
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
a2dBoundingBox GetMappedBbox(a2dIterC &ic, bool withExtend=true)
first translate boundingbox with cworld and recalculate at new position
Definition: canobj.cpp:3256
double m_y
y endpoint of line
Definition: polyver.h:235
virtual bool Submit(a2dCommand *command, bool storeIt=true)
Definition: drawing.cpp:5966
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
Reuse last straight segment at begin or end of line, dynamic pins move with segment.
Definition: connectgen.h:162
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
used to release object from a a2dCanvasDocument in the current parent
Definition: drawing.h:1437
void SetBoundingBox(const a2dBoundingBox &bbox)
if valid, objects must fit in this boundingbox
Definition: algos.h:285
static const a2dCanvasObjectFlagsMask VISIBLE
Definition: candefs.h:186
wxString GetName() const
get the name given to the pin.
Definition: canpin.h:322
void AddEditobject(a2dCanvasObject *object)
Add an editcopy object to the tool/document.
Definition: tools.cpp:916
a2dConnectionGenerator * GetConnectionGenerator() const
Get class for generating new connection objects between object and pins.
Definition: canpin.h:723
double GetAbsAngle() const
get absolute angle of the pin ( after applying the parent its matrix and it own matrix ) ...
Definition: canpin.cpp:990
a2dPinClass * m_anypinclass
template pinclass
Definition: connectgen.h:389
Generate pins on objects, and test which can connect to the given object.
Definition: algos.h:1415
bool GetRelease() const
get release flag
Definition: gen.h:1350
a2dCanvasCommandProcessor * GetCanvasCommandProcessor()
get a pointer to the command processor
Definition: drawing.cpp:375
wire classes for connecting objects.
double GetHitMarginWorld()
Get HitMargin in World units.
Definition: canobj.cpp:606
bool Start(a2dCanvasObject *object)
Start traversing at object, returns true.
Definition: algos.cpp:2722
An object of this class will update a a2dIterC with the required information.
Definition: canobj.h:3123
a2dConnectionGeneratorDirectedFlow()
constructor
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.
Set pins in begin state after wiring up some pins.
Definition: algos.h:1331
static a2dPinClass * Standard
Pins of this class can only connect to pins of the same class.
Definition: canpin.h:766
Same as StraightEndSegment, unless there are dynamic pins on segment.
Definition: connectgen.h:164
bool GetRouteOneLine()
see SetRouteOneLine()
Definition: wire.h:68
bool RerouteWire(a2dWirePolylineL *wire, a2dPin *dispin, a2dPin *startpin, bool startisbegin, bool final)
Reroute a wire.
Definition: route.cpp:367
void PrepareForRerouteWires(a2dBaseTool *tool=NULL, a2dRefMap *refs=NULL)
Definition: connectgen.cpp:495
static a2dPinClass * FlowAOutput
Pins of this class can only connect to FlowAWireInput and FlowAInput pins.
Definition: connectgen.h:558
bool Start(a2dCanvasObject *object)
called from within a2dCanvasDocument
Definition: algos.cpp:2480
Convert straight segments to manhattan lines and keep manhattan lines at end intact.
Definition: connectgen.h:169
static a2dPinClass * ObjectOutput
Pins of this class can only connect to WireOutput pins.
Definition: connectgen.h:515
base classes for tools and controller on top of the tools.
The a2dBoundingBox class stores one a2dBoundingBox of a a2dCanvasObject.
Definition: bbox.h:39
bool Invert(void)
Invert matrix.
Definition: afmatrix.cpp:197
virtual void SetPinsToBeginState(a2dCanvasObject *root, a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::VISIBLE)
set begin state of pins, before a tools starts asking feedback or after tool is finsihed ...
void SetRerouteAdded(bool onOff)
indicated if the wire is added recently to be rerouted, used in routing algorithms of wire between ob...
Definition: wire.h:77
Classes for generating connection between pins in canvas objects.
double Length()
calculate length of path
Definition: polyver.cpp:1772
static bool GetWorldBased()
get if pin sizes are in world coordinates, else it is in pixels.
Definition: canpin.h:319
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 Start(a2dCanvasObject *object)
called from within a2dCanvasDocument
Definition: algos.cpp:2340
void SetConnectObjectFlowB(a2dCanvasObject *tmplObject)
the template object is used as a template for creating new wires between pins.
a2dCanvasGlobal * a2dCanvasGlobals
global a2dCanvasGlobal to have easy access to global settings
Definition: canglob.cpp:1234
virtual bool AdjustAfterChange(bool final)
Definition: wire.cpp:446
virtual a2dPinClass * GetPinClassForTask(a2dPinClass *pinClass, a2dConnectTask task, a2dCanvasObject *obj=NULL, a2dPinClass *pinClassTo=NULL, a2dPin *pinFrom=NULL) const
return a a2dPinClass which should be used to connect to the input a2dPinClass.
size_t GetNumberOfSegments()
get the number of points in the pointlist
Definition: polygon.h:229
Reroute using Lee routing.
Definition: connectgen.h:163
static a2dPinClass * Wire
Pins of this class can only connect to Object pins.
Definition: connectgen.h:479
Connect objects, which can connect to the given object.
Definition: algos.h:1443
wxUint8 GetPriority() const
See SetPriority()
Definition: wire.h:86
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
void Append(a2dCanvasObject *obj)
append a a2dCanvasObject to the childobjects
Definition: canobj.cpp:6224
a2dCanvasObject * GetParent() const
get parent object of the pin
Definition: canpin.h:295
void SetEnd(a2dCanvasObject *end)
set object to draw as end point
Definition: polygon.cpp:1840
void SetAngleLine(bool value)
is there an angle line on the pin
Definition: canpin.h:668
stack based tools controller and tools for drawing and editing.
Set pins in end state after wiring up some pins.
Definition: algos.h:1352
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
static a2dPinClass * FlowBInput
Pins of this class can only connect to FlowBWireOutput and FlowBOutput pins.
Definition: connectgen.h:565
find normal object pinclass, given Connect/wire pinclass
Definition: connectgen.h:52
when a new wire or other connection object needs to be created,
Definition: connectgen.h:153
bool GetReroute() const
see SetReroute()
Definition: wire.h:74
wxInt64 GetUniqueSerializationId() const
return a unique id for this object
Definition: gen.cpp:1450
bool EliminateMatrix()
reduce matrix to identity without replacing object
Definition: polygon.cpp:812
general canvas module declarations and classes
static a2dPinClass * WireInput
Pins of this class can only connect to ObjectInput pins.
Definition: connectgen.h:517
connectgen.cpp Source File -- Sun Oct 12 2014 17:04:15 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation