wxArt2D
sttool.cpp
Go to the documentation of this file.
1 /*! \file canvas/src/sttool.cpp
2  \author Klaas Holwerda
3 
4  Copyright: 2001-2004 (c) Klaas Holwerda
5 
6  Licence: wxWidgets Licence
7 
8  RCS-ID: $Id: sttool.cpp,v 1.389 2009/10/01 19:22:35 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 <algorithm>
22 
23 #include "wx/canvas/canmod.h"
24 #include "wx/filename.h"
25 
26 #include "wx/canvas/sttool.h"
27 #include "wx/canvas/edit.h"
28 
29 #if defined(__WXMSW__) && defined(__MEMDEBUG__)
30 #include <wx/msw/msvcrt.h>
31 #endif
32 
33 #define CDRAWER2D GetDrawingPart()->GetDrawer2D()
34 
35 //#include "wx/genart/prfl.h"
36 //#include "wx/genart/prfltmr.h"
37 //#include "wx/genart/prflenbl.h"
38 
39 IMPLEMENT_CLASS( a2dStToolContr, a2dToolContr )
40 IMPLEMENT_CLASS( a2dStTool, a2dBaseTool )
41 IMPLEMENT_CLASS( a2dZoomTool, a2dStTool )
42 IMPLEMENT_CLASS( a2dDragTool, a2dStTool )
43 IMPLEMENT_CLASS( a2dDragOrgTool, a2dStTool )
44 IMPLEMENT_CLASS( a2dDragNewTool, a2dDragTool )
45 IMPLEMENT_CLASS( a2dCopyTool, a2dDragTool )
46 IMPLEMENT_CLASS( a2dRotateTool, a2dStTool )
47 IMPLEMENT_CLASS( a2dDeleteTool, a2dStTool )
48 IMPLEMENT_CLASS( a2dSelectTool, a2dStTool )
49 IMPLEMENT_CLASS( a2dStDrawTool, a2dStTool )
50 IMPLEMENT_CLASS( a2dImageTool, a2dStDrawTool )
51 IMPLEMENT_CLASS( a2dDrawRectangleTool, a2dStDrawTool )
52 IMPLEMENT_CLASS( a2dDrawCircleTool, a2dStDrawTool )
53 IMPLEMENT_CLASS( a2dDrawLineTool, a2dStDrawTool )
54 IMPLEMENT_CLASS( a2dDrawEllipseTool, a2dStDrawTool )
55 IMPLEMENT_CLASS( a2dDrawEllipticArcTool, a2dStDrawTool )
56 IMPLEMENT_CLASS( a2dDrawArcTool, a2dStDrawTool )
57 IMPLEMENT_CLASS( a2dDrawPolylineLTool, a2dStDrawTool )
58 IMPLEMENT_CLASS( a2dDrawWirePolylineLTool, a2dDrawPolylineLTool )
59 IMPLEMENT_CLASS( a2dDrawPolygonLTool, a2dStDrawTool )
60 IMPLEMENT_CLASS( a2dDrawVPathTool, a2dStDrawTool )
61 IMPLEMENT_CLASS( a2dDrawTextTool, a2dStDrawTool )
62 IMPLEMENT_CLASS( a2dDragMultiTool, a2dStTool )
63 IMPLEMENT_CLASS( a2dDragMultiNewTool, a2dDragMultiTool )
64 IMPLEMENT_CLASS( a2dCopyMultiTool, a2dDragMultiTool )
65 IMPLEMENT_CLASS( a2dPropertyTool, a2dStTool )
66 IMPLEMENT_CLASS( a2dFollowLink, a2dStTool )
67 IMPLEMENT_CLASS( a2dMovePinTool, a2dStTool )
68 
69 const a2dCommandId a2dDrawRectangleTool::COMID_PushTool_DrawRectangle( wxT( "PushTool_DrawRectangle" ) );
70 const a2dCommandId a2dZoomTool::COMID_PushTool_Zoom( wxT( "PushTool_Zoom" ) );
71 const a2dCommandId a2dSelectTool::COMID_PushTool_Select( wxT( "PushTool_Select" ) );
72 const a2dCommandId a2dImageTool::COMID_PushTool_Image( wxT( "PushTool_Image" ) );
73 const a2dCommandId a2dDragTool::COMID_PushTool_Drag( wxT( "PushTool_Drag" ) );
74 const a2dCommandId a2dDragOrgTool::COMID_PushTool_DragOrg( wxT( "PushTool_DragOrg" ) );
75 const a2dCommandId a2dDragNewTool::COMID_PushTool_DragNew( wxT( "PushTool_DragNew" ) );
76 const a2dCommandId a2dCopyTool::COMID_PushTool_Copy( wxT( "PushTool_Copy" ) );
77 const a2dCommandId a2dRotateTool::COMID_PushTool_Rotate( wxT( "PushTool_Rotate" ) );
78 const a2dCommandId a2dDeleteTool::COMID_PushTool_Delete( wxT( "PushTool_Delete" ) );
79 const a2dCommandId a2dDrawCircleTool::COMID_PushTool_DrawCircle( wxT( "PushTool_DrawCircle" ) );
80 const a2dCommandId a2dDrawLineTool::COMID_PushTool_DrawLine( wxT( "PushTool_DrawLine" ) );
81 const a2dCommandId a2dDrawLineTool::COMID_PushTool_DrawLineScaledArrow( wxT( "PushTool_DrawLineScaledArrow" ) );
82 const a2dCommandId a2dDrawEllipseTool::COMID_PushTool_DrawEllipse( wxT( "PushTool_DrawEllipse" ) );
83 const a2dCommandId a2dDrawEllipticArcTool::COMID_PushTool_DrawEllipticArc( wxT( "PushTool_EllipticArc" ) );
84 const a2dCommandId a2dDrawEllipticArcTool::COMID_PushTool_DrawEllipticArc_Chord( wxT( "PushTool_EllipticArcChord" ) );
85 const a2dCommandId a2dDrawArcTool::COMID_PushTool_DrawArc( wxT( "PushTool_DrawArc" ) );
86 const a2dCommandId a2dDrawArcTool::COMID_PushTool_DrawArc_Chord( wxT( "PushTool_DrawArcChord" ) );
87 const a2dCommandId a2dDrawPolygonLTool::COMID_PushTool_DrawPolygonL( wxT( "PushTool_DrawPolygonL" ) );
88 const a2dCommandId a2dDrawPolygonLTool::COMID_PushTool_DrawPolygonL_Splined( wxT( "PushTool_DrawPolygonL_Splined" ) );
89 const a2dCommandId a2dDrawPolylineLTool::COMID_PushTool_DrawPolylineL( wxT( "PushTool_DrawPolylineL" ) );
90 const a2dCommandId a2dDrawPolylineLTool::COMID_PushTool_DrawPolylineL_Splined( wxT( "PushTool_DrawPolylineL_Splined" ) );
91 const a2dCommandId a2dDrawWirePolylineLTool::COMID_PushTool_DrawWirePolylineL( wxT( "PushTool_DrawWirePolylineL" ) );
92 const a2dCommandId a2dDragMultiTool::COMID_PushTool_DragMulti( wxT( "PushTool_DragMulti" ) );
93 const a2dCommandId a2dCopyMultiTool::COMID_PushTool_CopyMulti( wxT( "PushTool_CopyMulti" ) );
94 const a2dCommandId a2dDrawTextTool::COMID_PushTool_DrawText( wxT( "PushTool_DrawText" ) );
95 const a2dCommandId a2dPropertyTool::COMID_PushTool_Property( wxT( "PushTool_Property" ) );
96 const a2dCommandId a2dDrawVPathTool::COMID_PushTool_DrawVPath( wxT( "PushTool_DrawVPath" ) );
97 const a2dCommandId a2dFollowLink::COMID_PushTool_FollowLink( wxT( "PushTool_FollowLink" ) );
98 
99 WX_DEFINE_LIST( wxZoomList );
100 
101 extern const long TC_UNDO = wxNewId();
102 extern const long TC_REDO = wxNewId();
103 extern const long TC_ENDTOOL = wxNewId();
104 extern const long TC_ZOOMIN = wxNewId();
105 extern const long TC_ZOOMOUT = wxNewId();
106 extern const long TC_ZOOMBACK = wxNewId();
107 extern const long TC_ZOOMOUT2 = wxNewId();
108 extern const long TC_ZOOMIN2 = wxNewId();
109 extern const long TC_ZOOMPANXY = wxNewId();
110 extern const long TC_PROPERTY_XY = wxNewId();
111 
112 #define DEFAULTOpacityFactor 125 ;
113 
114 const a2dPropertyIdBool a2dStToolContr::PROPID_zoomfirst( wxT( "zoomfirst" ), a2dPropertyId::flag_none, false );
115 
116 DEFINE_EVENT_TYPE( a2dStToolContr::sm_showCursor )
117 
118 BEGIN_EVENT_TABLE( a2dStToolContr, a2dToolContr )
119  EVT_COM_EVENT( a2dStToolContr::OnComEvent )
120  EVT_MOUSE_EVENTS( a2dStToolContr::OnMouseEvent )
121  EVT_CHAR( a2dStToolContr::OnChar )
122  EVT_KEY_DOWN( a2dStToolContr::OnKeyDown )
123  EVT_KEY_UP( a2dStToolContr::OnKeyUp )
124  EVT_MENU( TC_UNDO , a2dStToolContr::Undo )
125  EVT_MENU( TC_REDO , a2dStToolContr::Redo )
126  EVT_MENU( TC_ENDTOOL , a2dStToolContr::EndTool )
127  EVT_MENU( TC_ZOOMIN , a2dStToolContr::ZoomWindowMenu )
128  EVT_MENU( TC_ZOOMBACK , a2dStToolContr::ZoomUndoMenu )
129  EVT_MENU( TC_ZOOMOUT , a2dStToolContr::ZoomoutMenu )
130  EVT_MENU( TC_ZOOMPANXY , a2dStToolContr::ZoomPanMenu )
131  EVT_MENU( TC_ZOOMOUT2 , a2dStToolContr::Zoomout2Menu )
132  EVT_MENU( TC_ZOOMIN2 , a2dStToolContr::Zoomin2Menu )
133  EVT_MENU( TC_PROPERTY_XY , a2dStToolContr::EditProperties )
134  EVT_MENUSTRINGS( a2dStToolContr::OnSetmenuStrings )
135 
136 END_EVENT_TABLE()
137 
138 
139 a2dStToolContr::a2dStToolContr( a2dDrawingPart* drawingPart, wxFrame* where, bool noStatusEvent ): a2dToolContr( drawingPart )
140 {
141  m_selectionStateUndo = false;
142  m_selectedAtEnd = false;
143 
144  m_defaultEventHandler = new a2dStToolEvtHandler( this );
145  m_defaultEventHandlerFixedStyle = new a2dStToolFixedToolStyleEvtHandler( this );
146 
147  m_noStatusEvent = noStatusEvent;
148  m_format = wxT( "%6.1f" );
149  m_statusStrings.push_back( "" );
150  m_statusStrings.push_back( "" );
151  m_statusStrings.push_back( "" );
152  m_statusStrings.push_back( "" );
153  m_statusStrings.push_back( "" );
154  m_statusStrings.push_back( "" );
155  m_statusStrings.push_back( "" );
156  m_statusStrings.push_back( "" );
157  m_statusStrings.push_back( "" );
158  m_statusStrings.push_back( "" );
159  m_statusStrings.push_back( "" );
160  m_statusStrings.push_back( "" );
161  m_statusStrings.push_back( "" );
162  m_statusStrings.push_back( "" );
163  m_statusStrings.push_back( "" );
164  m_statusStrings.push_back( "" );
165  m_statusStrings.push_back( "" );
166  m_statusStrings.push_back( "" );
167  m_statusStrings.push_back( "" );
168  m_statusStrings.push_back( "" );
169  m_statusStrings.push_back( "" );
170  m_drawingPart->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_ARROW ) );
171 
172  m_useEditOpaque = false;
173  m_editOpacityFactor = DEFAULTOpacityFactor;
174  m_zoomoutCentered = true;
175  m_draggingCanvas = false;
176  m_draggingCanvasOption = true;
177  m_dragstartx = 0;
178  m_dragstarty = 0;
179  m_mouse_x = m_mouse_y = 0;
180 
181  m_dragmode = wxDRAW_COPY;
182  m_drawmode = a2dFILLED;
183  m_defaultBehavior = wxTC_DefaultBehavior;
184  m_where = where;
185  m_noSnapkey = 0;
186 
187  m_topTool = NULL;
188  m_toolForZoom = new a2dZoomTool( this );
189  //OR
190  //m_topTool = m_toolForZoom;
191  //PushTool(m_topTool);
192 
193  m_mousemenu = new wxMenu( _( "ZOOM" ), ( long )0 );
194  m_mousemenu->Append( TC_ENDTOOL, _( "end tool" ) );
195  m_mousemenu->AppendSeparator();
196  m_mousemenu->Append( TC_UNDO, _( "undo" ) );
197  m_mousemenu->Append( TC_REDO, _( "redo" ) );
198  m_mousemenu->AppendSeparator();
199  m_mousemenu->Append( TC_ZOOMIN, _( "Zoom Window" ) );
200  m_mousemenu->Append( TC_ZOOMBACK, _( "Zoom Undo" ) );
201  m_mousemenu->Append( TC_ZOOMOUT, _( "Zoom out" ) );
202  m_mousemenu->Append( TC_ZOOMOUT2, _( "Zoom out 2X" ) );
203  m_mousemenu->Append( TC_ZOOMIN2, _( "Zoom in 2X" ) );
204  m_mousemenu->Append( TC_ZOOMPANXY, _( "Pan to XY" ) );
205  m_mousemenu->Append( TC_PROPERTY_XY, _( "Edit Properties" ) );
206 }
207 
208 
210 {
211  if( m_mousemenu )
212  delete m_mousemenu;
213 
214  m_drawingPart = NULL;
215 
217  a2dToolContr::PopTool( tool );
218  while ( tool )
219  {
220  tool = NULL;
221  a2dToolContr::PopTool( tool );
222  }
223 
224  m_zoomstack.DeleteContents( true );
225 }
226 
228 {
229  StopAllTools();
230  if ( m_topTool )
231  {
233  PushTool( m_topTool );
234  }
235 }
236 
237 void a2dStToolContr::SetMousePopupMenu( wxMenu* mousemenu )
238 {
239  if ( m_mousemenu )
240  delete m_mousemenu;
241  m_mousemenu = mousemenu;
242 }
243 
244 void a2dStToolContr::Undo( wxCommandEvent& )
245 {
246  a2dDrawing* drawing = m_drawingPart->GetDrawing();
247  drawing->GetCommandProcessor()->Undo();
248 }
249 
250 void a2dStToolContr::Redo( wxCommandEvent& )
251 {
252  a2dDrawing* drawing = m_drawingPart->GetDrawing();
253  drawing->GetCommandProcessor()->Redo();
254 }
255 
256 void a2dStToolContr::EndTool( wxCommandEvent& )
257 {
259  if ( GetFirstTool() && GetFirstTool()->AllowPop() )
260  PopTool( tool );
261 }
262 
263 void a2dStToolContr::EditProperties( wxCommandEvent& )
264 {
265  a2dPropertyTool* propedit = new a2dPropertyTool( this );
266  PushTool( propedit );
267  propedit->SetOneShot();
268  propedit->StartEditing( m_mouse_x, m_mouse_y );
269 }
270 
272 {
273  if ( m_drawingPart->GetDrawing() &&
275  event.GetEventObject() == m_drawingPart->GetDrawing()->GetCommandProcessor() &&
277  )
278  {
279  if ( m_mousemenu->FindItem( TC_UNDO ) )
280  {
281  m_mousemenu->SetLabel( TC_UNDO, event.GetUndoMenuLabel() );
282  m_mousemenu->Enable( TC_UNDO, event.CanUndo() );
283  }
284  if ( m_mousemenu->FindItem( TC_REDO ) )
285  {
286  m_mousemenu->SetLabel( TC_REDO, event.GetRedoMenuLabel() );
287  m_mousemenu->Enable( TC_REDO, event.CanRedo() );
288  }
289  }
290  event.Skip();
291 }
292 
293 void a2dStToolContr::SetZoomFirst( bool zoomfirst )
294 {
295  if ( !GetFirstTool() && zoomfirst )
296  {
298  PushTool( m_topTool );
299  }
300 }
301 
303 {
304  m_topTool = toolOnTop;
305  if ( !GetFirstTool() && m_topTool )
306  PushTool( m_topTool );
307 }
308 
310 {
311  wxASSERT_MSG( wxDynamicCast( toolForZoom, a2dStTool ) != 0, wxT( "Only a2dStTool can be pushed into a2dStToolContr, and not NULL" ) );
312  m_toolForZoom = toolForZoom;
313 }
314 
315 void a2dStToolContr::ZoomWindowMenu( wxCommandEvent& )
316 {
317  ZoomWindow();
318 }
319 
320 void a2dStToolContr::ZoomPanMenu( wxCommandEvent& )
321 {
322  ZoomPan();
323 }
324 
325 void a2dStToolContr::ZoomUndoMenu( wxCommandEvent& )
326 {
327  ZoomUndo();
328 }
329 
330 void a2dStToolContr::ZoomoutMenu( wxCommandEvent& )
331 {
332  Zoomout();
333 }
334 
335 void a2dStToolContr::Zoomout2Menu( wxCommandEvent& )
336 {
337  Zoomout2();
338 }
339 
340 void a2dStToolContr::Zoomin2Menu( wxCommandEvent& )
341 {
342  Zoomin2();
343 }
344 
346 {
347  a2dBaseTool* tool = m_toolForZoom->TClone( clone_deep );
348  tool->SetOneShot();
349  PushTool( tool );
350 }
351 
353 {
354  double mouse_worldx, mouse_worldy;
355  GetDrawingPart()->MouseToToolWorld( m_mouse_x, m_mouse_y, mouse_worldx, mouse_worldy );
356  mouse_worldx -= CDRAWER2D->GetVisibleWidth() / 2;
357  mouse_worldy -= CDRAWER2D->GetVisibleHeight() / 2;
358 
359  Zoom( mouse_worldx, mouse_worldy, CDRAWER2D->GetUppX(), CDRAWER2D->GetUppY() );
360 }
361 
363 {
364  a2dBoundingBox zoom;
365  if ( !m_zoomstack.size() )
366  {
367  Zoomout();
368  return;
369  }
370  wxZoomList::compatibility_iterator node = m_zoomstack.GetFirst();
371  zoom = *node->GetData();
372  delete node->GetData();
373  m_zoomstack.DeleteNode( node );
374 
375  CDRAWER2D->SetMappingWidthHeight( zoom.GetMinX(), zoom.GetMinY(), zoom.GetWidth(), zoom.GetHeight() );
376 }
377 
379 {
380  if ( wxDynamicCast( m_drawingPart->GetDisplayWindow(), a2dCanvas ) )
381  {
382  a2dCanvas* can = wxStaticCast( m_drawingPart->GetDisplayWindow(), a2dCanvas );
384  }
385  else if ( wxDynamicCast( m_drawingPart->GetDisplayWindow(), a2dCanvasSim ) )
386  {
387  a2dCanvasSim* can = wxStaticCast( m_drawingPart->GetDisplayWindow(), a2dCanvasSim );
389  }
390  else
391  wxASSERT_MSG( 0, wxT( "not implemented for this type of canvas" ) );
392  a2dGeneralGlobals->RecordF( this, _T( "zoomout" ) );
393 }
394 
396 {
397  int dx, dy;
398  m_drawingPart->GetDisplayWindow()->GetClientSize( &dx, &dy );
399  if ( dy > dx ) dx = dy;
400 
401  Zoom( CDRAWER2D->GetVisibleMinX() - CDRAWER2D->GetUppX()*dx / 2,
402  CDRAWER2D->GetVisibleMinY() - CDRAWER2D->GetUppY()*dy / 2,
403  CDRAWER2D->GetUppX() * 2, CDRAWER2D->GetUppY() * 2 );
404 }
405 
407 {
408  int dx, dy;
409  m_drawingPart->GetDisplayWindow()->GetClientSize( &dx, &dy );
410  if ( dy > dx ) dx = dy;
411 
412  Zoom( CDRAWER2D->GetVisibleMinX() + CDRAWER2D->GetUppX()*dx / 4,
413  CDRAWER2D->GetVisibleMinY() + CDRAWER2D->GetUppY()*dy / 4,
414  CDRAWER2D->GetUppX() * 0.5, CDRAWER2D->GetUppY() * 0.5 );
415 }
416 
418 {
419  int dx, dy;
420  m_drawingPart->GetDisplayWindow()->GetClientSize( &dx, &dy );
421  if ( dy > dx ) dx = dy;
422 
423  double mouse_worldx, mouse_worldy;
424  GetDrawingPart()->MouseToToolWorld( m_mouse_x, m_mouse_y, mouse_worldx, mouse_worldy );
425  mouse_worldx -= CDRAWER2D->GetUppX() * dx / 2;
426  mouse_worldy -= CDRAWER2D->GetUppY() * dy / 2;
427 
428  Zoom( mouse_worldx, mouse_worldy, CDRAWER2D->GetUppX() * 2, CDRAWER2D->GetUppY() * 2 );
429 }
430 
432 {
433  int dx, dy;
434  m_drawingPart->GetDisplayWindow()->GetClientSize( &dx, &dy );
435  if ( dy > dx ) dx = dy;
436 
437  double mouse_worldx, mouse_worldy;
438  GetDrawingPart()->MouseToToolWorld( m_mouse_x, m_mouse_y, mouse_worldx, mouse_worldy );
439  mouse_worldx -= CDRAWER2D->GetUppX() * dx / 4;
440  mouse_worldy -= CDRAWER2D->GetUppY() * dy / 4;
441 
442  Zoom( mouse_worldx, mouse_worldy, CDRAWER2D->GetUppX() * 0.5, CDRAWER2D->GetUppY() * 0.5 );
443 }
444 
445 void a2dStToolContr::Zoom( double x, double y, double uppx, double uppy )
446 {
447  CDRAWER2D->SetMappingUpp( x, y, uppx, uppy );
448  a2dGeneralGlobals->RecordF( this, _T( "zoom %f %f %f %f upp" ), x, y, uppx, uppy );
449 }
450 
452 {
454  wxASSERT_MSG( wxDynamicCast( tool, a2dStTool ) != 0, wxT( "Only a2dStTool can be pushed into a2dStToolContr" ) );
455 
456  bool res = a2dToolContr::PushTool( tool );
457  SetStateString();
458  return res;
459 }
460 
462 {
464  a2dToolContr::PopTool( tool, abort );
465 
466  if ( !tool )
467  return false;
468 
469  if ( GetFirstTool() ) //more tools stacked
470  {
471  //recursive pop tools until no more stopped tools.
472  if ( GetFirstTool()->GetStopTool() )
473  PopTool( tool );
474 
475  ActivateTop( true );
476  }
477  else
478  {
479  //always available
480  if ( m_topTool )
481  {
482  PushTool( m_topTool );
483  ActivateTop( true );
484  }
485  else
486  m_drawingPart->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_ARROW ) );
487  }
488  SetStateString();
489  return true;
490 }
491 
493 {
494  if ( GetEvtHandlerEnabled() && m_drawingPart )
495  {
496  if ( event.GetId() == a2dComEvent::sm_changedProperty )
497  {
498  a2dNamedProperty* property = event.GetProperty();
499 
500  /* todo
501  if ( property->GetId() == a2dCentralCanvasCommandProcessor::PROPID_Snap )
502  {
503  SetSnap( wxStaticCast( property, a2dNamedProperty )->GetBool() );
504  }
505  */
506  }
507  if ( event.GetId() == a2dDrawingPart::sig_changedShowObject )
508  {
509  if ( event.GetEventObject() == GetDrawingPart() )
510  {
511  // an existing corridor on a view will become invalid when the ShowObject changes.
512  // Most tools can handle a change in corridor, for those there is no need to remove them after a change
513  // in ShowObject.
514  a2dCanvasObject* newtop = wxDynamicCast( event.GetProperty()->GetRefObject(), a2dCanvasObject );
515  if ( m_topTool && newtop )
516  {
517  a2dCorridor corridor( *GetDrawingPart() );
518  corridor.Push( newtop );
519  m_topTool->SetCorridor( corridor );
520  m_toolForZoom->SetCorridor( corridor );
521  event.Skip(); //base class and tools
522  }
523  }
524  else
525  event.Skip();
526  }
527  else
528  event.Skip(); //base class
529  }
530  else
531  event.Skip(); //base class
532 }
533 
534 
535 //!called on key events
536 void a2dStToolContr::OnChar( wxKeyEvent& event )
537 {
538 
539  /*
540  switch(event.GetKeyCode())
541  {
542  case 'Z':
543  case 'z':
544  {
545  a2dZoomTool* zoom = new a2dZoomTool(this);
546  PushTool(zoom);
547  }
548  break;
549  default:
550  event.Skip();
551  }
552  */
553  event.Skip();
554 }
555 
556 void a2dStToolContr::OnKeyDown( wxKeyEvent& event )
557 {
558  //wxLogDebug(wxT("key %d"), event.GetKeyCode());
559 
561  {
562  event.Skip();
563  return;
564  }
565 
566  switch( event.GetKeyCode() )
567  {
568 
569  case WXK_CONTROL:
570  {
571  if ( !GetFirstTool() || ( GetFirstTool() && !GetFirstTool()->GetBusy() ) )
572  {
573  a2dDragTool* c = wxDynamicCast( GetFirstTool(), a2dDragTool );
574  if ( !c )
575  {
576  a2dDragTool* drag = new a2dDragTool( this );
577  PushTool( drag );
578  drag->SetOneShot();
579  }
580  }
581  }
582  break;
583 
584  /* shift keys already used in tools.
585  case WXK_SHIFT:
586  {
587  if ( !GetFirstTool() || (GetFirstTool() && !GetFirstTool()->GetBusy()) )
588  {
589  a2dSelectTool *c = wxDynamicCast(GetFirstTool(), a2dSelectTool);
590  if (!c)
591  {
592  a2dSelectTool* select = new a2dSelectTool(this);
593  PushTool(select);
594  select->SetOneShot();
595  }
596  }
597  }
598  break;
599  */
600  case WXK_ESCAPE:
601  {
602  if ( GetFirstTool() && GetFirstTool()->AllowPop() )
603  {
605  PopTool( poped );
606  }
607 
608  SetStateString();
609 
610  }
611  break;
612  case 'Z':
613  case 'z':
614  {
615  if ( event.m_controlDown && event.m_shiftDown )
617  else if ( event.m_controlDown )
619  else if ( !GetFirstTool() || ( GetFirstTool() && !GetFirstTool()->GetBusy() ) )
620  {
621  a2dBaseTool* tool = m_toolForZoom->TClone( clone_deep );
622  PushTool( tool );
623  }
624  else
625  event.Skip();
626  break;
627  }
628  case 'Y':
629  case 'y':
630  {
631  if ( event.m_controlDown )
633  else
634  event.Skip();
635  break;
636  }
637  case 'r':
638  case 'R':
639  {
641  break;
642  }
643  case 't':
644  case 'T':
645  {
647  break;
648  }
649  case WXK_NUMPAD_ENTER:
650  {
651  Zoomout();
652  break;
653  }
654  case WXK_NUMPAD_ADD:
655  {
656  if ( event.m_controlDown )
657  ZoomIn2AtMouse();
658  else
659  Zoomin2();
660  break;
661  }
662  case WXK_NUMPAD_SUBTRACT:
663  {
664  if ( event.m_controlDown )
665  ZoomOut2AtMouse();
666  else
667  Zoomout2();
668  break;
669  }
670  default:
671  {
672  a2dRestrictionEngine* restrictEngine = m_drawingPart->GetDrawing()->GetHabitat()->GetRestrictionEngine();
673  if ( event.GetKeyCode() == m_noSnapkey )
674  {
675  if ( restrictEngine )
676  restrictEngine->SetReleaseSnap( true );
677  break;
678  }
679  else
680  event.Skip();
681  }
682  }
683 }
684 
685 void a2dStToolContr::OnKeyUp( wxKeyEvent& event )
686 {
688  {
689  event.Skip();
690  return;
691  }
692 
693  if ( GetFirstTool() && !GetFirstTool()->GetBusy() )
694  {
695  switch( event.GetKeyCode() )
696  {
697  case WXK_F1:
698  break;
699 
700 
701  case WXK_CONTROL:
702  {
703  a2dDragTool* c = wxDynamicCast( GetFirstTool(), a2dDragTool );
704  if ( c )
705  {
707  PopTool( poped );
708  }
709  break;
710  }
711  /*
712  case WXK_SHIFT:
713  {
714  a2dSelectTool *c = wxDynamicCast(GetFirstTool(), a2dSelectTool);
715  if (c)
716  {
717  a2dSmrtPtr<a2dBaseTool> poped;
718  PopTool( poped );
719  }
720  break;
721  }
722  */
723  default:
724  {
725  a2dRestrictionEngine* restrictEngine = m_drawingPart->GetDrawing()->GetHabitat()->GetRestrictionEngine();
726  if ( event.GetKeyCode() == m_noSnapkey )
727  {
728  if ( restrictEngine )
729  restrictEngine->SetReleaseSnap( false );
730  break;
731  }
732  else
733  event.Skip();
734  }
735  }
736  }
737  else
738  event.Skip();
739 
740 }
741 
743 {
744  std::vector<wxString>::iterator it;
745  it = m_statusStrings.end();
746  for ( it= m_statusStrings.begin(); it != m_statusStrings.end(); ++it)
747  {
748  *it = "";
749  }
750 
751 }
752 
753 void a2dStToolContr::SetStateString( const wxString& message, size_t field )
754 {
755  m_statusStrings[ field ] = message;
756 
757  //first element always show cursor info.
758  {
759  wxString str;
760  str.Printf( _T( "%d : %d" ), m_mouse_x, m_mouse_y );
761  m_statusStrings[ STAT_Xd_Yd ] = str;
762  }
763  {
764  double mouse_worldx, mouse_worldy;
765  GetDrawingPart()->MouseToToolWorld( m_mouse_x, m_mouse_y, mouse_worldx, mouse_worldy );
766  if ( GetDrawingPart()->GetDrawing() )
767  {
768  mouse_worldx = mouse_worldx * GetDrawingPart()->GetDrawing()->GetUnitsScale();
769  mouse_worldy = mouse_worldy * GetDrawingPart()->GetDrawing()->GetUnitsScale();
770  }
771  wxString form = GetFormat() + " : " + GetFormat();
772  wxString str;
773  str.Printf( form, mouse_worldx, mouse_worldy );
774  m_statusStrings[ STAT_Xw_Yw ] = str;
775  }
776  {
777  wxString str;
778  if ( GetFirstTool() )
779  {
780  str = GetFirstTool()->GetToolString();
781  }
782  m_statusStrings[ STAT_ToolString ] = str;
783  }
784  if ( m_where )
785  {
786  if ( m_noStatusEvent )
787  {
788  if ( m_where->GetStatusBar() )
789  {
790  wxString str;
791  str = m_statusStrings[ STAT_Xd_Yd ];
792  str = str + _T( " : " ) + m_statusStrings[ STAT_Xw_Yw ];
793  str = str + _T( " : " ) + m_statusStrings[ STAT_ToolString ];
794  m_where->SetStatusText( str );
795  }
796  }
797  else
798  {
799  a2dComEvent event( this, sm_showCursor );
800  if ( GetFirstTool() )
801  {
802  if ( ! GetFirstTool()->ProcessEvent( event ) )
803  m_where->GetEventHandler()->ProcessEvent( event );
804  }
805  }
806  }
807 }
808 
809 void a2dStToolContr::OnMouseEvent( wxMouseEvent& event )
810 {
811  wxPoint pos = event.GetPosition();
812 
813  m_mouse_x = pos.x;
814  m_mouse_y = pos.y;
815 
816  SetStateString( "", 0 );
817 
819  {
820  if ( event.LeftDown() && !m_drawingPart->GetDisplayWindow()->HasFocus() )
821  {
822  m_drawingPart->GetDisplayWindow()->SetFocus();
823  }
824 
825  if ( event.Dragging() && m_draggingCanvas )
826  {
827  double dxworld = m_drawingPart->GetDrawer2D()->DeviceToWorldXRel( floor( m_mouse_xprev - m_mouse_x + 0.5 ) );
828  double dyworld = m_drawingPart->GetDrawer2D()->DeviceToWorldYRel( floor( m_mouse_yprev - m_mouse_y + 0.5 ) );
829 
830  m_drawingPart->GetCanvas()->ScrollWindowConstrained( dxworld, dyworld );
833  }
834  else if( event.RightDown() && !m_draggingCanvas )
835  {
836  m_drawingPart->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Move ) );
837  m_draggingCanvas = true;
838  GetDrawingPart()->GetDisplayWindow()->CaptureMouse();
843  }
844  else if( event.RightUp() && m_draggingCanvas )
845  {
846  GetDrawingPart()->GetDisplayWindow()->ReleaseMouse();
847  m_draggingCanvas = false;
849  {
850  //try tool first
851  if ( ToolsProcessEvent( event ) )
852  return;
853  else if ( ! ( m_defaultBehavior & wxTC_NoContextMenu ) && m_mousemenu )
854  m_drawingPart->GetDisplayWindow()->PopupMenu( GetMousePopupMenu(), m_mouse_x, m_mouse_y );
855  }
856  else
857  {
858  // finish drag
859  if ( GetFirstTool() && GetFirstTool()->GetBusy() )
860  m_drawingPart->SetCursor( GetFirstTool()->GetBusyCursorType() );
861  else if ( GetFirstTool() && !GetFirstTool()->GetBusy() )
862  m_drawingPart->SetCursor( GetFirstTool()->GetCursorType() );
863  else
864  m_drawingPart->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_ARROW ) );
865  }
866  }
867  else
868  //let the baseclass a2dToolContr
869  //handle the event, in order to redirect it to the tools
870  event.Skip();
871  }
872  else
873  {
874  if ( event.LeftDown() && wxWindow::FindFocus() != m_drawingPart->GetDisplayWindow() )
875  {
876  // normally handler in a2dDrawingPart::OnActive()
877  if ( !m_drawingPart->GetDisplayWindow()->HasFocus() )
878  m_drawingPart->GetDisplayWindow()->SetFocus();
879  }
880  if ( event.RightDown() && !GetDrawingPart()->GetDisplayWindow()->GetCapture() )
881  {
882  //we first try the tools here, since it can have a popup menu too.
883  //If not processed, and not processed in here either, then it will once more
884  //be processed by the tools. This fact is not a problem.
885  if ( ToolsProcessEvent( event ) )
886  return;
887 
889  {
890  m_drawingPart->GetDisplayWindow()->PopupMenu( m_mousemenu, pos.x, pos.y );
891  event.Skip( false ); //event is processed.
892  return;
893  }
894  }
895  else if ( GetFirstTool() && !GetFirstTool()->GetBusy()
897  {
898  if ( !wxDynamicCast( GetFirstTool(), a2dZoomTool ) && event.m_controlDown && event.m_shiftDown )
899  {
900  a2dBaseTool* tool = m_toolForZoom->TClone( clone_deep );
901  tool->SetOneShot();
902  PushTool( tool );
903  }
904  if ( !wxDynamicCast( GetFirstTool(), a2dDragTool ) && event.m_controlDown )
905  {
906  a2dDragTool* drag = new a2dDragTool( this );
907  PushTool( drag );
908  drag->SetOneShot();
909  }
910  /*
911  else if ( !wxDynamicCast(GetFirstTool(), a2dSelectTool) && event.m_shiftDown)
912  {
913  a2dSelectTool* select= new a2dSelectTool(this);
914  PushTool(select);
915  select->SetOneShot();
916  }
917  */
918  }
919  else
920  //let the baseclass a2dToolContr
921  //handle the event, in order to redirect it to the tools
922  event.Skip();
923  }
924 }
925 
927 {
928  a2dObjectEditTool* edit = new a2dObjectEditTool( this );
929  PushTool( edit );
930  edit->StartToEdit( objectToEdit );
931  return true;
932 }
933 
935 {
936  a2dObjectEditTool* edit = new a2dObjectEditTool( this, ic );
937  PushTool( edit );
938  edit->StartToEdit( objectToEdit );
939  return true;
940 }
941 
942 bool a2dStToolContr::TriggerReStartEdit( wxUint16 editmode )
943 {
945  if ( edit )
946  {
947  edit->TriggerReStartEdit( editmode );
948  return true;
949  }
950  return false;
951 }
952 
954 {
955  if ( GetFirstTool() )
956  {
957  return GetFirstTool()->RotateObject90LeftRight( right );
958  }
959  return false;
960 }
961 
962 
963 /********************************************************************************
964 a2dStTool
965 ********************************************************************************/
966 
967 const a2dSignal a2dStTool::sig_toolComEventAddObject = wxNewId();
968 const a2dSignal a2dStTool::sig_toolComEventSetEditObject = wxNewId();
969 
970 BEGIN_EVENT_TABLE( a2dStTool, a2dBaseTool )
971  EVT_KEY_DOWN( a2dStTool::OnKeyDown )
972  EVT_KEY_UP( a2dStTool::OnKeyUp )
973  EVT_CHAR( a2dStTool::OnChar )
974  EVT_MOUSE_EVENTS( a2dStTool::OnMouseEvent )
975  EVT_COM_EVENT( a2dStTool::OnComEvent )
976  EVT_PAINT( a2dStTool::OnPaint )
977  EVT_IDLE( a2dStTool::OnIdle )
978  EVT_DO( a2dStTool::OnDoEvent )
979  EVT_UNDO( a2dStTool::OnUndoEvent )
980 END_EVENT_TABLE()
981 
982 a2dStTool::a2dStTool( a2dStToolContr* controller ): a2dBaseTool( ( a2dToolContr* )controller )
983 {
984  m_eventHandler = controller->GetDefaultToolEventHandler();
985 
986  m_useEditOpaque = a2dOpaqueMode_Controller;
987  m_editOpacityFactor = DEFAULTOpacityFactor;
988 
989  m_editatend = false;
990 
991  m_anotate = false;
992 
993  m_canvasobject = 0;
994  m_original = 0;
995 
996  m_stcontroller = controller;
997  m_connectionGenerator = GetDrawing()->GetHabitat()->GetConnectionGenerator();
998  m_xanotation = m_yanotation = 0;
999  m_commandgroup = 0;
1000 
1001  m_dragStarted = false;
1002  m_xprev = 0;
1003  m_yprev = 0;
1004  m_dragstartx = 0;
1005  m_dragstarty = 0;
1006  m_xwprev = 0.0;
1007  m_ywprev = 0.0;
1008 
1009  m_snapSourceFeatures = a2dRestrictionEngine::snapToNone;
1010 
1011  m_snapTargetFeatures = a2dRestrictionEngine::snapToNone;
1012 
1013 
1014  // WARNING: This will call the base class version for basic initialization
1015  // The derived class version is called e.g. at the beginning of rendering.
1016  // If it is not sifficient, AdjustRenderOptions must be called in the derived
1017  // class constructor.
1018  AdjustRenderOptions();
1019 }
1020 
1021 a2dStTool::a2dStTool( const a2dStTool& other, CloneOptions options, a2dRefMap* refs )
1022  : a2dBaseTool( other, options, refs )
1023 {
1025 
1028 
1029  m_editatend = other.m_editatend;
1030 
1031  m_anotate = other.m_anotate;
1032 
1033  m_canvasobject = 0;
1034  m_original = 0;
1035 
1038  m_xanotation = other.m_xanotation;
1039  m_yanotation = other.m_yanotation;
1041 }
1042 
1044 {
1045 }
1046 
1047 void a2dStTool::SetStateString( const wxString& message, size_t field )
1048 {
1049  m_stcontroller->SetStateString( message, field );
1050 }
1051 
1053 {
1054  m_corridor = a2dCorridor( ic );
1055  m_parentobject = m_corridor.back();
1056 
1057  m_canvasobject = startObject;
1058  return true;
1059 }
1060 
1062 {
1063  a2dIterC ic( GetDrawingPart() );
1064  a2dIterCU cu( ic );
1065 
1066  return object->GetAbsoluteArea( ic );
1067 }
1068 
1069 void a2dStTool::GetTextExtent( const wxString& string, wxCoord* w, wxCoord* h, wxCoord* descent, wxCoord* externalLeading )
1070 {
1071  wxMemoryDC dc;
1072  dc.SetFont( m_annotateFont );
1073  dc.GetTextExtent( string, w, h, descent, externalLeading );
1074 }
1075 
1076 bool a2dStTool::OnPushNewTool( a2dBaseTool* WXUNUSED( newtool ) )
1077 {
1078  // If tool is busy, it will enter halted state
1079  if ( GetBusy() && !m_halted )
1080  {
1081  m_halted = true;
1082  }
1083  m_pending = true;
1084  return false; //do not pop this tool before pushing new tool.
1085 }
1086 
1088 {
1089  // Set the style of the documents command-processor to the style of this tool
1090  if ( GetDrawingPart()->GetDrawing() )
1091  {
1092  a2dComEvent event( this, objectToAdd, sig_toolComEventAddObject );
1093  ProcessEvent( event );
1094  }
1095 
1096  GetCanvasCommandProcessor()->AddCurrent( objectToAdd, true, NULL, m_parentobject );
1097 }
1098 
1099 void a2dStTool::SetActive( bool active )
1100 {
1101  a2dBaseTool::SetActive( active );
1102  m_pending = true;
1103 
1104  if ( active )
1105  {
1106  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
1107  if( restrict )
1108  {
1109  restrict->SetParentSnapObjects( m_parentobject );
1110  }
1111 
1112  // Tool is activated
1113 
1114  // Set tool cursor
1115  if ( GetBusy() && GetDrawingPart()->GetDrawing() )
1116  {
1117  GetDrawingPart()->SetCursor( m_toolBusyCursor );
1118  }
1119  else
1120  {
1121  GetDrawingPart()->SetCursor( m_toolcursor );
1122  }
1123 
1124  // Is tool reactivated ?
1125  if ( m_halted )
1126  {
1127  m_halted = false;
1128  // The command group is closed in a2dBaseTool::SetActive, but
1129  // not reopended, because this does only make sense for stacked tools
1130  OpenCommandGroup( true );
1131  }
1132  m_pending = true;
1133  }
1134  else
1135  {
1136  // Tool is deactivated
1137 
1138  //the subedit or other subtools should not influence style of the object.
1139  //When this tool is activated again, the CurrentCanvasObject is set right again.
1140  if ( GetDrawingPart() && GetDrawingPart()->GetShowObject() )
1142 
1143  m_pending = true;
1144  }
1145 }
1146 
1148 {
1150  return false;
1151 
1152  if( !CreateToolObjects() )
1153  {
1155  return false;
1156  }
1157 
1158  return true;
1159 }
1160 
1161 void a2dStTool::FinishBusyMode( bool closeCommandGroup )
1162 {
1164 
1165  // Even tools deleting m_original want it to become visible for undo commands
1166  if( m_original )
1167  {
1168  m_original->SetVisible( true );
1169  m_original->SetSnapTo( true );
1170  m_original = 0;
1171  }
1172  m_canvasobject = 0;
1174 
1175  a2dBaseTool::FinishBusyMode( closeCommandGroup );
1176 }
1177 
1179 {
1181 
1182  // Even tools deleting m_original want it to become visible for undo commands
1183  if( m_original )
1184  {
1185  m_original->SetVisible( true );
1186  m_original->SetPending( true );
1187  m_original = 0;
1188  }
1189  m_canvasobject = 0;
1191 
1193 }
1194 
1195 void a2dStTool::DeselectAll()
1196 {
1197  GetCanvasCommandProcessor()->DeselectAll();
1198 
1199  // !!!! should deslect all, but no idea how to do this properly
1200  // a2dGeneralGlobals->RecordF( this, _T( "deselect %f %f %f %f" ), -1e10, -1e10, 1e10, 1e10 );
1201 }
1202 
1203 void a2dStTool::OnMouseEvent( wxMouseEvent& event )
1204 {
1205  wxPoint pos = event.GetPosition();
1206  if ( event.RightUp() && m_mousemenu )
1207  {
1208  GetDrawingPart()->GetDisplayWindow()->PopupMenu( m_mousemenu, pos.x, pos.y );
1209  }
1210  else
1211  event.Skip();
1212 }
1213 
1215 {
1216  switch( m_stcontroller->GetDragMode() )
1217  {
1218  case wxDRAW_RECTANGLE:
1219  m_renderOriginal = false;
1220  m_renderEditcopy = false;
1221  m_renderEditcopyOnTop = false;
1222  m_renderEditcopyEdit = false;
1224  break;
1225 
1226  case wxDRAW_ONTOP:
1227  m_renderOriginal = false;
1228  m_renderEditcopy = false;
1229  m_renderEditcopyOnTop = true;
1230  m_renderEditcopyEdit = false;
1231  m_renderEditcopyRectangle = false;
1232  break;
1233 
1234  case wxDRAW_REDRAW:
1235  m_renderOriginal = true;
1236  m_renderEditcopy = false;
1237  m_renderEditcopyOnTop = false;
1238  m_renderEditcopyEdit = false;
1239  m_renderEditcopyRectangle = false;
1240  break;
1241 
1242  case wxDRAW_COPY:
1243  m_renderOriginal = true;
1244  m_renderEditcopy = false;
1245  m_renderEditcopyOnTop = false;
1246  m_renderEditcopyEdit = true;
1247  m_renderEditcopyRectangle = false;
1248  break;
1249 
1250  default:
1251  wxASSERT( 0 );
1252  m_renderOriginal = true;
1253  m_renderEditcopy = false;
1254  m_renderEditcopyOnTop = false;
1255  m_renderEditcopyEdit = true;
1256  m_renderEditcopyRectangle = false;
1257  }
1258 }
1259 
1261 {
1262  return true;
1263 }
1264 
1266 {
1267 
1268  for( a2dCanvasObjectList::iterator iter = m_parentobject->GetChildObjectList()->begin(); iter != m_parentobject->GetChildObjectList()->end(); ++iter )
1269  {
1270  a2dCanvasObjectList::value_type obj = *iter;
1271 
1272  bool release = false;
1273  //if ( obj->GetAlgoSkip() )
1274  {
1276  if( tool == this )
1277  {
1278  a2dCanvasObject* original = a2dCanvasObject::PROPID_Original->GetPropertyValue( obj );
1279  if( original && obj->GetEditingRender() )
1280  obj->EndEdit();
1281  release = true;
1282  }
1283  else if ( a2dCanvasObject::PROPID_ToolDecoration->GetPropertyValue( obj ) )
1284  {
1285  release = true;
1286  }
1287  }
1288 
1289  if( release )
1290  {
1291  a2dWalker_RemovePropertyCandoc setp( a2dCanvasObject::PROPID_Original );
1292  setp.AddPropertyId( a2dCanvasObject::PROPID_Editcopy );
1293  setp.SetSkipNotRenderedInDrawing( true );
1294  setp.Start( obj );
1295 
1296  // Creative tools might reuse this editcopy as real object, so clean it up a bit
1297  obj->RemoveProperty( a2dCanvasObject::PROPID_ToolObject );
1298  obj->RemoveProperty( a2dCanvasObject::PROPID_ToolDecoration );
1299  obj->RemoveProperty( a2dCanvasObject::PROPID_ViewSpecific );
1300  //we do delayed release, to make subediting possible ( meaning editcopy is used
1301  //to create extra tools, so it may not be deleted yet )
1302  obj->SetRelease( true );
1303  obj->SetPending( true );
1304  //wrong to erase directly;
1305  }
1306  }
1308 
1309  // Possibly was set invisible in CreateToolObjects
1310  if( m_original )
1311  {
1312  m_original->SetVisible( true );
1313  }
1314 }
1315 
1316 void a2dStTool::GetKeyIncrement( double* xIncr, double* yIncr )
1317 {
1318  double pixel = GetDrawer2D()->DeviceToWorldXRel( 1 );
1319 
1320 
1321  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
1322  if( restrict )
1323  {
1324  if( restrict->GetSnapGridX() )
1325  *xIncr = restrict->GetSnapGridX() / GetDrawingPart()->GetDrawing()->GetUnitsScale();
1326  else
1327  *xIncr = pixel;
1328 
1329  if( restrict->GetSnapGridY() )
1330  *yIncr = restrict->GetSnapGridY() / GetDrawingPart()->GetDrawing()->GetUnitsScale();
1331  else
1332  *yIncr = pixel;
1333  }
1334  else
1335  {
1336  *xIncr = pixel;
1337  *yIncr = pixel;
1338  }
1339 
1340  if ( !GetDrawer2D()->GetYaxis() )
1341  {
1342  *yIncr = -*yIncr;
1343  }
1344 }
1345 
1347 {
1348  // Add old (and later new) annotation area to pending region
1350 
1351  m_anotation = _T( "" );
1352  m_xanotation = m_x;
1353  m_yanotation = m_y;
1354 
1356 }
1357 
1359 {
1360  if ( m_anotate )
1361  {
1362  wxCoord w, h, descent, external;
1363  GetTextExtent( m_anotation, &w, &h, &descent, &external );
1364 
1365  wxRect text( m_xanotation, m_yanotation, w, h );
1366  GetDrawingPart()->AddPendingUpdateArea( text.Inflate( 2, 2 ) );
1367  }
1368 }
1369 
1370 void a2dStTool::OnIdle( wxIdleEvent& event )
1371 {
1372  if ( m_canvasobject && m_pending && GetBusy() )
1373  {
1374  m_pending = false;
1378 
1379  // Add anotation area to the pending areas
1380  // old and new annotation area are calculated and added as pendingarea.
1382  }
1383  else
1384  event.Skip();
1385 }
1386 
1387 void a2dStTool::OnPaint( wxPaintEvent& event )
1388 {
1389  if ( GetBusy() )
1390  {
1391  //CYCLIC paint event result because of a2dStTool::OnIdle() regenerating not paint events somehow
1392  //m_pending = true;
1393  }
1394  event.Skip();
1395 }
1396 
1397 // This is usefull for special breakpoints in debug mode
1398 #ifdef _DEBUG
1399 bool renderingtool = false;
1400 #endif
1401 
1403 {
1404 #ifdef _DEBUG
1405  renderingtool = true;
1406 #endif
1407 
1408  if ( m_canvasobject && GetBusy() )
1409  {
1411 
1412  if ( m_original )
1413  {
1417  }
1418 
1419  // Render edit objects in On-Top mode
1420  if( m_renderEditcopyOnTop )
1421  {
1423  }
1424 
1425  // Render edit objects in Edit mode
1426  if( m_renderEditcopyEdit )
1427  {
1429  {
1433  }
1435  {
1436  a2dFill fill = *a2dTRANSPARENT_FILL;
1437  a2dStroke stroke = GetDrawing()->GetHabitat()->GetHandle()->GetStroke();
1439  GetDrawingPart()->SetFixedStyleFill( fill );
1440  GetDrawingPart()->SetFixedStyleStroke( stroke );
1443  }
1445  {
1449  }
1450  else //if ( m_useEditOpaque == a2dOpaqueMode_Off )
1451  {
1452  a2dFill fill = *a2dTRANSPARENT_FILL;
1453  a2dStroke stroke = GetDrawing()->GetHabitat()->GetHandle()->GetStroke();
1455  GetDrawingPart()->SetFixedStyleFill( fill );
1456  GetDrawingPart()->SetFixedStyleStroke( stroke );
1458  }
1459  }
1460 
1461  // Render edit objects in Edit mode as rectangles
1463  {
1465  GetDrawingPart()->SetFixedStyleStroke( GetDrawing()->GetHabitat()->GetHandle()->GetStroke() );
1467  }
1468 
1470 
1471  RenderAnotation();
1472  }
1473 
1474 #ifdef _DEBUG
1475  renderingtool = false;
1476 #endif
1477 }
1478 
1480 {
1481  if ( m_anotate && m_canvasobject && GetBusy() )
1482  {
1484  }
1485 }
1486 
1488 {
1489  event.Skip();
1490 }
1491 
1493 {
1494  event.Skip();
1495 }
1496 
1498 {
1499  if ( GetEvtHandlerEnabled() )
1500  {
1501  if ( event.GetId() == a2dBaseTool::sig_toolPoped )
1502  {
1503  // if edit tool ended, we still need to close the command group
1504  if ( !GetBusy() && m_editatend )
1506  }
1507  }
1508 
1509  event.Skip();
1510 }
1511 
1512 void a2dStTool::OnKeyDown( wxKeyEvent& event )
1513 {
1514  if ( GetBusy() )
1515  {
1516  a2dRestrictionEngine* restrictEngine = GetDrawing()->GetHabitat()->GetRestrictionEngine();
1517  if ( event.GetKeyCode() == WXK_SHIFT )
1518  {
1519  if ( restrictEngine )
1520  restrictEngine->SetShiftKeyDown( true );
1521  }
1522  else
1523  event.Skip();
1524  }
1525  else
1526  {
1527  event.Skip();
1528  /* interfears with DrawTextTool when typing t, it is eaten here.
1529  switch( event.GetKeyCode() )
1530  {
1531  case 'r':
1532  case 'R':
1533  {
1534  GetDrawing()->GetHabitat()->GetConnectionGenerator()->RotateRouteMethod();
1535  break;
1536  }
1537  case 't':
1538  case 'T':
1539  {
1540  GetDrawing()->GetHabitat()->GetConnectionGenerator()->SetRouteWhenDrag( !GetDrawing()->GetHabitat()->GetConnectionGenerator()->GetRouteWhenDrag() );
1541  break;
1542  }
1543  default:
1544  event.Skip();
1545  }
1546  */
1547  }
1548 }
1549 
1550 void a2dStTool::OnKeyUp( wxKeyEvent& event )
1551 {
1552  if ( GetBusy() )
1553  {
1554  a2dRestrictionEngine* restrictEngine = GetDrawing()->GetHabitat()->GetRestrictionEngine();
1555  if ( event.GetKeyCode() == WXK_SHIFT )
1556  {
1557  if ( restrictEngine )
1558  restrictEngine->SetShiftKeyDown( false );
1559  }
1560  else
1561  event.Skip();
1562  }
1563  else
1564  event.Skip();
1565 }
1566 
1567 
1568 void a2dStTool::OnChar( wxKeyEvent& event )
1569 {
1571  {
1572  double dx = m_xwprev - m_canvasobject->GetPosX();
1573  double dy = m_ywprev - m_canvasobject->GetPosY();
1574 
1577 
1578  double shiftx;
1579  double shifty;
1580  GetKeyIncrement( &shiftx, &shifty );
1581 
1582  //now shift with snap distances in X or Y
1583 
1584  switch( event.GetKeyCode() )
1585  {
1586  case WXK_UP:
1587  shiftx = 0;
1588  break;
1589 
1590  case WXK_DOWN:
1591  shiftx = 0;
1592  shifty = -shifty;
1593  break;
1594 
1595  case WXK_LEFT:
1596  shiftx = -shiftx;
1597  shifty = 0;
1598  break;
1599 
1600  case WXK_RIGHT:
1601  shifty = 0;
1602  break;
1603  default:
1604  {
1605  shiftx = 0;
1606  shifty = 0;
1607  event.Skip();
1608  }
1609  }
1610 
1611  m_xwprev += shiftx;
1612  m_ywprev += shifty;
1613 
1614  m_canvasobject->Translate( shiftx, shifty );
1615 
1616  m_pending = true;
1617  }
1618  else
1619  event.Skip();
1620 }
1621 
1622 void a2dStTool::MouseToToolWorld( int x, int y, double& xWorldLocal, double& yWorldLocal )
1623 {
1624  GetDrawingPart()->MouseToToolWorld( x, y, xWorldLocal, yWorldLocal );
1625  a2dAffineMatrix cworld;
1626  cworld = GetDrawingPart()->GetShowObject()->GetTransform();
1627  cworld.Invert();
1628  cworld.TransformPoint( xWorldLocal, yWorldLocal, xWorldLocal, yWorldLocal );
1629  m_corridor.GetTransform().TransformPoint( xWorldLocal, yWorldLocal, xWorldLocal, yWorldLocal );
1630 }
1631 
1633 {
1634  //TODO maybe better add a seperate function to reset style and current object in command processor
1636 
1637  if ( m_editatend )
1638  {
1639  a2dStTool::FinishBusyMode( false );
1640 
1641  //make sure all updates have bin processed first
1642  //GetDrawingPart()->Update( a2dCANVIEW_UPDATE_SYNC_DRAWERS );
1643 
1645  //take over event handler e.g. to have fixed style
1646  edit->SetEvtHandler( GetEventHandler() );
1647  edit->SetFill( m_fill );
1648  edit->SetStroke( m_stroke );
1649  m_stcontroller->PushTool( edit );
1650  objecttoedit->SetVisible( true );
1651  edit->StartToEdit( objecttoedit );
1652  return edit;
1653  }
1654  else
1655  {
1656  a2dStTool::FinishBusyMode( true );
1657  // add update area for redraw of last state of the tool
1658  // GetDrawingPart()->AddPendingUpdateArea( m_new );
1659  GetDrawingPart()->Update( a2dCANVIEW_UPDATE_SYNC_DRAWERS );
1660  return NULL;
1661  }
1662 }
1663 
1664 a2dCanvasObject* a2dStTool::FindTaggedObject()
1665 {
1666  a2dCanvasObject* ret = NULL;
1667  for( a2dCanvasObjectList::iterator iter = m_parentobject->GetChildObjectList()->begin(); iter != m_parentobject->GetChildObjectList()->end(); ++iter )
1668  {
1669  a2dCanvasObjectList::value_type obj = *iter;
1671  if ( tagsp )
1672  {
1673  a2dTag tag = tagsp->Last();
1674  ret = obj;
1675  }
1676  }
1677  return ret;
1678 }
1679 
1680 void a2dStTool::PrepareForRewire( a2dCanvasObjectList& dragList, bool walkWires, bool selected, bool stopAtSelectedWire, bool CreateExtraWires, a2dRefMap* refs )
1681 {
1682  GetDrawing()->GetHabitat()->GetConnectionGenerator()->SetNoEditCopy( false );
1683  GetDrawing()->GetHabitat()->GetConnectionGenerator()->PrepareForRewire( m_parentobject, dragList, walkWires, selected, stopAtSelectedWire, CreateExtraWires, this, refs );
1684 }
1685 
1686 
1687 /********************************************************************************
1688 a2dStDrawTool
1689 ********************************************************************************/
1690 
1691 
1692 BEGIN_EVENT_TABLE( a2dStDrawTool, a2dStTool )
1693  EVT_KEY_DOWN( a2dStDrawTool::OnKeyDown )
1694  EVT_KEY_UP( a2dStDrawTool::OnKeyUp )
1695  EVT_CHAR( a2dStDrawTool::OnChar )
1696 END_EVENT_TABLE()
1697 
1698 a2dStDrawTool::a2dStDrawTool( a2dStToolContr* controller ): a2dStTool( controller )
1699 {
1700  // the base tool sets layer style using a2dBLACK_STROKE->Clone()->SetNoStroke() etc.
1701  // This for debug.
1702  m_stroke = a2dStroke( *wxBLACK, 0 );
1703  m_fill = a2dFill( *wxRED );
1704  m_AllowModifyTemplate = true;
1705 }
1706 
1708 {
1709 }
1710 
1712 {
1714 
1715  // Clone the original drag object
1717  // we don't want to snap points to the drawing objects itself
1718  m_original->SetSnapTo( false );
1719 
1720  m_canvasobject->SetSelected( false );
1721 
1723 
1726 
1727  m_pending = true;
1728  return true;
1729 }
1730 
1732 {
1733  m_pending = true;
1734  return a2dStTool::EnterBusyMode();
1735 }
1736 
1737 void a2dStDrawTool::FinishBusyMode( bool closeCommandGroup )
1738 {
1740  m_pending = true;
1741  a2dCanvasObjectPtr original = m_original;
1742  if( GetDrawingPart() )
1743  {
1744  if ( m_stcontroller->GetSelectAtEnd() )
1745  {
1746  DeselectAll();
1747  original->SetSelected( true );
1748  original->SetSelected2( true );
1749  }
1751  {
1754  }
1755 
1756  StartEditTool( original );
1757  }
1758  else
1759  a2dStTool::FinishBusyMode( closeCommandGroup );
1760 
1761 }
1762 
1764 {
1765  m_pending = true;
1767 }
1768 
1769 void a2dStDrawTool::OnKeyDown( wxKeyEvent& event )
1770 {
1771  if ( GetBusy() )
1772  {
1773  switch( event.GetKeyCode() )
1774  {
1775  case WXK_SPACE:
1776  {
1777  FinishBusyMode();
1778  break;
1779  }
1780  case WXK_ESCAPE:
1781  {
1782  AbortBusyMode();
1783  break;
1784  }
1785  default:
1786  event.Skip();
1787  }
1788  }
1789  else
1790  event.Skip();
1791 }
1792 
1793 void a2dStDrawTool::OnKeyUp( wxKeyEvent& event )
1794 {
1795  event.Skip();
1796 }
1797 
1798 void a2dStDrawTool::OnChar( wxKeyEvent& event )
1799 {
1800  if ( GetBusy() )
1801  {
1802  }
1803  else
1804  event.Skip();
1805 }
1806 
1808 {
1810 }
1811 
1812 //----------------------------------------------------------------------------
1813 // a2dDrawRectangleTool
1814 //----------------------------------------------------------------------------
1815 
1816 BEGIN_EVENT_TABLE( a2dDrawRectangleTool, a2dStDrawTool )
1817  EVT_CHAR( a2dDrawRectangleTool::OnChar )
1818  EVT_MOUSE_EVENTS( a2dDrawRectangleTool::OnMouseEvent )
1819 END_EVENT_TABLE()
1820 
1821 a2dDrawRectangleTool::a2dDrawRectangleTool( a2dStToolContr* controller ): a2dStDrawTool( controller )
1822 {
1823  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_PENCIL );
1824  m_toolBusyCursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS );
1825  m_radius = 0;
1826 }
1827 
1828 a2dDrawRectangleTool::~a2dDrawRectangleTool()
1829 {
1830 }
1831 
1833 {
1834  // Add old (and later new) annotation area to pending region
1836 
1837  a2dRect* rec = wxStaticCast( m_canvasobject.Get(), a2dRect );
1838  m_anotation.Printf( _T( "w %6.3f h %6.3f" ), rec->GetWidth(), rec->GetHeight() );
1839 
1840  wxCoord w, h, descent, external;
1841  GetTextExtent( m_anotation, &w, &h, &descent, &external );
1842 
1843  m_xanotation = m_x + h;
1844  m_yanotation = m_y + h;
1845 
1847 }
1848 
1849 void a2dDrawRectangleTool::OnMouseEvent( wxMouseEvent& event )
1850 {
1851  if ( !m_active )
1852  {
1853  event.Skip();
1854  return;
1855  }
1856  /*
1857  if ( GetBusy() )
1858  GetDrawingPart()->SetCursor( m_toolBusyCursor );
1859  else
1860  GetDrawingPart()->SetCursor( m_toolcursor );
1861  */
1862  m_x = event.GetX();
1863  m_y = event.GetY();
1865 
1866  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
1867  if( restrict )
1868  restrict->RestrictPoint( m_xwprev, m_ywprev );
1869 
1870  if ( event.LeftDown() && !GetBusy() )
1871  {
1872  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
1874  m_original = new a2dRect( m_xwprev, m_ywprev, 0, 0, m_radius );
1875  if ( !EnterBusyMode() )
1876  return;
1878 
1879  a2dRect* rec = wxStaticCast( m_canvasobject.Get(), a2dRect );
1880  double unitScale = GetDrawing()->GetUnitsScale();
1881  wxString state;
1882  wxString form = m_stcontroller->GetFormat() + " " + m_stcontroller->GetFormat();
1883  state.Printf( form, rec->GetPosX()*unitScale, rec->GetPosY()*unitScale );
1884  SetStateString( state, 10 );
1885  form = _T("width = ") + m_stcontroller->GetFormat() + _T(" height = ") + m_stcontroller->GetFormat();
1886  state.Printf( form, rec->GetWidth()*unitScale, rec->GetHeight()*unitScale );
1887  SetStateString( state, 11 );
1888 
1889  }
1890  else if ( event.LeftDown() && GetBusy() )
1891  {
1893  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
1894  a2dRect* rec = wxStaticCast( m_canvasobject.Get(), a2dRect );
1895 
1896  a2dGeneralGlobals->RecordF( this, _T( "rect %f %f %f %f" ), rec->GetPosX(), rec->GetPosY(), rec->GetWidth(), rec->GetHeight() );
1897 
1898  FinishBusyMode();
1899  }
1900  else if ( ( event.Dragging() && GetBusy() ) || ( event.Moving() && GetBusy() ) )
1901  {
1902  a2dRect* rec = wxStaticCast( m_canvasobject.Get(), a2dRect );
1903  rec->SetWidth( m_xwprev - rec->GetPosX() );
1904  rec->SetHeight( m_ywprev - rec->GetPosY() );
1905 
1906  a2dRect* recorg = wxStaticCast( m_original.Get(), a2dRect );
1907  recorg->SetWidth( rec->GetWidth() );
1908  recorg->SetHeight( rec->GetHeight() );
1909 
1910  double unitScale = GetDrawing()->GetUnitsScale();
1911  wxString state;
1912  wxString form = m_stcontroller->GetFormat() + " " + m_stcontroller->GetFormat();
1913  state.Printf( form, rec->GetPosX()*unitScale, rec->GetPosY()*unitScale );
1914  SetStateString( state, 10 );
1915  form = _T("width = ") + m_stcontroller->GetFormat() + _T(" height = ") + m_stcontroller->GetFormat();
1916  state.Printf( form, rec->GetWidth()*unitScale, rec->GetHeight()*unitScale );
1917  SetStateString( state, 11 );
1918 
1919  m_pending = true;
1920  }
1921  else
1922  event.Skip();
1923 }
1924 
1925 //----------------------------------------------------------------------------
1926 // a2dZoomTool
1927 //----------------------------------------------------------------------------
1928 
1929 BEGIN_EVENT_TABLE( a2dZoomTool, a2dStTool )
1930  EVT_CHAR( a2dZoomTool::OnChar )
1931  EVT_MOUSE_EVENTS( a2dZoomTool::OnMouseEvent )
1932 END_EVENT_TABLE()
1933 
1934 a2dZoomTool::a2dZoomTool( a2dStToolContr* controller ): a2dStTool( controller )
1935 {
1936  m_eventHandler = controller->GetDefaultToolEventHandlerFixedStyle();
1937 
1938  m_isEditTool = false;
1939  m_anotate = true;//false;
1940  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_MAGNIFIER );
1941  m_toolBusyCursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS );
1942 
1943  if ( GetDrawingPart()->GetDrawer2D()->HasAlpha() || GetDrawingPart()->GetTrippleBuf() )
1944  {
1945  SetFill( a2dFill( wxColour( 66, 159, 235, 50 ) ) );
1946  SetStroke( a2dStroke( wxColour( 66, 159, 235, 165 ), 2, a2dSTROKE_LONG_DASH ) );
1947  }
1948  else
1949  {
1950  SetFill( *a2dTRANSPARENT_FILL );
1951  SetStroke( a2dStroke( *wxBLACK, 1, a2dSTROKE_LONG_DASH ) );
1952  }
1953 }
1954 
1955 a2dZoomTool::a2dZoomTool( const a2dZoomTool& other, CloneOptions options, a2dRefMap* refs )
1956  : a2dStTool( other, options, refs )
1957 {
1959 
1960  m_anotate = other.m_anotate;
1961  m_toolcursor = other.m_toolcursor;
1963  m_isEditTool = other.m_isEditTool;
1964 
1965  m_fill = other.m_fill;
1966  m_stroke = other.m_stroke;
1967 }
1968 
1969 a2dObject* a2dZoomTool::DoClone( CloneOptions options, a2dRefMap* refs ) const
1970 {
1971  return new a2dZoomTool( *this, options, refs );
1972 }
1973 
1975 {
1976 }
1977 
1979 {
1980  // Add old (and later new) annotation area to pending region
1982 
1983  a2dRect* rec = wxStaticCast( m_canvasobject.Get(), a2dRect );
1984  m_anotation.Printf( _T( "w %6.3f h %6.3f" ), rec->GetWidth(), rec->GetHeight() );
1985  m_xanotation = m_x;
1986  m_yanotation = m_y;
1987 
1988  wxCoord w, h, descent, external;
1989  GetTextExtent( m_anotation, &w, &h, &descent, &external );
1990 
1991  m_xanotation = m_x + h;
1992  m_yanotation = m_y + h;
1993 
1995 }
1996 
1997 void a2dZoomTool::OnChar( wxKeyEvent& event )
1998 {
1999  if ( !GetBusy() )
2000  {
2001  switch( event.GetKeyCode() )
2002  {
2003  case WXK_RETURN:
2004  {
2006  }
2007  break;
2008  case WXK_SUBTRACT:
2009  {
2011  }
2012  break;
2013  default:
2014  event.Skip();
2015  }
2016  }
2017  else
2018  event.Skip();
2019 }
2020 
2021 void a2dZoomTool::OnMouseEvent( wxMouseEvent& event )
2022 {
2023  if ( !m_active )
2024  {
2025  event.Skip();
2026  return;
2027  }
2028 
2029  if ( GetBusy() )
2030  GetDrawingPart()->SetCursor( m_toolBusyCursor );
2031  else
2032  GetDrawingPart()->SetCursor( m_toolcursor );
2033 
2034  m_x = event.GetX();
2035  m_y = event.GetY();
2036 
2037  if ( event.LeftDClick() && !GetBusy() )
2038  {
2040  }
2041  else if ( event.LeftDown() && !GetBusy() )
2042  {
2044  a2dRect* rec = new a2dRect( m_xwprev, m_ywprev, 0, 0, 0 );
2045  m_canvasobject = rec;
2046  // objects are rendered via tool, but stored in document or view.
2047  if ( GetDrawingPart()->GetTrippleBuf() )
2048  GetDrawingPart()->AddOverlayObject( rec );
2049  else
2050  AddDecorationObject( rec );
2051  rec->SetFill( m_fill );
2052  rec->SetStroke( m_stroke );
2054  m_pending = true;
2055 
2056  //special case to have the canvas itself recieve at least this one also.
2057  //because often the zoomtool is active as only tool, but
2058  //some object on the canvas are meant to react to MD (Href's etc.)
2059  event.Skip();
2060  if ( !EnterBusyMode() )
2061  return;
2062  }
2063  else if ( event.LeftUp() /*event.LeftDown()*/ && GetBusy() )
2064  {
2065  a2dRect* rec = wxStaticCast( m_canvasobject.Get(), a2dRect );
2066  //Prevent this object from being visible before it is deleted.
2067  m_canvasobject->SetVisible( false );
2068 
2069  double w = GetDrawer2D()->WorldToDeviceXRel( rec->GetWidth() );
2070  double h = GetDrawer2D()->WorldToDeviceYRel( rec->GetHeight() );
2071 
2072  //to be able to intercept doubleclick
2073  //ignore the LeftDown and LeftUp if mouse position is the same
2074  if ( fabs( w ) < 3 && fabs( h ) < 3 )
2075  {
2076  GetDisplayWindow()->Refresh();
2077  FinishBusyMode();
2078  event.Skip();
2079  }
2080  else
2081  {
2082  double x1 = rec->GetBboxMinX();
2083 
2084  double y1 = rec->GetBboxMinY();
2085 
2086  //Get the current window size to put on zoomstack
2087  a2dBoundingBox* bbox = new a2dBoundingBox( GetDrawer2D()->GetVisibleMinX(),
2088  GetDrawer2D()->GetVisibleMinY(),
2089  GetDrawer2D()->GetVisibleMaxX(),
2090  GetDrawer2D()->GetVisibleMaxY()
2091  );
2092 
2093  m_stcontroller->GetZoomList().Insert( bbox );
2094 
2095  GetCanvasCommandProcessor()->Zoom( x1, y1, rec->GetBboxWidth(), rec->GetBboxHeight(), false );
2096 
2097  a2dGeneralGlobals->RecordF( this, _T( "zoom %f %f %f %f" ), x1, y1, x1 + rec->GetBboxWidth(), y1 + rec->GetBboxHeight() );
2098 
2099  //generate an OnPaint event in order to redraw
2100  //other tools that are busy at this moment
2101  //GetDrawingPart()->Refresh();
2102 
2103  FinishBusyMode();
2105 
2106  event.Skip();
2107  }
2108  }
2109  else if ( ( event.Dragging() && GetBusy() ) /*|| (event.Moving() && GetBusy())*/ )
2110  {
2111  a2dRect* rec = wxStaticCast( m_canvasobject.Get(), a2dRect );
2112 
2114 
2115  rec->SetWidth( m_xwprev - rec->GetPosX() );
2116  rec->SetHeight( m_ywprev - rec->GetPosY() );
2117  rec->SetPending( true );
2118  m_pending = true;
2119  }
2120  else if( event.RightUp() )
2121  {
2122  if ( m_oneshot )
2123  StopTool();
2124  event.Skip(); //for popup menu in stcontroller.
2125  }
2126  else
2127  event.Skip();
2128 }
2129 
2130 BEGIN_EVENT_TABLE( a2dSelectTool, a2dStTool )
2131  EVT_CHAR( a2dSelectTool::OnChar )
2132  EVT_MOUSE_EVENTS( a2dSelectTool::OnMouseEvent )
2133 END_EVENT_TABLE()
2134 
2135 a2dSelectTool::a2dSelectTool( a2dStToolContr* controller ): a2dStTool( controller )
2136 {
2137  m_storeUndo = false;
2138 
2139  m_eventHandler = controller->GetDefaultToolEventHandlerFixedStyle();
2140 
2141  m_isEditTool = false;
2142  m_anotate = true;//false;
2143  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS );
2144  m_toolBusyCursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS );
2145  m_shift_is_add = false;
2146 
2147  if ( GetDrawingPart()->GetDrawer2D()->HasAlpha() || GetDrawingPart()->GetTrippleBuf() )
2148  {
2149  SetFill( a2dFill( wxColour( 233, 15, 23, 20 ) ) );
2150  SetStroke( a2dStroke( wxColour( 255, 59, 25, 65 ), 1, a2dSTROKE_LONG_DASH ) );
2151  }
2152  else
2153  {
2154  SetFill( *a2dTRANSPARENT_FILL );
2155  SetStroke( a2dStroke( *wxRED, 1, a2dSTROKE_LONG_DASH ) );
2156  }
2157 }
2158 
2159 a2dSelectTool::~a2dSelectTool()
2160 {
2161 }
2162 
2163 void a2dSelectTool::DeselectAll()
2164 {
2165  a2dStTool::DeselectAll();
2166  //GetCanvasCommandProcessor()->Submit( new a2dCommand_Select( m_parentobject, a2dCommand_Select::Args().what( a2dCommand_Select::DeSelectAll ) ) );
2167 }
2168 
2170 {
2171  // Add old (and later new) annotation area to pending region
2173 
2174  a2dRect* rec = wxStaticCast( m_canvasobject.Get(), a2dRect );
2175  m_anotation.Printf( _T( "w %6.3f h %6.3f" ), rec->GetWidth(), rec->GetHeight() );
2176 
2177  wxCoord w, h, descent, external;
2178  GetTextExtent( m_anotation, &w, &h, &descent, &external );
2179 
2180  m_xanotation = m_x + h;
2181  m_yanotation = m_y + h;
2182 
2184 }
2185 
2186 void a2dSelectTool::OnChar( wxKeyEvent& event )
2187 {
2188  if ( !GetBusy() )
2189  {
2190  switch( event.GetKeyCode() )
2191  {
2192  case WXK_RETURN:
2193  {
2195  }
2196  break;
2197  case WXK_SUBTRACT:
2198  {
2200  }
2201  break;
2202  default:
2203  event.Skip();
2204  }
2205  }
2206  else
2207  event.Skip();
2208 }
2209 
2210 void a2dSelectTool::OnMouseEvent( wxMouseEvent& event )
2211 {
2212  if ( !m_active )
2213  {
2214  event.Skip();
2215  return;
2216  }
2217 
2218  m_x = event.GetX();
2219  m_y = event.GetY();
2221 
2222  if ( event.Moving() )
2223  {
2224  if ( !GetBusy() )
2225  {
2226  double xWorld, yWorld;
2227  GetDrawingPart()->MouseToToolWorld( m_x, m_y, xWorld, yWorld );
2228 
2229  static a2dCanvasObject* oldhitobject = NULL;
2230  a2dCanvasObject* hitobject = NULL;
2231  hitobject = GetDrawingPart()->IsHitWorld( xWorld, yWorld, wxLAYER_ALL, a2dCANOBJHITOPTION_LAYERS, true );
2232  if ( hitobject )
2233  {
2234  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_HAND ) );
2235  }
2236  else
2237  GetDrawingPart()->SetCursor( m_toolcursor );
2238  }
2239  else
2240  GetDrawingPart()->SetCursor( m_toolBusyCursor );
2241  }
2242 
2243  if ( event.LeftDClick() && !GetBusy() )
2244  {
2245 
2246  }
2247  else if ( event.LeftDown() && !GetBusy() )
2248  {
2249  if ( !EnterBusyMode() )
2250  return;
2251 
2252  //special case to have the canvas itself recieve at least this one also.
2253  //because often the zoomtool is active as only tool, but
2254  //some object on the canvas are meant to react to MD (Href's etc.)
2255  event.Skip();
2256  }
2257  else if ( event.LeftUp() && GetBusy() )
2258  {
2259  if ( m_storeUndo )
2260  OpenCommandGroup( false );
2261 
2262  a2dRect* rec = wxStaticCast( m_canvasobject.Get(), a2dRect );
2263  //Prevent this object from being visible before it is deleted.
2264  m_canvasobject->SetVisible( false );
2265 
2266  double w = GetDrawer2D()->WorldToDeviceXRel( rec->GetWidth() );
2267  double h = GetDrawer2D()->WorldToDeviceYRel( rec->GetHeight() );
2268 
2269  if ( fabs( w ) < 3 && fabs( h ) < 3 )
2270  {
2271  // The user did click somewhere ( no drag )
2272 
2273  a2dCanvasObject* hitobject = GetDrawingPart()->IsHitWorld( m_xwprev, m_ywprev, wxLAYER_ALL, a2dCANOBJHITOPTION_LAYERS, true );
2274 
2275  if( m_shift_is_add )
2276  {
2277  if ( !event.m_shiftDown )
2278  {
2279  //if NOT shift down, deselect all and set selection to hit object.
2280  DeselectAll();
2281 
2282  if ( hitobject ) //set selection to hit object.
2283  {
2285  new a2dCommand_SetSelectFlag( hitobject, true )
2286  , m_storeUndo
2287  );
2288  }
2289  }
2290  else
2291  {
2292  //if shift down, add to selection when hit on object, else nothing
2293  if ( hitobject ) // deselect all if not on an object
2294  {
2296  new a2dCommand_SetSelectFlag( hitobject, !hitobject->GetSelected() )
2297  , m_storeUndo
2298  );
2299  }
2300  }
2301 
2302  if ( !hitobject )
2303  {
2304  if( !m_oneshot )
2305  event.Skip();
2306  FinishBusyMode( m_storeUndo );
2307  return;
2308  }
2309  }
2310  else
2311  {
2312  if ( !hitobject )
2313  {
2314  if( !m_oneshot )
2315  event.Skip();
2316  FinishBusyMode( m_storeUndo );
2317  return;
2318  }
2319 
2320  if ( event.m_shiftDown || hitobject->GetSelected() )
2321  {
2323  new a2dCommand_SetSelectFlag( hitobject, false )
2324  , m_storeUndo
2325  );
2326  }
2327  else
2328  {
2330  new a2dCommand_SetSelectFlag( hitobject, true )
2331  , m_storeUndo
2332  );
2333  }
2334  }
2335  }
2336  else
2337  {
2338  if( m_shift_is_add )
2339  {
2340  //if shift is not down, start a new selection, by first deslecting all,
2341  //and dragging a new selection rectangle
2342 
2343  if ( !event.m_shiftDown )
2344  {
2345  DeselectAll();
2349  .x1( rec->GetBbox().GetMinX() )
2350  .y1( rec->GetBbox().GetMinY() )
2351  .x2( rec->GetBbox().GetMaxX() )
2352  .y2( rec->GetBbox().GetMaxY() )
2353  )
2354  , m_storeUndo
2355  );
2356  }
2357  else
2358  {
2362  .x1( rec->GetBbox().GetMinX() )
2363  .y1( rec->GetBbox().GetMinY() )
2364  .x2( rec->GetBbox().GetMaxX() )
2365  .y2( rec->GetBbox().GetMaxY() )
2366  )
2367  , m_storeUndo
2368  );
2369  }
2370  }
2371  else
2372  {
2373  if ( event.m_shiftDown )
2374  {
2378  .x1( rec->GetBbox().GetMinX() )
2379  .y1( rec->GetBbox().GetMinY() )
2380  .x2( rec->GetBbox().GetMaxX() )
2381  .y2( rec->GetBbox().GetMaxY() )
2382  )
2383  , m_storeUndo
2384  );
2385  }
2386  else
2387  {
2391  .x1( rec->GetBbox().GetMinX() )
2392  .y1( rec->GetBbox().GetMinY() )
2393  .x2( rec->GetBbox().GetMaxX() )
2394  .y2( rec->GetBbox().GetMaxY() )
2395  )
2396  , m_storeUndo
2397  );
2398  }
2399  }
2400  }
2401 
2402  m_pending = true;
2404  FinishBusyMode( m_storeUndo );
2405  GetDrawingPart()->Update( a2dCANVIEW_UPDATE_SYNC_DRAWERS );
2406  }
2407  else if ( ( event.Dragging() && GetBusy() ) /*|| (event.Moving() && GetBusy())*/ )
2408  {
2409  a2dRect* rec = wxStaticCast( m_canvasobject.Get(), a2dRect );
2410  rec->SetWidth( m_xwprev - rec->GetPosX() );
2411  rec->SetHeight( m_ywprev - rec->GetPosY() );
2412  rec->SetPending( true );
2413 
2414  m_pending = true;
2415  }
2416  else
2417  event.Skip();
2418 }
2419 
2421 {
2422  EnterBusyModeNoGroup();
2423 
2424  if( !CreateToolObjects() )
2425  {
2427  return false;
2428  }
2429 
2430  return true;
2431 }
2432 
2434 {
2435  // The base class CleanupToolObjects is fine and also does an equivalent of
2436  // RemoveEditobject, so this is not overloaded
2437  a2dRect* rec = new a2dRect( m_xwprev, m_ywprev, 0, 0, 0 );
2438  m_canvasobject = rec;
2439  rec->SetFill( m_fill );
2440  rec->SetStroke( m_stroke );
2442  rec->SetPending( true );
2443  AddDecorationObject( rec );
2444  return true;
2445 }
2446 
2447 BEGIN_EVENT_TABLE( a2dImageTool, a2dStDrawTool )
2448  EVT_CHAR( a2dImageTool::OnChar )
2449  EVT_MOUSE_EVENTS( a2dImageTool::OnMouseEvent )
2450 END_EVENT_TABLE()
2451 
2452 a2dImageTool::a2dImageTool( a2dStToolContr* controller ): a2dStDrawTool( controller )
2453 {
2454  m_eventHandler = controller->GetDefaultToolEventHandlerFixedStyle();
2455 
2456  m_drawPatternOnTop = false;
2457  m_anotate = true;//false;
2458  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_PENCIL );
2459  m_toolBusyCursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS );
2460 
2461  //i like transparent fill and specific stroke
2462  SetFill( *a2dTRANSPARENT_FILL );
2463  SetStroke( a2dStroke( *wxRED, 1, a2dSTROKE_DOT ) );
2464 }
2465 
2466 a2dImageTool::~a2dImageTool()
2467 {
2468 }
2469 
2471 {
2472  // Add old (and later new) annotation area to pending region
2474 
2475  a2dRect* rec = wxStaticCast( m_canvasobject.Get(), a2dRect );
2476  m_anotation.Printf( _T( "w %6.3f h %6.3f" ), rec->GetWidth(), rec->GetHeight() );
2477 
2478  wxCoord w, h, d, l;
2479  GetTextExtent( m_anotation, &w, &h, &d, &l );
2480  m_xanotation = m_x + ( int ) h;
2481  m_yanotation = m_y + ( int ) h;
2483 }
2484 
2485 void a2dImageTool::OnChar( wxKeyEvent& event )
2486 {
2487  if ( !GetBusy() )
2488  {
2489  switch( event.GetKeyCode() )
2490  {
2491  case WXK_RETURN:
2492  {
2494  }
2495  break;
2496  case WXK_SUBTRACT:
2497  {
2499  }
2500  break;
2501  default:
2502  event.Skip();
2503  }
2504  }
2505  else
2506  event.Skip();
2507 }
2508 
2509 void a2dImageTool::OnMouseEvent( wxMouseEvent& event )
2510 {
2511  if ( !m_active )
2512  {
2513  event.Skip();
2514  return;
2515  }
2516 
2517  if ( GetBusy() )
2518  GetDrawingPart()->SetCursor( m_toolBusyCursor );
2519  else
2520  GetDrawingPart()->SetCursor( m_toolcursor );
2521 
2522  m_x = event.GetX();
2523  m_y = event.GetY();
2525 
2526  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
2527  if( restrict )
2528  restrict->RestrictPoint( m_xwprev, m_ywprev );
2529 
2530  if ( event.LeftDClick() && !GetBusy() )
2531  {
2532 
2533  }
2534  else if ( event.LeftDown() && !GetBusy() )
2535  {
2536  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
2537  a2dRect* rec = new a2dRect( m_xwprev, m_ywprev, 0, 0, 0 );
2538  rec->SetRoot( GetDrawingPart()->GetDrawing(), false );
2539  rec->SetFill( m_fill );
2540  rec->SetStroke( m_stroke );
2542 
2543  m_original = rec;
2544  if ( !EnterBusyMode() )
2545  return;
2546 
2547  //special case to have the canvas itself recieve at least this one also.
2548  //because often the zoomtool is active as only tool, but
2549  //some object on the canvas are meant to react to MD (Href's etc.)
2550  event.Skip();
2551  }
2552  else if ( event.LeftDown() && GetBusy() )
2553  {
2554  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
2556 
2557  a2dRect* rec = wxStaticCast( m_canvasobject.Get(), a2dRect );
2558 
2559  double w = GetDrawer2D()->WorldToDeviceXRel( rec->GetWidth() );
2560  double h = GetDrawer2D()->WorldToDeviceYRel( rec->GetHeight() );
2561 
2562  static wxString image_dir = _T( "./" );
2563  static wxString filter = _T( "All files (*.*)| *.*| BMP files (*.bmp)|*.bmp| GIF files (*.gif)|*.gif| JPEG files (*.jpg)|*.jpg;*.JPG| PNG files (*.png)| *.png" );
2564 
2565  wxFileName image_file;
2566 
2567  wxFileDialog dialog( GetDisplayWindow(), _T( "Select Image File" ), image_dir, image_file.GetFullPath(), filter, wxFD_OPEN );
2568 
2569  if ( dialog.ShowModal() != wxID_OK )
2570  return;
2571 
2572  // save for the next time
2573  image_dir = dialog.GetDirectory();
2574  image_file = dialog.GetFilename();
2575 
2576  wxBitmapType type = wxBITMAP_TYPE_ANY;
2577 
2578  if ( image_file.GetExt() == _T( "bmp" ) )
2579  type = wxBITMAP_TYPE_BMP;
2580  else if ( image_file.GetExt() == _T( "gif" ) )
2581  type = wxBITMAP_TYPE_GIF;
2582  else if ( image_file.GetExt() == _T( "jpg" ) )
2583  type = wxBITMAP_TYPE_JPEG;
2584  else if ( image_file.GetExt() == _T( "png" ) )
2585  type = wxBITMAP_TYPE_PNG;
2586  else
2587  type = wxBITMAP_TYPE_ANY;
2588 
2589  wxImage image;
2590 
2591  a2dImage* canvas_image; //canvas image object to create
2592 
2593 #ifdef __WXMSW__
2594  const wxChar SEP = wxT( '\\' );
2595 #else
2596  const wxChar SEP = wxT( '/' );
2597 #endif
2598 
2599  wxString image_fullpath = image_dir + SEP + image_file.GetFullPath();
2600  image.LoadFile( image_fullpath, type );
2601 
2602  double x1 = rec->GetBbox().GetMinX();
2603  double y1 = rec->GetBbox().GetMinY();
2604  double image_w = fabs( rec->GetWidth() );
2605  double image_h = fabs( rec->GetHeight() );
2606 
2607  if ( fabs( w ) < 3 && fabs( h ) < 3 )
2608  {
2609  image_w = image.GetWidth();
2610  image_h = image.GetHeight();
2611 
2612  canvas_image = new a2dImage( image, x1 + image_w / 2 , y1 + image_h / 2, 0, 0 );
2613  }
2614  else
2615  {
2616  canvas_image = new a2dImage( image, x1 + image_w / 2 , y1 + image_h / 2, image_w, image_h );
2617  }
2618  canvas_image->SetFilename( image_fullpath, type, false );
2619  canvas_image->SetRoot( GetDrawingPart()->GetDrawing(), false );
2620  canvas_image->SetFill( *a2dTRANSPARENT_FILL );
2621  canvas_image->SetStroke( *a2dTRANSPARENT_STROKE );
2622  canvas_image->SetLayer( m_layer );
2623  canvas_image->SetImageType( type );
2624  canvas_image->SetDrawPatternOnTop( m_drawPatternOnTop );
2625 
2626  m_original = canvas_image;
2627  AddCurrent( canvas_image );
2628 
2630  FinishBusyMode();
2631  GetDrawingPart()->Update( a2dCANVIEW_UPDATE_SYNC_DRAWERS );
2632  }
2633  else if ( ( event.Dragging() && GetBusy() ) || ( event.Moving() && GetBusy() ) )
2634  {
2635  a2dRect* rec = wxStaticCast( m_canvasobject.Get(), a2dRect );
2636  rec->SetWidth( m_xwprev - rec->GetPosX() );
2637  rec->SetHeight( m_ywprev - rec->GetPosY() );
2638 
2639  m_pending = true;
2640  }
2641  else
2642  event.Skip();
2643 }
2644 
2645 
2646 BEGIN_EVENT_TABLE( a2dCopyTool, a2dDragTool )
2647  EVT_MOUSE_EVENTS( a2dCopyTool::OnMouseEvent )
2648 END_EVENT_TABLE()
2649 
2650 a2dCopyTool::a2dCopyTool( a2dStToolContr* controller, a2dCanvasObject* copyobject, double xw, double yw ): a2dDragTool( controller )
2651 {
2652  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_ARROW );
2653  m_toolBusyCursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_Copy );
2654  m_mindist = GetDrawing()->GetHabitat()->GetCopyMinDistance();
2655  m_deepCopy = true;
2656 
2657  if ( copyobject )
2658  {
2659  m_original = GetDrawingPart()->IsHitWorld( xw, yw, wxLAYER_ALL, a2dCANOBJHITOPTION_LAYERS );
2660 
2661  if ( !m_original )
2662  {
2663  m_original = 0;
2664  return;
2665  }
2666  if ( !m_original->GetDraggable() )
2667  {
2668  m_original = 0;
2669  return;
2670  }
2671 
2672  if ( !EnterBusyMode() )
2673  return;
2674 
2675  GetDrawingPart()->SetCursor( m_toolcursor );
2676  m_xwprev = xw;
2677  m_ywprev = yw;
2678  m_startMousex = xw;
2679  m_startMousey = yw;
2680 
2681  double dx = xw - m_startMousex;
2682  double dy = yw - m_startMousey;
2683  AdjustShift( &dx, &dy );
2684  DragAbsolute( m_startObjectx + dx, m_startObjecty + dy );
2685  }
2686 }
2687 
2689 {
2690  // Don't clone connected wires as in a2dDragTool
2692  m_canvasobject->SetSelected( false );
2693 
2695  m_pending = true;
2696 
2697  return true;
2698 }
2699 
2701 {
2702  if( !a2dStTool::EnterBusyMode() )
2703  return false;
2704 
2705  CaptureMouse();
2706 
2708  m_original->DoConnect( false );
2709  //the drag copy should not connect while dragging
2710  m_canvasobject->DoConnect( false );
2711  m_original->DoConnect( false );
2712 
2715 
2716  return true;
2717 }
2718 
2719 void a2dCopyTool::FinishBusyMode( bool closeCommandGroup )
2720 {
2721  //restore connect backup
2723  a2dCanvasObjectPtr copy = NULL;
2724  if ( m_deepCopy )
2725  copy = m_original->TClone( clone_deep );
2726  else
2727  copy = m_original->TClone( clone_flat | clone_childs | clone_noCameleonRef );
2728 
2731  );
2732 
2734  new a2dCommand_SetCanvasProperty( copy, a2dCanvasObject::PROPID_TransformMatrix, m_canvasobject->GetTransformMatrix() )
2735  );
2736 
2737  if ( m_stcontroller->GetSelectAtEnd() )
2738  {
2739  DeselectAll();
2740  m_original->SetSelected( true );
2741  m_original->SetSelected2( true );
2742  }
2744  {
2747  }
2748 
2749  ReleaseMouse();
2750 
2751  a2dIterC ic( GetDrawingPart() );
2752 
2753  if ( m_lateconnect && m_wasMayConnect )
2754  {
2755  //functionality to connect object pins to objectpins which now can connect.
2756  m_original->SetAlgoSkip( true );
2757  m_canvasobject->SetAlgoSkip( true );
2758  copy->SetAlgoSkip( true );
2759  //a2dCanvasObject::PROPID_DisableFeedback->SetPropertyToObject( m_original, true );
2760  //a2dCanvasObject::PROPID_DisableFeedback->SetPropertyToObject( m_canvasobject, true );
2761  GetDrawing()->GetHabitat()->GetConnectionGenerator()->
2762  ConnectToPinsObject( GetDrawingPart()->GetShowObject(), copy, GetHitMargin() );
2763 
2764  m_original->SetAlgoSkip( false );
2765  m_canvasobject->SetAlgoSkip( false );
2766  copy->SetAlgoSkip( false );
2767  //m_original->RemoveProperty( a2dCanvasObject::PROPID_DisableFeedback );
2768  //m_canvasobject->RemoveProperty( a2dCanvasObject::PROPID_DisableFeedback );
2769  }
2770 
2772 }
2773 
2774 void a2dCopyTool::OnMouseEvent( wxMouseEvent& event )
2775 {
2776  if ( !m_active )
2777  {
2778  event.Skip();
2779  return;
2780  }
2781 
2782  int x = event.GetX();
2783  int y = event.GetY();
2784 
2785  //to world coordinates to do hit test in world coordinates
2786  double xw, yw;
2787  MouseToToolWorld( x, y, xw, yw );
2788 
2789  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
2790  if( restrict )
2791  {
2792  restrict->SetShiftKeyDown( event.ShiftDown() );
2793  }
2794 
2795  if ( event.Moving() && !GetBusy() )
2796  {
2797  a2dCanvasObject* hit = GetDrawingPart()->IsHitWorld( xw, yw );
2798  if ( hit && hit->GetDraggable() )
2799  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_HAND ) );
2800  else
2801  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_ARROW ) );
2802 
2803  }
2804 
2805  if ( event.LeftDown() )
2806  {
2807  m_original = GetDrawingPart()->IsHitWorld( xw, yw, wxLAYER_ALL, a2dCANOBJHITOPTION_LAYERS );
2808 
2809  if ( !m_original )
2810  {
2811  m_original = 0;
2812  return;
2813  }
2814  if ( !m_original->GetDraggable() )
2815  {
2816  m_original = 0;
2817  return;
2818  }
2819 
2820  if ( !EnterBusyMode() )
2821  return;
2822 
2823  GetDrawingPart()->SetCursor( m_toolcursor );
2824  m_xwprev = xw;
2825  m_ywprev = yw;
2826  m_startMousex = xw;
2827  m_startMousey = yw;
2828 
2829  if( restrict )
2831 
2832  double dx = xw - m_startMousex;
2833  double dy = yw - m_startMousey;
2834  AdjustShift( &dx, &dy );
2836  }
2837  else if ( event.LeftUp() && GetBusy() )
2838  {
2839  GetDrawingPart()->SetCursor( m_toolcursor );
2840 
2841  // Needed by FinishBusyMode
2842  m_xwprev = xw;
2843  m_ywprev = yw;
2844 
2845  FinishBusyMode();
2846  }
2847  else if ( GetBusy() )
2848  {
2849  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_HAND ) );
2850  double dx = xw - m_startMousex;
2851  double dy = yw - m_startMousey;
2852  AdjustShift( &dx, &dy );
2854  m_xwprev = xw;
2855  m_ywprev = yw;
2856  }
2857  else
2858  {
2859  event.Skip();
2860  }
2861 }
2862 
2863 void a2dCopyTool::AdjustShift( double* dx, double* dy )
2864 {
2865  if( ( *dx ) * ( *dx ) + ( *dy ) * ( *dy ) < m_mindist )
2866  {
2867  if( ( *dx ) == 0 && ( *dy ) == 0 )
2868  {
2869  ( *dx ) = m_mindist * 1.0;
2870  ( *dy ) = m_mindist * 0.5;
2871  }
2872  else
2873  {
2874  double fac = m_mindist / sqrt( ( *dx ) * ( *dx ) + ( *dy ) * ( *dy ) );
2875  ( *dx ) *= fac;
2876  ( *dy ) *= fac;
2877  }
2878  }
2879 }
2880 
2881 BEGIN_EVENT_TABLE( a2dDragTool, a2dStTool )
2882  EVT_MOUSE_EVENTS( a2dDragTool::OnMouseEvent )
2883  EVT_CHAR( a2dDragTool::OnChar )
2884 END_EVENT_TABLE()
2885 
2886 a2dDragTool::a2dDragTool( a2dStToolContr* controller, a2dCanvasObject* dragobject, double xw, double yw ): a2dStTool( controller )
2887 {
2888  m_eventHandler = controller->GetDefaultToolEventHandlerFixedStyle();
2889 
2890  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_ARROW );
2891  m_toolBusyCursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_Drag );
2892  m_mousecaptured = false;
2893  m_deleteonoutsidedrop = false;
2894  m_dropAndDrop = false;
2895 
2896  m_anotate = false;
2897  m_lateconnect = true;
2898 
2899  //i like transparent fill and specific stroke
2900  SetFill( *a2dTRANSPARENT_FILL );
2901  SetStroke( a2dStroke( *wxRED, 1, a2dSTROKE_DOT ) );
2902 
2903  if ( dragobject )
2904  {
2905  GetDrawingPart()->ToolWorldToMouse( xw, yw, m_x, m_y );
2906  GetDrawing()->GetHabitat()->SetLastXyEntry( xw, yw );
2907  a2dCanvasObject* original = GetDrawingPart()->IsHitWorld( xw, yw, wxLAYER_ALL, a2dCANOBJHITOPTION_LAYERS );
2908 
2909  if ( !StartDragging( m_x, m_y, original ) )
2910  return;
2911  }
2912 
2913  m_snapSourceFeatures = a2dRestrictionEngine::snapToNone;
2914 
2915  //only modes which are usefull in dragging
2916  m_snapTargetFeatures =
2917  a2dRestrictionEngine::snapToGridPos |
2920  a2dRestrictionEngine::snapToObjectPos |
2921  //a2dRestrictionEngine::snapToPinsUnconnected |
2925 }
2926 
2928 {
2929 }
2930 
2931 void a2dDragTool::OnChar( wxKeyEvent& event )
2932 {
2933  if ( GetBusy() )
2934  {
2935  double xw = m_xwprev;
2936  double yw = m_ywprev;
2937 
2938  double shiftx;
2939  double shifty;
2940  GetKeyIncrement( &shiftx, &shifty );
2941 
2942  //now shift with snap distances in X or Y
2943  switch( event.GetKeyCode() )
2944  {
2945  case WXK_DELETE:
2946  {
2947  // if busy do nothing with this key.
2948  break;
2949  }
2950  case WXK_UP:
2951  shiftx = 0;
2952  m_xwprev = xw + shiftx;
2953  m_ywprev = yw + shifty;
2955 
2956  GetDrawingPart()->Update( a2dCANVIEW_UPDATE_SYNC_DRAWERS );
2957  GetDisplayWindow()->WarpPointer( GetDrawer2D()->WorldToDeviceX( m_xwprev ), GetDrawer2D()->WorldToDeviceY( m_ywprev ) );
2958  break;
2959 
2960  case WXK_DOWN:
2961  shiftx = 0;
2962  shifty = -shifty;
2963  m_xwprev = xw + shiftx;
2964  m_ywprev = yw + shifty;
2966 
2967  GetDrawingPart()->Update( a2dCANVIEW_UPDATE_SYNC_DRAWERS );
2968  GetDisplayWindow()->WarpPointer( GetDrawer2D()->WorldToDeviceX( m_xwprev ), GetDrawer2D()->WorldToDeviceY( m_ywprev ) );
2969  break;
2970 
2971  case WXK_LEFT:
2972  shiftx = -shiftx;
2973  shifty = 0;
2974  m_xwprev = xw + shiftx;
2975  m_ywprev = yw + shifty;
2977 
2978  GetDrawingPart()->Update( a2dCANVIEW_UPDATE_SYNC_DRAWERS );
2979  GetDisplayWindow()->WarpPointer( GetDrawer2D()->WorldToDeviceX( m_xwprev ), GetDrawer2D()->WorldToDeviceY( m_ywprev ) );
2980  break;
2981 
2982  case WXK_RIGHT:
2983  shifty = 0;
2984  m_xwprev = xw + shiftx;
2985  m_ywprev = yw + shifty;
2987 
2988  GetDrawingPart()->Update( a2dCANVIEW_UPDATE_SYNC_DRAWERS );
2989  GetDisplayWindow()->WarpPointer( GetDrawer2D()->WorldToDeviceX( m_xwprev ), GetDrawer2D()->WorldToDeviceY( m_ywprev ) );
2990  break;
2991 
2992  case '9':
2993  {
2994  //if ( event.m_controlDown )
2995  if ( GetBusy() )
2996  {
2997  a2dAffineMatrix mat = m_canvasobject->GetTransform();
2999  m_canvasobject->SetTransform( mat );
3000  }
3001  break;
3002  }
3003  default:
3004  {
3005  shiftx = 0;
3006  shifty = 0;
3007  event.Skip();
3008  }
3009  }
3010  }
3011  else
3012  event.Skip();
3013 
3014 }
3015 
3017 {
3018  if ( m_original && GetBusy() )
3019  {
3021  }
3022 }
3023 
3024 void a2dDragTool::AdjustShift( double* WXUNUSED( x ), double* WXUNUSED( y ) )
3025 {
3026 }
3027 
3028 bool a2dDragTool::StartDragging( int x, int y, a2dCanvasObject* original )
3029 {
3030  m_x = x;
3031  m_y = y;
3033 
3034  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
3035 
3036  m_original = original;
3037 
3038  if ( !m_original || !m_original->GetDraggable() )
3039  {
3040  m_original = 0;
3041  return false;
3042  }
3043 
3045 
3046  if ( !EnterBusyMode() )
3047  return false;
3048 
3051 
3052  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
3053  if( restrict )
3055  return true;
3056 }
3057 
3058 void a2dDragTool::OnMouseEvent( wxMouseEvent& event )
3059 {
3060  if ( !m_active )
3061  {
3062  event.Skip();
3063  return;
3064  }
3065 
3066  m_x = event.GetX();
3067  m_y = event.GetY();
3068 
3069  //to world coordinates to do hit test in world coordinates
3071 
3072  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
3073  if( restrict )
3074  {
3075  restrict->SetShiftKeyDown( event.ShiftDown() );
3076  }
3077 
3078  if ( event.Moving() && !GetBusy() )
3079  {
3081  if ( hit && hit->GetDraggable() )
3082  GetDrawingPart()->SetCursor( m_toolBusyCursor );
3083  else
3084  GetDrawingPart()->SetCursor( m_toolcursor );
3085  // this to allow EVT_CANVASOBJECT_LEAVE_EVENT
3086  event.Skip();
3087  }
3088 
3089  if ( event.LeftDown() && !GetBusy() )
3090  {
3091  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
3093 
3094  if ( m_dropAndDrop && original )
3095  {
3096  ReleaseMouse();
3097  a2dCanvasObject* clone = original->TClone( clone_members | clone_childs );
3098  a2dDnDCanvasObjectDataCVG shapeData( GetDrawingPart() );
3099  shapeData.Append( clone );
3100  wxDropSource source(shapeData, GetDrawingPart()->GetDisplayWindow() );
3101 
3102  const wxChar *pc = NULL;
3103  switch ( source.DoDragDrop(true) )
3104  {
3105  default:
3106  case wxDragError:
3107  wxLogError(wxT("An error occurred during drag and drop operation"));
3108  break;
3109 
3110  case wxDragNone:
3111  SetStateString( _("No drop happened"), STAT_toolHelp );
3112  break;
3113 
3114  case wxDragCopy:
3115  pc = wxT("copied");
3116  break;
3117 
3118  case wxDragMove:
3119  pc = wxT("moved");
3120  break;
3121 
3122  case wxDragCancel:
3123  SetStateString( _("Drag and drop operation cancelled"), STAT_toolHelp );
3124  break;
3125  }
3126 
3127  if ( pc )
3128  {
3129  SetStateString(wxString(wxT("Shape successfully ")) + pc, STAT_toolHelp );
3130  }
3131  //else: status text already set
3132 
3133  }
3134  else if ( !StartDragging( m_x, m_y, original ) )
3135  return;
3136 
3137  }
3138  else if ( event.LeftUp() && GetBusy() )
3139  {
3140  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
3141 
3142  if ( !m_deleteonoutsidedrop &&
3143  ( m_xwprev < GetDrawer2D()->GetVisibleMinX() ||
3144  m_xwprev > GetDrawer2D()->GetVisibleMaxX() ||
3145  m_ywprev < GetDrawer2D()->GetVisibleMinY() ||
3146  m_ywprev > GetDrawer2D()->GetVisibleMaxY()
3147  )
3148  )
3149  {
3150  AbortBusyMode();
3151  return;
3152  }
3153  else
3154  FinishBusyMode();
3155  }
3156  else if ( event.RightDown() )
3157  {
3158  event.Skip();
3159  }
3160  else if ( GetBusy() )
3161  {
3162  //PRFL_AUTO_TMR( a2dDragTool_MouseMove );
3163 
3164  GetDrawingPart()->SetCursor( m_toolBusyCursor );
3165 
3166  double xPosObject = m_startObjectx + m_xwprev - m_startMousex;
3167  double yPosObject = m_startObjecty + m_ywprev - m_startMousey;
3168  DragAbsolute( xPosObject, yPosObject );
3169 
3170  event.Skip(); //scroll wheel will work
3171 
3172  double unitScale = GetDrawing()->GetUnitsScale();
3173  wxString state, form;
3174  form = m_stcontroller->GetFormat() + " " + m_stcontroller->GetFormat();
3175  state.Printf( form, m_canvasobject->GetBboxMinX()*unitScale, m_canvasobject->GetBboxMinY()*unitScale );
3176  SetStateString( state, 10 );
3177  form = _T("width = ") + m_stcontroller->GetFormat() + _T(" height = ") + m_stcontroller->GetFormat();
3178  state.Printf( form, m_canvasobject->GetBboxWidth()*unitScale, m_canvasobject->GetBboxHeight()*unitScale );
3179  SetStateString( state, 11 );
3180  }
3181  //!todo skip is needed if object should connect itself, in a2dCanvasObject::Update()
3182  // Do this to be able to scroll inout using mouse wheel.
3183  else
3184  event.Skip();
3185 }
3186 
3187 
3189 {
3191  GetDrawingPart()->GetDisplayWindow()->CaptureMouse();
3192  m_mousecaptured = true;
3193 }
3194 
3196 {
3197  if( m_mousecaptured )
3198  {
3199  GetDrawingPart()->SetCaptured( NULL );
3200  GetDrawingPart()->GetDisplayWindow()->ReleaseMouse();
3201  }
3202  m_mousecaptured = false;
3203 }
3204 
3206 {
3207  if( !a2dStTool::EnterBusyMode() )
3208  return false;
3209 
3210  CaptureMouse();
3211 
3212  //the drag copy should not connect while dragging
3213  m_canvasobject->DoConnect( false );
3215  m_original->DoConnect( false );
3216 
3219 
3220  return true;
3221 }
3222 
3223 void a2dDragTool::FinishBusyMode( bool closeCommandGroup )
3224 {
3225  //restore connect backup
3227  if(
3228  ( m_deleteonoutsidedrop ) &&
3229  (
3230  m_xwprev < GetDrawer2D()->GetVisibleMinX() ||
3231  m_xwprev > GetDrawer2D()->GetVisibleMaxX() ||
3232  m_ywprev < GetDrawer2D()->GetVisibleMinY() ||
3233  m_ywprev > GetDrawer2D()->GetVisibleMaxY()
3234  )
3235  )
3236  {
3237  if ( m_deleteonoutsidedrop )
3238  {
3239  ReleaseMouse();
3240 
3241  // the object was dropped outside of the window
3242  // The code below is copied from a2dDeleteTool
3243  m_original->SetPending( true );
3244  m_original->SetVisible( false );
3245 
3246  //redraw in buffer what should be there without this object
3248 
3249  GetDrawing()->GetHabitat()->GetConnectionGenerator()->RerouteWires( true );
3250  //delete object from document (actually move to command for redo)
3253  }
3254  }
3255  else
3256  {
3257  ReleaseMouse();
3258 
3259  //the next has internal the functionality to connect object pins to objectpins which now can connect.
3261  new a2dCommand_SetCanvasProperty( m_original, a2dCanvasObject::PROPID_TransformMatrix, m_canvasobject->GetTransformMatrix() )
3262  );
3263  GetDrawing()->GetHabitat()->GetConnectionGenerator()->RerouteWires( true );
3264  }
3265 
3266  /* TODO maybe
3267  The next would be a way to drag object from this level to one deeper.
3268  But in that case we also want the other way around.
3269  So we would need a drag in a clipper go to one level higher.
3270  a2dCanvasObject* canvasobjecttophit = GetDrawingPart()->IsHitWorld(xw,yw);
3271 
3272  if (canvasobjecttophit)
3273  {
3274  a2dPolygonLClipper* clipper = wxDynamicCast(canvasobjecttophit,a2dPolygonLClipper);
3275  if (clipper && clipper != m_canvasobject )
3276  {
3277  GetDrawing()->Remove(m_canvasobject,false);
3278  clipper->Append(m_canvasobject);
3279  }
3280  }
3281  */
3282 
3283  if ( m_lateconnect && m_wasMayConnect )
3284  {
3285  m_original->SetAlgoSkip( true );
3286  m_canvasobject->SetAlgoSkip( true );
3287  GetDrawing()->GetHabitat()->GetConnectionGenerator()->
3288  ConnectToPinsObject( GetDrawingPart()->GetShowObject(), m_original, GetHitMargin() );
3289 
3290  m_original->SetAlgoSkip( false );
3291  m_canvasobject->SetAlgoSkip( false );
3292  }
3293 
3295 }
3296 
3298 {
3300  ReleaseMouse();
3301  GetDrawing()->GetHabitat()->GetConnectionGenerator()->RerouteWires( true );
3303 }
3304 
3305 void a2dDragTool::DragAbsolute( double x, double y )
3306 {
3307  a2dPoint2D oldpos = m_canvasobject->GetPosXY();
3308 
3309  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
3310  if( restrict )
3311  {
3312  bool snapold = m_original->GetSnapTo(); //do not snap to original
3313  m_original->SetSnapTo( false );
3314  //temporarily restore position according to the mouse position, which is the unrestricted position.
3315  m_canvasobject->SetPosXY( x, y );
3316 
3317  a2dPoint2D point;
3318  double dx, dy; //detect restriction distance of any point.
3319 
3320  if ( restrict->GetShiftKeyDown() )
3321  {
3322  restrict->RestrictPoint( x, y );
3323  }
3324  else
3325  {
3327  a2dSnapToWhatMask was = restrict->GetSnapSourceFeatures();
3330  if ( snapTo == a2dRestrictionEngine::snapToNone )
3331  restrict->GetSnapTargetFeatures();
3332 
3333  if ( restrict->RestrictCanvasObjectAtVertexes( m_canvasobject, point, dx, dy, snapTo, true ) )
3334  {
3335  //restrict the object drawing to that point
3336  x += dx;
3337  y += dy;
3338  //wxLogDebug( wxT( " dx =%12.6lf, dy =%12.6lf" ), dx, dy );
3339  }
3340  //wxLogDebug( wxT( "cx =%12.6lf, cy =%12.6lf" ), x, y );
3341  restrict->SetSnapSourceFeatures( was );
3342  }
3343  m_original->SetSnapTo( snapold );
3344  }
3345 
3346  // show the object according to the restricted position.
3347  m_canvasobject->SetPosXY( x, y );
3349  {
3350  m_original->SetPosXY( x, y );
3351  }
3352 
3353  if ( oldpos != m_canvasobject->GetPosXY() )
3354  {
3356 
3357  GetDrawing()->GetHabitat()->GetConnectionGenerator()->RerouteWires( false );
3358  m_pending = true;
3359  }
3360 }
3361 
3363 {
3364  //as a result of dragging ad rerouting, sometimes object connected to itself, now (also) correcting it.
3365  m_original->DisConnectWith( m_original, "", true );
3366 
3367  // Clone the original drag object
3368  a2dRefMap refs;
3370  m_canvasobject->SetSelected( false );
3371  m_original->SetSnapTo( false );
3372 
3373  // Add the draged object clone and connected object clones to the parent
3375  // Set the visibility of the original dragged object and the original connected wires
3377 
3378  //drag is comming so first create wires where there are non.
3379  a2dCanvasObjectList dragList;
3380  dragList.push_back( m_original );
3381  PrepareForRewire( dragList, true, false, false, true, &refs );
3382 
3383  refs.LinkReferences();
3384 
3385  m_pending = true;
3386  return true;
3387 }
3388 
3390 {
3392 }
3393 
3394 BEGIN_EVENT_TABLE( a2dDragOrgTool, a2dStTool )
3395  EVT_MOUSE_EVENTS( a2dDragOrgTool::OnMouseEvent )
3396  EVT_CHAR( a2dDragOrgTool::OnChar )
3397 END_EVENT_TABLE()
3398 
3399 a2dDragOrgTool::a2dDragOrgTool( a2dStToolContr* controller ): a2dStTool( controller )
3400 {
3401  m_eventHandler = controller->GetDefaultToolEventHandlerFixedStyle();
3402 
3403  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_ARROW );
3404  m_toolBusyCursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_Drag );
3405  m_mousecaptured = false;
3406  m_deleteonoutsidedrop = false;
3407 
3408  m_anotate = false;
3409  m_lateconnect = true;
3410 
3411  //i like transparent fill and specific stroke
3412  SetFill( *a2dTRANSPARENT_FILL );
3413  SetStroke( a2dStroke( *wxRED, 1, a2dSTROKE_DOT ) );
3414 }
3415 
3417 {
3418 }
3419 
3420 void a2dDragOrgTool::OnChar( wxKeyEvent& event )
3421 {
3422  if ( GetBusy() )
3423  {
3424  double xw = m_xwprev;
3425  double yw = m_ywprev;
3426 
3427  double shiftx;
3428  double shifty;
3429  GetKeyIncrement( &shiftx, &shifty );
3430 
3431  //now shift with snap distances in X or Y
3432  switch( event.GetKeyCode() )
3433  {
3434  case WXK_UP:
3435  shiftx = 0;
3436  break;
3437 
3438  case WXK_DOWN:
3439  shiftx = 0;
3440  shifty = -shifty;
3441  break;
3442 
3443  case WXK_LEFT:
3444  shiftx = -shiftx;
3445  shifty = 0;
3446  break;
3447 
3448  case WXK_RIGHT:
3449  shifty = 0;
3450  break;
3451  default:
3452  {
3453  shiftx = 0;
3454  shifty = 0;
3455  event.Skip();
3456  }
3457  }
3458 
3459  m_xwprev = xw + shiftx;
3460  m_ywprev = yw + shifty;
3462  GetDrawingPart()->Update( a2dCANVIEW_UPDATE_SYNC_DRAWERS );
3463  GetDisplayWindow()->WarpPointer( GetDrawer2D()->WorldToDeviceX( m_xwprev ), GetDrawer2D()->WorldToDeviceY( m_ywprev ) );
3464  }
3465  else
3466  event.Skip();
3467 
3468 }
3469 
3471 {
3472  if ( m_original && GetBusy() )
3473  {
3475  }
3476 }
3477 
3478 void a2dDragOrgTool::AdjustShift( double* WXUNUSED( x ), double* WXUNUSED( y ) )
3479 {
3480 }
3481 
3482 bool a2dDragOrgTool::StartDragging( int x, int y, a2dCanvasObject* original )
3483 {
3484  m_x = x;
3485  m_y = y;
3487 
3488  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
3489 
3490  m_original = original;
3491 
3492  if ( !m_original || !m_original->GetDraggable() )
3493  {
3494  m_original = 0;
3495  return false;
3496  }
3497 
3499 
3500  if ( !EnterBusyMode() )
3501  return false;
3502 
3505 
3506  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
3507  if( restrict )
3509  return true;
3510 }
3511 
3512 void a2dDragOrgTool::OnMouseEvent( wxMouseEvent& event )
3513 {
3514  if ( !m_active )
3515  {
3516  event.Skip();
3517  return;
3518  }
3519 
3520  m_x = event.GetX();
3521  m_y = event.GetY();
3522 
3523  //to world coordinates to do hit test in world coordinates
3525 
3526  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
3527  if( restrict )
3528  restrict->RestrictPoint( m_xwprev, m_ywprev );
3529 
3530  if ( event.Moving() && !GetBusy() )
3531  {
3533  if ( hit && hit->GetDraggable() )
3534  GetDrawingPart()->SetCursor( m_toolBusyCursor );
3535  else
3536  GetDrawingPart()->SetCursor( m_toolcursor );
3537  }
3538 
3539  if ( event.LeftDown() && !GetBusy() )
3540  {
3541  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
3543 
3544  if ( !StartDragging( m_xwprev, m_ywprev, original ) )
3545  return;
3546  }
3547  else if ( event.LeftUp() && GetBusy() )
3548  {
3549  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
3550  FinishBusyMode();
3551  }
3552  else if ( event.RightDown() )
3553  {
3554  event.Skip();
3555  }
3556  else if ( GetBusy() )
3557  {
3558  GetDrawingPart()->SetCursor( m_toolBusyCursor );
3560  }
3561  //!todo skip is needed if object should connect itself, in a2dCanvasObject::Update()
3562  //else
3563  // event.Skip();
3564 }
3565 
3566 
3568 {
3570  GetDrawingPart()->GetDisplayWindow()->CaptureMouse();
3571  m_mousecaptured = true;
3572 }
3573 
3575 {
3576  if( m_mousecaptured )
3577  {
3578  GetDrawingPart()->SetCaptured( NULL );
3579  GetDrawingPart()->GetDisplayWindow()->ReleaseMouse();
3580  }
3581  m_mousecaptured = false;
3582 }
3583 
3585 {
3586  if( !a2dStTool::EnterBusyMode() )
3587  return false;
3588 
3589  CaptureMouse();
3590 
3591  //the drag copy should not connect while dragging
3592  m_canvasobject->DoConnect( false );
3594  m_original->DoConnect( false );
3595 
3598 
3599  return true;
3600 }
3601 
3602 void a2dDragOrgTool::FinishBusyMode( bool closeCommandGroup )
3603 {
3604  //restore connect backup
3606 
3607  if(
3609  (
3610  m_xwprev < GetDrawer2D()->GetVisibleMinX() ||
3611  m_xwprev > GetDrawer2D()->GetVisibleMaxX() ||
3612  m_ywprev < GetDrawer2D()->GetVisibleMinY() ||
3613  m_ywprev > GetDrawer2D()->GetVisibleMaxY()
3614  )
3615  )
3616  {
3617  // the object was dropped outside of the window
3618  // The code below is copied from a2dDeleteTool
3619  m_original->SetPending( true );
3620  m_original->SetVisible( false );
3621 
3622  //redraw in buffer what should be there without this object
3624 
3625  //delete object from document (actually move to command for redo)
3628  }
3629  else
3630  {
3631  //the next has internal the functionality to connect object pins to objectpins which now can connect.
3633  new a2dCommand_SetCanvasProperty( m_original, a2dCanvasObject::PROPID_TransformMatrix, m_canvasobject->GetTransformMatrix() )
3634  );
3635 
3636  GetDrawing()->GetHabitat()->GetConnectionGenerator()->RerouteWires( true );
3637  }
3638 
3639  ReleaseMouse();
3640 
3641  a2dStTool::FinishBusyMode( closeCommandGroup );
3642 }
3643 
3645 {
3646  ReleaseMouse();
3647 
3649 }
3650 
3651 void a2dDragOrgTool::DragAbsolute( double x, double y )
3652 {
3653  a2dPoint2D oldpos = m_canvasobject->GetPosXY();
3654 
3655  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
3656  if( restrict )
3657  {
3658  //temporarily restore position according to the mouse position, which is the unrestricted position.
3659  m_canvasobject->SetPosXY( x, y );
3660 
3661  a2dPoint2D point;
3662  double dx, dy; //detect restriction distance of any point.
3663  if ( restrict->RestrictCanvasObjectAtVertexes( m_canvasobject, point, dx, dy ) )
3664  {
3665  //restrict the object drawing to that point
3666  x += dx;
3667  y += dy;
3668  }
3669  }
3670 
3671  // show the object according to the restricted position.
3672  m_canvasobject->SetPosXY( x, y );
3674  m_original->SetPosXY( x, y );
3675 
3676  if( oldpos != m_canvasobject->GetPosXY() )
3677  {
3678  a2dIterC ic( GetDrawingPart() );
3680 
3681  GetDrawing()->GetHabitat()->GetConnectionGenerator()->RerouteWires( false );
3682 
3683  m_pending = true;
3684  }
3685 }
3686 
3688 {
3689  // Clone the original drag object
3691  m_canvasobject->SetSelected( false );
3692  m_original->SetSnapTo( false );
3693 
3694  a2dRefMap refs;
3695  //drag is comming so first create wires where there are non.
3696  a2dCanvasObjectList dragList;
3697  dragList.push_back( m_original );
3698  PrepareForRewire( dragList, true, false, false, true, &refs );
3699  refs.LinkReferences();
3700 
3701  m_pending = true;
3702 
3703  return true;
3704 }
3705 
3706 
3708 {
3710 }
3711 
3712 DEFINE_MENU_ITEMID( CmdMenu_NoDragMenu, wxTRANSLATE("Drag the new object"), wxTRANSLATE("Drag new object in place") )
3713 
3714 BEGIN_EVENT_TABLE( a2dDragNewTool, a2dDragTool )
3715  EVT_ENTER_WINDOW( a2dDragNewTool::OnEnter )
3716  EVT_MOUSE_EVENTS( a2dDragNewTool::OnMouseEvent )
3717  EVT_COM_EVENT( a2dDragNewTool::OnComEvent )
3718  EVT_CHAR( a2dDragNewTool::OnChar )
3719 END_EVENT_TABLE()
3720 
3721 a2dDragNewTool::a2dDragNewTool( a2dStToolContr* controller, a2dCanvasObject* newObject, const a2dMenuIdItem& initiatingMenuId )
3722  : a2dDragTool( controller )
3723 {
3724  m_initiatingMenuId = &initiatingMenuId;
3725  m_eventHandler = controller->GetDefaultToolEventHandlerFixedStyle();
3726  m_newObject = newObject;
3727  m_boxCenterDrag = false;
3728 }
3729 
3730 a2dDragNewTool::~a2dDragNewTool()
3731 {
3732 }
3733 
3735 {
3736  if ( GetBusy() )
3737  {
3738  a2dAffineMatrix mat = m_canvasobject->GetTransform();
3739  if ( right )
3741  else
3742  mat.Rotate( -90, m_canvasobject->GetPosX(), m_canvasobject->GetPosY() );
3743  m_canvasobject->SetTransform( mat );
3744  a2dAffineMatrix matn = m_newObject->GetTransform();
3745  matn.Rotate( 90, m_newObject->GetPosX(), m_newObject->GetPosY() );
3746  m_newObject->SetTransform( matn );
3747  }
3748  return true;
3749 }
3750 
3751 void a2dDragNewTool::OnComEvent( a2dComEvent& event )
3752 {
3753  if ( GetBusy() )
3754  {
3755  if ( event.GetId() == a2dStTool::sig_toolBeforePush )
3756  {
3757  a2dProperty* property = ( a2dProperty* ) event.GetProperty();
3758  a2dStTool* newtool = wxStaticCast( property->GetRefObject(), a2dStTool );
3759  if ( GetBusy() )
3760  {
3761  if ( !wxDynamicCast( newtool, a2dZoomTool ) )
3762  {
3763  FinishBusyMode();
3764  }
3765  else
3766  {
3767  m_halted = true;
3768  }
3769  }
3770  SetPending( true );
3771  }
3772  else
3773  event.Skip();
3774  }
3775  else
3776  event.Skip();
3777 }
3778 
3779 void a2dDragNewTool::OnEnter( wxMouseEvent& WXUNUSED( event ) )
3780 {
3781  if ( GetDrawingPart()->GetDisplayWindow() && !GetDrawingPart()->GetDisplayWindow()->HasFocus() )
3782  GetDrawingPart()->GetDisplayWindow()->SetFocus();
3783 }
3784 
3785 void a2dDragNewTool::OnChar( wxKeyEvent& event )
3786 {
3787  if ( GetBusy() )
3788  {
3789  switch( event.GetKeyCode() )
3790  {
3791  case '9':
3792  {
3793  //if ( event.m_controlDown )
3794  RotateObject90LeftRight( true );
3795  break;
3796  }
3797  default:
3798  {
3799  event.Skip();
3800  }
3801  }
3802  }
3803  else
3804  event.Skip();
3805 
3806 }
3807 
3808 void a2dDragNewTool::OnMouseEvent( wxMouseEvent& event )
3809 {
3810  if ( !m_active )
3811  {
3812  event.Skip();
3813  return;
3814  }
3815 
3816  m_x = event.GetX();
3817  m_y = event.GetY();
3818 
3819  //to world coordinates to do hit test in world coordinates
3820  double xw, yw;
3821  MouseToToolWorld( m_x, m_y, xw, yw );
3822 
3823  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
3824  if( restrict )
3825  restrict->RestrictPoint( xw, yw );
3826 
3827  if( !GetBusy() )
3828  {
3829  //m_original = m_newObject->TClone( clone_deep );
3830  //! todo Object having reference sometimes better not deep.
3831  m_original = m_newObject->TClone( clone_deep | clone_noCameleonRef | clone_noReference );
3832 
3834  if ( m_boxCenterDrag )
3835  m_original->SetPosXY( xw - box.GetWidth()/2.0, yw - box.GetHeight()/2.0 );
3836  else
3837  m_original->SetPosXY( xw, yw );
3839 
3840  // AddCurrent adjusts the objects style and submits an a2dCommand_AddObject
3842 
3844 
3845  if ( !EnterBusyMode() )
3846  return;
3847 
3849 
3850  m_xwprev = xw;
3851  m_ywprev = yw;
3852  m_startMousex = xw;
3853  m_startMousey = yw;
3854  }
3855  else if ( event.LeftDown() )
3856  {
3857  // don't process this in the base class
3858  }
3859  else if ( event.RightDown() )
3860  {
3861  event.Skip();
3862  }
3863  else if ( event.LeftUp() )
3864  {
3865  a2dDragTool::OnMouseEvent( event );
3867  }
3868  else
3869  {
3870  // all the rest is as with a usual drag
3871  a2dDragTool::OnMouseEvent( event );
3872  }
3873 }
3874 
3876 {
3877  // we generally don't want the original to be visible, regardless of the mode
3878  // this is because the original was cloned from the template object, and is not a
3879  // true original object
3880  m_renderOriginal = false;
3881 }
3882 
3883 void a2dDragNewTool::DoStopTool( bool WXUNUSED( abort ) )
3884 {
3885  // a a2dDragNewTool can be stopped, even if it is busy. This is because the
3886  // tool can be busy with mouse up.
3887  if( GetBusy() )
3888  {
3889  wxASSERT( m_original );
3890  AbortBusyMode();
3891  }
3892 
3893  if ( m_commandgroup )
3895 }
3896 
3898 {
3900  return false;
3901 
3902  // we don't want the mouse to be captured, so undo this
3903  ReleaseMouse();
3904 
3905  // Note: there is no need to overload Finish/AbortBusyMode,
3906  // because the base class stores if it did capture the mouse
3907 
3908  return true;
3909 }
3910 
3911 void a2dDragNewTool::FinishBusyMode( bool closeCommandGroup )
3912 {
3913  //restore connect backup
3915 
3916  //the next has internal the functionality to connect object pins to objectpins which now can connect.
3918  new a2dCommand_SetCanvasProperty( m_original, a2dCanvasObject::PROPID_TransformMatrix, m_canvasobject->GetTransformMatrix() )
3919  );
3922 
3923  if ( m_stcontroller->GetSelectAtEnd() )
3924  {
3925  DeselectAll();
3926  m_original->SetSelected( true );
3927  m_original->SetSelected2( true );
3928  }
3930  {
3933  }
3934 
3935  GetDrawing()->GetHabitat()->GetConnectionGenerator()->RerouteWires( true );
3936  //ReleaseMouse();
3937 
3939 }
3940 
3941 
3942 BEGIN_EVENT_TABLE( a2dDeleteTool, a2dStTool )
3943  EVT_CHAR( a2dDeleteTool::OnChar )
3944  EVT_MOUSE_EVENTS( a2dDeleteTool::OnMouseEvent )
3945 END_EVENT_TABLE()
3946 
3947 a2dDeleteTool::a2dDeleteTool( a2dStToolContr* controller, a2dCanvasObjectFlagsMask whichobjects )
3948  :
3949  a2dStTool( controller )
3950 {
3951  m_eventHandler = controller->GetDefaultToolEventHandlerFixedStyle();
3952 
3953  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_BULLSEYE );
3954  m_canvasobject = 0;
3955  m_whichobjects = whichobjects;
3956 }
3957 
3958 void a2dDeleteTool::OnChar( wxKeyEvent& event )
3959 {
3960  if ( GetBusy() )
3961  {
3962  switch( event.GetKeyCode() )
3963  {
3964  case WXK_SPACE:
3965  {
3966  if( m_canvasobject )
3967  {
3968  OpenCommandGroup( false );
3969  //delete object from document (actually move to command for redo)
3972  m_canvasobject->SetVisible( true );
3973  FinishBusyMode();
3974  }
3975  }
3976  break;
3977  default:
3978  event.Skip();
3979  }
3980  }
3981  else
3982  event.Skip();
3983 
3984 }
3985 
3986 void a2dDeleteTool::OnMouseEvent( wxMouseEvent& event )
3987 {
3988  if ( !m_active )
3989  {
3990  event.Skip();
3991  return;
3992  }
3993  GetDrawingPart()->SetCursor( m_toolcursor );
3994 
3995  int x = event.GetX();
3996  int y = event.GetY();
3997 
3998  //to world coordinates to do hit test in world coordinates
3999  double xw, yw;
4000  MouseToToolWorld( x, y, xw, yw );
4001 
4002  if ( event.LeftDown() )
4003  {
4004  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
4006 
4007  if ( !m_canvasobject )
4008  {
4009  m_canvasobject = 0;
4010  event.Skip();
4011  if ( m_oneshot )
4012  StopTool();
4013  return;
4014  }
4015 
4016  if( !m_canvasobject->CheckMask( m_whichobjects ) )
4017  {
4018  if ( m_oneshot )
4019  StopTool();
4020  return;
4021  }
4022 
4023  if ( !EnterBusyMode() )
4024  return;
4025 
4026  m_canvasobject->SetPending( true );
4027  m_canvasobject->SetVisible( false );
4028 
4029  //redraw in buffer what should be there without this object
4031 
4032  //delete object from document (actually move to command for redo)
4035 
4036  GetDrawing()->GetHabitat()->GetConnectionGenerator()->SetPinsToBeginState( GetDrawingPart()->GetShowObject() );
4037 
4038  //make visible on undo stack
4039  m_canvasobject->SetVisible( true );
4040  FinishBusyMode();
4041  }
4042  else
4043  event.Skip();
4044 
4045 }
4046 
4047 BEGIN_EVENT_TABLE( a2dDrawCircleTool, a2dStDrawTool )
4048  EVT_IDLE( a2dDrawCircleTool::OnIdle )
4049  EVT_CHAR( a2dDrawCircleTool::OnChar )
4050  EVT_MOUSE_EVENTS( a2dDrawCircleTool::OnMouseEvent )
4051 END_EVENT_TABLE()
4052 
4053 a2dDrawCircleTool::a2dDrawCircleTool( a2dStToolContr* controller ): a2dStDrawTool( controller )
4054 {
4055  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_PENCIL );
4056  m_toolBusyCursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS );
4057 }
4058 
4060 {
4061  // Add old (and later new) annotation area to pending region
4063 
4064  //a2dCircle* cir = wxStaticCast( m_canvasobject.Get(), a2dCircle );
4065 
4066  m_anotation.Printf( _T( "radius %6.3f" ), m_radius );
4067 
4068  wxCoord w, h, descent, external;
4069  GetTextExtent( m_anotation, &w, &h, &descent, &external );
4070 
4071  m_xanotation = m_x + h;
4072  m_yanotation = m_y + h;
4073 
4075 }
4076 
4077 
4078 void a2dDrawCircleTool::OnIdle( wxIdleEvent& event )
4079 {
4080  if ( m_pending && GetBusy() )
4081  {
4083 
4085  a2dSLine* ll = new a2dSLine( cir->GetPosX(), cir->GetPosY(), m_xwprev, m_ywprev );
4086  ll->SetStroke( *wxRED, 0, a2dSTROKE_DOT );
4087 
4088  a2dCircle* zero = new a2dCircle( m_start_x, m_start_y, GetDrawer2D()->DeviceToWorldXRel( 3 ) );
4089  zero->SetFill( *wxRED );
4090 
4091  a2dRect* around = new a2dRect( cir->GetBboxMinX(), cir->GetBboxMinY(), cir->GetBboxWidth(), cir->GetBboxHeight() );
4092  around->SetStroke( *wxRED, 0, a2dSTROKE_LONG_DASH );
4093  around->SetFill( *a2dTRANSPARENT_FILL );
4094 
4095  AddDecorationObject( around );
4096  AddDecorationObject( ll );
4097  AddDecorationObject( zero );
4098 
4099  event.Skip();
4100  }
4101  else
4102  event.Skip();
4103 }
4104 
4105 void a2dDrawCircleTool::OnChar( wxKeyEvent& event )
4106 {
4107  if ( GetBusy() )
4108  {
4109  switch( event.GetKeyCode() )
4110  {
4111  case WXK_TAB:
4112  {
4113  m_mode++;
4114  SetMode( m_mode );
4115  }
4116  break;
4117 
4118  default:
4119  event.Skip();
4120  }
4121  }
4122  else
4123  event.Skip();
4124 
4125 }
4126 
4128 {
4129  m_mode = mode;
4130  if ( m_mode > 2 ) m_mode = 0;
4131 
4132  if ( !m_canvasobject )
4133  return;
4134 
4136  a2dCircle* cirorg = wxStaticCast( m_original.Get(), a2dCircle );
4137  switch ( m_mode )
4138  {
4139  case 0:
4140  {
4141  double dx, dy;
4142 
4143  if ( fabs( m_xwprev - m_start_x ) > fabs( m_ywprev - m_start_y ) )
4144  {
4145  dx = ( m_xwprev - m_start_x ) / 2 ;
4146  m_radius = fabs( dx );
4147  if ( m_ywprev > m_start_y )
4148  dy = m_radius;
4149  else
4150  dy = -m_radius;
4151  }
4152  else
4153  {
4154  dy = ( m_ywprev - m_start_y ) / 2 ;
4155  m_radius = fabs( dy );
4156  if ( m_xwprev > m_start_x )
4157  dx = m_radius;
4158  else
4159  dx = -m_radius;
4160  }
4161  cir->SetPosXY( m_start_x + dx , m_start_y + dy );
4162  cirorg->SetPosXY( m_start_x + dx , m_start_y + dy );
4163  break;
4164  }
4165  case 1:
4166  {
4167  cir->SetPosXY( m_start_x, m_start_y );
4168  cirorg->SetPosXY( m_start_x, m_start_y );
4169  m_radius = sqrt( pow( m_xwprev - cir->GetPosX(), 2 ) + pow( m_ywprev - cir->GetPosY(), 2 ) );
4170  break;
4171  }
4172  case 2:
4173  {
4174  cir->SetPosXY( ( m_xwprev + m_start_x ) / 2, ( m_ywprev + m_start_y ) / 2 );
4175  cirorg->SetPosXY( ( m_xwprev + m_start_x ) / 2, ( m_ywprev + m_start_y ) / 2 );
4176  m_radius = sqrt( pow( m_xwprev - m_start_x, 2 ) + pow( m_ywprev - m_start_y, 2 ) ) / 2;
4177  break;
4178  }
4179  default:
4180  break;
4181  }
4182 
4183  cir->SetRadius( m_radius );
4184  cirorg->SetRadius( m_radius );
4185 
4186  double unitScale = GetDrawing()->GetUnitsScale();
4187  wxString state;
4188  wxString form = m_stcontroller->GetFormat() + " " + m_stcontroller->GetFormat();
4189  state.Printf( form, cir->GetPosX()*unitScale, cir->GetPosY()*unitScale );
4190  SetStateString( state, 10 );
4191  form = _T("radius = ") + m_stcontroller->GetFormat();
4192  state.Printf( form, m_radius*unitScale );
4193  SetStateString( state, 11 );
4194 
4195  m_pending = true;
4196 }
4197 
4198 void a2dDrawCircleTool::OnMouseEvent( wxMouseEvent& event )
4199 {
4200  if ( !m_active )
4201  {
4202  event.Skip();
4203  return;
4204  }
4205 
4206  if ( GetBusy() )
4207  GetDrawingPart()->SetCursor( m_toolBusyCursor );
4208  else
4209  GetDrawingPart()->SetCursor( m_toolcursor );
4210 
4211  m_x = event.GetX();
4212  m_y = event.GetY();
4214 
4215  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
4216  if( restrict )
4217  restrict->RestrictPoint( m_xwprev, m_ywprev );
4218 
4219  if ( event.LeftDown() && !GetBusy() )
4220  {
4221  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
4222  m_radius = 0;
4223  m_original = new a2dCircle( m_xwprev, m_ywprev, m_radius );
4224  m_start_x = m_xwprev;
4225  m_start_y = m_ywprev;
4226 
4227  if ( !EnterBusyMode() )
4228  return;
4230  }
4231  else if ( event.LeftDown() && GetBusy() )
4232  {
4233  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
4234  a2dGeneralGlobals->RecordF( this, _T( "circle %f %f %f" ), m_canvasobject->GetPosX(), m_canvasobject->GetPosY(), m_radius );
4235 
4236  FinishBusyMode();
4237  }
4238  else if ( ( event.Dragging() && GetBusy() ) || ( event.Moving() && GetBusy() ) )
4239  {
4240  SetMode( m_mode );
4241  }
4242  else
4243  event.Skip();
4244 }
4245 
4246 BEGIN_EVENT_TABLE( a2dDrawPolygonLTool, a2dStDrawTool )
4247  EVT_IDLE( a2dDrawPolygonLTool::OnIdle )
4248  EVT_CHAR( a2dDrawPolygonLTool::OnChar )
4249  EVT_MOUSE_EVENTS( a2dDrawPolygonLTool::OnMouseEvent )
4250  EVT_DO( a2dDrawPolygonLTool::OnDoEvent )
4251  EVT_UNDO( a2dDrawPolygonLTool::OnUndoEvent )
4252  EVT_REDO( a2dDrawPolygonLTool::OnRedoEvent )
4253 END_EVENT_TABLE()
4254 
4255 void a2dDrawPolygonLTool::AddPoint( a2dLineSegment* point )
4256 {
4257  if ( m_reverse )
4258  m_points->push_front( point );
4259  else
4260  m_points->push_back( point );
4261 }
4262 
4263 a2dDrawPolygonLTool::a2dDrawPolygonLTool( a2dStToolContr* controller, a2dPolygonL* templateObject ): a2dStDrawTool( controller )
4264 {
4265  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_PENCIL );
4266  m_toolBusyCursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS );
4268 
4270  m_points = ( a2dVertexList* ) 0;
4271 
4272  m_reverse = false;
4273 
4274  m_templateObject = templateObject;
4275  if ( !m_templateObject )
4276  {
4277  m_templateObject = new a2dPolygonL();
4278  m_templateObject->SetContourWidth( GetDrawing()->GetHabitat()->GetContourWidthInDataBaseUnits() );
4280  m_templateObject->SetSpline( GetDrawing()->GetHabitat()->GetSpline() );
4281  }
4282  else
4283  {
4285  m_fill = m_templateObject->GetFill();
4286  m_stroke = m_templateObject->GetStroke();
4288  }
4289 }
4290 
4291 a2dDrawPolygonLTool::~a2dDrawPolygonLTool()
4292 {
4293 }
4294 
4296 {
4297  m_templateObject->SetSpline( spline );
4298 }
4299 
4300 void a2dDrawPolygonLTool::OnIdle( wxIdleEvent& event )
4301 {
4302  if ( m_pending && GetBusy() )
4303  {
4305 
4307  a2dRect* around = NULL;
4308  a2dPolygonL* nonSplined = NULL;
4309 
4310  switch ( m_mode )
4311  {
4312  case 2:
4313  {
4314  //a nice to see normal polygon around it and if stroke transparent show it.
4315  if ( poly->GetSpline() )
4316  {
4317  nonSplined = ( a2dPolygonL* ) poly->TClone( clone_childs );
4318  nonSplined->SetVisible( true );
4319  nonSplined->SetSpline( false );
4320  nonSplined->SetFill( *a2dTRANSPARENT_FILL );
4321 
4322  nonSplined->SetStroke( *wxBLACK, 0, a2dSTROKE_DOT_DASH );
4323  AddDecorationObject( nonSplined );
4324 
4325  }
4326  }
4327  case 1:
4328  {
4329  around = new a2dRect( poly->GetBboxMinX(), poly->GetBboxMinY(), poly->GetBboxWidth(), poly->GetBboxHeight() );
4330  around->SetStroke( *wxRED, 0, a2dSTROKE_DOT_DASH );
4331  around->SetFill( *a2dTRANSPARENT_FILL );
4332  around->SetRoot( GetDrawingPart()->GetDrawing(), false );
4333  AddDecorationObject( around );
4334  break;
4335  }
4336  default:
4337  break;
4338  }
4339 
4340  event.Skip();
4341  }
4342  else
4343  event.Skip();
4344 }
4345 
4346 void a2dDrawPolygonLTool::BeginPolygon( double x, double y )
4347 {
4348  m_xwprev = x;
4349  m_ywprev = y;
4350 
4351  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
4352  if( restrict )
4353  restrict->RestrictPoint( m_xwprev, m_ywprev );
4354  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
4362 
4363  if ( !EnterBusyMode() )
4364  return;
4366 
4368 
4369  // Append first point to original
4372  );
4373  // Append first point to editcopy
4374  m_points = wxStaticCast( m_canvasobject.Get(), a2dPolygonL )->GetSegments();
4376  AddPoint( m_point );
4377 
4378  // Record commands
4379  a2dGeneralGlobals->RecordF( this, _T( "polygon" ) );
4380  a2dGeneralGlobals->RecordF( this, _T( "addpoint %f %f" ), m_xwprev, m_ywprev );
4381 
4382  //add second point to drag
4384  AddPoint( m_point );
4385 
4386  m_prev_x = m_xwprev;
4387  m_prev_y = m_ywprev;
4388  m_pending = true;
4389  if( restrict )
4390  restrict->SetRestrictPoint( m_xwprev, m_ywprev );
4391 }
4392 
4393 void a2dDrawPolygonLTool::AddPoint( double x, double y )
4394 {
4395  m_xwprev = x;
4396  m_ywprev = y;
4397  m_point->m_x = m_xwprev;
4398  m_point->m_y = m_ywprev;
4399 
4400  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
4401  if( restrict )
4402  restrict->RestrictPoint( m_xwprev, m_ywprev );
4403  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
4404  int xd = GetDrawer2D()->WorldToDeviceX( m_prev_x );
4405  int yd = GetDrawer2D()->WorldToDeviceY( m_prev_y );
4406  if ( abs( m_x - xd ) >= 3 || abs( m_y - yd ) >= 3 )
4407  {
4410  );
4411 
4412  a2dGeneralGlobals->RecordF( this, _T( "addpoint %f %f " ), m_xwprev, m_ywprev );
4413 
4415  AddPoint( m_point );
4416  m_prev_x = m_xwprev;
4417  m_prev_y = m_ywprev;
4418  }
4419  m_pending = true;
4420  if( restrict )
4421  restrict->SetRestrictPoint( m_xwprev, m_ywprev );
4422 }
4423 
4424 void a2dDrawPolygonLTool::OnDoEvent( a2dCommandProcessorEvent& event )
4425 {
4426  if ( GetBusy() && !m_halted )
4427  {
4428  if ( event.GetCommand()->GetCommandId() == &a2dCommand_SetCursor::Id )
4429  {
4431  AddPoint( setcursor->GetX(), setcursor->GetY() );
4432  }
4433  }
4434  else
4435  {
4436  if ( event.GetCommand()->GetCommandId() == &a2dCommand_SetCursor::Id )
4437  {
4439  BeginPolygon( setcursor->GetX(), setcursor->GetY() );
4440  }
4441  }
4442  event.Skip();
4443 }
4444 
4445 void a2dDrawPolygonLTool::OnUndoEvent( a2dCommandProcessorEvent& WXUNUSED( event ) )
4446 {
4447  if ( GetBusy() && !m_halted )
4448  {
4449  // recreate edit copies so the edit copy becomes updated from the original.
4450 
4451  a2dPolygonL* poly = wxStaticCast( m_original.Get(), a2dPolygonL );
4452  if ( poly->GetNumberOfSegments() )
4453  {
4454  a2dLineSegment* lastpoint = poly->GetSegments()->back();
4455 
4459  m_points = wxStaticCast( m_canvasobject.Get(), a2dPolygonL )->GetSegments();
4460  m_point = lastpoint->Clone();
4461  m_points->push_back( m_point );
4462  }
4463  }
4464 }
4465 
4466 void a2dDrawPolygonLTool::OnRedoEvent( a2dCommandProcessorEvent& event )
4467 {
4468  OnUndoEvent( event );
4469 }
4470 
4472 {
4473  m_mode = mode;
4474  if ( m_mode > 2 ) m_mode = 0;
4475 
4476  if ( !m_canvasobject )
4477  return;
4478 
4479  m_pending = true;
4480 }
4481 
4482 void a2dDrawPolygonLTool::OnChar( wxKeyEvent& event )
4483 {
4484  if ( GetBusy() && m_canvasobject )
4485  {
4486  double shiftx;
4487  double shifty;
4488  GetKeyIncrement( &shiftx, &shifty );
4489 
4490  switch( event.GetKeyCode() )
4491  {
4492  case WXK_TAB:
4493  {
4494  m_mode++;
4495  SetMode( m_mode );
4496  return;
4497  }
4498  break;
4499 
4500  case WXK_UP:
4501  shiftx = 0;
4502  break;
4503 
4504  case WXK_DOWN:
4505  shiftx = 0;
4506  shifty = -shifty;
4507  break;
4508 
4509  case WXK_LEFT:
4510  shiftx = -shiftx;
4511  shifty = 0;
4512  break;
4513 
4514  case WXK_RIGHT:
4515  shifty = 0;
4516  break;
4517 
4518  default:
4519  {
4520  shiftx = 0;
4521  shifty = 0;
4522  event.Skip();
4523  }
4524  }
4525 
4526  if ( event.m_controlDown )
4527  {
4528  double x = m_canvasobject->GetPosX();
4529  double y = m_canvasobject->GetPosY();
4530  m_canvasobject->SetPosXY( x + shiftx, y + shifty, true );
4532  poly->EliminateMatrix();
4533  }
4534  else
4535  {
4536  m_point->m_x += shiftx;
4537  m_point->m_y += shifty;
4538  }
4539 
4540  GetDisplayWindow()->WarpPointer( GetDrawer2D()->WorldToDeviceX( m_point->m_x ), GetDrawer2D()->WorldToDeviceY( m_point->m_y ) );
4541 
4542  m_pending = true;
4543  }
4544  else
4545  event.Skip();
4546 
4547 }
4548 
4549 void a2dDrawPolygonLTool::OnMouseEvent( wxMouseEvent& event )
4550 {
4551  if ( !m_active )
4552  {
4553  event.Skip();
4554  return;
4555  }
4556 
4557  if ( GetBusy() )
4558  GetDrawingPart()->SetCursor( m_toolBusyCursor );
4559  else
4560  GetDrawingPart()->SetCursor( m_toolcursor );
4561 
4562  m_x = event.GetX();
4563  m_y = event.GetY();
4565 
4566  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
4567  if ( event.LeftDown() && !GetBusy() )
4568  {
4569  BeginPolygon( m_xwprev, m_ywprev );
4570  }
4571  else if ( event.LeftDown() && GetBusy() )
4572  {
4573  AddPoint( m_xwprev, m_ywprev );
4574  }
4575  else if ( event.Moving() && GetBusy() )
4576  {
4577  if( restrict )
4578  restrict->RestrictPoint( m_xwprev, m_ywprev );
4579  a2dBoundingBox updateareas;
4580  //AddPoint( m_point );
4581 
4582  updateareas.Expand( m_prev_x, m_prev_y );
4583  updateareas.Expand( m_point->GetPoint() );
4584  //a2dCanvasObject::PROPID_BoundingBox->SetPropertyToObject( m_canvasobject, updateareas );
4585  updateareas.Reset();
4586  updateareas.Expand( m_points->front()->GetPoint() );
4587  updateareas.Expand( m_point->GetPoint() );
4588  //a2dCanvasObject::PROPID_BoundingBox->SetPropertyToObject( m_canvasobject, updateareas );
4589 
4590  m_point->m_x = m_xwprev;
4591  m_point->m_y = m_ywprev;
4592  m_canvasobject->SetPending( true );
4593 
4594  updateareas.Reset();
4595  updateareas.Expand( m_prev_x, m_prev_y );
4596  updateareas.Expand( m_point->GetPoint() );
4597  //a2dCanvasObject::PROPID_BoundingBox->SetPropertyToObject( m_canvasobject, updateareas );
4598 
4599  updateareas.Reset();
4600  updateareas.Expand( m_points->front()->GetPoint() );
4601  updateareas.Expand( m_point->GetPoint() );
4602  //a2dCanvasObject::PROPID_BoundingBox->SetPropertyToObject( m_canvasobject, updateareas );
4603 
4604  m_pending = true;
4605 
4606  double dx = m_xwprev - m_prev_x;
4607  double dy = m_ywprev - m_prev_y;
4608 
4609  double unitScale = GetDrawing()->GetUnitsScale();
4610  wxString state;
4611  wxString form = _("Lpx") + m_stcontroller->GetFormat() + _(" Lpy") + m_stcontroller->GetFormat();
4612  state.Printf( form, m_prev_x*unitScale, m_prev_y*unitScale );
4613  SetStateString( state, 10 );
4614  form = _("dx = ") + m_stcontroller->GetFormat() + _(" dy = ") + m_stcontroller->GetFormat();
4615  state.Printf( form, dx*unitScale, dy*unitScale );
4616  SetStateString( state, 11 );
4617 
4618  event.Skip();
4619  }
4620  else if ( ( event.LeftDClick() || event.RightUp() ) && GetBusy() )
4621  {
4622  if( restrict )
4623  restrict->RestrictPoint( m_xwprev, m_ywprev );
4624  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
4625  a2dGeneralGlobals->RecordF( this, _T( "end" ) );
4626  FinishBusyMode();
4627  }
4628  else
4629  event.Skip();
4630 }
4631 
4632 BEGIN_EVENT_TABLE( a2dDrawPolylineLTool, a2dDrawPolygonLTool )
4633  EVT_MOUSE_EVENTS( a2dDrawPolylineLTool::OnMouseEvent )
4634  EVT_DO( a2dDrawPolylineLTool::OnDoEvent )
4635  EVT_COM_EVENT( a2dDrawPolylineLTool::OnComEvent )
4636 END_EVENT_TABLE()
4637 
4638 a2dDrawPolylineLTool::a2dDrawPolylineLTool( a2dStToolContr* controller, a2dPolylineL* templateObject ):
4639  a2dDrawPolygonLTool( controller, NULL )
4640 {
4641  a2dCanvasGlobals->ConnectEvent( a2dEVT_COM_EVENT, this );
4642 
4643  m_AllowModifyTemplate = true;
4644  m_templatePline = templateObject;
4645  m_templateObject = templateObject;
4646  if ( !m_templatePline )
4647  {
4648  m_templatePline = new a2dPolylineL();
4649  m_templateObject = ( a2dPolygonL* ) m_templatePline;
4650  m_templatePline->SetEndScaleX( GetDrawing()->GetHabitat()->GetEndScaleX() );
4651  m_templatePline->SetEndScaleY( GetDrawing()->GetHabitat()->GetEndScaleY() );
4652  m_templatePline->SetBegin( GetDrawing()->GetHabitat()->GetLineBegin() );
4653  m_templatePline->SetEnd( GetDrawing()->GetHabitat()->GetLineEnd() );
4654  m_templatePline->SetPathType( GetDrawing()->GetHabitat()->GetPathType() );
4655  m_templatePline->SetContourWidth( GetDrawing()->GetHabitat()->GetContourWidthInDataBaseUnits() );
4656  m_contourwidth = GetDrawing()->GetHabitat()->GetContourWidthInDataBaseUnits();
4657  }
4658  else
4659  {
4660  m_layer = m_templatePline->GetLayer();
4661  m_fill = m_templatePline->GetFill();
4662  m_stroke = m_templatePline->GetStroke();
4663  m_contourwidth = m_templatePline->GetContourWidth();
4664  }
4665 }
4666 
4667 a2dDrawPolylineLTool::~a2dDrawPolylineLTool()
4668 {
4669  a2dCanvasGlobals->DisconnectEvent( a2dEVT_COM_EVENT, this );
4670 }
4671 
4673 {
4674  if ( GetBusy() )
4675  {
4676  a2dPolylineL* poly = wxStaticCastNull( m_canvasobject.Get(), a2dPolylineL );
4677  poly->SetPathType( pathtype );
4678  a2dPolylineL* polyorg = wxStaticCastNull( m_original.Get(), a2dPolylineL );
4679  polyorg->SetPathType( pathtype );
4680  }
4681 
4682  m_templatePline->SetPathType( pathtype );
4683 }
4684 
4686 {
4687  m_templatePline->SetBegin( begin );
4688 }
4689 
4691 {
4692  m_templatePline->SetEnd( end );
4693 }
4694 
4696 {
4697  m_templatePline->SetEndScaleX( xs );
4698 }
4699 
4700 
4702 {
4703  m_templatePline->SetEndScaleY( ys );
4704 }
4705 
4706 void a2dDrawPolylineLTool::OnComEvent( a2dComEvent& event )
4707 {
4708  if ( m_AllowModifyTemplate )
4709  {
4710  if ( event.GetId() == a2dHabitat::sig_SetContourWidth )
4711  {
4713  if ( GetBusy() )
4714  {
4717  }
4718  }
4719  else if ( event.GetId() == a2dHabitat::sig_SetPathType )
4720  {
4721  a2dPATH_END_TYPE pathtype = GetDrawing()->GetHabitat()->GetPathType();
4722  if ( GetBusy() )
4723  {
4725  poly->SetPathType( pathtype );
4726  poly = wxStaticCast( m_canvasobject.Get(), a2dPolylineL );
4727  poly->SetPathType( pathtype );
4728  }
4729  }
4730  else
4731  event.Skip();
4732  }
4733  else
4734  event.Skip();
4735 }
4736 
4737 void a2dDrawPolylineLTool::OnDoEvent( a2dCommandProcessorEvent& event )
4738 {
4739  if ( !m_templateObject )
4740  {
4741  }
4742  event.Skip();
4743 }
4744 
4745 void a2dDrawPolylineLTool::OnMouseEvent( wxMouseEvent& event )
4746 {
4747  if ( !m_active )
4748  {
4749  event.Skip();
4750  return;
4751  }
4752 
4753  if ( GetBusy() )
4754  GetDrawingPart()->SetCursor( m_toolBusyCursor );
4755  else
4756  GetDrawingPart()->SetCursor( m_toolcursor );
4757 
4758  m_x = event.GetX();
4759  m_y = event.GetY();
4761 
4762  if ( event.LeftDown() && !GetBusy() )
4763  {
4764  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
4765  if( restrict )
4766  {
4767  restrict->SetShiftKeyDown( event.ShiftDown() );
4768  restrict->RestrictPoint( m_xwprev, m_ywprev );
4769  }
4770  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
4776  if ( m_original->GetFilled() )
4780  if ( line->GetBegin() && line->GetBegin()->GetFlag( a2dCanvasOFlags::normalized ) )
4781  {
4782  line->GetBegin()->SetSpecificFlags( false, a2dCanvasOFlags::normalized );
4783  double norm = GetDrawing()->GetNormalizeScale();
4784  line->GetBegin()->Scale( norm, norm );
4785  }
4786  if ( line->GetEnd() && line->GetEnd()->GetFlag( a2dCanvasOFlags::normalized ) )
4787  {
4788  line->GetEnd()->SetSpecificFlags( false, a2dCanvasOFlags::normalized );
4789  double norm = GetDrawing()->GetNormalizeScale();
4790  line->GetEnd()->Scale( norm, norm );
4791  }
4792 
4793  if ( !EnterBusyMode() )
4794  return;
4798  m_points = poly->GetSegments();
4799 
4800  a2dGeneralGlobals->RecordF( this, _T( "polyline" ) );
4801 
4803 
4804  // add point to the original
4805  if ( m_reverse )
4808  );
4809  else
4812  );
4813 
4815  AddPoint( m_point );
4816 
4817  a2dGeneralGlobals->RecordF( this, _T( "addpoint %f %f " ), m_xwprev, m_ywprev );
4818 
4819  //add second point to drag
4821  AddPoint( m_point );
4822 
4823  m_prev_x = m_xwprev;
4824  m_prev_y = m_ywprev;
4825 
4826  if( restrict )
4827  restrict->SetRestrictPoint( m_xwprev, m_ywprev );
4828 
4829  m_pending = true;
4830  }
4831  else
4832  event.Skip();
4833 }
4834 
4835 BEGIN_EVENT_TABLE( a2dDrawWirePolylineLTool, a2dDrawPolylineLTool )
4836  EVT_MOUSE_EVENTS( a2dDrawWirePolylineLTool::OnMouseEvent )
4837  EVT_KEY_DOWN( a2dDrawWirePolylineLTool::OnKeyDown )
4838  EVT_CHAR( a2dDrawWirePolylineLTool::OnChar )
4839  EVT_UNDO( a2dDrawWirePolylineLTool::OnUndoEvent )
4840  EVT_REDO( a2dDrawWirePolylineLTool::OnRedoEvent )
4841  EVT_IDLE( a2dDrawWirePolylineLTool::OnIdle )
4842 END_EVENT_TABLE()
4843 
4844 a2dDrawWirePolylineLTool::a2dDrawWirePolylineLTool( a2dStToolContr* controller )
4845  : a2dDrawPolylineLTool( controller )
4846 {
4847  m_hadDoubleClick = false;
4848 
4849  m_eventHandler = controller->GetDefaultToolEventHandlerFixedStyle();
4850 
4851  m_pinClassStartWire = NULL;
4852  m_pinClassEndWire = NULL;
4853  m_wiringMode = a2d_BasedOnClassStartPin;
4854 
4855  m_toolBusyCursor = *wxSTANDARD_CURSOR;
4856  m_splitAtEnd = true;
4857  m_startWireX = 0;
4858  m_startWireY = 0;
4859  m_manhattan = false;
4860  m_endSegmentMode = a2dCanvasGlobals->GetHabitat()->GetEndSegmentMode();
4861 
4862  //only modes which are usefull here
4863  m_snapTargetFeatures =
4864  a2dRestrictionEngine::snapToGridPos |
4870 
4871  // pins on wire need to snap.
4872  m_snapSourceFeatures = a2dRestrictionEngine::snapToPins;
4873 }
4874 
4875 a2dDrawWirePolylineLTool::~a2dDrawWirePolylineLTool()
4876 {
4877 }
4878 
4880 {
4881  // The only realy reasonable mode for wire drawing is OnTop mode, so always use this one
4882  m_renderOriginal = false;
4883  m_renderEditcopy = false;
4884  m_renderEditcopyEdit = false;
4885  m_renderEditcopyOnTop = true;
4886  m_renderEditcopyRectangle = false;
4887 
4888  m_renderOriginal = true;
4889  m_renderEditcopy = false;
4890  m_renderEditcopyOnTop = false;
4891  m_renderEditcopyEdit = true;
4892  m_renderEditcopyRectangle = false;
4893 }
4894 
4896 {
4897  // the next will remove temporary pins, but we stil need to find them!!
4898  // GetDrawing()->GetHabitat()->GetConnectionGenerator()->SetPinsToBeginState( GetDrawingPart()->GetShowObject() );
4899 
4900  //there is no wire nor pin yet, therefore we can just feedback possible pin connection, based on the
4901  // m_connectionGenerator.
4902  a2dPin* pin = GetDrawing()->GetHabitat()->GetConnectionGenerator()->
4903  SearchPinForStartWire( GetDrawingPart()->GetShowObject(), x, y, a2dPinClass::Any, GetHitMargin() );
4904 
4905  if ( pin )
4906  {
4907  switch ( m_wiringMode )
4908  {
4910  m_pinClassStartWire = GetDrawing()->GetHabitat()->GetConnectionGenerator()->GetReturnPinClass();
4911  return pin;
4912  break;
4915  return pin;
4916  break;
4917  case a2d_BasedOnObjectClassRequired:
4919  return pin;
4920  break;
4921  case a2d_StartGenerateSearchFinish:
4923  return pin;
4924  break;
4925  }
4926  }
4927  return NULL;
4928 
4929 /*
4930  // Check if the parent of this pin is a DIRECT child of the root given
4931  assert( !m_canvasobject || root->Find( m_canvasobject ) );
4932 
4933  root->GetChildObjectList()->SetSpecificFlags( false, a2dCanvasOFlags::BIN );
4934 
4935  // The pin calculates its coordinates in roots coordinate system
4936  a2dAffineMatrix tRootInv = root->GetTransformMatrix();
4937  tRootInv.Invert();
4938  double xh, yh;
4939  tRootInv.TransformPoint( x, y, xh, yh );
4940 
4941 
4942  // normal hittests go reverse drawing order of layers, eventually hiting what is drawn last.
4943  // Drawn last is of course on top of everything else.
4944  // In this case here we only want to hit pins, even if this pin is part of an object
4945  // is displayed underneath another object having pins too.
4946  // So the pin is not displayed on top still we want to hit it.
4947  // Therefore we need a special hittest here, to only search for pins, still when
4948  // we find a pin we do a normal hittest on that pin.
4949 
4950  // Go through the childs of the root and look for objects having pins
4951  for( a2dCanvasObjectList::iterator iter = root->GetChildObjectList()->begin(); iter != root->GetChildObjectList()->end(); ++iter )
4952  {
4953  a2dCanvasObject* obj = *iter;
4954 
4955  if( !obj->HasPins() )
4956  continue;
4957  if( obj == m_canvasobject )
4958  continue;
4959  if( obj == m_original )
4960  continue;
4961 
4962  a2dIterC ic( GetDrawingPart() );
4963  a2dIterCU cu( ic );
4964 
4965  // Check if obj has a pin that can connect to this pin
4966 
4967  for( a2dCanvasObjectList::iterator iterp = obj->GetChildObjectList()->begin(); iterp != obj->GetChildObjectList()->end(); ++iterp )
4968  {
4969  a2dPin* pin = wxDynamicCast( ( *iterp ).Get(), a2dPin );
4970  if ( pin )
4971  {
4972  // Don't return connected pins or pins that are to be deleted
4973  if( pin->ConnectedTo() || pin->GetRelease( ) )
4974  continue;
4975 
4976  a2dIterCU cu( ic, obj );
4977  a2dHitEvent hitevent = a2dHitEvent( xh, yh, false );
4978  if ( pin->IsHitWorld( ic, hitevent ) )
4979  {
4980  switch ( m_wiringMode )
4981  {
4982  case a2d_BasedOnClassStartPin:
4983  if ( m_pinClassStartWire = pin->GetPinClass()->GetPinClassForTask( a2d_ToConnectPinClassWire_ObjectPinClass_InOut, obj ) )
4984  return pin;
4985  break;
4986  case a2d_BasedOnWireClassRequired:
4987  if ( m_pinClassStartWire->CanConnectTo( pin->GetPinClass(), a2dPinClass::PC_input | a2dPinClass::PC_output ) )
4988  return pin;
4989  break;
4990  case a2d_BasedOnObjectClassRequired:
4991  if ( pin->GetPinClass()->CanConnectTo( m_pinClassStartWire, a2dPinClass::PC_input | a2dPinClass::PC_output ) )
4992  return pin;
4993  break;
4994  case a2d_StartGenerateSearchFinish:
4995  if ( m_pinClassStartWire = pin->GetPinClass()->GetPinClassForTask( a2d_StartWire, obj, pin->GetPinClass() ) )
4996  return pin;
4997  break;
4998  }
4999  }
5000  }
5001  }
5002  }
5003  return 0;
5004 */
5005 }
5006 
5007 /* todo
5008 a2dPin* a2dDrawWirePolylineLTool::FindFinishPin( a2dCanvasObject* root, a2dPin* wirefinishpin )
5009 {
5010  // Check if the parent of this pin is a DIRECT child of the root given
5011  assert( !m_canvasobject || root->Find( m_canvasobject ) );
5012 
5013  root->GetChildObjectList()->SetSpecificFlags( false, a2dCanvasOFlags::BIN );
5014 
5015  // The pin calculates its coordinates in roots coordinate system
5016  //a2dAffineMatrix tRootInv = root->GetTransformMatrix();
5017  //tRootInv.Invert();
5018  //tRootInv.TransformPoint( x, y, xh, yh );
5019  double xh, yh;
5020  xh = wirefinishpin->GetAbsX();
5021  yh = wirefinishpin->GetAbsY();
5022 
5023 
5024  // normal hittests go reverse drawing order of layers, eventually hiting what is drawn last.
5025  // Drawn last is of course on top of everything else.
5026  // In this case here we only want to hit pins, even if this pin is part of an object
5027  // is displayed underneath another object having pins too.
5028  // So the pin is not displayed on top still we want to hit it.
5029  // Therefore we need a special hittest here, to only search for pins, still when
5030  // we find a pin we do a normal hittest on that pin.
5031 
5032  // Go through the childs of the root and look for objects having pins
5033  for( a2dCanvasObjectList::iterator iter = root->GetChildObjectList()->begin(); iter != root->GetChildObjectList()->end(); ++iter )
5034  {
5035  a2dCanvasObject* obj = *iter;
5036 
5037  if( !obj->HasPins() )
5038  continue;
5039  if( obj == m_canvasobject )
5040  continue;
5041  if( obj == m_original )
5042  continue;
5043 
5044  a2dIterC ic( GetDrawingPart() );
5045  a2dIterCU cu( ic );
5046 
5047  // Check if obj has a pin that can connect to this pin
5048 
5049  for( a2dCanvasObjectList::iterator iterp = obj->GetChildObjectList()->begin(); iterp != obj->GetChildObjectList()->end(); ++iterp )
5050  {
5051  a2dPin* pin = wxDynamicCast( ( *iterp ).Get(), a2dPin );
5052  if ( pin )
5053  {
5054  // Don't return connected pins or pins that are to be deleted
5055  if( pin->ConnectedTo() || pin->GetRelease( ) )
5056  continue;
5057 
5058  a2dIterCU cu( ic, obj );
5059  a2dHitEvent hitevent = a2dHitEvent( xh, yh, false );
5060  if ( pin->IsHitWorld( ic, hitevent ) )
5061  {
5062  a2dConnectTask task = a2d_ToConnectPinClassWire_ObjectPinClass_InOut;
5063 
5064  switch ( m_wiringMode )
5065  {
5066  case a2d_BasedOnClassStartPin:
5067  if ( m_pinClassEndWire->CanConnectTo( pin->GetPinClass(), a2dPinClass::PC_input | a2dPinClass::PC_output ) )
5068  return pin;
5069  break;
5070  case a2d_BasedOnWireClassRequired:
5071  if ( m_pinClassEndWire->GetPinClassForTask( task, obj ) == pin->GetPinClass() )
5072  return pin;
5073  break;
5074  case a2d_BasedOnObjectClassRequired:
5075  if ( m_pinClassEndWire->GetPinClassForTask( task, obj ) == pin->GetPinClass() )
5076  return pin;
5077  break;
5078  case a2d_StartGenerateSearchFinish:
5079  if ( m_pinClassEndWire->GetPinClassForTask( a2d_FinishWire, obj, pin->GetPinClass(), wirefinishpin ) )
5080  return pin;
5081  break;
5082  }
5083  }
5084  }
5085  }
5086  }
5087  return 0;
5088 }
5089 */
5090 
5092 {
5094 }
5095 
5096 void a2dDrawWirePolylineLTool::FinishBusyMode( bool closeCommandGroup )
5097 {
5098  GetDrawing()->GetHabitat()->GetConnectionGenerator()->SetPinsToEndState( GetDrawingPart()->GetShowObject() );
5099 
5101 }
5102 
5104 {
5105  GetDrawing()->GetHabitat()->GetConnectionGenerator()->SetPinsToEndState( GetDrawingPart()->GetShowObject() );
5107 }
5108 
5109 void a2dDrawWirePolylineLTool::OnIdle( wxIdleEvent& event )
5110 {
5111  if ( m_pending && GetBusy() )
5112  {
5113 
5114  }
5115 }
5116 
5118 {
5119  m_endSegmentMode = mode;
5120  switch ( m_endSegmentMode )
5121  {
5122  case 0:
5123  {
5124  m_manhattan = false;
5125  m_like = true;
5126  break;
5127  }
5128 
5129  case 1:
5130  {
5131  m_manhattan = true;
5132  m_like = true;
5133  break;
5134  }
5135  case 2:
5136  {
5137  m_manhattan = true;
5138  m_like = false;
5139  break;
5140  }
5141  default:
5142  m_manhattan = false;
5143  m_like = true;
5144  break;
5145  }
5146 
5147  if ( !m_canvasobject )
5148  return;
5149 
5150  if ( m_like )
5151  {
5152  m_manx = m_xwprev;
5153  m_many = m_prev_y;
5154  }
5155  else
5156  {
5157  m_manx = m_prev_x;
5158  m_many = m_ywprev;
5159  }
5160 
5161  a2dPolygonL* poly = wxStaticCast( m_original.Get(), a2dPolygonL );
5162  if ( poly->GetNumberOfSegments() )
5163  {
5164  a2dLineSegment* lastpoint = poly->GetSegments()->back();
5165 
5169  //CreateToolObjects makes a deep copy, which includes the created pins made by GetConnectionGenerator().
5170  //That is less atractive here, the next remove them, instead we could have overridden CreateToolObjects too.
5171  m_canvasobject->RemovePins( true, false, true );
5172 
5173  m_points = wxStaticCast( m_canvasobject.Get(), a2dPolygonL )->GetSegments();
5174  if ( m_manhattan )
5175  {
5176  m_pointmanhattan = new a2dLineSegment( m_manx, m_many );
5177  AddPoint( m_pointmanhattan );
5178  }
5180  AddPoint( m_point );
5181  }
5182 
5183  a2dPin* drawPin;
5184  if ( m_reverse )
5185  drawPin = m_original->HasPinNamed( wxT( "begin" ) );
5186  else
5187  drawPin = m_original->HasPinNamed( wxT( "end" ) );
5188  if ( drawPin )
5189  {
5190  drawPin->SetPosXY( m_point->m_x, m_point->m_y );
5191  }
5192 
5193  m_original->SetPending( true );
5194  m_canvasobject->SetPending( true );
5195  m_pending = true;
5196 }
5197 
5198 void a2dDrawWirePolylineLTool::OnKeyDown( wxKeyEvent& event )
5199 {
5200  if ( GetBusy() )
5201  {
5202  switch( event.GetKeyCode() )
5203  {
5204  case WXK_SPACE:
5205  {
5206  AtNewVertex();
5207  if ( !m_stop )
5208  {
5209  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
5210  if( restrict )
5211  restrict->RestrictPoint( m_xwprev, m_ywprev );
5212 
5213  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
5214  a2dGeneralGlobals->RecordF( this, _T( "end" ) );
5215  m_original->SetGeneratePins( true );
5216  m_original->SetAlgoSkip( false );
5217 
5218  int endx = m_x;
5219  int endy = m_y;
5220  if ( abs( m_startWireXdev - endx ) > GetDrawing()->GetHabitat()->GetHandle()->GetWidth() || abs( m_startWireYdev - endy ) > GetDrawing()->GetHabitat()->GetHandle()->GetWidth() ) //prevent zero lines
5221  FinishBusyMode();
5222  else
5223  AbortBusyMode();
5224  }
5225  break;
5226  }
5227  case WXK_ESCAPE:
5228  {
5229  AbortBusyMode();
5230  break;
5231  }
5232  default:
5233  event.Skip();
5234  }
5235  }
5236  else
5237  event.Skip();
5238 }
5239 
5240 void a2dDrawWirePolylineLTool::OnChar( wxKeyEvent& event )
5241 {
5242  if ( GetBusy() && m_canvasobject )
5243  {
5244  double shiftx;
5245  double shifty;
5246  GetKeyIncrement( &shiftx, &shifty );
5247 
5248  switch( event.GetKeyCode() )
5249  {
5250  case WXK_TAB:
5251  {
5252  //rotate mode
5253  if ( m_endSegmentMode == WIREEND_STRAIGHT )
5254  m_endSegmentMode = WIREEND_MANHATTAN_X;
5255  else if ( m_endSegmentMode == WIREEND_MANHATTAN_X )
5256  m_endSegmentMode = WIREEND_MANHATTAN_Y;
5257  else if ( m_endSegmentMode == WIREEND_MANHATTAN_Y )
5258  m_endSegmentMode = WIREEND_STRAIGHT;
5259  SetEndSegmentMode( m_endSegmentMode );
5260  return;
5261  }
5262  break;
5263 
5264  case WXK_UP:
5265  shiftx = 0;
5266  break;
5267 
5268  case WXK_DOWN:
5269  shiftx = 0;
5270  shifty = -shifty;
5271  break;
5272 
5273  case WXK_LEFT:
5274  shiftx = -shiftx;
5275  shifty = 0;
5276  break;
5277 
5278  case WXK_RIGHT:
5279  shifty = 0;
5280  break;
5281 
5282  default:
5283  {
5284  shiftx = 0;
5285  shifty = 0;
5286  event.Skip();
5287  }
5288  }
5289 
5290  if ( event.m_controlDown )
5291  {
5292  m_xwprev += shiftx;
5293  m_ywprev += shifty;
5294  }
5295  else
5296  {
5297  m_xwprev += shiftx;
5298  m_ywprev += shifty;
5299  }
5300 
5301  m_point->m_x = m_xwprev;
5302  m_point->m_y = m_ywprev;
5303  GetDisplayWindow()->WarpPointer( GetDrawer2D()->WorldToDeviceX( m_xwprev ), GetDrawer2D()->WorldToDeviceY( m_ywprev ) );
5304 
5305  m_pending = true;
5306  }
5307  else
5308  event.Skip();
5309 
5310 }
5311 
5312 
5313 void a2dDrawWirePolylineLTool::AtNewVertex()
5314 {
5315  double unRestx = m_xwprev;
5316  double unResty = m_ywprev;
5317  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
5318 
5319  if( restrict )
5320  {
5322  a2dSnapToWhatMask was = restrict->GetSnapSourceFeatures();
5325  if ( snapTo == a2dRestrictionEngine::snapToNone )
5326  restrict->GetSnapTargetFeatures();
5327 
5328  restrict->RestrictPoint( m_xwprev, m_ywprev, snapTo, true );
5329  restrict->SetSnapSourceFeatures( was );
5330  }
5331 
5332  m_point->m_x = m_xwprev;
5333  m_point->m_y = m_ywprev;
5334 
5335  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
5336  m_original->RemovePins( true, true );
5337 
5338  a2dPin* drawPin;
5339  if ( m_reverse )
5340  drawPin = m_canvasobject->HasPinNamed( wxT( "begin" ) );
5341  else
5342  drawPin = m_canvasobject->HasPinNamed( wxT( "end" ) );
5343  if ( drawPin )
5344  drawPin->SetPosXY( m_xwprev, m_ywprev );
5345 
5346  if ( m_reverse )
5347  drawPin = m_original->HasPinNamed( wxT( "begin" ) );
5348  else
5349  drawPin = m_original->HasPinNamed( wxT( "end" ) );
5350  drawPin->SetPosXY( m_xwprev, m_ywprev );
5351 
5352  double hitDistance = GetHitMargin();
5353 
5354  a2dPin* pin = drawPin->GetPinClass()->GetConnectionGenerator()->
5355  SearchPinForFinishWire( GetDrawingPart()->GetShowObject(), drawPin, NULL, hitDistance );
5356 
5357  if( !pin )
5358  {
5359  drawPin->SetPosXY( unRestx, unResty );
5360  //second try for un-snapped pin.
5361  pin = drawPin->GetPinClass()->GetConnectionGenerator()->
5362  SearchPinForFinishWire( GetDrawingPart()->GetShowObject(), drawPin, NULL, hitDistance );
5363  }
5364 
5365  int x = GetDrawer2D()->WorldToDeviceX( m_prev_x );
5366  int y = GetDrawer2D()->WorldToDeviceY( m_prev_y );
5367  if ( abs( m_x - x ) >= 3 || abs( m_y - y ) >= 3 ) //to close a second point is not excepted??
5368  {
5369  if( pin && !pin->GetPinClass()->CanConnectTo( m_original->HasPinNamed( m_reverse ? wxT( "begin" ) : wxT( "end" ) )->GetPinClass() ) )
5370  {
5371  ( void )wxMessageBox( _( "You cannot connect to this end pin" ), _( "Connect" ), wxICON_INFORMATION | wxOK );
5372  }
5373  else
5374  {
5375  // for next point to draw
5376  if( restrict )
5377  restrict->SetRestrictPoint( m_xwprev, m_ywprev );
5378 
5379  if ( pin )
5380  {
5381  //the intention is to click on the pin and therefore snap to that pin,
5382  // even if not perfect on the grid.
5383  m_xwprev = pin->GetAbsX();
5384  m_ywprev = pin->GetAbsY();
5385  drawPin->SetPosXY( m_xwprev, m_ywprev );
5386  }
5387  else
5388  drawPin->SetPosXY( m_xwprev, m_ywprev );
5389 
5390  double dx = m_xwprev - m_prev_x;
5391  double dy = m_ywprev - m_prev_y;
5392 
5393  if ( m_manhattan )
5394  {
5395  if ( m_like )
5396  {
5397  m_manx = m_xwprev;
5398  m_many = m_prev_y;
5399  }
5400  else
5401  {
5402  m_manx = m_prev_x;
5403  m_many = m_ywprev;
5404  }
5405 
5406  m_pointmanhattan->m_x = m_manx;
5407  m_pointmanhattan->m_y = m_many;
5408 
5409  // add point to the original
5410  if ( m_reverse )
5412  new a2dCommand_AddPoint( m_original, m_manx, m_many, 0 )
5413  );
5414  else
5416  new a2dCommand_AddPoint( m_original, m_manx, m_many, -1 )
5417  );
5418 
5419  // add point to editcopy
5421  AddPoint( m_pointmanhattan );
5422  }
5423 
5424  // add point to the original
5425  if ( m_reverse )
5428  );
5429  else
5432  );
5433 
5434  // add point to editcopy
5436  AddPoint( m_point );
5437 
5438  m_prev_x = m_xwprev;
5439  m_prev_y = m_ywprev;
5440 
5441  // add point to record
5442  a2dGeneralGlobals->RecordF( this, _T( "addpoint %f %f " ), m_xwprev, m_ywprev );
5443 
5445  wire->RemoveRedundantPoints();
5446 
5447  // if it was a pin hit, add the pin at the last point
5448  // also end the tool then
5449  if( pin )
5450  {
5451  if ( pin->IsTemporaryPin() ) //those pins are generated without commands, not good for undo.
5452  {
5453  pin = wxStaticCast( pin->Clone( clone_deep ), a2dPin );
5454  pin->SetTemporaryPin( false );
5455  GetCanvasCommandProcessor()->Submit( new a2dCommand_AddObject( pin->GetParent(), pin ), true ); //this makes it save
5456  }
5457  GetCanvasCommandProcessor()->Submit( new a2dCommand_ConnectPins( drawPin, pin ), true );
5458  if ( m_splitAtEnd == true && pin->IsDynamicPin() && pin->GetParent()->IsConnect() )
5459  {
5460  a2dWirePolylineL* wireconnected = wxStaticCast( pin->GetParent(), a2dWirePolylineL );
5461  if ( wireconnected )
5462  {
5463  bool done = GetCanvasCommandProcessor()->Submit( new a2dCommand_SplitAtPin( GetDrawingPart()->GetShowObject(), pin, GetHitMargin() ) );
5464  }
5465  }
5466  a2dGeneralGlobals->RecordF( this, _T( "end" ) );
5467 
5468  m_original->SetGeneratePins( true );
5469  m_original->SetAlgoSkip( false );
5470  // restrict prevent
5471  // m_original->SetHitFlags( a2dCANOBJ_EVENT_ALL );
5472  // m_canvasobject->SetHitFlags( a2dCANOBJ_EVENT_ALL );
5473 
5474  //m_original->RemoveProperty( a2dCanvasObject::PROPID_DisableFeedback );
5475  FinishBusyMode();
5476  }
5477  }
5478  }
5479 }
5480 
5481 
5482 void a2dDrawWirePolylineLTool::OnMouseEvent( wxMouseEvent& event )
5483 {
5484  // This is mostly a copy of a2dDrawPolylineLTool::OnMouseEvent
5485  // changes are
5486  // - type of created object
5487  // - recorded event names
5488  // - creation and connection of a2dPin's
5489  // - end of tool if a pin is hint when adding a point
5490 
5491  if ( !m_active )
5492  {
5493  event.Skip();
5494  return;
5495  }
5496 
5497  if ( GetBusy() )
5498  GetDrawingPart()->SetCursor( m_toolBusyCursor );
5499  else
5500  GetDrawingPart()->SetCursor( m_toolcursor );
5501 
5502  m_x = event.GetX();
5503  m_y = event.GetY();
5505 
5506  double unRestx = m_xwprev;
5507  double unResty = m_ywprev;
5508 
5509  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
5510  if ( event.LeftDown() )
5511  {
5512  m_hadDoubleClick = false;
5513  m_dragstartx = m_x;
5514  m_dragstarty = m_y;
5515  }
5516  else if ( event.LeftUp() && !GetBusy() && m_hadDoubleClick )
5517  {
5518  m_hadDoubleClick = false;
5519  }
5520  else if ( event.LeftUp() && !GetBusy() )
5521  {
5522  if ( abs( m_x - m_dragstartx ) >= 3 || abs( m_y - m_dragstarty ) >= 3 ) //to close a second point is not excepted??
5523  {
5524  ( void )wxMessageBox( _( "you can not drag a pin" ), _( "Connect" ), wxICON_INFORMATION | wxOK );
5525  return;
5526  }
5527 
5528  if( restrict )
5529  {
5531  a2dSnapToWhatMask was = restrict->GetSnapSourceFeatures();
5534  if ( snapTo == a2dRestrictionEngine::snapToNone )
5535  restrict->GetSnapTargetFeatures();
5536 
5537  restrict->RestrictPoint( m_xwprev, m_ywprev, snapTo, true );
5538  restrict->SetSnapSourceFeatures( was );
5539  }
5540 
5541  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
5542  // Check if the user clicked on a pin
5543  a2dPin* pin = FindPin( GetDrawingPart()->GetShowObject(), m_xwprev, m_ywprev );
5544  if( !pin )
5545  pin = FindPin( GetDrawingPart()->GetShowObject(), unRestx, unResty );
5546  if( !pin )
5547  {
5548  ( void )wxMessageBox( _( "A connection must start at a pin or another connection" ), _( "Connect" ), wxICON_INFORMATION | wxOK );
5549  if( m_oneshot )
5550  StopTool();
5551  return;
5552  }
5553  if ( !pin->GetParent()->DoConnect() )
5554  return;
5555 
5556  // starting a new group here, and not closing it, will have EnterBusyMode() using this group instead of creating
5557  // one itself.
5558  OpenCommandGroupNamed( wxT( "create connection" ) );
5559 
5560  if ( pin->IsTemporaryPin() ) //those pins are generated without commands, not good for undo.
5561  {
5562  pin = wxStaticCast( pin->Clone( clone_deep ), a2dPin );
5563  pin->SetTemporaryPin( false );
5564  GetCanvasCommandProcessor()->Submit( new a2dCommand_AddObject( pin->GetParent(), pin ), true ); //this makes it save
5565  }
5566 
5567  if ( m_splitAtEnd == true && pin->IsDynamicPin() && pin->GetParent()->IsConnect() )
5568  {
5569  a2dWirePolylineL* wireconnected = wxStaticCast( pin->GetParent(), a2dWirePolylineL );
5570  if ( wireconnected )
5571  {
5572  bool done = GetCanvasCommandProcessor()->Submit( new a2dCommand_SplitAtPin( GetDrawingPart()->GetShowObject(), pin, GetHitMargin() ) );
5573  }
5574  }
5575 
5576  //we want to start and connect to the pin, so snap to it, even if pin is not on the grid.
5577  m_xwprev = pin->GetAbsX();
5578  m_ywprev = pin->GetAbsY();
5579 
5580  m_original = pin->GetParent()->CreateConnectObject( m_parentobject, pin, NULL, true );
5581  if ( !m_original )
5582  return;
5583  m_original->SetAlgoSkip( true );
5584  //a2dCanvasObject::PROPID_DisableFeedback->SetPropertyToObject( m_original, true );
5585  m_original->SetGeneratePins( false );
5587  wxASSERT_MSG( m_original.Get() != 0, wxT( "a connection object could not be created for the pin clicked" ) );
5588 
5589  // Either clone the template object or create a new one
5590  //m_original->Translate( m_xwprev, m_ywprev );
5592 
5593  if ( !EnterBusyMode() )
5594  return;
5595 
5596  //CreateToolObjects makes a deep copy, which includes the created pins made by GetConnectionGenerator().
5597  //That is less atractive here, the next remove them, instead we could have overridden CreateToolObjects too.
5598  m_canvasobject->RemovePins( true, false, true );
5599 
5600  m_points = wxStaticCast( m_canvasobject.Get(), a2dPolylineL )->GetSegments();
5602  AddPoint( m_point );
5603 
5604  // restrict prevent
5605  //m_original->SetHitFlags( a2dCANOBJ_EVENT_NON );
5606  //m_canvasobject->SetHitFlags( a2dCANOBJ_EVENT_NON );
5607 
5608  // Highlight matching pins in other objects
5609  {
5610  a2dPin* drawPin;
5611  if ( m_reverse )
5612  drawPin = m_original->HasPinNamed( wxT( "begin" ) );
5613  else
5614  drawPin = m_original->HasPinNamed( wxT( "end" ) );
5615  m_pinClassEndWire = drawPin->GetPinClass();
5616  //drawPin->SetVisible( false );
5617  }
5618 
5619  // Record commands
5620  a2dGeneralGlobals->RecordF( this, _T( "polylinewire" ) );
5621  a2dGeneralGlobals->RecordF( this, _T( "addpoint %f %f " ), m_xwprev, m_ywprev );
5622 
5623  if ( m_manhattan )
5624  {
5626  AddPoint( m_pointmanhattan );
5627  }
5628  //add second point to drag
5630  AddPoint( m_point );
5631 
5632  m_prev_x = m_xwprev;
5633  m_prev_y = m_ywprev;
5634 
5635  if( restrict )
5636  restrict->SetRestrictPoint( m_xwprev, m_ywprev );
5637 
5638  m_startWireX = m_xwprev;
5639  m_startWireY = m_ywprev;
5640  m_startWireXdev = m_x;
5641  m_startWireYdev = m_y;
5642 
5643  m_pending = true;
5644 
5645  }
5646  else if ( event.LeftUp() && GetBusy() )
5647  {
5648  AtNewVertex();
5649  }
5650  else if ( event.LeftDClick() && GetBusy() )
5651  {
5652  m_hadDoubleClick = true;
5653 
5654  if( restrict )
5655  restrict->RestrictPoint( m_xwprev, m_ywprev );
5656 
5657  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
5658  a2dGeneralGlobals->RecordF( this, _T( "end" ) );
5659  m_original->SetGeneratePins( true );
5660  m_original->SetAlgoSkip( false );
5661 
5662  int endx = m_x;
5663  int endy = m_y;
5664  if ( abs( m_startWireXdev - endx ) > GetDrawing()->GetHabitat()->GetHandle()->GetWidth() || abs( m_startWireYdev - endy ) > GetDrawing()->GetHabitat()->GetHandle()->GetWidth() ) //prevent zero lines
5665  FinishBusyMode();
5666  else
5667  AbortBusyMode();
5668  }
5669  else if ( event.RightUp() && GetBusy() )
5670  {
5671  m_hadDoubleClick = true;
5672  if( restrict )
5673  restrict->RestrictPoint( m_xwprev, m_ywprev );
5674 
5675  a2dPin* drawPin;
5677  if ( m_reverse )
5678  {
5679  m_point = org->GetFirstPoint();
5680  m_xwprev = m_point->m_x;
5681  m_ywprev = m_point->m_y;
5682  drawPin = org->HasPinNamed( wxT( "begin" ) );
5683  }
5684  else
5685  {
5686  m_xwprev = m_prev_x;
5687  m_ywprev = m_prev_y;
5688  drawPin = org->HasPinNamed( wxT( "end" ) );
5689  }
5690  drawPin->SetPosXY( m_xwprev, m_ywprev );
5691 
5692  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
5693  a2dGeneralGlobals->RecordF( this, _T( "end" ) );
5694  m_original->SetGeneratePins( true );
5695  m_original->SetAlgoSkip( false );
5696 
5697  int endx = m_x;
5698  int endy = m_y;
5699  if ( ( m_manhattan && org->GetNumberOfSegments() > 2 ) ||
5700  ( !m_manhattan && org->GetNumberOfSegments() > 1 ) )
5701  FinishBusyMode();
5702  else
5703  AbortBusyMode();
5704  }
5705  else if ( ( event.Dragging() || event.Moving() ) && GetBusy() )
5706  {
5707  if( restrict )
5708  {
5710  a2dSnapToWhatMask was = restrict->GetSnapSourceFeatures();
5713  if ( snapTo == a2dRestrictionEngine::snapToNone )
5714  restrict->GetSnapTargetFeatures();
5715 
5716  restrict->RestrictPoint( m_xwprev, m_ywprev, snapTo, true );
5717  restrict->SetSnapSourceFeatures( was );
5718  }
5719  //The wire was created, and a clone also.
5720  //Show end/begin pin at right position.
5721  a2dPin* drawPin;
5722  if ( m_reverse )
5723  drawPin = m_original->HasPinNamed( wxT( "begin" ) );
5724  else
5725  drawPin = m_original->HasPinNamed( wxT( "end" ) );
5726  drawPin->SetPosXY( m_xwprev, m_ywprev );
5727 
5728  // Give other objects an opportunity to show dynamic pins
5729  drawPin->GetPinClass()->GetConnectionGenerator()->SetPinsToBeginState( GetDrawingPart()->GetShowObject() );
5730  drawPin->GetPinClass()->GetConnectionGenerator()->
5731  GeneratePinsToConnect( GetDrawingPart(), GetDrawingPart()->GetShowObject(), drawPin->GetPinClass(), a2d_GeneratePinsForFinishWire, m_xwprev, m_ywprev );
5732 
5733  double hitDistance = GetHitMargin();
5734 
5735  a2dPin* foundPin = NULL;
5736  //there is no wire nor pin yet, therefore we can just feedback possible pin connection, based on the
5737  // m_connectionGenerator.
5738  switch ( m_wiringMode )
5739  {
5741  {
5742  foundPin = drawPin->GetPinClass()->GetConnectionGenerator()->
5743  SearchPinForFinishWire( GetDrawingPart()->GetShowObject(), drawPin, m_pinClassEndWire, hitDistance );
5744  }
5745  break;
5747  case a2d_BasedOnObjectClassRequired:
5748  {
5749  foundPin = drawPin->GetPinClass()->GetConnectionGenerator()->
5750  SearchPinForFinishWire( GetDrawingPart()->GetShowObject(), drawPin, m_pinClassStartWire, hitDistance );
5751  }
5752  break;
5753  case a2d_StartGenerateSearchFinish:
5754  {
5755  foundPin = drawPin->GetPinClass()->GetConnectionGenerator()->
5756  SearchPinForFinishWire( GetDrawingPart()->GetShowObject(), drawPin, drawPin->GetPinClass(), hitDistance );
5757  }
5758  break;
5759  }
5760  if ( foundPin )
5761  SetStateString( _("Click to end wire at this pin"), STAT_toolHelp );
5762  else
5763  SetStateString( _("Click to add vertex or end wire at other pin or at Double Click"), STAT_toolHelp );
5764 
5765  a2dBoundingBox updateareas;
5766  //AddPoint( m_point );
5767 
5768  updateareas.Expand( m_prev_x, m_prev_y );
5769  updateareas.Expand( m_point->GetPoint() );
5770  //a2dCanvasObject::PROPID_BoundingBox->SetPropertyToObject( m_canvasobject, updateareas );
5771  updateareas.Reset();
5772  updateareas.Expand( m_points->front()->GetPoint() );
5773  updateareas.Expand( m_point->GetPoint() );
5774  //a2dCanvasObject::PROPID_BoundingBox->SetPropertyToObject( m_canvasobject, updateareas );
5775 
5776  double dx = m_xwprev - m_prev_x;
5777  double dy = m_ywprev - m_prev_y;
5778  int x = GetDrawer2D()->WorldToDeviceX( m_prev_x );
5779  int y = GetDrawer2D()->WorldToDeviceY( m_prev_y );
5780  float dxdev = x - m_x;
5781  float dydev = y - m_y;
5782  double lendev = sqrt( dxdev*dxdev + dydev*dydev );
5783 
5784  if ( lendev < 25 )
5785  {
5786  if ( fabs( dx ) < fabs( dy ) )
5787  m_like = false;
5788  else
5789  m_like = true;
5790  }
5791 
5792  if ( m_like )
5793  {
5794  m_manx = m_xwprev;
5795  m_many = m_prev_y;
5796  }
5797  else
5798  {
5799  m_manx = m_prev_x;
5800  m_many = m_ywprev;
5801  }
5802 
5803  if ( m_manhattan )
5804  {
5805  m_pointmanhattan->m_x = m_manx;
5806  m_pointmanhattan->m_y = m_many;
5807  }
5808 
5809  m_point->m_x = m_xwprev;
5810  m_point->m_y = m_ywprev;
5811  m_canvasobject->SetPending( true );
5812 
5813  updateareas.Reset();
5814  updateareas.Expand( m_prev_x, m_prev_y );
5815  updateareas.Expand( m_point->GetPoint() );
5816  //a2dCanvasObject::PROPID_BoundingBox->SetPropertyToObject( m_canvasobject, updateareas );
5817 
5818  updateareas.Reset();
5819  updateareas.Expand( m_points->front()->GetPoint() );
5820  updateareas.Expand( m_point->GetPoint() );
5821  //a2dCanvasObject::PROPID_BoundingBox->SetPropertyToObject( m_canvasobject, updateareas );
5822  // do not skip the event, which would lead to another restrict in a2dDrawPolygonLTool.
5824  m_pending = true;
5825 
5826  double unitScale = GetDrawing()->GetUnitsScale();
5827  wxString state;
5828  wxString form = _("Lpx") + m_stcontroller->GetFormat() + _(" Lpy") + m_stcontroller->GetFormat();
5829  state.Printf( form, m_prev_x*unitScale, m_prev_y*unitScale );
5830  SetStateString( state, 10 );
5831  form = _("dx = ") + m_stcontroller->GetFormat() + _(" dy = ") + m_stcontroller->GetFormat();
5832  state.Printf( form, dx*unitScale, dy*unitScale );
5833  SetStateString( state, 11 );
5834  }
5835  else if ( event.Moving() && !GetBusy() )
5836  {
5837  if( restrict )
5838  restrict->RestrictPoint( m_xwprev, m_ywprev );
5839 
5840  //there is no wire nor pin yet, therefore we can just feedback possible pin connection, based on the
5841  // m_connectionGenerator.
5842  GetDrawing()->GetHabitat()->GetConnectionGenerator()->SetPinsToBeginState( GetDrawingPart()->GetShowObject() );
5843  GetDrawing()->GetHabitat()->GetConnectionGenerator()->
5844  GeneratePinsToConnect( GetDrawingPart(), GetDrawingPart()->GetShowObject(), a2dPinClass::Any, a2d_GeneratePinsForStartWire, unRestx, unResty );
5845 
5846  double hitDistance = GetHitMargin();
5847 
5848  //there is no wire nor pin yet, therefore we can just feedback possible pin connection, based on the
5849  // m_connectionGenerator.
5850  switch ( m_wiringMode )
5851  {
5853  {
5854  GetDrawing()->GetHabitat()->GetConnectionGenerator()->
5855  SearchPinForStartWire( GetDrawingPart()->GetShowObject(), unRestx, unResty, a2dPinClass::Any, hitDistance );
5856  }
5857  break;
5859  case a2d_BasedOnObjectClassRequired:
5860  {
5861  GetDrawing()->GetHabitat()->GetConnectionGenerator()->
5862  SearchPinForStartWire( GetDrawingPart()->GetShowObject(), unRestx, unResty, m_pinClassStartWire, hitDistance );
5863  }
5864  break;
5865  case a2d_StartGenerateSearchFinish:
5866  {
5867  GetDrawing()->GetHabitat()->GetConnectionGenerator()->
5868  SearchPinForStartWire( GetDrawingPart()->GetShowObject(), unRestx, unResty, a2dPinClass::Any, hitDistance );
5869  }
5870  break;
5871  }
5873  }
5874  else
5875  {
5876  event.Skip();
5877  }
5878 }
5879 
5881 {
5882  // reset editing hints
5883  if( !active )
5884  {
5885  if( GetDrawingPart() )
5886  {
5887  GetDrawing()->GetHabitat()->GetConnectionGenerator()->SetPinsToEndState( GetDrawingPart()->GetShowObject() );
5888  }
5889  }
5891 }
5892 
5893 void a2dDrawWirePolylineLTool::OnUndoEvent( a2dCommandProcessorEvent& event )
5894 {
5895  if ( GetBusy() && !m_halted )
5896  {
5897  // recreate edit copies so the edit copy becomes updated from the original.
5898 
5899  a2dPolygonL* poly = wxStaticCast( m_original.Get(), a2dPolygonL );
5900  if ( poly->GetNumberOfSegments() )
5901  {
5902  a2dLineSegment* lastpoint = poly->GetSegments()->back();
5903 
5907  //CreateToolObjects makes a deep copy, which includes the created pins made by GetConnectionGenerator().
5908  //That is less atractive here, the next remove them, instead we could have overridden CreateToolObjects too.
5909  m_canvasobject->RemovePins( true, false, true );
5910  m_points = wxStaticCast( m_canvasobject.Get(), a2dPolygonL )->GetSegments();
5911  if ( m_manhattan )
5912  {
5913  m_pointmanhattan = lastpoint->Clone();
5914  m_points->push_back( m_pointmanhattan );
5915  }
5916  m_point = lastpoint->Clone();
5917  m_points->push_back( m_point );
5918  m_prev_x = m_xwprev = m_point->m_x;
5919  m_prev_y = m_ywprev = m_point->m_y;
5920 
5921  }
5922  a2dPin* drawPin;
5923  if ( m_reverse )
5924  drawPin = m_original->HasPinNamed( wxT( "begin" ) );
5925  else
5926  drawPin = m_original->HasPinNamed( wxT( "end" ) );
5927  if ( drawPin )
5928  {
5929  drawPin->SetPosXY( m_point->m_x, m_point->m_y );
5930  }
5931  else
5932  AbortBusyMode();
5933 
5934  }
5935 }
5936 
5937 void a2dDrawWirePolylineLTool::OnRedoEvent( a2dCommandProcessorEvent& event )
5938 {
5939  OnUndoEvent( event );
5940 }
5941 
5942 BEGIN_EVENT_TABLE( a2dDrawEllipseTool, a2dStDrawTool )
5943  EVT_IDLE( a2dDrawEllipseTool::OnIdle )
5944  EVT_CHAR( a2dDrawEllipseTool::OnChar )
5945  EVT_MOUSE_EVENTS( a2dDrawEllipseTool::OnMouseEvent )
5946 END_EVENT_TABLE()
5947 
5948 a2dDrawEllipseTool::a2dDrawEllipseTool( a2dStToolContr* controller ): a2dStDrawTool( controller )
5949 {
5950  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_PENCIL );
5951  m_toolBusyCursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS );
5952 }
5953 
5955 {
5956  // Add old (and later new) annotation area to pending region
5958 
5959  a2dEllipse* ellip = wxStaticCast( m_canvasobject.Get(), a2dEllipse );
5960 
5961  m_anotation.Printf( _T( "w %6.3f h %6.3f" ), ellip->GetWidth(), ellip->GetHeight() );
5962 
5963  wxCoord w, h, descent, external;
5964  GetTextExtent( m_anotation, &w, &h, &descent, &external );
5965 
5966  m_xanotation = m_x + h;
5967  m_yanotation = m_y + h;
5968 
5970 }
5971 
5972 void a2dDrawEllipseTool::OnIdle( wxIdleEvent& event )
5973 {
5974  if ( m_pending && GetBusy() )
5975  {
5977 
5978  a2dEllipse* ellip = wxStaticCast( m_canvasobject.Get(), a2dEllipse );
5979  a2dSLine* ll = new a2dSLine( ellip->GetPosX(), ellip->GetPosY(), m_xwprev, m_ywprev );
5980  ll->SetStroke( *wxRED, 0, a2dSTROKE_DOT );
5981 
5982  a2dCircle* zero = new a2dCircle( m_start_x, m_start_y, GetDrawer2D()->DeviceToWorldXRel( 3 ) );
5983  zero->SetFill( *wxRED );
5984 
5985  a2dRect* around = new a2dRect( ellip->GetBboxMinX(), ellip->GetBboxMinY(), ellip->GetBboxWidth(), ellip->GetBboxHeight() );
5986  around->SetStroke( *wxRED, 0, a2dSTROKE_LONG_DASH );
5987  around->SetFill( *a2dTRANSPARENT_FILL );
5988 
5989  AddDecorationObject( around );
5990  AddDecorationObject( ll );
5991  AddDecorationObject( zero );
5992 
5993  event.Skip();
5994  }
5995  else
5996  event.Skip();
5997 }
5998 
6000 {
6001  m_mode = mode;
6002  if ( m_mode > 1 ) m_mode = 0;
6003 
6004  if ( !m_canvasobject )
6005  return;
6006 
6007  a2dEllipse* ellip = wxStaticCast( m_canvasobject.Get(), a2dEllipse );
6008  a2dEllipse* elliporg = wxStaticCast( m_original.Get(), a2dEllipse );
6009 
6010  switch ( m_mode )
6011  {
6012  case 0:
6013  {
6014  ellip->SetPosXY( m_start_x, m_start_y );
6015  elliporg->SetPosXY( m_start_x, m_start_y );
6016 
6017  //modify object
6018  double xs, ys;
6019  xs = m_xwprev - ellip->GetPosX();
6020  ys = m_ywprev - ellip->GetPosY();
6021 
6022  ellip->SetWidth( fabs( xs * 2 ) );
6023  ellip->SetHeight( fabs( ys * 2 ) );
6024  elliporg->SetWidth( fabs( xs * 2 ) );
6025  elliporg->SetHeight( fabs( ys * 2 ) );
6026  break;
6027  }
6028  case 1:
6029  {
6030  ellip->SetPosXY( ( m_xwprev + m_start_x ) / 2, ( m_ywprev + m_start_y ) / 2 );
6031  elliporg->SetPosXY( ( m_xwprev + m_start_x ) / 2, ( m_ywprev + m_start_y ) / 2 );
6032 
6033  //modify object
6034  double xs, ys;
6035  xs = m_xwprev - ellip->GetPosX();
6036  ys = m_ywprev - ellip->GetPosY();
6037 
6038  ellip->SetWidth( fabs( xs * 2 ) );
6039  ellip->SetHeight( fabs( ys * 2 ) );
6040  elliporg->SetWidth( fabs( xs * 2 ) );
6041  elliporg->SetHeight( fabs( ys * 2 ) );
6042  break;
6043  }
6044  default:
6045  break;
6046  }
6047 
6048  double unitScale = GetDrawing()->GetUnitsScale();
6049  wxString state;
6050  wxString form = m_stcontroller->GetFormat() + " " + m_stcontroller->GetFormat();
6051  state.Printf( form, ellip->GetPosX()*unitScale, ellip->GetPosY()*unitScale );
6052  SetStateString( state, 10 );
6053  form = _T("width = ") + m_stcontroller->GetFormat() + _T(" height = ") + m_stcontroller->GetFormat();
6054  state.Printf( form, ellip->GetWidth()*unitScale, ellip->GetHeight()*unitScale );
6055  SetStateString( state, 11 );
6056 
6057 
6058  m_pending = true;
6059 }
6060 
6061 void a2dDrawEllipseTool::OnChar( wxKeyEvent& event )
6062 {
6063  if ( GetBusy() )
6064  {
6065  switch( event.GetKeyCode() )
6066  {
6067  case WXK_TAB:
6068  {
6069  m_mode++;
6070  SetMode( m_mode );
6071  }
6072  break;
6073 
6074  default:
6075  event.Skip();
6076  }
6077  }
6078  else
6079  event.Skip();
6080 
6081 }
6082 
6083 void a2dDrawEllipseTool::OnMouseEvent( wxMouseEvent& event )
6084 {
6085  if ( !m_active )
6086  {
6087  event.Skip();
6088  return;
6089  }
6090 
6091  if ( GetBusy() )
6092  GetDrawingPart()->SetCursor( m_toolBusyCursor );
6093  else
6094  GetDrawingPart()->SetCursor( m_toolcursor );
6095 
6096  m_x = event.GetX();
6097  m_y = event.GetY();
6098  MouseToToolWorld( m_x, m_y, m_xwprev, m_ywprev );
6099 
6100  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
6101  if( restrict )
6102  restrict->RestrictPoint( m_xwprev, m_ywprev );
6103 
6104  if ( event.LeftDown() && !GetBusy() )
6105  {
6106  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
6107  m_original = new a2dEllipse( m_xwprev, m_ywprev, 0, 0 );
6108  m_start_x = m_xwprev;
6109  m_start_y = m_ywprev;
6110  a2dEllipse* ellip = wxStaticCast( m_original.Get(), a2dEllipse );
6111  ellip->SetRoot( GetDrawingPart()->GetDrawing() );
6112  if ( !EnterBusyMode() )
6113  return;
6115  }
6116  else if ( event.LeftDown() && GetBusy() )
6117  {
6118  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
6119  a2dEllipse* ellip = wxStaticCast( m_canvasobject.Get(), a2dEllipse );
6120  a2dGeneralGlobals->RecordF( this, _T( "ellipse %f %f %f %f" ), ellip->GetPosX(), ellip->GetPosY(), ellip->GetWidth(), ellip->GetHeight() );
6121  FinishBusyMode();
6122  }
6123  else if ( ( event.Dragging() && GetBusy() ) || ( event.Moving() && GetBusy() ) )
6124  {
6125  SetMode( m_mode );
6126  }
6127  else
6128  event.Skip();
6129 }
6130 
6131 BEGIN_EVENT_TABLE( a2dDrawEllipticArcTool, a2dStDrawTool )
6132  EVT_IDLE( a2dDrawEllipticArcTool::OnIdle )
6133  EVT_CHAR( a2dDrawEllipticArcTool::OnChar )
6134  EVT_MOUSE_EVENTS( a2dDrawEllipticArcTool::OnMouseEvent )
6135 END_EVENT_TABLE()
6136 
6137 a2dDrawEllipticArcTool::a2dDrawEllipticArcTool( a2dStToolContr* controller, a2dEllipticArc* templateobject ): a2dStDrawTool( controller )
6138 {
6139  m_mode2 = 0;
6140  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_PENCIL );
6141  m_toolBusyCursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS );
6142  m_arcstart = 45;
6143  m_arcend = 315;
6144  m_chord = false;
6145 
6146  m_templateobject = templateobject;
6147 }
6148 
6150 {
6151  // Add old (and later new) annotation area to pending region
6153 
6155 
6156  m_anotation.Printf( _T( "w %6.3f h %6.3f" ), ellip->GetWidth(), ellip->GetHeight() );
6157 
6158  wxCoord w, h, descent, external;
6159  GetTextExtent( m_anotation, &w, &h, &descent, &external );
6160 
6161  m_xanotation = m_x + h;
6162  m_yanotation = m_y + h;
6163 
6165 }
6166 
6167 void a2dDrawEllipticArcTool::OnIdle( wxIdleEvent& event )
6168 {
6169  if ( m_pending && GetBusy() )
6170  {
6172 
6174  a2dSLine* ll = new a2dSLine( ellip->GetPosX(), ellip->GetPosY(), m_xwprev, m_ywprev );
6175  ll->SetStroke( *wxRED, 0, a2dSTROKE_DOT );
6176 
6177  a2dCircle* zero = new a2dCircle( m_start_x, m_start_y, GetDrawer2D()->DeviceToWorldXRel( 3 ) );
6178  zero->SetFill( *wxRED );
6179 
6180  a2dRect* around = new a2dRect( ellip->GetBboxMinX(), ellip->GetBboxMinY(), ellip->GetBboxWidth(), ellip->GetBboxHeight() );
6181  around->SetStroke( *wxRED, 0, a2dSTROKE_LONG_DASH );
6182  around->SetFill( *a2dTRANSPARENT_FILL );
6183 
6184  AddDecorationObject( ll );
6185  AddDecorationObject( around );
6186  AddDecorationObject( zero );
6187 
6188  event.Skip();
6189  }
6190  else
6191  event.Skip();
6192 }
6193 
6195 {
6196  m_mode = mode;
6197  if ( m_mode > 1 ) m_mode = 0;
6198 
6199  if ( !m_canvasobject )
6200  return;
6201 
6203  a2dEllipticArc* elliporg = wxStaticCast( m_original.Get(), a2dEllipticArc );
6204 
6205  switch ( m_mode )
6206  {
6207  case 0:
6208  {
6209  ellip->SetPosXY( m_start_x, m_start_y );
6210  elliporg->SetPosXY( m_start_x, m_start_y );
6211 
6212  //modify object
6213  double xs, ys;
6214  xs = m_xwprev - ellip->GetPosX();
6215  ys = m_ywprev - ellip->GetPosY();
6216 
6217  ellip->SetWidth( fabs( xs * 2 ) );
6218  ellip->SetHeight( fabs( ys * 2 ) );
6219  elliporg->SetWidth( fabs( xs * 2 ) );
6220  elliporg->SetHeight( fabs( ys * 2 ) );
6221  break;
6222  }
6223  case 1:
6224  {
6225  ellip->SetPosXY( ( m_xwprev + m_start_x ) / 2, ( m_ywprev + m_start_y ) / 2 );
6226  elliporg->SetPosXY( ( m_xwprev + m_start_x ) / 2, ( m_ywprev + m_start_y ) / 2 );
6227 
6228  //modify object
6229  double xs, ys;
6230  xs = m_xwprev - ellip->GetPosX();
6231  ys = m_ywprev - ellip->GetPosY();
6232 
6233  ellip->SetWidth( fabs( xs * 2 ) );
6234  ellip->SetHeight( fabs( ys * 2 ) );
6235  elliporg->SetWidth( fabs( xs * 2 ) );
6236  elliporg->SetHeight( fabs( ys * 2 ) );
6237  break;
6238  }
6239  default:
6240  break;
6241  }
6242 
6243  double unitScale = GetDrawing()->GetUnitsScale();
6244  wxString state;
6245  wxString form = m_stcontroller->GetFormat() + " " + m_stcontroller->GetFormat();
6246  state.Printf( form, ellip->GetPosX()*unitScale, ellip->GetPosY()*unitScale );
6247  SetStateString( state, 10 );
6248  form = _T("width = ") + m_stcontroller->GetFormat() + _T(" height = ") + m_stcontroller->GetFormat();
6249  state.Printf( form, ellip->GetWidth()*unitScale, ellip->GetHeight()*unitScale );
6250  SetStateString( state, 11 );
6251 
6252  m_pending = true;
6253 }
6254 
6256 {
6257  m_mode2 = mode;
6258  if ( m_mode2 > 2 ) m_mode2 = 0;
6259 
6260  if ( !m_canvasobject )
6261  return;
6262 
6263  m_pending = true;
6264 }
6265 
6266 void a2dDrawEllipticArcTool::OnChar( wxKeyEvent& event )
6267 {
6268  if ( GetBusy() )
6269  {
6270  switch( event.GetKeyCode() )
6271  {
6272  case WXK_SPACE:
6273  {
6275  a2dGeneralGlobals->RecordF( this, _T( "ellipticArc %f %f% f %f %f %f" ),
6276  ellip->GetPosX(), ellip->GetPosY(),
6277  ellip->GetWidth(), ellip->GetHeight(),
6278  ellip->GetStart(), ellip->GetEnd()
6279  );
6280  FinishBusyMode();
6281  }
6282  break;
6283  case WXK_TAB:
6284  {
6285  m_mode++;
6286  SetMode( m_mode );
6287  }
6288  break;
6289 
6290  case WXK_RETURN:
6291  {
6292  m_mode2++;
6293  SetMode2( m_mode2 );
6294  }
6295  break;
6296 
6297  default:
6298  event.Skip();
6299  }
6300  }
6301  else
6302  event.Skip();
6303 
6304 }
6305 
6306 
6307 void a2dDrawEllipticArcTool::OnMouseEvent( wxMouseEvent& event )
6308 {
6309  if ( !m_active )
6310  {
6311  event.Skip();
6312  return;
6313  }
6314 
6315  if ( GetBusy() )
6316  GetDrawingPart()->SetCursor( m_toolBusyCursor );
6317  else
6318  GetDrawingPart()->SetCursor( m_toolcursor );
6319 
6320  m_x = event.GetX();
6321  m_y = event.GetY();
6322  MouseToToolWorld( m_x, m_y, m_xwprev, m_ywprev );
6323 
6324  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
6325  if( restrict )
6326  restrict->RestrictPoint( m_xwprev, m_ywprev );
6327 
6328  if ( event.LeftDown() && !GetBusy() )
6329  {
6330  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
6331  a2dEllipticArc* ellip = 0;
6332  if ( m_templateobject )
6333  {
6335  ellip = wxStaticCast( m_original.Get(), a2dEllipticArc );
6336  ellip->SetStart( m_arcstart );
6337  ellip->SetEnd( m_arcend );
6338  m_original->Translate( m_xwprev, m_ywprev );
6340  }
6341  else
6342  {
6343  m_original = new a2dEllipticArc( m_xwprev, m_ywprev, 0, 0, m_arcstart, m_arcend );
6344  ellip = wxStaticCast( m_original.Get(), a2dEllipticArc );
6345  ellip->SetChord( m_chord );
6346  }
6347  if ( !EnterBusyMode() )
6348  return;
6350  m_start_x = m_xwprev;
6351  m_start_y = m_ywprev;
6352  }
6353  else if ( event.LeftDown() && GetBusy() )
6354  {
6355  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
6356  m_mode2 = 0;
6357 
6359  a2dGeneralGlobals->RecordF( this, _T( "ellipticArc %f %f %f %f %f %f" ),
6360  ellip->GetPosX(), ellip->GetPosY(),
6361  ellip->GetWidth(), ellip->GetHeight(),
6362  ellip->GetStart(), ellip->GetEnd()
6363  );
6364  FinishBusyMode();
6365  }
6366  else if ( ( event.Dragging() && GetBusy() ) || ( event.Moving() && GetBusy() ) )
6367  {
6369  a2dEllipticArc* elliporg = wxStaticCast( m_original.Get(), a2dEllipticArc );
6370  //modify object
6371  double xs, ys;
6372  xs = m_xwprev - ellip->GetPosX();
6373  ys = m_ywprev - ellip->GetPosY();
6374 
6375  if ( m_mode2 == 1 )
6376  {
6377  m_arcstart = wxRadToDeg( atan2( ys, xs ) );
6378  ellip->SetStart( m_arcstart );
6379  elliporg->SetStart( m_arcstart );
6380  }
6381  else if ( m_mode2 == 2 )
6382  {
6383  m_arcend = wxRadToDeg( atan2( ys, xs ) );
6384  ellip->SetEnd( m_arcend );
6385  elliporg->SetEnd( m_arcend );
6386  }
6387  else
6388  {
6389  SetMode( m_mode );
6390  }
6391  m_pending = true;
6392  }
6393  else
6394  event.Skip();
6395 }
6396 
6397 BEGIN_EVENT_TABLE( a2dDrawArcTool, a2dStDrawTool )
6398  EVT_IDLE( a2dDrawArcTool::OnIdle )
6399  EVT_CHAR( a2dDrawArcTool::OnChar )
6400  EVT_MOUSE_EVENTS( a2dDrawArcTool::OnMouseEvent )
6401 END_EVENT_TABLE()
6402 
6403 a2dDrawArcTool::a2dDrawArcTool( a2dStToolContr* controller ): a2dStDrawTool( controller )
6404 {
6405  m_mode2 = 0;
6406  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_PENCIL );
6407  m_toolBusyCursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS );
6408  m_arcstart = 45;
6409  m_arcend = 315;
6410  m_chord = false;
6411 }
6412 
6414 {
6415  // Add old (and later new) annotation area to pending region
6417 
6418  a2dArc* arc = wxStaticCast( m_canvasobject.Get(), a2dArc );
6419 
6420  m_anotation.Printf( _T( "radius %6.3f" ), arc->GetRadius() );
6421 
6422  wxCoord w, h, descent, external;
6423  GetTextExtent( m_anotation, &w, &h, &descent, &external );
6424 
6425  m_xanotation = m_x + h;
6426  m_yanotation = m_y + h;
6427 
6429 }
6430 
6431 void a2dDrawArcTool::OnIdle( wxIdleEvent& event )
6432 {
6433  if ( m_pending && GetBusy() )
6434  {
6436 
6437  a2dArc* cir = wxStaticCast( m_canvasobject.Get(), a2dArc );
6438  a2dSLine* ll = new a2dSLine( cir->GetPosX(), cir->GetPosY(), m_xwprev, m_ywprev );
6439  ll->SetStroke( *wxRED, 0, a2dSTROKE_DOT );
6440 
6441  a2dCircle* zero = new a2dCircle( m_start_x, m_start_y, GetDrawer2D()->DeviceToWorldXRel( 3 ) );
6442  zero->SetFill( *wxRED );
6443 
6444  a2dRect* around = new a2dRect( cir->GetBboxMinX(), cir->GetBboxMinY(), cir->GetBboxWidth(), cir->GetBboxHeight() );
6445  around->SetStroke( *wxRED, 0, a2dSTROKE_LONG_DASH );
6446  around->SetFill( *a2dTRANSPARENT_FILL );
6447 
6448  AddDecorationObject( ll );
6449  AddDecorationObject( around );
6450  AddDecorationObject( zero );
6451 
6452  event.Skip();
6453  }
6454  else
6455  event.Skip();
6456 }
6457 
6458 void a2dDrawArcTool::OnChar( wxKeyEvent& event )
6459 {
6460  if ( GetBusy() )
6461  {
6462  switch( event.GetKeyCode() )
6463  {
6464  case WXK_SPACE:
6465  {
6466  a2dArc* arc = wxStaticCast( m_canvasobject.Get(), a2dArc );
6467  a2dGeneralGlobals->RecordF( this, _T( "arc %f %f %f %f %f" ),
6468  arc->GetPosX(), arc->GetPosY(),
6469  arc->GetRadius(),
6470  m_arcstart, m_arcend );
6471  FinishBusyMode();
6472  }
6473  break;
6474  case WXK_TAB:
6475  {
6476  m_mode++;
6477  SetMode( m_mode );
6478  }
6479  break;
6480 
6481  case WXK_RETURN:
6482  {
6483  m_mode2++;
6484  SetMode2( m_mode2 );
6485  }
6486  break;
6487 
6488  default:
6489  event.Skip();
6490  }
6491  }
6492  else
6493  event.Skip();
6494 
6495 }
6496 
6497 void a2dDrawArcTool::SetMode( int mode )
6498 {
6499  m_mode = mode;
6500  if ( m_mode > 2 ) m_mode = 0;
6501 
6502  if ( !m_canvasobject )
6503  return;
6504 
6505  a2dArc* cir = wxStaticCast( m_canvasobject.Get(), a2dArc );
6506  a2dArc* cirorg = wxStaticCast( m_original.Get(), a2dArc );
6507  double radius = 0;
6508  switch ( m_mode )
6509  {
6510  case 0:
6511  {
6512  double dx, dy;
6513 
6514  if ( fabs( m_xwprev - m_start_x ) > fabs( m_ywprev - m_start_y ) )
6515  {
6516  dx = ( m_xwprev - m_start_x ) / 2 ;
6517  radius = fabs( dx );
6518  if ( m_ywprev > m_start_y )
6519  dy = radius;
6520  else
6521  dy = -radius;
6522  }
6523  else
6524  {
6525  dy = ( m_ywprev - m_start_y ) / 2 ;
6526  radius = fabs( dy );
6527  if ( m_xwprev > m_start_x )
6528  dx = radius;
6529  else
6530  dx = -radius;
6531  }
6532  cir->SetPosXY( m_start_x + dx , m_start_y + dy );
6533  cirorg->SetPosXY( m_start_x + dx , m_start_y + dy );
6534  break;
6535  }
6536  case 1:
6537  {
6538  cir->SetPosXY( m_start_x, m_start_y );
6539  cirorg->SetPosXY( m_start_x, m_start_y );
6540  radius = sqrt( pow( m_xwprev - cir->GetPosX(), 2 ) + pow( m_ywprev - cir->GetPosY(), 2 ) );
6541  break;
6542  }
6543  case 2:
6544  {
6545  cir->SetPosXY( ( m_xwprev + m_start_x ) / 2, ( m_ywprev + m_start_y ) / 2 );
6546  cirorg->SetPosXY( ( m_xwprev + m_start_x ) / 2, ( m_ywprev + m_start_y ) / 2 );
6547  radius = sqrt( pow( m_xwprev - m_start_x, 2 ) + pow( m_ywprev - m_start_y, 2 ) ) / 2;
6548  break;
6549  }
6550  default:
6551  break;
6552  }
6553 
6554  cir->SetRadius( radius );
6555  cirorg->SetRadius( radius );
6556 
6557  double unitScale = GetDrawing()->GetUnitsScale();
6558  wxString state;
6559  wxString form = m_stcontroller->GetFormat() + " " + m_stcontroller->GetFormat();
6560  state.Printf( form, cir->GetPosX()*unitScale, cir->GetPosY()*unitScale );
6561  SetStateString( state, 10 );
6562  form = _T("radius = ") + m_stcontroller->GetFormat();
6563  state.Printf( form, radius*unitScale );
6564  SetStateString( state, 11 );
6565 
6566  m_pending = true;
6567 }
6568 
6569 
6571 
6572 {
6573  m_mode2 = mode;
6574  if ( m_mode2 > 2 ) m_mode2 = 0;
6575 
6576  if ( !m_canvasobject )
6577  return;
6578 
6579  m_pending = true;
6580 }
6581 
6582 
6583 void a2dDrawArcTool::OnMouseEvent( wxMouseEvent& event )
6584 {
6585  if ( !m_active )
6586  {
6587  event.Skip();
6588  return;
6589  }
6590 
6591  if ( GetBusy() )
6592  GetDrawingPart()->SetCursor( m_toolBusyCursor );
6593  else
6594  GetDrawingPart()->SetCursor( m_toolcursor );
6595 
6596  m_x = event.GetX();
6597  m_y = event.GetY();
6598  MouseToToolWorld( m_x, m_y, m_xwprev, m_ywprev );
6599 
6600  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
6601  if( restrict )
6602  restrict->RestrictPoint( m_xwprev, m_ywprev );
6603 
6604  if ( event.LeftDown() && !GetBusy() )
6605  {
6606  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
6607  double radius = 0.00001; //needs to be something to initialize properly on angle
6608  m_original = new a2dArc( m_xwprev, m_ywprev, radius, m_arcstart, m_arcend );
6609  a2dArc* arc = wxStaticCast( m_original.Get(), a2dArc );
6610  m_start_x = m_xwprev;
6611  m_start_y = m_ywprev;
6612  arc->SetChord( m_chord );
6613  if ( !EnterBusyMode() )
6614  return;
6616  }
6617  else if ( event.LeftDown() && GetBusy() )
6618  {
6619  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
6620  m_mode2 = 0;
6621  a2dArc* arc = wxStaticCast( m_canvasobject.Get(), a2dArc );
6622  a2dGeneralGlobals->RecordF( this, _T( "arc %f %f %f %f %f" ),
6623  arc->GetPosX(), arc->GetPosY(),
6624  arc->GetRadius(),
6625  m_arcstart, m_arcend );
6626  FinishBusyMode();
6627  }
6628  else if ( ( event.Dragging() && GetBusy() ) || ( event.Moving() && GetBusy() ) )
6629  {
6630  a2dArc* arc = wxStaticCast( m_canvasobject.Get(), a2dArc );
6631  a2dArc* arcorg = wxStaticCast( m_original.Get(), a2dArc );
6632  //modify object
6633  double xs, ys;
6634  xs = m_xwprev - arc->GetPosX();
6635  ys = m_ywprev - arc->GetPosY();
6636 
6637  if ( m_mode2 == 1 )
6638  {
6639  double radius = arc->GetRadius();
6640 
6641  m_arcstart = wxRadToDeg( atan2( ys, xs ) );
6642 
6643  //normalize to same radius
6644  arc->SetX1( cos( atan2( ys, xs ) ) * radius );
6645  arc->SetY1( sin( atan2( ys, xs ) ) * radius );
6646  arcorg->SetX1( cos( atan2( ys, xs ) ) * radius );
6647  arcorg->SetY1( sin( atan2( ys, xs ) ) * radius );
6648  }
6649  else if ( m_mode2 == 2 )
6650  {
6651  //no need to normalize to same radius because it does not change
6652  arc->SetX2( xs );
6653  arc->SetY2( ys );
6654  arcorg->SetX2( xs );
6655  arcorg->SetY2( ys );
6656  m_arcend = wxRadToDeg( atan2( ys, xs ) );
6657  }
6658  else
6659  {
6660  SetMode( m_mode );
6661  }
6662  m_pending = true;
6663  }
6664  else
6665  event.Skip();
6666 }
6667 
6668 
6669 BEGIN_EVENT_TABLE( a2dDrawLineTool, a2dStDrawTool )
6670  EVT_CHAR( a2dDrawLineTool::OnChar )
6671  EVT_MOUSE_EVENTS( a2dDrawLineTool::OnMouseEvent )
6672  EVT_DO( a2dDrawLineTool::OnDoEvent )
6673 END_EVENT_TABLE()
6674 
6675 a2dDrawLineTool::a2dDrawLineTool( a2dStToolContr* controller, a2dSLine* templateObject ): a2dStDrawTool( controller )
6676 {
6677  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_PENCIL );
6678  m_toolBusyCursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS );
6679 
6680  m_AllowModifyTemplate = true;
6681  m_templateObject = templateObject;
6682  if ( !m_templateObject )
6683  {
6684  m_templateObject = new a2dEndsLine();
6685  m_templateObject->SetEndScaleX( GetDrawing()->GetHabitat()->GetEndScaleX() );
6686  m_templateObject->SetEndScaleY( GetDrawing()->GetHabitat()->GetEndScaleY() );
6687  m_templateObject->SetBegin( GetDrawing()->GetHabitat()->GetLineBegin() );
6688  m_templateObject->SetEnd( GetDrawing()->GetHabitat()->GetLineEnd() );
6689  m_templateObject->SetPathType( GetDrawing()->GetHabitat()->GetPathType() );
6690  m_templateObject->SetContourWidth( GetDrawing()->GetHabitat()->GetContourWidthInDataBaseUnits() );
6691  m_contourwidth = GetDrawing()->GetHabitat()->GetContourWidthInDataBaseUnits();
6692  }
6693  else
6694  {
6695  m_layer = m_templateObject->GetLayer();
6696  m_fill = m_templateObject->GetFill();
6697  m_stroke = m_templateObject->GetStroke();
6698  m_contourwidth = m_templateObject->GetContourWidth();
6699  }
6700 }
6701 
6702 a2dDrawLineTool::~a2dDrawLineTool()
6703 {
6704 }
6705 
6707 {
6708  m_templateObject->SetBegin( begin );
6709 }
6710 
6712 
6713 {
6714  m_templateObject->SetEnd( end );
6715 }
6716 
6718 {
6720 }
6721 
6722 
6724 {
6726 }
6727 
6729 {
6730  if ( GetBusy() )
6731  {
6732  a2dSLine* line = wxStaticCast( m_original.Get(), a2dSLine );
6733  line->SetPathType( pathtype );
6734  line = wxStaticCast( m_canvasobject.Get(), a2dSLine );
6735  line->SetPathType( pathtype );
6736  }
6737 
6738  m_templateObject->SetPathType( pathtype );
6739 }
6740 
6741 
6742 void a2dDrawLineTool::OnDoEvent( a2dCommandProcessorEvent& event )
6743 {
6744  event.Skip();
6745 }
6746 
6748 {
6749  // Add old (and later new) annotation area to pending region
6751 
6752  a2dSLine* line = wxStaticCast( m_canvasobject.Get(), a2dSLine );
6753 
6754  m_anotation.Printf( _T( "x %6.3f y %6.3f l %6.3f" ), m_x2, m_y2, line->GetLength() );
6755 
6756  wxCoord w, h, d, l;
6757  GetTextExtent( m_anotation, &w, &h, &d, &l );
6758  m_xanotation = GetDrawer2D()->WorldToDeviceX( m_x2 ) + ( int ) h;
6759  m_yanotation = GetDrawer2D()->WorldToDeviceY( m_y2 ) - ( int ) h;
6760 
6762 }
6763 
6764 void a2dDrawLineTool::OnChar( wxKeyEvent& event )
6765 {
6766  if ( GetBusy() )
6767  {
6768  if ( event.GetKeyCode() == WXK_SPACE )
6769  {
6770  a2dGeneralGlobals->RecordF( this, _T( "line %f %f %f %f" ), m_x1, m_y1, m_x2, m_y2 );
6771 
6772  FinishBusyMode();
6773  return;
6774  }
6775 
6776  double shiftx;
6777  double shifty;
6778  GetKeyIncrement( &shiftx, &shifty );
6779 
6780  //now shift with snap distances in X or Y
6781  switch( event.GetKeyCode() )
6782  {
6783  case WXK_UP:
6784  shiftx = 0;
6785  break;
6786 
6787  case WXK_DOWN:
6788  shiftx = 0;
6789  shifty = -shifty;
6790  break;
6791 
6792  case WXK_LEFT:
6793  shiftx = -shiftx;
6794  shifty = 0;
6795  break;
6796 
6797  case WXK_RIGHT:
6798  shifty = 0;
6799  break;
6800  default:
6801  {
6802  shiftx = 0;
6803  shifty = 0;
6804  event.Skip();
6805  }
6806  }
6807 
6808  a2dSLine* line = wxStaticCast( m_canvasobject.Get(), a2dSLine );
6809  if ( event.m_controlDown )
6810  {
6811  m_x2 += shiftx;
6812  m_y2 += shifty;
6813  line->EliminateMatrix();
6814  line->SetPosXY12( m_x1, m_y1, m_x2, m_y2 );
6815  }
6816  else
6817  {
6818  m_x1 += shiftx;
6819  m_y1 += shifty;
6820  m_x2 += shiftx;
6821  m_y2 += shifty;
6822  line->EliminateMatrix();
6823  line->SetPosXY12( m_x1, m_y1, m_x2, m_y2 );
6824  }
6825 
6826  GetDisplayWindow()->WarpPointer( GetDrawer2D()->WorldToDeviceX( m_x2 ), GetDrawer2D()->WorldToDeviceY( m_y2 ) );
6827 
6828  m_pending = true;
6829  }
6830  else
6831  event.Skip();
6832 
6833 }
6834 
6835 void a2dDrawLineTool::OnMouseEvent( wxMouseEvent& event )
6836 {
6837  if ( !m_active )
6838  {
6839  event.Skip();
6840  return;
6841  }
6842 
6843  if ( GetBusy() )
6844  GetDrawingPart()->SetCursor( m_toolBusyCursor );
6845  else
6846  GetDrawingPart()->SetCursor( m_toolcursor );
6847 
6848  m_x = event.GetX();
6849  m_y = event.GetY();
6850  MouseToToolWorld( m_x, m_y, m_xwprev, m_ywprev );
6851 
6852  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
6853  if( restrict )
6854  restrict->RestrictPoint( m_xwprev, m_ywprev );
6855 
6856  if ( event.LeftDown() && !GetBusy() )
6857  {
6858  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
6859  m_x2 = m_x1 = m_xwprev;
6860  m_y2 = m_y1 = m_ywprev;
6861 
6863  m_original->Translate( m_xwprev, m_ywprev );
6869 
6870  a2dSLine* line = wxStaticCast( m_original.Get(), a2dSLine );
6871  if ( line->GetBegin() && line->GetBegin()->GetFlag( a2dCanvasOFlags::normalized ) )
6872  {
6874  double norm = GetDrawing()->GetNormalizeScale();
6875  line->GetBegin()->Scale( norm, norm );
6876  }
6877  if ( line->GetEnd() && line->GetEnd()->GetFlag( a2dCanvasOFlags::normalized ) )
6878  {
6880  double norm = GetDrawing()->GetNormalizeScale();
6881  line->GetEnd()->Scale( norm, norm );
6882  }
6883 
6884  if ( !EnterBusyMode() )
6885  return;
6887  }
6888  else if ( event.LeftDown() && GetBusy() )
6889  {
6890  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
6891  //a2dSLine* line = wxStaticCast( m_canvasobject.Get(), a2dSLine );
6892 
6893  a2dGeneralGlobals->RecordF( this, _T( "line %f %f %f %f" ), m_x1, m_y1, m_x2, m_y2 );
6894 
6895  FinishBusyMode();
6896  }
6897  else if ( ( event.Dragging() && GetBusy() ) || ( event.Moving() && GetBusy() ) )
6898  {
6899  a2dSLine* line = wxStaticCast( m_canvasobject.Get(), a2dSLine );
6900  a2dSLine* lineorg = wxStaticCast( m_original.Get(), a2dSLine );
6901 
6902  m_x2 = m_xwprev;
6903  m_y2 = m_ywprev;
6904 
6905  line->SetPosXY12( m_x1, m_y1, m_x2, m_y2 );
6906  lineorg->SetPosXY12( m_x1, m_y1, m_x2, m_y2 );
6907 
6908  m_pending = true;
6909  }
6910  else
6911  event.Skip();
6912 
6913 }
6914 
6915 BEGIN_EVENT_TABLE( a2dRotateTool, a2dStTool )
6916  EVT_CHAR( a2dRotateTool::OnChar )
6917  EVT_MOUSE_EVENTS( a2dRotateTool::OnMouseEvent )
6918  EVT_IDLE( a2dRotateTool::OnIdle )
6919  EVT_KEY_DOWN( a2dRotateTool::OnKeyDown )
6920 END_EVENT_TABLE()
6921 
6922 a2dRotateTool::a2dRotateTool( a2dStToolContr* controller ): a2dStTool( controller )
6923 {
6924  m_eventHandler = controller->GetDefaultToolEventHandlerFixedStyle();
6925 
6926  m_canvasobject = 0;
6927  m_mode = false;
6928 }
6929 
6930 a2dRotateTool::~a2dRotateTool()
6931 {
6932 }
6933 
6935 {
6936  if( !a2dStTool::EnterBusyMode() )
6937  return false;
6938  CaptureMouse();
6939  return true;
6940 }
6941 
6942 void a2dRotateTool::FinishBusyMode( bool closeCommandGroup )
6943 {
6944  ReleaseMouse();
6946 }
6947 
6949 {
6950  ReleaseMouse();
6952 }
6953 
6954 void a2dRotateTool::OnChar( wxKeyEvent& event )
6955 {
6956  if ( GetBusy() && m_canvasobject )
6957  {
6958  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
6959 
6960  double dx = m_xwprev - m_xr;
6961  double dy = m_ywprev - m_yr;
6962  double ang;
6963  if ( !dx && !dy )
6964  ang = 0;
6965  else
6966  ang = atan2( dy, dx );
6967 
6968  double shiftx;
6969  double shifty;
6970  double xw;
6971  double yw;
6972 
6973  GetKeyIncrement( &shiftx, &shifty );
6974 
6975  switch( event.GetKeyCode() )
6976  {
6977  case WXK_UP:
6978  {
6979  yw = m_yr + shifty;
6980  }
6981  break;
6982 
6983  case WXK_DOWN:
6984  {
6985  yw = m_yr - shifty;
6986  }
6987  break;
6988 
6989  case WXK_LEFT:
6990  {
6991  xw = m_xr - shiftx;
6992  }
6993  break;
6994 
6995  case WXK_RIGHT:
6996  {
6997  xw = m_xr + shiftx;
6998  }
6999  break;
7000  case WXK_SPACE:
7001  {
7002  m_canvasobject->SetVisible( true );
7004  new a2dCommand_SetCanvasProperty( m_canvasobject, a2dCanvasObject::PROPID_TransformMatrix, m_transform )
7005  );
7006  FinishBusyMode();
7007  }
7008  break;
7009  default:
7010  event.Skip();
7011  }
7012 
7013  if( restrict )
7014  restrict->RestrictPoint( xw, yw, a2dRestrictionEngine::snapToPointAngle );
7015 
7016  dx = xw - m_xr;
7017  dy = yw - m_yr;
7018 
7019  double angn;
7020  if ( !dx && !dy )
7021  angn = 0;
7022  else
7023  angn = atan2( dy, dx );
7024 
7025  m_ang = wxRadToDeg( angn );
7026  angn = angn - ang;
7027  if ( angn <= 0 ) angn += 2.0 * wxPI;
7028  if ( ang < 0 ) ang += 2.0 * wxPI;
7029  angn = angn + ang;
7030  ang = angn - ang;
7031 
7032  a2dAffineMatrix rotate;
7033  rotate.Translate( -m_xr, -m_yr );
7034  rotate.Rotate( wxRadToDeg( -ang ) );
7035  rotate.Translate( m_xr, m_yr );
7036 
7037  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS ) );
7038 
7039  m_canvasobject->Transform( rotate );
7040 
7041  m_pending = true;
7042 
7043  m_xwprev = xw;
7044  m_ywprev = yw;
7045 
7046  m_pending = true;
7047 
7048  //GetDisplayWindow()->WarpPointer( GetDrawer2D()->WorldToDeviceX(m_xr), GetDrawer2D()->WorldToDeviceY(m_yr) );
7049  }
7050  else
7051  event.Skip();
7052 
7053 
7054 }
7055 
7056 void a2dRotateTool::OnIdle( wxIdleEvent& event )
7057 {
7058  if ( m_pending && GetBusy() )
7059  {
7061 
7062  a2dSLine* ll = new a2dSLine( m_xr, m_yr, m_xwprev, m_ywprev );
7063  ll->SetStroke( *wxRED, 0 );
7064  ll->SetRoot( GetDrawingPart()->GetDrawing() );
7065 
7066  m_anotation.Printf( _T( "angle %6.3f" ), m_ang );
7067  m_xanotation = GetDrawer2D()->WorldToDeviceX( m_xwprev );
7069 
7070  AddDecorationObject( ll );
7071 
7072  event.Skip();
7073  }
7074  else
7075  event.Skip();
7076 }
7077 
7078 void a2dRotateTool::OnMouseEvent( wxMouseEvent& event )
7079 {
7080  if ( !m_active )
7081  {
7082  event.Skip();
7083  return;
7084  }
7085 
7086  static int px, py;
7087 
7088  m_x = event.GetX();
7089  m_y = event.GetY();
7090 
7091  //to world coordinates to do hit test in world coordinates
7092  double xw, yw;
7093  MouseToToolWorld( m_x, m_y, xw, yw );
7094 
7095  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
7096 
7097  if ( event.Moving() && !GetBusy() )
7098  {
7099  if ( GetDrawingPart()->IsHitWorld( xw, yw ) )
7100  GetDrawingPart()->SetCursor( m_toolcursor );
7101  else
7102  GetDrawingPart()->SetCursor( m_toolBusyCursor );
7103 
7104  }
7105 
7106  if ( event.LeftDown() && !GetBusy() )
7107  {
7108  if( restrict )
7109  restrict->RestrictPoint( m_xwprev, m_ywprev );
7110  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
7111 
7113 
7114  if ( !m_canvasobject )
7115  {
7116  m_canvasobject = 0;
7117  return;
7118  }
7119  if ( !m_canvasobject->GetDraggable() )
7120  {
7121  m_canvasobject = 0;
7122  return;
7123  }
7124 
7125  if ( !EnterBusyMode() )
7126  return;
7127 
7129 
7130  if ( event.m_shiftDown )
7131  m_mode = true;
7132  else
7133  m_mode = false;
7134 
7135  if ( m_mode )
7136  {
7137  m_xr = m_canvasobject->GetPosX();
7138  m_yr = m_canvasobject->GetPosY();
7139  }
7140  else
7141  {
7142  m_xr = xw;
7143  m_yr = yw;
7144  }
7145 
7146  m_xwprev = xw;
7147  m_ywprev = yw;
7148 
7149  if( restrict )
7150  restrict->SetRestrictPoint( m_xr, m_yr );
7151  }
7152  else if ( event.LeftUp() && GetBusy() )
7153  {
7154  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
7155  GetDrawingPart()->SetCursor( *wxSTANDARD_CURSOR );
7156 
7159 
7161  new a2dCommand_SetCanvasProperty( m_canvasobject, a2dCanvasObject::PROPID_TransformMatrix, newtransform )
7162  );
7163 
7164  FinishBusyMode();
7165  }
7166  else if ( ( event.Dragging() && GetBusy() ) || ( event.Moving() && GetBusy() ) )
7167  {
7168  if ( px != m_x || py != m_y )
7169  {
7170  double dx, dy;
7171 
7172  // like this around object position
7173  a2dAffineMatrix rotate;
7174 
7175  if( restrict )
7176  restrict->RestrictPoint( xw, yw, a2dRestrictionEngine::snapToPointAngle );
7177 
7178  dx = m_xwprev - m_xr;
7179  dy = m_ywprev - m_yr;
7180 
7181  double ang;
7182  if ( !dx && !dy )
7183  ang = 0;
7184  else
7185  ang = atan2( dy, dx );
7186 
7187  dx = xw - m_xr;
7188  dy = yw - m_yr;
7189  double angn;
7190  if ( !dx && !dy )
7191  angn = 0;
7192  else
7193  angn = atan2( dy, dx );
7194 
7195  m_ang = wxRadToDeg( angn );
7196 
7197  angn = angn - ang;
7198  if ( angn <= 0 ) angn += 2.0 * wxPI;
7199 
7200  if ( ang < 0 ) ang += 2.0 * wxPI;
7201 
7202  angn = angn + ang;
7203 
7204  ang = angn - ang;
7205 
7206  rotate.Translate( -m_xr, -m_yr );
7207  rotate.Rotate( wxRadToDeg( -ang ) );
7208  rotate.Translate( m_xr, m_yr );
7209 
7210  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS ) );
7211 
7212  m_canvasobject->Transform( rotate );
7213 
7214  m_pending = true;
7215 
7216  m_xwprev = xw;
7217  m_ywprev = yw;
7218  px = m_x;
7219  py = m_y;
7220  }
7221  }
7222  else
7223  {
7224  event.Skip();
7225  }
7226 }
7227 
7229 {
7231  GetDrawingPart()->GetDisplayWindow()->CaptureMouse();
7232 }
7233 
7235 {
7236  GetDrawingPart()->SetCaptured( NULL );
7237  GetDrawingPart()->GetDisplayWindow()->ReleaseMouse();
7238 }
7239 
7240 
7241 BEGIN_EVENT_TABLE( a2dDrawTextTool, a2dStDrawTool )
7242  EVT_MOUSE_EVENTS( a2dDrawTextTool::OnMouseEvent )
7243 END_EVENT_TABLE()
7244 
7245 INITIALIZE_PROPERTIES( a2dDrawTextTool, a2dStDrawTool )
7246 {
7247  return true;
7248 }
7249 
7250 a2dDrawTextTool::a2dDrawTextTool( a2dStToolContr* controller, a2dText* templateObject ): a2dStDrawTool( controller )
7251 {
7253  m_templateObject = templateObject;
7254  if ( !m_templateObject )
7255  {
7256  m_templateObject = new a2dText( _T( "" ), 0,0, GetDrawing()->GetHabitat()->GetTextTemplateObject()->GetFont(), 0, false );
7257  a2dText* textobject = m_templateObject.Get();
7258  textobject->SetCaret( 0 );
7259  textobject->SetCaretShow( false );
7260  //textobject->SetLineSpacing( ? );
7261  bool up = false;
7262  if ( GetDrawingPart() && GetDrawingPart()->GetDrawer2D() )
7263  up = !GetDrawingPart()->GetDrawer2D()->GetYaxis();
7264  textobject->SetNextLineDirection( up );
7265  //textobject->SetDrawFrame( true );
7266  //textobject->SetBackGround( true );
7267 
7268  textobject->SetFill( m_fill );
7269  textobject->SetStroke( m_stroke );
7270  }
7271  else
7272  {
7273  m_fill = m_templateObject->GetFill();
7274  m_stroke = m_templateObject->GetStroke();
7275  }
7276 
7277  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_PENCIL );
7278  m_canvasobject = 0;
7279 }
7280 
7281 a2dDrawTextTool::~a2dDrawTextTool()
7282 {
7283 }
7284 
7285 void a2dDrawTextTool::OnMouseEvent( wxMouseEvent& event )
7286 {
7287  if ( !m_active )
7288  {
7289  event.Skip();
7290  return;
7291  }
7292 
7293  if ( GetBusy() )
7294  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_IBEAM ) );
7295  else
7296  GetDrawingPart()->SetCursor( m_toolcursor );
7297 
7298  m_x = event.GetX();
7299  m_y = event.GetY();
7300 
7301  //to world coordinates to do hit test in world coordinates
7302  MouseToToolWorld( m_x, m_y, m_xwprev, m_ywprev );
7303 
7304  a2dCanvasObject* hitobject = NULL;
7305  if ( event.Moving() )
7306  {
7307  if ( !GetBusy() )
7308  {
7309  GetDrawingPart()->MouseToToolWorld( m_x, m_y, m_xwprev, m_ywprev );
7310  hitobject = GetDrawingPart()->IsHitWorld( m_xwprev, m_ywprev, wxLAYER_ALL, a2dCANOBJHITOPTION_LAYERS, true );
7311  if ( hitobject && !event.m_shiftDown )
7312  {
7313  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Edit ) );
7314  }
7315  else
7316  GetDrawingPart()->SetCursor( m_toolcursor );
7317  }
7318  else
7319  GetDrawingPart()->SetCursor( m_toolBusyCursor );
7320  }
7321 
7322  if ( event.LeftDown() && !GetBusy() )
7323  {
7324  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
7325  GetDrawingPart()->MouseToToolWorld( m_x, m_y, m_xwprev, m_ywprev );
7326  hitobject = GetDrawingPart()->IsHitWorld( m_xwprev, m_ywprev, wxLAYER_ALL, a2dCANOBJHITOPTION_LAYERS, true );
7327  if ( hitobject && !event.m_shiftDown )
7328  m_original = hitobject;
7329  else
7330  {
7332  m_original->SetPosXY( m_xwprev, m_ywprev );
7333  }
7334  if ( !a2dBaseTool::EnterBusyMode() )
7335  return;
7336  bool backupstartedit = m_editatend;
7337  m_editatend = true;
7338  if ( ! ( hitobject && !event.m_shiftDown ) )
7342  //CloseCommandGroup();delayed to pop of edit tool
7343  if( m_oneshot )
7344  StopTool();
7345  m_editatend = backupstartedit;
7346  }
7347  else
7348  event.Skip();
7349 }
7350 
7351 //----------------------------------------------------------------------------
7352 // a2dDragMultiTool
7353 //----------------------------------------------------------------------------
7354 
7355 BEGIN_EVENT_TABLE( a2dDragMultiTool, a2dStTool )
7356  EVT_KEY_DOWN( a2dDragMultiTool::OnKeyDown )
7357  EVT_KEY_UP( a2dDragMultiTool::OnKeyUp )
7358  EVT_CHAR( a2dDragMultiTool::OnChar )
7359  EVT_MOUSE_EVENTS( a2dDragMultiTool::OnMouseEvent )
7360 END_EVENT_TABLE()
7361 
7362 a2dDragMultiTool::a2dDragMultiTool( a2dStToolContr* controller ): a2dStTool( controller )
7363 {
7364  m_eventHandler = controller->GetDefaultToolEventHandlerFixedStyle();
7365  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_ARROW );
7366  m_toolBusyCursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_Drag );
7367  m_onlyKeys = false;
7368 
7369  //only modes which are usefull in dragging
7370  m_snapTargetFeatures =
7371  a2dRestrictionEngine::snapToGridPos |
7374  a2dRestrictionEngine::snapToObjectPos |
7375  //a2dRestrictionEngine::snapToPinsUnconnected |
7379 
7380 }
7381 
7382 a2dDragMultiTool::~a2dDragMultiTool()
7383 {
7384 }
7385 
7386 void a2dDragMultiTool::OnKeyDown( wxKeyEvent& event )
7387 {
7388  if ( !m_active )
7389  {
7390  event.Skip();
7391  return;
7392  }
7393 
7394  if ( !GetBusy() )
7395  {
7397  if ( selected )
7398  {
7399  m_original = selected;
7400 
7402  {
7403  m_original = 0;
7404  return;
7405  }
7406 
7408  if ( !EnterBusyMode() )
7409  return;
7410 
7411  double shiftx;
7412  double shifty;
7413  GetKeyIncrement( &shiftx, &shifty );
7414 
7415  //now shift with snap distances in X or Y
7416 
7417  switch( event.GetKeyCode() )
7418  {
7419  case WXK_UP:
7420  shiftx = 0;
7421  break;
7422 
7423  case WXK_DOWN:
7424  shiftx = 0;
7425  shifty = -shifty;
7426  break;
7427 
7428  case WXK_LEFT:
7429  shiftx = -shiftx;
7430  shifty = 0;
7431  break;
7432 
7433  case WXK_RIGHT:
7434  shifty = 0;
7435  break;
7436  default:
7437  {
7438  shiftx = 0;
7439  shifty = 0;
7440  event.Skip();
7441  }
7442  }
7443 
7444  if ( shiftx || shifty )
7445  {
7446  m_xwprev += shiftx;
7447  m_ywprev += shifty;
7448 
7449  DragAbsolute( m_xwprev, m_ywprev );
7450  m_pending = true;
7451  }
7452  }
7453  else
7454  event.Skip();
7455  }
7456  else
7457  {
7458  double shiftx;
7459  double shifty;
7460  GetKeyIncrement( &shiftx, &shifty );
7461 
7462  //now shift with snap distances in X or Y
7463 
7464  switch( event.GetKeyCode() )
7465  {
7466  case WXK_UP:
7467  shiftx = 0;
7468  break;
7469 
7470  case WXK_DOWN:
7471  shiftx = 0;
7472  shifty = -shifty;
7473  break;
7474 
7475  case WXK_LEFT:
7476  shiftx = -shiftx;
7477  shifty = 0;
7478  break;
7479 
7480  case WXK_RIGHT:
7481  shifty = 0;
7482  break;
7483  default:
7484  {
7485  shiftx = 0;
7486  shifty = 0;
7487  event.Skip();
7488  }
7489  }
7490 
7491  if ( shiftx || shifty )
7492  {
7493  m_xwprev += shiftx;
7494  m_ywprev += shifty;
7495 
7496  double dxm = m_xwprev - m_startMousexw;
7497  double dym = m_ywprev - m_startMouseyw;
7498  DragAbsolute( dxm + m_startObjectx, dym + m_startObjecty );
7499 
7500  m_pending = true;
7501  }
7502  }
7503 }
7504 
7505 void a2dDragMultiTool::OnKeyUp( wxKeyEvent& event )
7506 {
7507  if ( !m_active )
7508  {
7509  event.Skip();
7510  return;
7511  }
7512 
7513  if ( GetBusy() )
7514  {
7515  switch( event.GetKeyCode() )
7516  {
7517  case WXK_UP:
7518  case WXK_DOWN:
7519  case WXK_LEFT:
7520  case WXK_RIGHT:
7521  FinishBusyMode();
7522  break;
7523  default:
7524  {
7525  event.Skip();
7526  }
7527  }
7528  }
7529  else
7530  event.Skip();
7531 
7532 }
7533 
7534 void a2dDragMultiTool::OnChar( wxKeyEvent& event )
7535 {
7536  if ( GetBusy() )
7537  {
7538  switch( event.GetKeyCode() )
7539  {
7540  case WXK_DELETE:
7541  {
7542  // if busy do nothing with this key.
7543  break;
7544  }
7545  default:
7546  event.Skip();
7547 
7548  }
7549  }
7550  else
7551  {
7552  switch( event.GetKeyCode() )
7553  {
7554  case WXK_SPACE:
7555  {
7557  break;
7558  }
7559  default:
7560  event.Skip();
7561  }
7562  }
7563 }
7564 
7565 bool a2dDragMultiTool::StartDragging( int x, int y, a2dCanvasObject* original )
7566 {
7567  m_x = x;
7568  m_y = y;
7569  MouseToToolWorld( m_x, m_y, m_xwprev, m_ywprev );
7570 
7571  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
7572 
7573  m_original = original;
7574 
7576  {
7577  m_original = 0;
7578  return false;
7579  }
7580 
7581  // collect selected objects
7583  if ( !EnterBusyMode() )
7584  return false;
7585 
7590 
7591  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
7592  if( restrict )
7593  {
7595  }
7596  return true;
7597 }
7598 
7599 void a2dDragMultiTool::OnMouseEvent( wxMouseEvent& event )
7600 {
7601  if ( m_onlyKeys )
7602  return;
7603 
7604  if ( !m_active )
7605  {
7606  event.Skip();
7607  return;
7608  }
7609 
7610  m_x = event.GetX();
7611  m_y = event.GetY();
7612  MouseToToolWorld( m_x, m_y, m_xwprev, m_ywprev );
7613 
7614  if ( event.Moving() && !GetBusy() )
7615  {
7616  a2dCanvasObject* hit = GetDrawingPart()->IsHitWorld( m_xwprev, m_ywprev );
7617  if ( hit && hit->GetDraggable() )
7618  GetDrawingPart()->SetCursor( m_toolBusyCursor );
7619  else
7620  GetDrawingPart()->SetCursor( m_toolcursor );
7621  // this to allow EVT_CANVASOBJECT_LEAVE_EVENT
7622  event.Skip();
7623  }
7624 
7625  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
7626  if( restrict )
7627  {
7628  restrict->SetShiftKeyDown( event.ShiftDown() );
7629  }
7630 
7631  if ( event.LeftDown() && !GetBusy() )
7632  {
7633  a2dCanvasObject* original = GetDrawingPart()->IsHitWorld( m_xwprev, m_ywprev, wxLAYER_ALL, a2dCANOBJHITOPTION_LAYERS, true );
7634  if ( !StartDragging( m_x, m_y, original ) )
7635  return;
7636  }
7637  else if ( event.LeftUp() && GetBusy() )
7638  {
7639  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
7640  if (
7641  m_xwprev < GetDrawer2D()->GetVisibleMinX() ||
7642  m_xwprev > GetDrawer2D()->GetVisibleMaxX() ||
7643  m_ywprev < GetDrawer2D()->GetVisibleMinY() ||
7644  m_ywprev > GetDrawer2D()->GetVisibleMaxY()
7645  )
7646  AbortBusyMode();
7647  else
7648  FinishBusyMode();
7649 
7650  //GetDrawingPart()->GetDrawing()->UpdateAllViews( NULL, a2dCANVIEW_UPDATE_ALL );
7651  //if (m_oneshot)
7652  // StopTool();
7653  }
7654  else if ( GetBusy() )
7655  {
7656  if ( !m_canvasobject )
7657  return; //todo why does this happen
7658  double dxm = m_xwprev - m_startMousexw;
7659  double dym = m_ywprev - m_startMouseyw;
7660  AdjustShift( &dxm, &dym );
7661  // drag main object
7662  // calculate the shift resulting from this
7663  DragAbsolute( dxm + m_startObjectx, dym + m_startObjecty );
7664 
7665  event.Skip(); //scroll wheel will work
7666 
7667  double unitScale = GetDrawing()->GetUnitsScale();
7668  wxString state, form;
7669  form = m_stcontroller->GetFormat() + " " + m_stcontroller->GetFormat();
7670  state.Printf( form, m_canvasobject->GetBboxMinX()*unitScale, m_canvasobject->GetBboxMinY()*unitScale );
7671  SetStateString( state, 10 );
7672  form = _T("width = ") + m_stcontroller->GetFormat() + _T(" height = ") + m_stcontroller->GetFormat();
7673  state.Printf( form, m_canvasobject->GetBboxWidth()*unitScale, m_canvasobject->GetBboxHeight()*unitScale );
7674  SetStateString( state, 11 );
7675  }
7676  else
7677  {
7678  event.Skip();
7679  }
7680 }
7681 
7683 {
7684  if( !a2dStTool::EnterBusyMode() )
7685  return false;
7686  CaptureMouse();
7687  return true;
7688 }
7689 
7690 void a2dDragMultiTool::FinishBusyMode( bool closeCommandGroup )
7691 {
7692  ReleaseMouse();
7693 
7694  for( a2dCanvasObjectList::iterator iter = m_copies.begin(); iter != m_copies.end(); ++iter )
7695  {
7696  a2dCanvasObject* copy = *iter;
7697  a2dCanvasObject* original = a2dCanvasObject::PROPID_Original->GetPropertyValue( copy );
7698 
7700  new a2dCommand_SetCanvasProperty( original, a2dCanvasObject::PROPID_TransformMatrix, copy->GetTransformMatrix() )
7701  );
7702  }
7703 
7704  //eliminate matrix, to correctly optimize wires.
7705  for( a2dCanvasObjectList::iterator iter = m_objects.begin(); iter != m_objects.end(); ++iter )
7706  {
7707  a2dCanvasObject* connect = *iter;
7708  if ( !connect->GetRelease() && connect->IsConnect() )
7709  {
7710  a2dWirePolylineL* wire = wxStaticCast( connect, a2dWirePolylineL );
7711  if ( wire && ! wire->GetTransformMatrix().IsIdentity() )
7713  }
7714  (*iter)->SetBin2( false );
7715  }
7716 
7717  GetDrawing()->GetHabitat()->GetConnectionGenerator()->RerouteWires( true );
7718 
7719  m_copies.clear();
7720 
7721  if ( m_lateconnect )
7722  {
7723  double hitDistance = GetHitMargin();
7724 
7725  for( a2dCanvasObjectList::iterator iter = m_objects.begin(); iter != m_objects.end(); ++iter )
7726  {
7727  a2dCanvasObject* obj = *iter;
7728  if ( !obj->IsConnect() )
7729  {
7730  obj->SetAlgoSkip( true );
7731  GetDrawing()->GetHabitat()->GetConnectionGenerator()->
7732  ConnectToPinsObject( GetDrawingPart()->GetShowObject(), obj, hitDistance );
7733  obj->SetAlgoSkip( false );
7734  }
7735  }
7736  }
7737 
7738  m_objects.clear();
7739 
7742 
7744 }
7745 
7747 {
7748  ReleaseMouse();
7749  GetDrawing()->GetHabitat()->GetConnectionGenerator()->RerouteWires( true );
7750  m_copies.clear();
7751  m_objects.clear();
7752 
7754 }
7755 
7757 {
7758  wxASSERT( m_canvasobject );
7760  GetDrawingPart()->GetDisplayWindow()->CaptureMouse();
7761 }
7762 
7764 {
7765  GetDrawingPart()->SetCaptured( NULL );
7766  GetDrawingPart()->GetDisplayWindow()->ReleaseMouse();
7767 }
7768 
7769 void a2dDragMultiTool::DragAbsolute( double x, double y )
7770 {
7771  a2dPoint2D oldpos = m_canvasobject->GetPosXY();
7772 
7773  a2dBoundingBox bbox;
7774  for( a2dCanvasObjectList::iterator iter = m_copies.begin(); iter != m_copies.end(); ++iter )
7775  {
7776  a2dCanvasObject* obj = *iter;
7777  bbox.Expand( obj->GetBbox() );
7778  }
7779 
7780  // show the object according to the restricted position.
7781  m_canvasobject->SetPosXY( x, y );
7782 
7783  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
7784  if( restrict )
7785  {
7786  bool snapold = m_original->GetSnapTo(); //do not snap to original
7787  m_original->SetSnapTo( false );
7788  //temporarily restore position according to the mouse position, which is the unrestricted position.
7789  m_canvasobject->SetPosXY( x, y );
7790 
7791  a2dPoint2D point;
7792  double dx, dy; //detect restriction distance of any point.
7793 
7794  if ( restrict->GetShiftKeyDown() )
7795  {
7796  restrict->RestrictPoint( x, y );
7797  }
7798  else
7799  {
7801  a2dSnapToWhatMask was = restrict->GetSnapSourceFeatures();
7804  if ( snapTo == a2dRestrictionEngine::snapToNone )
7805  restrict->GetSnapTargetFeatures();
7806 
7807  if ( restrict->RestrictCanvasObjectAtVertexes( m_canvasobject, point, dx, dy, snapTo, true ) )
7808  {
7809  //restrict the object drawing to that point
7810  x += dx;
7811  y += dy;
7812  }
7813  restrict->SetSnapSourceFeatures( was );
7814  }
7815  m_original->SetSnapTo( snapold );
7816  }
7817 
7818  // show the object according to the restricted position.
7819  m_canvasobject->SetPosXY( x, y );
7820 
7821  if( oldpos != m_canvasobject->GetPosXY() )
7822  {
7823  double dx = x - oldpos.m_x;
7824  double dy = y - oldpos.m_y;
7825  for( a2dCanvasObjectList::iterator iter = m_copies.begin(); iter != m_copies.end(); ++iter )
7826  {
7827  a2dCanvasObject* obj = *iter;
7828  if( obj != m_canvasobject )
7829  obj->Translate( dx, dy );
7830  }
7831 
7832  if ( bbox.GetValid() )
7833  {
7834  double unitScale = GetDrawing()->GetUnitsScale();
7835  wxString state, form;
7836  form = m_stcontroller->GetFormat() + " " + m_stcontroller->GetFormat();
7837  state.Printf( form, (bbox.GetMinX()+dx)*unitScale, (bbox.GetMinY()+dy)*unitScale );
7838  SetStateString( state, 10 );
7839  form = _T("width = ") + m_stcontroller->GetFormat() + _T(" height = ") + m_stcontroller->GetFormat();
7840  state.Printf( form, bbox.GetWidth()*unitScale, bbox.GetHeight()*unitScale );
7841  SetStateString( state, 11 );
7842  }
7843 
7844  GetDrawing()->GetHabitat()->GetConnectionGenerator()->
7845  GeneratePinsToConnectObject( GetDrawingPart(), GetDrawingPart()->GetShowObject(), m_canvasobject );
7846 
7847  GetDrawing()->GetHabitat()->GetConnectionGenerator()->RerouteWires( false );
7848 
7849  m_pending = true;
7850  }
7851 }
7852 
7854 {
7855  if ( m_canvasobject && GetBusy() )
7856  {
7858  }
7859 }
7860 
7861 void a2dDragMultiTool::AdjustShift( double* WXUNUSED( dx ), double* WXUNUSED( dy ) )
7862 {
7863 }
7864 
7866 {
7868  a2dCanvasObjectList::iterator iter;
7869 
7870  // find wires which do connect selected objects (wire from a selected object to another selected object)
7872  setflags.SetSkipNotRenderedInDrawing( true );
7873  setflags.Start( m_parentobject, false );
7874  a2dCanvasObjectList inBetweenWires;
7875  for( iter = m_objects.begin(); iter != m_objects.end(); ++iter )
7876  {
7877  a2dCanvasObject* original = *iter;
7878  // correct connect to itself.
7879  original->DisConnectWith( original, "", true );
7880 
7881  if ( !original->IsConnect() )
7882  original->FindConnectedWires( inBetweenWires, NULL, true, true );
7883  }
7884 
7885  // if a wire was already selected as part of the dragged object, remove it here.
7886  iter = inBetweenWires.begin();
7887  while( iter != inBetweenWires.end() )
7888  {
7889  a2dCanvasObjectList::value_type wire = *iter;
7890  if ( std::find( m_objects.begin(), m_objects.end(), wire ) != m_objects.end() )
7891  iter = inBetweenWires.erase( iter );
7892  else
7893  {
7894  wire->SetSelected( true );
7895  iter++;
7896  }
7897  }
7898  setflags.Start( m_parentobject, false );
7899 
7900  // All that will be dragged without rerouting is found and selected.
7901  m_objects.TakeOverFrom( &inBetweenWires );
7902 
7903  a2dRefMap refs;
7904 
7905  // Clone all selected objects (including newly selected wires in between), in order to drag that
7906  for( iter = m_objects.begin(); iter != m_objects.end(); ++iter )
7907  {
7908  a2dCanvasObjectPtr original = *iter;
7909  //a2dCanvasObject* copy = original->TClone( clone_members | clone_childs | clone_seteditcopy | clone_setoriginal | clone_noCameleonRef );
7911 
7912  original->SetBin( true );
7913  m_copies.push_back( copy );
7914  copy->SetSelected( false );
7915  copy->SetSelected2( false );
7916 
7917  if( original == m_original )
7918  m_canvasobject = copy;
7919  }
7920  // Add the draged object clones to the parent
7921  for( iter = m_copies.begin(); iter != m_copies.end(); ++iter )
7922  {
7923  a2dCanvasObject* copy = *iter;
7924  AddEditobject( copy );
7925  }
7926 
7927  PrepareForRewire( m_objects, true, false, true, true, &refs );
7928 
7929  // Set the visibility of the original objects and the original wires
7931  //m_objects.SetSpecificFlags( true, a2dCanvasOFlags::VISIBLE );
7932 
7933  // only now we call this, earlier not possible, because clones of connectedwires not setup yet.
7934  refs.LinkReferences();
7935  m_pending = true;
7936 
7937  return true;
7938 }
7939 
7940 /* clonenbrother check
7941  for( iter = m_objects.begin(); iter != m_objects.end(); ++iter )
7942  //for( a2dCanvasObjectList::iterator iter = m_parentobject->GetChildObjectList()->begin(); iter != m_parentobject->GetChildObjectList()->end(); ++iter )
7943  {
7944  a2dCanvasObject* obj = *iter;
7945  for( a2dCanvasObjectList::iterator iter2 = obj->GetChildObjectList()->begin(); iter2 != obj->GetChildObjectList()->end(); ++iter2 )
7946  {
7947  a2dCanvasObject* obj2 = *iter2;
7948  a2dPin* pin = wxDynamicCast( obj2, a2dPin );
7949  if( !pin || pin->GetRelease( ) )
7950  continue;
7951 
7952  if ( pin->GetCloneBrother() )
7953  continue;
7954  if ( pin->ConnectedTo() && pin->ConnectedTo()->GetCloneBrother() )
7955  continue;
7956  }
7957  }
7958 */
7959 
7961 {
7963 }
7964 
7965 //----------------------------------------------------------------------------
7966 // a2dDragMultiNewTool
7967 //----------------------------------------------------------------------------
7968 
7969 BEGIN_EVENT_TABLE( a2dDragMultiNewTool, a2dDragMultiTool )
7970  EVT_ENTER_WINDOW( a2dDragMultiNewTool::OnEnter )
7971  EVT_MOUSE_EVENTS( a2dDragMultiNewTool::OnMouseEvent )
7972  EVT_COM_EVENT( a2dDragMultiNewTool::OnComEvent )
7973 END_EVENT_TABLE()
7974 
7975 a2dDragMultiNewTool::a2dDragMultiNewTool( a2dStToolContr* controller, a2dCanvasObjectList* originals )
7976  : a2dDragMultiTool( controller )
7977 {
7978  m_eventHandler = controller->GetDefaultToolEventHandlerFixedStyle();
7979  m_originals = *originals;
7980 }
7981 
7982 a2dDragMultiNewTool::~a2dDragMultiNewTool()
7983 {
7984  m_originals.clear();
7985  m_objects.clear();
7986 }
7987 
7988 void a2dDragMultiNewTool::OnComEvent( a2dComEvent& event )
7989 {
7990  if ( GetBusy() )
7991  {
7992  if ( event.GetId() == a2dStTool::sig_toolBeforePush )
7993  {
7994  a2dProperty* property = ( a2dProperty* ) event.GetProperty();
7995  a2dStTool* newtool = wxStaticCast( property->GetRefObject(), a2dStTool );
7996  if ( GetBusy() )
7997  {
7998  if ( !wxDynamicCast( newtool, a2dZoomTool ) )
7999  {
8000  FinishBusyMode();
8001  }
8002  else
8003  {
8004  m_halted = true;
8005  }
8006  }
8007  SetPending( true );
8008  }
8009  else
8010  event.Skip();
8011  }
8012  else
8013  event.Skip();
8014 }
8015 
8016 void a2dDragMultiNewTool::OnEnter( wxMouseEvent& WXUNUSED( event ) )
8017 {
8018  if ( GetDrawingPart()->GetDisplayWindow() && !GetDrawingPart()->GetDisplayWindow()->HasFocus() )
8019  GetDrawingPart()->GetDisplayWindow()->SetFocus();
8020 }
8021 
8022 bool a2dDragMultiNewTool::StartDragging( int x, int y )
8023 {
8024  m_x = x;
8025  m_y = y;
8026  MouseToToolWorld( m_x, m_y, m_xwprev, m_ywprev );
8027 
8028  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
8029  a2dRefMap refs;
8030 
8031  // Clone all given objects (including newly selected wires in between), in order to drag that
8032  a2dCanvasObjectList::iterator iter = m_originals.begin();
8033  for( iter = m_originals.begin(); iter != m_originals.end(); ++iter )
8034  {
8035  a2dCanvasObjectPtr original = *iter;
8036  //clone deep, because the cloned objects end up in the document, the originals not, they or only a template.
8037  a2dCanvasObject* copy = original->TClone( clone_deep | clone_noCameleonRef | clone_noReference | clone_seteditcopy | clone_setoriginal, &refs );
8038  copy->SetRoot( GetDrawing() );
8039  copy->SetSelected( true ); //this is used to find connected wires to new/copied objects.
8040  m_objects.push_back( copy );
8041  copy->Translate( m_xwprev, m_ywprev );
8042  }
8043  // if template is a bunch of connected objects, the clone needs to be reconnected.
8044  refs.LinkReferences();
8045 
8046  iter = m_originals.begin();
8047  for( iter = m_originals.begin(); iter != m_originals.end(); ++iter )
8048  {
8049  a2dCanvasObjectPtr original = *iter;
8050  original->RemoveProperty( a2dCanvasObject::PROPID_Editcopy );
8051  }
8052 
8053  m_original = m_objects.front();
8054 
8055  if ( !m_original )
8056  {
8057  m_original = 0;
8058  return false;
8059  }
8060 
8061  if ( !EnterBusyMode() )
8062  return false;
8063 
8064  m_startMousexw = m_xwprev;
8065  m_startMouseyw = m_ywprev;
8068 
8069  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
8070  if( restrict )
8071  {
8073  }
8074  DragAbsolute( m_startObjectx, m_startObjecty );
8075  return true;
8076 }
8077 
8078 void a2dDragMultiNewTool::OnMouseEvent( wxMouseEvent& event )
8079 {
8080  if ( !m_active )
8081  {
8082  event.Skip();
8083  return;
8084  }
8085 
8086  m_x = event.GetX();
8087  m_y = event.GetY();
8088 
8089  //to world coordinates to do hit test in world coordinates
8090  double xw, yw;
8091  MouseToToolWorld( m_x, m_y, xw, yw );
8092 
8093  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
8094  if( restrict )
8095  restrict->RestrictPoint( xw, yw );
8096 
8097  if( !GetBusy() )
8098  {
8099  StartDragging( m_x, m_y );
8100 
8101  // AddCurrent adjusts the objects style and submits an a2dCommand_AddObject
8102  //m_parentAddedTo = m_parentobject;
8103 
8104  //m_original->SetParent( m_parentAddedTo );
8105  }
8106  else if ( event.LeftDown() )
8107  {
8108  // don't process this in the base class
8109  }
8110  else if ( event.RightDown() )
8111  {
8112  event.Skip();
8113  }
8114  else if ( event.LeftUp() )
8115  {
8116  a2dDragMultiTool::OnMouseEvent( event );
8118  }
8119  else
8120  {
8121  // all the rest is as with a usual drag
8122  a2dDragMultiTool::OnMouseEvent( event );
8123  }
8124 }
8125 
8127 {
8128  // we generally don't want the original to be visible, regardless of the mode
8129  // this is because the original was cloned from the template object, and is not a
8130  // true original object
8131  m_renderOriginal = false;
8132 }
8133 
8134 void a2dDragMultiNewTool::DoStopTool( bool WXUNUSED( abort ) )
8135 {
8136  // a a2dDragMultiNewTool can be stopped, even if it is busy. This is because the
8137  // tool can be busy with mouse up.
8138  if( GetBusy() )
8139  {
8140  wxASSERT( m_original );
8141  AbortBusyMode();
8142  }
8143 
8144  if ( m_commandgroup )
8146 }
8147 
8149 {
8151  return false;
8152 
8153  // we don't want the mouse to be captured, so undo this
8154  ReleaseMouse();
8155  return true;
8156 }
8157 
8159 {
8160  GetDrawing()->GetHabitat()->GetConnectionGenerator()->RerouteWires( true );
8161  m_copies.clear();
8162  m_objects.clear();
8163 
8165 }
8166 
8167 void a2dDragMultiNewTool::FinishBusyMode( bool closeCommandGroup )
8168 {
8169  // only difference a2dDragMultiTool ReleaseMouse();
8170  for( a2dCanvasObjectList::iterator iter = m_copies.begin(); iter != m_copies.end(); ++iter )
8171  {
8172  a2dCanvasObject* copy = *iter;
8173  a2dCanvasObject* original = a2dCanvasObject::PROPID_Original->GetPropertyValue( copy );
8174 
8176  new a2dCommand_SetCanvasProperty( original, a2dCanvasObject::PROPID_TransformMatrix, copy->GetTransformMatrix() )
8177  );
8178  }
8179 
8181  new a2dCommand_AddObjects( GetDrawingPart()->GetShowObject(), m_objects )
8182  );
8183 
8184  //eliminate matrix, to correctly optimize wires.
8185  for( a2dCanvasObjectList::iterator iter = m_objects.begin(); iter != m_objects.end(); ++iter )
8186  {
8187  a2dCanvasObject* connect = *iter;
8188  if ( !connect->GetRelease() && connect->IsConnect() )
8189  {
8190  a2dWirePolylineL* wire = wxStaticCast( connect, a2dWirePolylineL );
8191  if ( wire && ! wire->GetTransformMatrix().IsIdentity() )
8193  }
8194  (*iter)->SetBin2( false );
8195  }
8196 
8197  GetDrawing()->GetHabitat()->GetConnectionGenerator()->RerouteWires( true );
8198 
8199  m_copies.clear();
8200 
8201  if ( m_lateconnect )
8202  {
8203  double hitDistance = GetHitMargin();
8204 
8205  for( a2dCanvasObjectList::iterator iter = m_objects.begin(); iter != m_objects.end(); ++iter )
8206  {
8207  a2dCanvasObject* obj = *iter;
8208  if ( !obj->IsConnect() )
8209  {
8210  obj->SetAlgoSkip( true );
8211  GetDrawing()->GetHabitat()->GetConnectionGenerator()->
8212  ConnectToPinsObject( GetDrawingPart()->GetShowObject(), obj, hitDistance );
8213  obj->SetAlgoSkip( false );
8214  }
8215  }
8216  }
8217 
8218  m_objects.clear();
8219 
8221 }
8222 
8223 
8224 BEGIN_EVENT_TABLE( a2dCopyMultiTool, a2dDragMultiTool )
8225  EVT_CHAR( a2dCopyMultiTool::OnChar )
8226  EVT_MOUSE_EVENTS( a2dCopyMultiTool::OnMouseEvent )
8227 END_EVENT_TABLE()
8228 
8229 a2dCopyMultiTool::a2dCopyMultiTool( a2dStToolContr* controller ): a2dDragMultiTool( controller )
8230 {
8231  m_mindist = GetDrawing()->GetHabitat()->GetCopyMinDistance();
8232 }
8233 
8234 void a2dCopyMultiTool::OnChar( wxKeyEvent& event )
8235 {
8236  if ( GetBusy() )
8237  {
8238  switch( event.GetKeyCode() )
8239  {
8240  case WXK_SPACE:
8241  {
8242  }
8243  break;
8244  default:
8245  event.Skip();
8246  }
8247  }
8248  else
8249  event.Skip();
8250 
8251 }
8252 
8253 bool a2dCopyMultiTool::StartDragging( int x, int y, a2dCanvasObject* original )
8254 {
8255  m_x = x;
8256  m_y = y;
8257  MouseToToolWorld( m_x, m_y, m_xwprev, m_ywprev );
8258 
8259  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
8260 
8261  m_original = original;
8262 
8264  {
8265  m_original = 0;
8266  return false;
8267  }
8268 
8269  // OpenCommandGroup must be issued before new objects are added
8270  // This is also done in EnterBusyMode, but it can be done more than once
8271  OpenCommandGroup( false );
8272  a2dRefMap refs;
8273  // Copy all selected objects
8274  // Deselect the original selected objects
8275  // Select the copied objects
8276  {
8277  bool originalfound = false;
8278  a2dCanvasObjectList::iterator iter;
8279  for( iter = m_parentobject->GetChildObjectList()->begin(); iter != m_parentobject->GetChildObjectList()->end(); ++iter )
8280  {
8281  a2dCanvasObject* obj = *iter;
8282  if( obj->GetSelected() )
8283  {
8284  a2dCanvasObject* objn = obj->TClone( clone_members | clone_childs, &refs );
8285  // Collect the new object into the active object list
8286  m_objects.push_back( objn );
8287  // Deselect the original objects
8289  // m_original must point to the copied object
8290  if( obj == m_original )
8291  {
8292  m_original = objn;
8293  originalfound = true;
8294  }
8295  }
8296  }
8297  wxASSERT( originalfound );
8298 
8299  for( iter = m_objects.begin(); iter != m_objects.end(); ++iter )
8300  {
8301  ( *iter )->SetSelected( true );
8302  // Add the new object
8304  }
8305 
8306  // Connect pins in copy as in source
8307  refs.LinkReferences();
8308  }
8309  if ( !EnterBusyMode() )
8310  return false;
8311 
8312  m_startMousexw = m_xwprev;
8313  m_startMouseyw = m_ywprev;
8316 
8317  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
8318  if( restrict )
8320 
8321  // Make one shift so that the copy is not over the original
8322  {
8323  double dxm = m_xwprev - m_startMousexw;
8324  double dym = m_ywprev - m_startMouseyw;
8325  AdjustShift( &dxm, &dym );
8326  // drag main object
8327  // calculate the shift resulting from this
8328  //DragAbsolute( dxm + m_startObjectx, dym + m_startObjecty );
8329  }
8330  return true;
8331 }
8332 
8333 void a2dCopyMultiTool::OnMouseEvent( wxMouseEvent& event )
8334 {
8335  if ( !m_active )
8336  {
8337  event.Skip();
8338  return;
8339  }
8340 
8341  int x = event.GetX();
8342  int y = event.GetY();
8343 
8344  //to world coordinates to do hit test in world coordinates
8345  MouseToToolWorld( x, y, m_xwprev, m_ywprev );
8346 
8347  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
8348  if( restrict )
8349  {
8350  restrict->SetShiftKeyDown( event.ShiftDown() );
8351  }
8352 
8353  if ( event.LeftDown() && !GetBusy() )
8354  {
8355  a2dCanvasObject* original = GetDrawingPart()->IsHitWorld( m_xwprev, m_ywprev, wxLAYER_ALL, a2dCANOBJHITOPTION_LAYERS, true );
8356  if ( !StartDragging( m_x, m_y, original ) )
8357  return;
8358  }
8359  else if ( event.LeftUp() && GetBusy() )
8360  {
8361  a2dDragMultiTool::OnMouseEvent( event );
8362  }
8363  else if ( GetBusy() )
8364  {
8365  a2dDragMultiTool::OnMouseEvent( event );
8366  }
8367  else
8368  {
8369  event.Skip();
8370  }
8371 }
8372 
8373 void a2dCopyMultiTool::AdjustShift( double* dx, double* dy )
8374 {
8375  if( ( *dx ) * ( *dx ) + ( *dy ) * ( *dy ) < m_mindist )
8376  {
8377  if( ( *dx ) == 0 && ( *dy ) == 0 )
8378  {
8379  ( *dx ) = m_mindist * 1.0;
8380  ( *dy ) = m_mindist * 0.5;
8381  }
8382  else
8383  {
8384  double fac = m_mindist / sqrt( ( *dx ) * ( *dx ) + ( *dy ) * ( *dy ) );
8385  ( *dx ) *= fac;
8386  ( *dy ) *= fac;
8387  }
8388  }
8389 }
8390 
8391 BEGIN_EVENT_TABLE( a2dPropertyTool, a2dStTool )
8392  EVT_CHAR( a2dPropertyTool::OnChar )
8393  EVT_MOUSE_EVENTS( a2dPropertyTool::OnMouseEvent )
8394 END_EVENT_TABLE()
8395 
8396 a2dPropertyTool::a2dPropertyTool( a2dStToolContr* controller ): a2dStTool( controller )
8397 {
8398  m_eventHandler = controller->GetDefaultToolEventHandlerFixedStyle();
8399 
8400  m_id = 0;
8401  m_withUndo = true;
8402 
8403  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_BULLSEYE );
8404  m_canvasobject = 0;
8405 }
8406 
8407 void a2dPropertyTool::OnChar( wxKeyEvent& event )
8408 {
8409  if ( GetBusy() )
8410  {
8411  switch( event.GetKeyCode() )
8412  {
8413  case WXK_SPACE:
8414  {
8415  FinishBusyMode();
8416  }
8417  break;
8418  default:
8419  event.Skip();
8420  }
8421  }
8422  else
8423  event.Skip();
8424 
8425 }
8426 
8427 void a2dPropertyTool::OnMouseEvent( wxMouseEvent& event )
8428 {
8429  if ( !m_active )
8430  {
8431  event.Skip();
8432  return;
8433  }
8434  GetDrawingPart()->SetCursor( m_toolcursor );
8435 
8436  int x = event.GetX();
8437  int y = event.GetY();
8438 
8439  //to world coordinates to do hit test in world coordinates
8440  double xw, yw;
8441  MouseToToolWorld( x, y, xw, yw );
8442 
8443  if ( event.LeftDown() )
8444  {
8446 
8447  if ( !m_canvasobject )
8448  {
8449  m_canvasobject = 0;
8450  event.Skip();
8451  return;
8452  }
8453 
8454  m_canvasobject->ConnectEvent( a2dEVT_PROPOBJECT_EDITPROPERTIES_EVENT, GetCanvasCommandProcessor() );
8455  a2dIterC ic( GetDrawingPart() );
8456  OpenCommandGroup( false );
8458  /*
8459  a2dPropertyIdInt32* propId = m_canvasobject->HasPropertyId( wxT("myprop" ) );
8460  if ( !propId )
8461  {
8462  propId = new a2dPropertyIdInt32( CLASSNAME( a2dCanvasObject ), wxT("myprop"), a2dPropertyId::flag_none, 0 );
8463  a2dGeneralGlobals->GetPropertyIdList().push_back( propId );
8464  }
8465  propId->SetPropertyToObject( m_canvasobject, 1234 );
8466  */
8467  m_canvasobject->DisconnectEvent( a2dEVT_PROPOBJECT_EDITPROPERTIES_EVENT, GetCanvasCommandProcessor() );
8468  m_canvasobject->SetPending( true );
8470  m_canvasobject = 0;
8471  if ( m_oneshot )
8472  StopTool();
8473  }
8474  else
8475  event.Skip();
8476 
8477 }
8478 
8479 bool a2dPropertyTool::StartEditing( double x, double y )
8480 {
8481  int mouse_x = GetDrawer2D()->WorldToDeviceX( x );
8482  int mouse_y = GetDrawer2D()->WorldToDeviceY( y );
8483 
8484  return StartEditing( mouse_x, mouse_y );
8485 }
8486 
8487 bool a2dPropertyTool::StartEditing( int x, int y )
8488 {
8489  wxMouseEvent event( wxEVT_LEFT_DOWN );
8490  event.m_x = x;
8491  event.m_y = y;
8492 
8493  OnMouseEvent( event );
8494 
8495  return true;
8496 }
8497 
8498 BEGIN_EVENT_TABLE( a2dFollowLink, a2dStTool )
8499  EVT_CHAR( a2dFollowLink::OnChar )
8500  EVT_MOUSE_EVENTS( a2dFollowLink::OnMouseEvent )
8501 END_EVENT_TABLE()
8502 
8503 a2dFollowLink::a2dFollowLink( a2dStToolContr* controller ): a2dStTool( controller )
8504 {
8505  m_eventHandler = controller->GetDefaultToolEventHandlerFixedStyle();
8506 
8507  m_withUndo = true;
8508 
8509  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_BULLSEYE );
8510  m_canvasobject = 0;
8511 }
8512 
8513 void a2dFollowLink::OnChar( wxKeyEvent& event )
8514 {
8515  if ( GetBusy() )
8516  {
8517  switch( event.GetKeyCode() )
8518  {
8519  case WXK_SPACE:
8520  {
8521  FinishBusyMode();
8522  }
8523  break;
8524  default:
8525  event.Skip();
8526  }
8527  }
8528  else
8529  event.Skip();
8530 
8531 }
8532 
8533 void a2dFollowLink::OnMouseEvent( wxMouseEvent& event )
8534 {
8535  if ( !m_active )
8536  {
8537  event.Skip();
8538  return;
8539  }
8540  GetDrawingPart()->SetCursor( m_toolcursor );
8541 
8542  int x = event.GetX();
8543  int y = event.GetY();
8544 
8545  //to world coordinates to do hit test in world coordinates
8546  double xw, yw;
8547  MouseToToolWorld( x, y, xw, yw );
8548 
8549  if ( event.LeftDown() )
8550  {
8552 
8553  if ( !m_canvasobject )
8554  {
8555  m_canvasobject = 0;
8556  event.Skip();
8557  return;
8558  }
8559 
8560  m_canvasobject->SetPending( true );
8562  m_canvasobject = 0;
8563  if ( m_oneshot )
8564  StopTool();
8565  }
8566  else
8567  event.Skip();
8568 
8569 }
8570 
8571 bool a2dFollowLink::StartEditing( double x, double y )
8572 {
8573  int mouse_x = GetDrawer2D()->WorldToDeviceX( x );
8574  int mouse_y = GetDrawer2D()->WorldToDeviceY( y );
8575 
8576  return StartEditing( mouse_x, mouse_y );
8577 }
8578 
8579 bool a2dFollowLink::StartEditing( int x, int y )
8580 {
8581  wxMouseEvent event( wxEVT_LEFT_DOWN );
8582  event.m_x = x;
8583  event.m_y = y;
8584 
8585  OnMouseEvent( event );
8586 
8587  return true;
8588 }
8589 
8590 //-----------------------------------------------------------
8591 // a2dStToolEvtHandler
8592 //-----------------------------------------------------------
8593 
8594 BEGIN_EVENT_TABLE( a2dStToolEvtHandler, a2dToolEvtHandler )
8595  EVT_KEY_DOWN( a2dStToolEvtHandler::OnKeyDown )
8596  EVT_KEY_UP( a2dStToolEvtHandler::OnKeyUp )
8597  EVT_COM_EVENT( a2dStToolEvtHandler::OnComEvent )
8598  EVT_DO( a2dStToolEvtHandler::OnDoEvent )
8599  EVT_UNDO( a2dStToolEvtHandler::OnUndoEvent )
8600  EVT_REDO( a2dStToolEvtHandler::OnRedoEvent )
8601  EVT_IDLE( a2dStToolEvtHandler::OnIdle )
8602 END_EVENT_TABLE()
8603 
8605 {
8606  m_stcontroller = controller;
8607  //a2dCanvasCommandProcessor* drawingCmdh = m_stcontroller->GetDrawingPart()->GetDrawing()->GetCanvasCommandProcessor();
8608  m_options = a2dTakeToolstyleFromCmdhOnPop | a2dTakeToolstyleFromCmdhOnPush | a2dTakeToolstyleToNewObject | a2dTakeToolstyleToCentral;
8609  a2dCanvasGlobals->ConnectEvent( a2dEVT_COM_EVENT, this );
8610 
8611  // to recieve central style changes
8612 /* already received via view
8613  if ( m_stcontroller->GetDrawingPart() && m_stcontroller->GetDrawingPart()->GetShowObject() )
8614  {
8615  drawingCmdh->ConnectEvent( wxEVT_DO, this );
8616  drawingCmdh->ConnectEvent( wxEVT_UNDO, this );
8617  drawingCmdh->ConnectEvent( wxEVT_REDO, this );
8618  drawingCmdh->ConnectEvent( a2dEVT_COM_EVENT, this );
8619  }
8620 */
8621 }
8622 
8624 {
8625  //a2dCanvasCommandProcessor* drawingCmdh = m_stcontroller->GetDrawingPart()->GetDrawing()->GetCanvasCommandProcessor();
8626 
8627  a2dCanvasGlobals->DisconnectEvent( a2dEVT_COM_EVENT, this );
8628 
8629 /* already received via view
8630  if ( m_stcontroller->GetDrawingPart() && m_stcontroller->GetDrawingPart()->GetDrawing() )
8631  {
8632  drawingCmdh->DisconnectEvent( wxEVT_DO, this );
8633  drawingCmdh->DisconnectEvent( wxEVT_UNDO, this );
8634  drawingCmdh->DisconnectEvent( wxEVT_REDO, this );
8635  drawingCmdh->DisconnectEvent( a2dEVT_COM_EVENT, this );
8636  }
8637 */
8638 }
8639 
8640 void a2dStToolEvtHandler::OnKeyDown( wxKeyEvent& event )
8641 {
8643  switch( event.GetKeyCode() )
8644  {
8645  case 'Z':
8646  case 'z':
8647  {
8648  if ( !first || ( first && !first->GetBusy() ) )
8649  {
8650  if ( event.m_controlDown && event.m_shiftDown )
8651  first->GetCanvasCommandProcessor()->Redo();
8652  else if ( event.m_controlDown )
8653  first->GetCanvasCommandProcessor()->Undo();
8654  else
8655  event.Skip();
8656  }
8657  else
8658  event.Skip();
8659  break;
8660  }
8661  case 'Y':
8662  case 'y':
8663  {
8664  if ( !first || ( first && !first->GetBusy() ) )
8665  {
8666  if ( event.m_controlDown )
8667  first->GetCanvasCommandProcessor()->Redo();
8668  else
8669  event.Skip();
8670  }
8671  else
8672  event.Skip();
8673  break;
8674  }
8675  default:
8676  event.Skip();
8677  }
8678 }
8679 
8680 void a2dStToolEvtHandler::OnKeyUp( wxKeyEvent& event )
8681 {
8682  event.Skip();
8683 }
8684 
8685 void a2dStToolEvtHandler::TakeToCmdhFromEditedObject( a2dObjectEditTool* editTool )
8686 {
8687  a2dHabitat* habitat = editTool->GetDrawing()->GetHabitat();
8688 
8689  editTool->SetLayer( editTool->m_original->GetLayer() );
8690  editTool->SetFill( editTool->m_original->GetFill() );
8691  editTool->SetStroke( editTool->m_original->GetStroke() );
8692  habitat->SetFill( editTool->m_original->GetFill() );
8693  habitat->SetStroke( editTool->m_original->GetStroke() );
8694  habitat->SetLayer( editTool->m_original->GetLayer() );
8695 
8696  if ( wxDynamicCast( editTool->m_original.Get(), a2dText ) )
8697  {
8698  a2dText* text = wxDynamicCast( editTool->m_original.Get(), a2dText );
8699  if ( text )
8700  habitat->SetFont( text->GetFont() );
8701  }
8702  if ( wxDynamicCast( editTool->m_original.Get(), a2dPolylineL ) )
8703  {
8704  a2dPolylineL* poly = wxDynamicCast( editTool->m_original.Get(), a2dPolylineL );
8705  if ( poly )
8706  {
8707  //habitat->SetSpline( poly->GetSpline() );
8708  habitat->SetLineBegin( poly->GetBegin() );
8709  habitat->SetLineEnd( poly->GetEnd() );
8710  habitat->SetEndScaleX( poly->GetEndScaleX() );
8711  habitat->SetEndScaleY( poly->GetEndScaleY() );
8712  }
8713  }
8714  if ( wxDynamicCast( editTool->m_original.Get(), a2dEndsLine ) )
8715  {
8716  a2dEndsLine* line = wxDynamicCast( editTool->m_original.Get(), a2dEndsLine );
8717  if ( line )
8718  {
8719  habitat->SetLineBegin( line->GetBegin() );
8720  habitat->SetLineEnd( line->GetEnd() );
8721  habitat->SetEndScaleX( line->GetEndScaleX() );
8722  habitat->SetEndScaleY( line->GetEndScaleY() );
8723  }
8724  }
8725  if ( editTool->m_original && editTool->m_original->GetContourWidth() != habitat->GetContourWidthInDataBaseUnits() )
8726  {
8728  editTool->m_contourwidth = editTool->m_original->GetContourWidth();
8729  editTool->m_original->SetContourWidth( editTool->m_contourwidth );
8730  }
8731  a2dPolylineL* poly = wxDynamicCast( editTool->m_original.Get(), a2dPolylineL );
8732  if ( poly && poly->GetPathType() != habitat->GetPathType() )
8733  habitat->SetPathType( poly->GetPathType() );
8734  a2dSLine* line = wxDynamicCast( editTool->m_canvasobject.Get(), a2dSLine );
8735  if ( line && line->GetPathType() != habitat->GetPathType() )
8736  habitat->SetPathType( line->GetPathType() );
8737 }
8738 
8739 void a2dStToolEvtHandler::OnIdle( wxIdleEvent& event )
8740 {
8741  /*
8742  static wxDateTime lastTimeHere = wxDateTime::UNow();
8743 
8744  if ( lastTimeHere + wxTimeSpan::Milliseconds( 100 ) > wxDateTime::UNow() )
8745  return;
8746 
8747  lastTimeHere = wxDateTime::UNow();
8748 
8749  a2dBaseTool* tool = m_stcontroller->GetFirstTool();
8750  if ( tool->GetActive() && tool->GetEvtHandlerEnabled() && tool->GetDrawingPart())
8751  {
8752  tool->SetEvtHandlerEnabled(false);
8753  }
8754  tool->SetEvtHandlerEnabled(true);
8755  */
8756  event.Skip();
8757 }
8758 
8760 {
8761  a2dSignal comId = event.GetId();
8762 
8763  if ( event.GetId() == a2dBaseTool::sig_toolBeforePush )
8764  {
8765  a2dNamedProperty* prop = event.GetProperty();
8766  a2dStTool* tool = wxDynamicCast( prop->GetRefObject(), a2dStTool ); //tool pushed
8767  if ( !wxDynamicCast( tool, a2dCopyMultiTool ) &&
8768  !wxDynamicCast( tool, a2dDragMultiTool ) &&
8769  !wxDynamicCast( tool, a2dFastDragMultiTool ) &&
8770  !wxDynamicCast( tool, a2dFastCopyMultiTool ) &&
8772  )
8773  {
8776  objects->SetSpecificFlags( false, a2dCanvasOFlags::SELECTED );
8777  tool->GetParentObject()->GetRoot()->SetUpdatesPending( true );
8778  }
8779  return;
8780  }
8781 
8782  bool baseContinue = true;
8784  {
8785  a2dObjectEditTool* tool = wxDynamicCast( event.GetEventObject(), a2dObjectEditTool );
8786  if ( tool && tool->GetActive() && tool->GetEvtHandlerEnabled() && tool->GetDrawingPart() )
8787  {
8788  tool->SetEvtHandlerEnabled( false );
8789  TakeToCmdhFromEditedObject( tool );
8790 
8791  //! this is used by dialogs and such to takeover style.
8792  tool->GetDrawing()->ProcessEvent( event );
8793 
8794  tool->SetEvtHandlerEnabled( true );
8795  }
8796  }
8797 
8798 
8799 
8800  if ( wxDynamicCast( event.GetEventObject(), a2dDrawWirePolylineLTool ) )
8801  {
8802  if ( m_options & a2dTakeToolstyleFromCmdhOnPush && event.GetId() == a2dStTool::sig_toolPushed )
8803  {
8804  a2dBaseTool* tool = wxStaticCast( event.GetEventObject(), a2dStTool );
8805  }
8806  if ( event.GetId() == a2dStTool::sig_toolPoped )
8807  {
8808  a2dBaseTool* tool = wxStaticCast( event.GetEventObject(), a2dStTool );
8809  }
8810  baseContinue = false;
8811  }
8812  else if ( wxDynamicCast( event.GetEventObject(), a2dDrawPolygonLTool ) )
8813  {
8814  a2dDrawPolygonLTool* tool = wxStaticCast( event.GetEventObject(), a2dDrawPolygonLTool );
8815  a2dHabitat* habitat = tool->GetDrawing()->GetHabitat();
8816  if ( m_options & a2dTakeToolstyleFromCmdhOnPush && event.GetId() == a2dStTool::sig_toolPushed )
8817  {
8818  habitat->SetSpline( tool->GetSpline() );
8819  }
8820  if ( m_options & a2dTakeToolstyleToCmdhOnPush && event.GetId() == a2dStTool::sig_toolPushed )
8821  {
8822  habitat->SetSpline( tool->GetSpline() );
8823  }
8824  }
8825  else if ( wxDynamicCast( event.GetEventObject(), a2dDrawPolylineLTool ) )
8826  {
8827  if ( m_options & a2dTakeToolstyleFromCmdhOnPush && event.GetId() == a2dStTool::sig_toolPushed )
8828  {
8829  a2dDrawPolylineLTool* tool = wxStaticCast( event.GetEventObject(), a2dDrawPolylineLTool );
8830  a2dHabitat* habitat = tool->GetDrawing()->GetHabitat();
8831 
8832  tool->SetSpline( habitat->GetSpline() );
8833  tool->SetLineBegin( habitat->GetLineBegin() );
8834  tool->SetLineEnd( habitat->GetLineEnd() );
8835  tool->SetEndScaleX( habitat->GetEndScaleX() );
8836  tool->SetEndScaleY( habitat->GetEndScaleY() );
8837  }
8838  if ( m_options & a2dTakeToolstyleToCmdhOnPush && event.GetId() == a2dStTool::sig_toolPushed )
8839  {
8840  a2dDrawPolylineLTool* tool = wxStaticCast( event.GetEventObject(), a2dDrawPolylineLTool );
8841  a2dHabitat* habitat = tool->GetDrawing()->GetHabitat();
8842 
8843  habitat->SetSpline( tool->GetSpline() );
8844  habitat->SetLineBegin( tool->GetLineBegin() );
8845  habitat->SetLineEnd( tool->GetLineEnd() );
8846  habitat->SetEndScaleX( tool->GetEndScaleX() );
8847  habitat->SetEndScaleY( tool->GetEndScaleY() );
8848  }
8849  }
8850  else if ( wxDynamicCast( event.GetEventObject(), a2dDrawLineTool ) )
8851  {
8852  if ( m_options & a2dTakeToolstyleFromCmdhOnPush && event.GetId() == a2dStTool::sig_toolPushed )
8853  {
8854  a2dDrawLineTool* tool = wxStaticCast( event.GetEventObject(), a2dDrawLineTool );
8855  a2dHabitat* habitat = tool->GetDrawing()->GetHabitat();
8856 
8857  tool->SetLineBegin( habitat->GetLineBegin() );
8858  tool->SetLineEnd( habitat->GetLineEnd() );
8859  tool->SetEndScaleX( habitat->GetEndScaleX() );
8860  tool->SetEndScaleY( habitat->GetEndScaleY() );
8861  }
8862  if ( m_options & a2dTakeToolstyleToCmdhOnPush && event.GetId() == a2dStTool::sig_toolPushed )
8863  {
8864  a2dDrawPolylineLTool* tool = wxStaticCast( event.GetEventObject(), a2dDrawPolylineLTool );
8865  a2dHabitat* habitat = tool->GetDrawing()->GetHabitat();
8866 
8867  habitat->SetLineBegin( tool->GetLineBegin() );
8868  habitat->SetLineEnd( tool->GetLineEnd() );
8869  habitat->SetEndScaleX( tool->GetEndScaleX() );
8870  habitat->SetEndScaleY( tool->GetEndScaleY() );
8871  }
8872  }
8873  else if ( wxDynamicCast( event.GetEventObject(), a2dDrawTextTool ) )
8874  {
8875  a2dDrawTextTool* tool = wxStaticCast( event.GetEventObject(), a2dDrawTextTool );
8876  a2dHabitat* habitat = tool->GetDrawing()->GetHabitat();
8877  if ( m_options & a2dTakeToolstyleFromCmdhOnPush && event.GetId() == a2dStTool::sig_toolPushed )
8878  {
8879  a2dFont globfont = habitat->GetTextTemplateObject()->GetFont();
8880  tool->GetTemplateObject()->SetFont( globfont );
8881  }
8882  if ( m_options & a2dTakeToolstyleToCmdhOnPush && event.GetId() == a2dStTool::sig_toolPushed )
8883  {
8884  habitat->SetFont( tool->GetTemplateObject()->GetFont() );
8885  }
8886  if ( m_options & a2dTakeToolstyleFromCmdhOnPop && event.GetId() == a2dStTool::sig_toolPoped )
8887  {
8888  tool->GetTemplateObject()->SetFont( habitat->GetTextTemplateObject()->GetFont() );
8889  }
8890  baseContinue = true;
8891  }
8892  else if ( wxDynamicCast( event.GetEventObject(), a2dRecursiveEditTool ) )
8893  {
8894  baseContinue = false;
8895  }
8896  else if ( wxDynamicCast( event.GetEventObject(), a2dObjectEditTool ) )
8897  {
8898  baseContinue = false;
8899  }
8900  else if ( wxDynamicCast( event.GetEventObject(), a2dDragNewTool ) )
8901  {
8902  baseContinue = false;
8903  }
8904 
8905 
8906  if ( baseContinue &&
8907  ( wxDynamicCast( event.GetEventObject(), a2dStDrawTool )
8908  )
8909  )
8910  {
8911  a2dStDrawTool* tool = wxDynamicCast( event.GetEventObject(), a2dStDrawTool );
8912  a2dHabitat* habitat = tool->GetDrawing()->GetHabitat();
8913  a2dDrawTextTool* textTool = wxDynamicCast( tool, a2dDrawTextTool );
8914  //Most Drawing tool takes style of the central global which may have changed by other
8915  //drawing tools or style commands etc.
8916  // Texttool has his own stroke and fill style based on the text template.
8917  if ( textTool )
8918  {
8919  if ( (m_options & a2dTakeToolstyleToCmdhOnPush) && event.GetId() == a2dStTool::sig_toolPushed )
8920  {
8921  habitat->GetTextTemplateObject()->SetFill( tool->GetFill() );
8922  habitat->GetTextTemplateObject()->SetStroke( tool->GetStroke() );
8923  habitat->GetTextTemplateObject()->SetLayer( tool->GetLayer() );
8924  }
8925  if ( (m_options & a2dTakeToolstyleFromCmdhOnPush) && event.GetId() == a2dStTool::sig_toolPushed )
8926  {
8927  a2dBaseTool::PROPID_Fill->SetPropertyToObject( tool, habitat->GetTextTemplateObject()->GetFill() );
8928  a2dBaseTool::PROPID_Stroke->SetPropertyToObject( tool, habitat->GetTextTemplateObject()->GetStroke() );
8929  a2dBaseTool::PROPID_Layer->SetPropertyToObject( tool, habitat->GetTextTemplateObject()->GetLayer() );
8930  }
8931  if ( m_options & a2dTakeToolstyleFromCmdhOnPop && event.GetId() == a2dStTool::sig_toolPoped )
8932  {
8933  a2dBaseTool::PROPID_Fill->SetPropertyToObject( tool, habitat->GetTextTemplateObject()->GetFill() );
8934  a2dBaseTool::PROPID_Stroke->SetPropertyToObject( tool, habitat->GetTextTemplateObject()->GetStroke() );
8935  a2dBaseTool::PROPID_Layer->SetPropertyToObject( tool, habitat->GetTextTemplateObject()->GetLayer() );
8936  }
8937  if ( event.GetId() == a2dStTool::sig_toolPoped )
8938  {
8939  tool->CloseCommandGroup();
8940  }
8941  if ( (m_options & a2dTakeToolstyleToNewObject) && event.GetId() == a2dStTool::sig_toolComEventAddObject )
8942  {
8943  a2dProperty *property = (a2dProperty *) event.GetProperty();
8944  a2dCanvasObject* obj = wxStaticCast( property->GetValue(), a2dCanvasObject );
8945 
8946  if ( obj->GetFilled() )
8947  a2dCanvasObject::PROPID_Fill->SetPropertyToObject( obj, tool->GetFill() );
8948  a2dCanvasObject::PROPID_Stroke->SetPropertyToObject( obj, tool->GetStroke() );
8949  a2dCanvasObject::PROPID_Layer->SetPropertyToObject( obj, tool->GetLayer() );
8950  }
8951  }
8952  else
8953  {
8954  if ( (m_options & a2dTakeToolstyleToCmdhOnPush) && event.GetId() == a2dStTool::sig_toolPushed )
8955  {
8956  habitat->SetFill( tool->GetFill() );
8957  habitat->SetStroke( tool->GetStroke() );
8958  habitat->SetLayer( tool->GetLayer() );
8959  }
8960  if ( (m_options & a2dTakeToolstyleFromCmdhOnPush) && event.GetId() == a2dStTool::sig_toolPushed )
8961  {
8962  a2dBaseTool::PROPID_Fill->SetPropertyToObject( tool, habitat->GetFill() );
8963  a2dBaseTool::PROPID_Stroke->SetPropertyToObject( tool, habitat->GetStroke() );
8964  a2dBaseTool::PROPID_Layer->SetPropertyToObject( tool, habitat->GetLayer() );
8965  }
8966  if ( m_options & a2dTakeToolstyleFromCmdhOnPop && event.GetId() == a2dStTool::sig_toolPoped )
8967  {
8968  a2dBaseTool::PROPID_Fill->SetPropertyToObject( tool, habitat->GetFill() );
8969  a2dBaseTool::PROPID_Stroke->SetPropertyToObject( tool, habitat->GetStroke() );
8970  a2dBaseTool::PROPID_Layer->SetPropertyToObject( tool, habitat->GetLayer() );
8971  }
8972  if ( event.GetId() == a2dStTool::sig_toolPoped )
8973  {
8974  tool->CloseCommandGroup();
8975  }
8976  if ( (m_options & a2dTakeToolstyleToNewObject) && event.GetId() == a2dStTool::sig_toolComEventAddObject )
8977  {
8978  a2dProperty *property = (a2dProperty *) event.GetProperty();
8979  a2dCanvasObject* obj = wxStaticCast( property->GetValue(), a2dCanvasObject );
8980 
8981  if ( obj->GetFilled() )
8982  a2dCanvasObject::PROPID_Fill->SetPropertyToObject( obj, tool->GetFill() );
8983  a2dCanvasObject::PROPID_Stroke->SetPropertyToObject( obj, tool->GetStroke() );
8984  a2dCanvasObject::PROPID_Layer->SetPropertyToObject( obj, tool->GetLayer() );
8985  }
8986  }
8987  }
8988 
8989  a2dStTool* tool = wxDynamicCast( m_stcontroller->GetFirstTool(), a2dStTool );
8990 
8991  if ( tool && tool->GetActive() && tool->GetEvtHandlerEnabled() && tool->GetDrawingPart() )
8992  {
8993  a2dHabitat* habitat = tool->GetDrawing()->GetHabitat();
8994  if ( ( wxDynamicCast( tool, a2dStDrawTool ) || wxDynamicCast( tool, a2dObjectEditTool ) ) &&
8995  ( comId == a2dHabitat::sig_changedFill ||
8996  comId == a2dHabitat::sig_changedStroke ||
8997  comId == a2dHabitat::sig_changedLayer ||
8998  comId == a2dHabitat::sig_changedFont ||
8999  comId == a2dHabitat::sig_changedTextFill ||
9000  comId == a2dHabitat::sig_changedTextStroke ||
9001  comId == a2dHabitat::sig_changedTextFont
9002  )
9003  )
9004  {
9005  //drawing tools set the style to the object that is drawn.
9006  a2dStTool* sttool = wxDynamicCast( tool, a2dStTool );
9007  a2dStDrawTool* drawtool = wxDynamicCast( tool, a2dStDrawTool );
9008  a2dDrawTextTool* textTool = wxDynamicCast( tool, a2dDrawTextTool );
9009  a2dObjectEditTool* editTool = wxDynamicCast( tool, a2dObjectEditTool );
9011 
9012  if ( !textTool )
9013  {
9014  if ( editTool && editTool->GetBusy() )
9015  {
9016  a2dText* text = wxDynamicCast( editTool->m_original.Get() , a2dText );
9017  if ( text )
9018  {
9019  a2dText* textcopy = wxStaticCast( editTool->m_canvasobject.Get() , a2dText );
9020  text->SetFont( habitat->GetTextFont() );
9021  text->SetStroke( habitat->GetTextStroke() );
9022  text->SetFill( habitat->GetTextFill() );
9023  textcopy->SetFont( habitat->GetTextFont() );
9024  textcopy->SetStroke( habitat->GetTextStroke() );
9025  textcopy->SetFill( habitat->GetTextFill() );
9026  }
9027  else
9028  {
9029  a2dCanvasObject* original = editTool->m_original;
9030  a2dCanvasObject* copy = editTool->m_canvasobject;
9031  original->SetStroke( habitat->GetStroke() );
9032  original->SetFill( habitat->GetFill() );
9033  copy->SetStroke( habitat->GetStroke() );
9034  copy->SetFill( habitat->GetFill() );
9035  }
9036  }
9037  else
9038  {
9039  a2dFill f = habitat->GetFill();
9040  if ( comId == a2dHabitat::sig_changedFill && ! tool->GetFill().IsSameAs( f ) )
9041  {
9042  tool->SetFill( f );
9043  if ( tool->GetBusy() )
9044  docCmdh->Submit( new a2dCommand_ChangeCanvasObjectStyle( sttool->m_original, f ) );
9045  }
9046  a2dStroke s = habitat->GetStroke();
9047  if ( comId == a2dHabitat::sig_changedStroke && ! tool->GetStroke().IsSameAs( s ) )
9048  {
9049  tool->SetStroke( s );
9050  if ( tool->GetBusy() )
9051  docCmdh->Submit( new a2dCommand_ChangeCanvasObjectStyle( sttool->m_original, s ) );
9052  }
9053  }
9054  }
9055  else //textTool
9056  {
9057  a2dFont font = habitat->GetTextFont();
9058  if ( ! textTool->GetTemplateObject()->GetFont().IsSameAs( font ) )
9059  {
9060  textTool->GetTemplateObject()->SetFont( habitat->GetTextFont() );
9061  }
9062  //special stroke and fill for text objects.
9063  a2dFill f = habitat->GetTextFill();
9064  if ( comId == a2dHabitat::sig_changedTextFill && ! tool->GetFill().IsSameAs( f ) )
9065  {
9066  tool->SetFill( f );
9067  if ( tool->GetBusy() )
9068  docCmdh->Submit( new a2dCommand_ChangeCanvasObjectStyle( sttool->m_original, f ) );
9069  }
9070  a2dStroke s = habitat->GetTextStroke();
9071  if ( comId == a2dHabitat::sig_changedTextStroke && ! tool->GetStroke().IsSameAs( s ) )
9072  {
9073  tool->SetStroke( s );
9074  if ( tool->GetBusy() )
9075  docCmdh->Submit( new a2dCommand_ChangeCanvasObjectStyle( sttool->m_original, s ) );
9076  }
9077  }
9078 
9079  if ( comId == a2dHabitat::sig_changedLayer && tool->GetLayer() != habitat->GetLayer() )
9080  {
9081  tool->SetLayer( habitat->GetLayer() );
9082  if ( drawtool && drawtool->m_original )
9083  {
9084  drawtool->m_original->SetLayer( habitat->GetLayer() );
9085  }
9086  if ( editTool && editTool->m_original )
9087  {
9088  editTool->m_original->SetLayer( habitat->GetLayer() );
9089  }
9090  }
9091  if ( comId == a2dHabitat::sig_changedFont )
9092  {
9093  if ( editTool && editTool->GetBusy() )
9094  {
9095  a2dText* text = wxDynamicCast( editTool->m_original.Get() , a2dText );
9096  if ( text )
9097  {
9098  a2dText* textcopy = wxStaticCast( editTool->m_canvasobject.Get() , a2dText );
9099  text->SetFont( habitat->GetFont() );
9100  textcopy->SetFont( habitat->GetFont() );
9101  }
9102  }
9103  }
9104  }
9105  else if ( comId == a2dHabitat::sig_changedTextFont && wxDynamicCast( tool, a2dDrawTextTool ) )
9106  {
9107  a2dDrawTextTool* textTool = wxDynamicCast( tool, a2dDrawTextTool );
9108  a2dHabitat* habitat = textTool->GetDrawing()->GetHabitat();
9109  a2dFont font = habitat->GetTextFont();
9110  if ( ! textTool->GetTemplateObject()->GetFont().IsSameAs( font ) )
9111  {
9112  textTool->GetTemplateObject()->SetFont( habitat->GetTextFont() );
9113  }
9114  }
9115  else if ( wxDynamicCast( tool, a2dDrawPolylineLTool ) )
9116  {
9117  a2dDrawPolylineLTool* toolt = wxStaticCast( tool, a2dDrawPolylineLTool );
9118  a2dHabitat* habitat = toolt->GetDrawing()->GetHabitat();
9119 
9120  if ( toolt->GetAllowModifyTemplate() )
9121  {
9122  if ( toolt->GetSpline() != habitat->GetSpline() )
9123  toolt->SetSpline( habitat->GetSpline() );
9124  if ( toolt->GetLineBegin() != habitat->GetLineBegin() )
9125  toolt->SetLineBegin( habitat->GetLineBegin() );
9126  if ( toolt->GetLineEnd() != habitat->GetLineEnd() )
9127  toolt->SetLineEnd( habitat->GetLineEnd() );
9128  if ( toolt->GetEndScaleX() != habitat->GetEndScaleX() )
9129  toolt->SetEndScaleX( habitat->GetEndScaleX() );
9130  if ( toolt->GetEndScaleY() != habitat->GetEndScaleY() )
9131  toolt->SetEndScaleY( habitat->GetEndScaleY() );
9132  toolt->SetContourWidth( habitat->GetContourWidth() );
9133  }
9134  }
9135  else if ( wxDynamicCast( tool, a2dDrawLineTool ) )
9136  {
9137  a2dDrawLineTool* toolt = wxStaticCast( tool, a2dDrawLineTool );
9138  a2dHabitat* habitat = toolt->GetDrawing()->GetHabitat();
9139 
9140  if ( toolt->GetAllowModifyTemplate() )
9141  {
9142  if ( toolt->GetLineBegin() != habitat->GetLineBegin() )
9143  toolt->SetLineBegin( habitat->GetLineBegin() );
9144  if ( toolt->GetLineEnd() != habitat->GetLineEnd() )
9145  toolt->SetLineEnd( habitat->GetLineEnd() );
9146  if ( toolt->GetEndScaleX() != habitat->GetEndScaleX() )
9147  toolt->SetEndScaleX( habitat->GetEndScaleX() );
9148  if ( toolt->GetEndScaleY() != habitat->GetEndScaleY() )
9149  toolt->SetEndScaleY( habitat->GetEndScaleY() );
9150  toolt->SetContourWidth( habitat->GetContourWidth() );
9151  }
9152  }
9153  /*
9154  if ( event.GetId() == &a2dComEvent::sm_changedProperty && *(m_propertiesTakeFromCommandProc.Find( (a2dPropertyId*) &(event.GetProperty()->GetId()) )) )
9155  {
9156  event.GetProperty()->SetToObjectClone( this );
9157  tool->SetPending(true);
9158  }
9159  if ( tool->GetBusy() && event.GetId() == &a2dComEvent::sm_changedProperty && *(m_propertiesSetToOriginalObject.Find( (a2dPropertyId*) &(event.GetProperty()->GetId()) )) )
9160  {
9161  if ( tool->m_original )
9162  event.GetProperty()->SetToObjectClone( tool->m_original );
9163 
9164  tool->SetPending(true);
9165  }
9166  if ( tool->GetBusy() && event.GetId() == &a2dComEvent::sm_changedProperty && *(m_propertiesSetToEditObject.Find( (a2dPropertyId*) &(event.GetProperty()->GetId()) )) )
9167  {
9168  if ( tool->m_canvasobject )
9169  event.GetProperty()->SetToObjectClone( tool->m_canvasobject );
9170 
9171  tool->SetPending(true);
9172  }
9173  */
9174  event.Skip();
9175 
9176  }
9177  event.Skip();
9178 
9179 }
9180 
9181 void a2dStToolEvtHandler::OnDoEvent( a2dCommandProcessorEvent& event )
9182 {
9184  const a2dCommandId* comId = event.GetCommand()->GetCommandId();
9185  if ( tool && tool->GetActive() && tool->GetEvtHandlerEnabled() && tool->GetDrawingPart() )
9186  {
9187  if ( ( wxDynamicCast( tool, a2dStDrawTool ) || wxDynamicCast( tool, a2dObjectEditTool ) ) )
9188  {
9189 
9190  //drawing tools set the style to the object that is drawn.
9191  a2dStTool* sttool = wxDynamicCast( tool, a2dStTool );
9192  a2dStDrawTool* drawtool = wxDynamicCast( tool, a2dStDrawTool );
9193  a2dObjectEditTool* editTool = wxDynamicCast( tool, a2dObjectEditTool );
9195  }
9196  }
9197  event.Skip();
9198 }
9199 
9200 void a2dStToolEvtHandler::OnUndoEvent( a2dCommandProcessorEvent& event )
9201 {
9203  if ( tool && tool->GetActive() && tool->GetEvtHandlerEnabled() && tool->GetDrawingPart() )
9204  {
9205  if ( wxDynamicCast( tool, a2dObjectEditTool ) )
9206  {
9207  }
9208  }
9209  event.Skip();
9210 
9211 }
9212 
9213 void a2dStToolEvtHandler::OnRedoEvent( a2dCommandProcessorEvent& event )
9214 {
9215  OnUndoEvent( event );
9216  event.Skip();
9217 }
9218 
9219 //-----------------------------------------------------------
9220 // a2dStToolFixedToolStyleEvtHandler
9221 //-----------------------------------------------------------
9222 
9224  EVT_KEY_DOWN( a2dStToolFixedToolStyleEvtHandler::OnKeyDown )
9225  EVT_KEY_UP( a2dStToolFixedToolStyleEvtHandler::OnKeyUp )
9230 END_EVENT_TABLE()
9231 
9233 {
9234  m_stcontroller = controller;
9235  m_takeToolstyleToCmdhOnPush = false;
9236 }
9237 
9239 {
9240 }
9241 
9242 void a2dStToolFixedToolStyleEvtHandler::OnKeyDown( wxKeyEvent& event )
9243 {
9245  switch( event.GetKeyCode() )
9246  {
9247  case 'Z':
9248  case 'z':
9249  {
9250  if ( !first || ( first && !first->GetBusy() ) )
9251  {
9252  if ( event.m_controlDown && event.m_shiftDown )
9253  first->GetCanvasCommandProcessor()->Redo();
9254  else if ( event.m_controlDown )
9255  first->GetCanvasCommandProcessor()->Undo();
9256  else
9257  event.Skip();
9258  }
9259  else
9260  event.Skip();
9261  break;
9262  }
9263  case 'Y':
9264  case 'y':
9265  {
9266  if ( !first || ( first && !first->GetBusy() ) )
9267  {
9268  if ( event.m_controlDown )
9269  first->GetCanvasCommandProcessor()->Redo();
9270  else
9271  event.Skip();
9272  }
9273  else
9274  event.Skip();
9275  break;
9276  }
9277  default:
9278  event.Skip();
9279  }
9280 }
9281 
9282 void a2dStToolFixedToolStyleEvtHandler::OnKeyUp( wxKeyEvent& event )
9283 {
9284  event.Skip();
9285 }
9286 
9287 void a2dStToolFixedToolStyleEvtHandler::OnComEvent( a2dComEvent& event )
9288 {
9289  if ( event.GetId() == a2dBaseTool::sig_toolBeforePush )
9290  {
9291  a2dNamedProperty* prop = event.GetProperty();
9292  a2dStTool* tool = wxDynamicCast( prop->GetRefObject(), a2dStTool ); //tool pushed
9293  if ( !wxDynamicCast( tool, a2dCopyMultiTool ) &&
9294  !wxDynamicCast( tool, a2dDragMultiTool ) &&
9295  !wxDynamicCast( tool, a2dFastDragMultiTool ) &&
9296  !wxDynamicCast( tool, a2dFastCopyMultiTool ) &&
9297  !wxDynamicCast( tool, a2dSelectTool )
9298  )
9299  {
9303  objects->SetSpecificFlags( false, a2dCanvasOFlags::SELECTED );
9304  objects->SetSpecificFlags( false, a2dCanvasOFlags::SELECTED2 );
9305  tool->GetParentObject()->GetRoot()->SetUpdatesPending( true );
9306  }
9307  return;
9308  }
9309 
9310  bool baseContinue = true;
9311  if ( baseContinue && wxDynamicCast( event.GetEventObject(), a2dStDrawTool ) )
9312  {
9313  //Most Drawing tool takes style of the commandprocessor which may have change by other
9314  //drawing tools or style commands etc.
9315  a2dStDrawTool* tool = wxDynamicCast( event.GetEventObject(), a2dStDrawTool );
9316  if ( m_takeToolstyleToCmdhOnPush && event.GetId() == a2dStTool::sig_toolPushed )
9317  {
9318  a2dHabitat* habitat = tool->GetDrawing()->GetHabitat();
9319  habitat->SetFill( tool->GetFill() );
9320  habitat->SetStroke( tool->GetStroke() );
9321  }
9322  if ( event.GetId() == a2dStTool::sig_toolPoped )
9323  {
9324  tool->CloseCommandGroup();
9325  }
9326  if ( event.GetId() == a2dStTool::sig_toolComEventAddObject )
9327  {
9328  a2dProperty* property = ( a2dProperty* ) event.GetProperty();
9329  a2dCanvasObject* obj = wxStaticCast( property->GetValue(), a2dCanvasObject );
9330 
9331  a2dCanvasObject::PROPID_Fill->SetPropertyToObject( obj, tool->GetFill() );
9332  a2dCanvasObject::PROPID_Stroke->SetPropertyToObject( obj, tool->GetStroke() );
9333  }
9334  }
9335  event.Skip();
9336 }
9337 
9338 void a2dStToolFixedToolStyleEvtHandler::OnDoEvent( a2dCommandProcessorEvent& event )
9339 {
9340  /*
9341  a2dBaseTool* tool = m_stcontroller->GetFirstTool();
9342  if ( tool->GetActive() && tool->GetEvtHandlerEnabled() && tool->GetDrawingPart())
9343  {
9344  }
9345  */
9346  event.Skip();
9347 }
9348 
9349 void a2dStToolFixedToolStyleEvtHandler::OnUndoEvent( a2dCommandProcessorEvent& event )
9350 {
9351  event.Skip();
9352 
9353 }
9354 
9355 void a2dStToolFixedToolStyleEvtHandler::OnRedoEvent( a2dCommandProcessorEvent& event )
9356 {
9357  event.Skip();
9358 }
9359 
9360 
9361 
9362 
9363 
9364 
9365 
9366 
9367 
9368 
9369 
9370 
9371 BEGIN_EVENT_TABLE( a2dDrawVPathTool, a2dStDrawTool )
9372  EVT_IDLE( a2dDrawVPathTool::OnIdle )
9373  EVT_CHAR( a2dDrawVPathTool::OnChar )
9374  EVT_MOUSE_EVENTS( a2dDrawVPathTool::OnMouseEvent )
9375  EVT_UNDO( a2dDrawVPathTool::OnUndoEvent )
9376  EVT_REDO( a2dDrawVPathTool::OnRedoEvent )
9377 END_EVENT_TABLE()
9378 
9379 void a2dDrawVPathTool::AddSegment( a2dVpathSegment* segment )
9380 {
9381  if ( m_reverse )
9382  m_vpath->Add( segment );
9383  else
9384  m_vpath->Add( segment );
9385 }
9386 
9387 a2dDrawVPathTool::a2dDrawVPathTool( a2dStToolContr* controller, a2dVectorPath* templateObject ): a2dStDrawTool( controller )
9388 {
9389  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_PENCIL );
9390  m_toolBusyCursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_CROSS );
9392  m_segment = NULL;
9393 
9395  m_vpath = ( a2dVpath* ) 0;
9396 
9397  m_reverse = false;
9398  m_controlSet = false;
9399 
9400  m_templateObject = templateObject;
9401  m_controlPoints = NULL;
9402 }
9403 
9404 a2dDrawVPathTool::~a2dDrawVPathTool()
9405 {
9406 }
9407 
9408 void a2dDrawVPathTool::OnIdle( wxIdleEvent& event )
9409 {
9410  if ( m_pending && GetBusy() )
9411  {
9413 
9415  a2dRect* around = NULL;
9416 
9417  switch ( m_mode )
9418  {
9419  case 0:
9420  {
9421  //a nice to see normal polygon around it and if stroke transparent show it.
9422  if ( m_segment && m_bezier )
9423  {
9424  m_controlPoints = new a2dPolylineL();
9425  m_controlPoints->AddPoint( m_segmentPrev->m_x1, m_segmentPrev->m_y1 );
9427  m_controlPoints->AddPoint( seg->m_x2, seg->m_y2 );
9428  m_controlPoints->AddPoint( seg->m_x3, seg->m_y3 );
9429  m_controlPoints->AddPoint( m_segment->m_x1, m_segment->m_y1 );
9430  m_controlPoints->SetVisible( true );
9431  m_controlPoints->SetFill( *a2dTRANSPARENT_FILL );
9432  //m_controlPoints->SetStroke( *wxRED, 0, a2dSTROKE_DOT_DASH );
9433  m_controlPoints->SetStroke( *wxRED, 0, a2dSTROKE_SOLID );
9434  AddDecorationObject( m_controlPoints );
9435  }
9436  break;
9437  }
9438  case 1:
9439  {
9440  around = new a2dRect( path->GetBboxMinX(), path->GetBboxMinY(), path->GetBboxWidth(), path->GetBboxHeight() );
9441  around->SetStroke( *wxRED, 0, a2dSTROKE_DOT_DASH );
9442  around->SetFill( *a2dTRANSPARENT_FILL );
9443  around->SetRoot( GetDrawingPart()->GetDrawing(), false );
9444  AddDecorationObject( around );
9445  break;
9446  }
9447  default:
9448  break;
9449  }
9450 
9451  event.Skip();
9452  }
9453  else
9454  event.Skip();
9455 }
9456 
9457 void a2dDrawVPathTool::OnUndoEvent( a2dCommandProcessorEvent& WXUNUSED( event ) )
9458 {
9459  if ( GetBusy() && !m_halted )
9460  {
9461  // recreate edit copies so the edit copy becomes updated from the original.
9462 
9464  if ( ! path->IsEmpty() )
9465  {
9466  a2dVpathSegment* lastpoint = path->GetSegments()->back();
9467 
9471  m_vpath = wxStaticCast( m_canvasobject.Get(), a2dVectorPath )->GetSegments();
9472  m_segment = lastpoint->Clone();
9473  m_vpath->push_back( m_segment );
9474  }
9475  }
9476 }
9477 
9478 void a2dDrawVPathTool::OnRedoEvent( a2dCommandProcessorEvent& event )
9479 {
9480  OnUndoEvent( event );
9481 }
9482 
9484 {
9485  m_mode = mode;
9486  if ( m_mode > 2 ) m_mode = 0;
9487 
9488  if ( !m_canvasobject )
9489  return;
9490 
9491  m_pending = true;
9492 }
9493 
9494 void a2dDrawVPathTool::OnChar( wxKeyEvent& event )
9495 {
9496  if ( GetBusy() && m_canvasobject )
9497  {
9498  double shiftx;
9499  double shifty;
9500  GetKeyIncrement( &shiftx, &shifty );
9501 
9502  switch( event.GetKeyCode() )
9503  {
9504  case WXK_TAB:
9505  {
9506  m_mode++;
9507  SetMode( m_mode );
9508  }
9509  break;
9510 
9511  case WXK_UP:
9512  shiftx = 0;
9513  break;
9514 
9515  case WXK_DOWN:
9516  shiftx = 0;
9517  shifty = -shifty;
9518  break;
9519 
9520  case WXK_LEFT:
9521  shiftx = -shiftx;
9522  shifty = 0;
9523  break;
9524 
9525  case WXK_RIGHT:
9526  shifty = 0;
9527  break;
9528 
9529  default:
9530  {
9531  shiftx = 0;
9532  shifty = 0;
9533  event.Skip();
9534  }
9535  }
9536 
9537  if ( event.m_controlDown )
9538  {
9539  m_segment->m_x1 += shiftx;
9540  m_segment->m_y1 += shifty;
9541  }
9542  else
9543  {
9544  double x = m_canvasobject->GetPosX();
9545  double y = m_canvasobject->GetPosY();
9546  m_canvasobject->SetPosXY( x + shiftx, y + shifty, true );
9548  path->EliminateMatrix();
9549  }
9550 
9551  GetDisplayWindow()->WarpPointer( GetDrawer2D()->WorldToDeviceX( m_segment->m_x1 ), GetDrawer2D()->WorldToDeviceY( m_segment->m_y1 ) );
9552 
9553  m_pending = true;
9554  }
9555  else
9556  event.Skip();
9557 
9558 }
9559 
9560 void a2dDrawVPathTool::OnMouseEvent( wxMouseEvent& event )
9561 {
9562  if ( !m_active )
9563  {
9564  event.Skip();
9565  return;
9566  }
9567 
9568  if ( GetBusy() )
9569  GetDrawingPart()->SetCursor( m_toolBusyCursor );
9570  else
9571  GetDrawingPart()->SetCursor( m_toolcursor );
9572 
9573  m_x = event.GetX();
9574  m_y = event.GetY();
9575  MouseToToolWorld( m_x, m_y, m_xwprev, m_ywprev );
9576 
9577  a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
9578  if( restrict )
9579  restrict->RestrictPoint( m_xwprev, m_ywprev );
9580  if ( event.LeftDown() && !GetBusy() )
9581  {
9582  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
9583  if ( m_templateObject )
9584  {
9586  m_original->Translate( m_xwprev, m_ywprev );
9588  }
9589  else
9590  {
9591  m_original = new a2dVectorPath();
9596  }
9597 
9598  if ( !EnterBusyMode() )
9599  return;
9603  /*
9604  // Append first point to original
9605  GetCanvasCommandProcessor()->Submit(
9606  new a2dCommand_AddPoint( m_original, m_xwprev, m_ywprev, -1 )
9607  );
9608  */
9609  path->Add( new a2dVpathSegment( m_xwprev, m_ywprev, a2dPATHSEG_MOVETO ) );
9610 
9611 
9612  // Append first point to editcopy
9614  m_vpath = pathedit->GetSegments();
9615  m_segmentPrev = new a2dVpathSegment( m_xwprev, m_ywprev, a2dPATHSEG_MOVETO );
9616  m_vpath->Add( m_segmentPrev );
9617  m_segment = new a2dVpathCBCurveSegment( m_xwprev, m_ywprev, m_xwprev, m_ywprev, m_xwprev, m_ywprev );
9618  m_vpath->Add( m_segment );
9619 
9620  // Record commands
9621  a2dGeneralGlobals->RecordF( this, _T( "polygon" ) );
9622  a2dGeneralGlobals->RecordF( this, _T( "addpoint %f %f" ), m_xwprev, m_ywprev );
9623 
9624  m_prev_x = m_xwprev;
9625  m_prev_y = m_ywprev;
9628  m_pending = true;
9629  m_controlSet = false;
9630  m_endSegment = false;
9631  m_bezier = false;
9632  if( restrict )
9633  restrict->SetRestrictPoint( m_xwprev, m_ywprev );
9634  }
9635  else if ( event.LeftDown() && GetBusy() )
9636  {
9637  if ( m_segmentPrev->m_x1 == m_xwprev && m_segmentPrev->m_y1 == m_ywprev )
9638  m_controlSet = false;
9639  else if ( !m_bezier && !m_endSegment )
9640  {
9641  m_controlSet = true;
9644  }
9645  }
9646  else if ( event.LeftUp() && GetBusy() )
9647  {
9648  if ( m_segmentPrev->m_x1 == m_xwprev && m_segmentPrev->m_y1 == m_ywprev )
9649  {
9650  }
9651  else if ( m_bezier && !m_controlSet )
9652  {
9653  m_controlSet = true;
9656  m_endSegment = true;
9657  }
9658  else if ( m_bezier && m_controlSet && !m_endSegment )
9659  {
9660  m_endSegment = true;
9661  }
9662  else if ( !m_bezier || ( m_bezier && m_endSegment ) )
9663  {
9664  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
9665  int x = GetDrawer2D()->WorldToDeviceX( m_prev_x );
9666  int y = GetDrawer2D()->WorldToDeviceY( m_prev_y );
9667  if ( abs( m_x - x ) >= 3 || abs( m_y - y ) >= 3 )
9668  {
9669  /*
9670  GetCanvasCommandProcessor()->Submit(
9671  new a2dCommand_AddPoint( m_original, m_xwprev, m_ywprev, -1 )
9672  );
9673 
9674  a2dGeneralGlobals->RecordF( this, _T("addpoint %f %f "), m_xwprev, m_ywprev );
9675  */
9677  path->Add( m_segment->Clone() );
9678 
9679  m_segmentPrev = m_segment;
9680 
9681  m_segment = new a2dVpathCBCurveSegment( m_xwprev, m_ywprev, m_xwprev, m_ywprev, m_xwprev, m_ywprev );
9682  //m_segment = new a2dVpathSegment(m_xwprev,m_ywprev);
9683  m_vpath->Add( m_segment );
9684  m_prev_x = m_xwprev;
9685  m_prev_y = m_ywprev;
9686  m_controlSet = false;
9687  m_endSegment = false;
9688  m_bezier = false;
9689  }
9690  m_pending = true;
9691  if( restrict )
9692  restrict->SetRestrictPoint( m_xwprev, m_ywprev );
9693  }
9694  }
9695  else if ( event.Moving() && GetBusy() )
9696  {
9697  m_segment->m_x1 = m_xwprev;
9698  m_segment->m_y1 = m_ywprev;
9699  m_canvasobject->SetPending( true );
9700  m_original->SetPending( true );
9701  m_pending = true;
9702  event.Skip();
9703  }
9704  else if ( event.Dragging() && GetBusy() )
9705  {
9706  m_bezier = true;
9707  if ( !m_endSegment )
9708  {
9709  double dx = m_xwprev - m_contrmid_x;
9710  double dy = m_ywprev - m_contrmid_y;
9712  if ( !m_controlSet )
9713  {
9714  seg->m_x2 = m_xwprev;
9715  seg->m_y2 = m_ywprev;
9716  }
9717  else
9718  {
9719  seg->m_x2 = m_contrmid_x - dx;
9720  seg->m_y2 = m_contrmid_y - dy;
9721  }
9722  seg->m_x3 = m_xwprev;
9723  seg->m_y3 = m_ywprev;
9724  seg->m_x1 = m_xwprev + 1;
9725  seg->m_y1 = m_ywprev + 1;
9726  }
9727  else
9728  {
9729  m_segment->m_x1 = m_xwprev;
9730  m_segment->m_y1 = m_ywprev;
9731  }
9732  m_canvasobject->SetPending( true );
9733  m_pending = true;
9734  event.Skip();
9735  }
9736  else if ( event.LeftDClick() && GetBusy() )
9737  {
9738  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
9739  a2dGeneralGlobals->RecordF( this, _T( "end" ) );
9740  FinishBusyMode();
9741  }
9742  else
9743  event.Skip();
9744 }
9745 
9746 BEGIN_EVENT_TABLE( a2dMovePinTool, a2dDragTool )
9747  EVT_MOUSE_EVENTS( a2dMovePinTool::OnMouseEvent )
9748  EVT_CHAR( a2dMovePinTool::OnChar )
9749 END_EVENT_TABLE()
9750 
9751 a2dMovePinTool::a2dMovePinTool( a2dStToolContr* controller, a2dPin* dragPin, double xw, double yw, bool disConnectFirst )
9752  : a2dDragTool( controller )
9753 {
9754  m_deleteonoutsidedrop = false;
9755  m_eventHandler = controller->GetDefaultToolEventHandlerFixedStyle();
9756 
9757 
9758  m_snapSourceFeatures = a2dRestrictionEngine::snapToPins;
9759 
9760  //only modes which are usefull in dragging
9761  m_snapTargetFeatures =
9762  a2dRestrictionEngine::snapToGridPos |
9765 
9766  m_dragPin = dragPin;
9767 
9768  SetFill( *a2dTRANSPARENT_FILL );
9769  SetStroke( a2dStroke( *wxRED, 1, a2dSTROKE_SOLID ) );
9770 
9771  if ( dragPin )
9772  {
9773  if ( disConnectFirst && m_dragPin && m_dragPin->FindNonWirePin() )
9774  {
9775  OpenCommandGroup( false );
9776  m_dragPin->GetParent()->DisConnectAt( m_dragPin, true );
9777  }
9778 
9779  GetDrawingPart()->ToolWorldToMouse( xw, yw, m_x, m_y );
9780 
9781  GetDrawing()->GetHabitat()->SetLastXyEntry( xw, yw );
9782 
9783  m_dragPinObj = new a2dRectC( xw, yw, 4*GetHitMargin(), 4*GetHitMargin() );
9784  m_dragPinObj->SetAlgoSkip( true );
9785 
9786  m_dragPinObjPin = wxStaticCast( dragPin->Clone( clone_deep ), a2dPin );
9787  m_dragPinObjPin->SetTemporaryPin( false );
9788  m_dragPinObjPin->SetPosXY( 0, 0 );
9789  m_dragPinObjPin->SetInternal( true );
9790  m_dragPinObjPin->SetParent( m_dragPinObj );
9791  m_dragPinObj->Append( m_dragPinObjPin );
9792  m_dragPinObj->HasPins( true );
9793  m_dragPinObj->SetSelected( true );
9794  m_dragPinObj->SetFill( m_fill );
9795  m_dragPinObj->SetStroke( m_stroke );
9796  dragPin->DuplicateConnectedToOtherPins( false );
9797  dragPin->ConnectTo( m_dragPinObjPin );
9798  m_dragPinObjPin->DuplicateConnectedPins( dragPin );
9799  GetDrawingPart()->GetShowObject()->Append( m_dragPinObj );
9800 
9801  if ( !StartDragging( m_x, m_y, m_dragPinObj ) )
9802  return;
9803  }
9804 }
9805 
9807 {
9808 }
9809 
9810 void a2dMovePinTool::OnEnter( wxMouseEvent& WXUNUSED( event ) )
9811 {
9812  if ( GetDrawingPart()->GetDisplayWindow() && !GetDrawingPart()->GetDisplayWindow()->HasFocus() )
9813  GetDrawingPart()->GetDisplayWindow()->SetFocus();
9814 }
9815 
9816 void a2dMovePinTool::OnMouseEvent( wxMouseEvent& event )
9817 {
9818  if ( !m_active )
9819  {
9820  event.Skip();
9821  return;
9822  }
9823 
9824  m_x = event.GetX();
9825  m_y = event.GetY();
9826 
9827  //to world coordinates to do hit test in world coordinates
9828  MouseToToolWorld( m_x, m_y, m_xwprev, m_ywprev );
9829 
9830  //a2dRestrictionEngine* restrict = GetDrawing()->GetHabitat()->GetRestrictionEngine();
9831  //if( restrict )
9832  // restrict->RestrictPoint( m_xwprev, m_ywprev );
9833 
9834  if( event.LeftDown() && !GetBusy() )
9835  {
9836  m_dragPin = GetDrawing()->GetHabitat()->GetConnectionGenerator()->
9837  SearchPinForStartWire( GetDrawingPart()->GetShowObject(), m_xwprev, m_ywprev, a2dPinClass::Any, GetHitMargin() );
9838 
9839  if ( m_dragPin )
9840  {
9841  GetDrawing()->GetHabitat()->SetLastXyEntry( m_xwprev, m_ywprev );
9842 
9843  m_dragPinObj = new a2dRectC( m_xwprev, m_ywprev, 4*GetHitMargin(), 4*GetHitMargin() );
9844  m_dragPinObj->SetAlgoSkip( true );
9845 
9846  m_dragPinObjPin = wxStaticCast( m_dragPin->Clone( clone_deep ), a2dPin );
9847  m_dragPinObjPin->SetTemporaryPin( false );
9848  m_dragPinObjPin->SetPosXY( 0, 0 );
9849  m_dragPinObjPin->SetInternal( true );
9852  m_dragPinObj->HasPins( true );
9853  m_dragPinObj->SetSelected( true );
9854  m_dragPin->DuplicateConnectedToOtherPins( false );
9855  m_dragPin->ConnectTo( m_dragPinObjPin );
9858 
9859  if ( !StartDragging( m_x, m_y, m_dragPinObj ) )
9860  return;
9861  }
9862  }
9863  else if ( event.RightDown() )
9864  {
9865  event.Skip();
9866  }
9867  else if ( event.LeftUp() )
9868  {
9869  a2dDragTool::OnMouseEvent( event );
9871  }
9872  else
9873  {
9874  // all the rest is as with a usual drag
9875  a2dDragTool::OnMouseEvent( event );
9876  }
9877 }
9878 
9880 {
9881  // we generally don't want the original to be visible, regardless of the mode
9882  // this is because the original was cloned from the template object, and is not a
9883  // true original object
9884  m_renderOriginal = false;
9885 }
9886 
9887 void a2dMovePinTool::DoStopTool( bool WXUNUSED( abort ) )
9888 {
9889  // a a2dMovePinTool can be stopped, even if it is busy. This is because the
9890  // tool can be busy with mouse up.
9891  if( GetBusy() )
9892  {
9893  wxASSERT( m_original );
9894  AbortBusyMode();
9895  }
9896 
9897  if ( m_commandgroup )
9899 }
9900 
9902 {
9904  return false;
9905 
9906  // we don't want the mouse to be captured, so undo this
9907  ReleaseMouse();
9908 
9909  // Note: there is no need to overload Finish/AbortBusyMode,
9910  // because the base class stores if it did capture the mouse
9911 
9912  return true;
9913 }
9914 
9915 void a2dMovePinTool::FinishBusyMode( bool closeCommandGroup )
9916 {
9917  m_dragPinObj->SetRelease( true );
9918 
9919  //restore connect backup
9921  ReleaseMouse();
9922 
9923  //the next has internal the functionality to connect object pins to objectpins which now can connect.
9925  new a2dCommand_SetCanvasProperty( m_original, a2dCanvasObject::PROPID_TransformMatrix, m_canvasobject->GetTransformMatrix() )
9926  );
9927  GetDrawing()->GetHabitat()->GetConnectionGenerator()->RerouteWires( true );
9928 
9929  a2dCanvasObjectPtr parentObjDragPin = m_dragPin->GetParent();
9930  parentObjDragPin->SetAlgoSkip( true );
9931  m_original->SetAlgoSkip( true );
9932  m_canvasobject->SetAlgoSkip( true );
9933 
9934  double hitDistance = GetHitMargin()/10.0; //make more accurate
9935  //double hitDistance = GetDrawing()->GetHabitat()->GetCoordinateEpsilon();//make more accurate
9936  a2dPin* pinother = m_dragPin->GetPinClass()->GetConnectionGenerator()->
9937  SearchPinForFinishWire( GetDrawingPart()->GetShowObject(), m_dragPin, NULL, hitDistance );
9938 
9939  if ( pinother && ! m_dragPin->IsConnectedTo( pinother ) )
9940  {
9941  GetCanvasCommandProcessor()->Submit( new a2dCommand_ConnectPins( m_dragPin, pinother ), true );
9942  }
9943 
9944  parentObjDragPin->SetAlgoSkip( false );
9945  m_original->SetAlgoSkip( false );
9946  m_canvasobject->SetAlgoSkip( false );
9947 
9948  //m_dragPin->DuplicateConnectedPins( m_dragPinObjPin, true );
9950 
9952 }
9953 
9955 {
9956  m_dragPinObj->SetRelease( true );
9957 
9959  ReleaseMouse();
9960  GetDrawing()->GetHabitat()->GetConnectionGenerator()->RerouteWires( true );
9962 }
can be used to set style to the a2dCentralCanvasCommandProcessor
Definition: sttool.h:2310
Prevent cloning a a2dCameleon reference at a deeper level.
Definition: gen.h:1219
static const a2dCanvasObjectFlagsMask SELECTED2
Definition: candefs.h:181
a2dStroke GetTextStroke() const
get the current text stroke
Definition: canglob.cpp:1025
double GetEndScaleX()
get scaling in X for begin and end objects of lines and polylines
Definition: sttool.h:1472
Display Part of a a2dDrawing, in which a2dCanvasObjects are shown.
Definition: drawer.h:470
int m_mouse_x
mouse position
Definition: sttool.h:735
bool m_renderEditcopy
if yes, the editcopy is rendered in place
Definition: sttool.h:400
virtual void GenerateAnotation()
to display a string along with a tool drawing.
Definition: sttool.cpp:1978
void PushCursor(const wxCursor &cursor)
push a cursor on the cursor stack, and set display cursor to new back being cursor.
Definition: drawer.cpp:1052
editing an object, its style becomes the central style.
Definition: sttool.h:2323
int WorldToDeviceXRel(double x) const
convert x relative from world to device coordinates
Definition: drawer2d.h:460
a2dCircle at x,y, and with radius
Definition: canprim.h:554
perform snapping to boundingbox of objects
Definition: restrict.h:137
wxPoint2DDouble a2dPoint2D
this to define if coordinate numbers are integer or doubles
Definition: artglob.h:47
a2dLineSegment * m_pointmanhattan
manhattan point
Definition: sttool.h:2004
void ReleaseMouse()
release the mouse capture for this object
Definition: sttool.cpp:3574
virtual void DoStopTool(bool abort)
to do tool specific stuff to stop a tool. Called from StopTool().
Definition: sttool.cpp:3883
bool GetFilled() const
Definition: canobj.h:1476
double GetHeight() const
returns height of the boundingbox
Definition: bbox.cpp:334
bool GetLastConnectCreationDirection() const
when a wire was created, this return the direction is was created ( first to last pin or visa versa )...
Definition: connectgen.h:249
a2dCanvasObjectPtr m_canvasobject
This is the object currently edited.
Definition: sttool.h:381
a2dPATH_END_TYPE
defines the way a polyline with a contour width is ended.
Definition: polyver.h:31
static const a2dCanvasObjectFlagsMask BIN
Definition: candefs.h:192
(In) Visible property that can be added to Docview Objects.
Definition: gen.h:1785
double GetAbsY() const
get absolute Y position of the pin ( after applying the parent&#39;s matrix and its own matrix ) ...
Definition: canpin.cpp:966
virtual bool DisConnectWith(a2dCanvasObject *toDisConnect=NULL, const wxString &pinname=wxT(""), bool undo=false)
Do Disconnect from another a2dCanvasObject by pin name.
Definition: canobj.cpp:7081
bool IsEmpty() const
Returns true if the array is empty, false otherwise.
Definition: vpath.h:137
bool m_chord
draw just a cord object, not filled.
Definition: sttool.h:1694
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
~a2dDragOrgTool()
destructor
Definition: sttool.cpp:3416
double GetEndScaleY()
scale begin and end object with this factor in X
Definition: polygon.h:398
bool m_draggingCanvasOption
can canvas be dragged using RightMouse.
Definition: sttool.h:750
#define wxDynamicCast(obj, className)
Define wxDynamicCast so that it will give a compiler error for unrelated types.
Definition: gen.h:75
virtual bool EnterBusyMode()
starts a new action (e.g drawing something ) in a tool that is already pushed.
Definition: sttool.cpp:3584
Base class for all types of strokes, understood by a2dDrawer2D classes.
Definition: stylebase.h:378
void SetRoot(a2dDrawing *root, bool recurse=true)
Sets this object to a a2dCanvasDocument.
Definition: canobj.cpp:5933
wxUint16 GetLayer() const
layer set for new objects.
Definition: canglob.h:930
Prevent cloning a reference at a deeper level.
Definition: gen.h:1217
virtual void AbortBusyMode()
Called when the user aborts editing a distinct object */.
Definition: sttool.cpp:5103
virtual void CleanupToolObjects()
Cleanup the editcopy other tool objects (e.g. decorations)
Definition: sttool.cpp:7960
virtual bool Undo()
Undo one command or command group.
Definition: comevt.cpp:918
static const a2dSignal sig_toolComEventAddObject
Definition: sttool.h:121
a2dCanvasObjectPtr m_parentobject
( if needed ) parent a2dCanvasObject relative to which the tool actions take place.
Definition: tools.h:854
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.
Interactive drag a new object into a drawing.
Definition: sttool.h:1189
a2dAffineMatrix m_transform
old transform
Definition: sttool.h:1334
virtual bool Redo()
Redo one command or command group.
Definition: comevt.cpp:933
virtual void DragAbsolute(double x, double y)
called when dragging is in progress
Definition: sttool.cpp:3305
void SetGeneratePins(bool value)
set the GeneratePins flag
Definition: canobj.h:2295
static const a2dSignal sig_changedFill
when active drawing is set, this signal is send to the drawing.
Definition: canglob.h:1187
bool m_renderEditcopyEdit
if yes, the editcopy is rendered on top in edit style
Definition: sttool.h:404
a2dSmrtPtr< a2dBaseTool > m_topTool
tool always on top of the stack, or non if NULL
Definition: sttool.h:770
bool m_pending
set when tool needs an redraw (after a a2dCanvas Repaint etc.)
Definition: tools.h:814
Drag Selected canvasObjects.
Definition: sttool2.h:208
bool PushTool(a2dBaseTool *tool)
specialize to keep first tool on the stack active
Definition: sttool.cpp:451
virtual void SetParent(a2dCanvasObject *parent)
set parent object of the pin or some other objects that needs a parent
Definition: canobj.h:2122
bool GetActive()
is the tool active?
Definition: tools.h:497
static const a2dSignal sm_changedProperty
Definition: gen.h:381
a2dCanvasCommandProcessor * GetCanvasCommandProcessor()
Returns a pointer to the command processor associated with this document.
Definition: tools.cpp:976
The a2dBaseTool is used to derive tools from that are controlled by.
Definition: tools.h:379
wxUint16 m_layer
layer for a new object
Definition: tools.h:832
void Push(a2dCanvasObject *object)
push object onto existing corridor
Definition: objlist.cpp:820
a2dCanvasObject * GetLineEnd()
get current line end object for line and polyline drawing tools
Definition: sttool.h:1464
void OnUndoEvent(a2dCommandProcessorEvent &event)
handler for Undo event
Definition: sttool.cpp:1487
void SetEndScaleX(double xs)
scaling in X for begin and end objects of lines and polylines
Definition: canglob.h:841
int WorldToDeviceY(double y) const
convert y from world to device coordinates
Definition: drawer2d.h:455
a2dDrawTextTool(a2dStToolContr *controller, a2dText *templateObject=NULL)
constructor
Definition: sttool.cpp:7250
virtual void SetEndScaleY(double ys)
dummies to be compatible with a2dEndsLine
Definition: canprim.h:1097
double m_start_x
start x
Definition: sttool.h:1613
virtual void AdjustRenderOptions()
Adjust the rendering options to the needs of this tool.
Definition: sttool.cpp:1214
void SetLayer(wxUint16 layer, bool setStyleOfLayer=false)
Definition: canglob.cpp:1076
a2dCanvasObject * GetLineEnd() const
get current line end object for line and polyline.
Definition: canglob.h:832
int m_mouse_y
mouse position
Definition: sttool.h:738
const a2dAffineMatrix & GetTransformMatrix() const
get the matrix used to position the object
Definition: canobj.h:500
void SetEndScaleX(double xs)
scale begin and end object with this factor in X
Definition: polygon.h:386
wxCursor m_toolcursor
cursor to use
Definition: tools.h:768
virtual void FinishBusyMode(bool closeCommandGroup=true)
Called when the user finishes editing a distinct object */.
Definition: sttool.cpp:3911
void SetRelease(bool value)
set release flag
Definition: gen.h:1346
a2dCanvasObject * GetLineBegin()
get current line begin object for line and polyline drawing tools.
Definition: sttool.h:1460
~a2dMovePinTool()
destructor
Definition: sttool.cpp:9806
if set, set in the clone the PROPID_Original property to the copied object
Definition: gen.h:1212
void SetLineEnd(a2dCanvasObject *end)
set current line end object for line and polyline.
Definition: canglob.h:838
can be used to set style to the a2dCentralCanvasCommandProcessor
Definition: sttool.h:2317
bool m_isEditTool
if tool does change drawing
Definition: tools.h:798
bool m_wasMayConnect
allow connecting to other obejcts
Definition: sttool.h:1069
a2dCommandGroup * m_commandgroup
the command group of the command processor
Definition: tools.h:848
void GetKeyIncrement(double *xIncr, double *yIncr)
get the increments used when moving is done with cursor keys
Definition: sttool.cpp:1316
void ReleaseMouse()
release the mouse capture for this object
Definition: sttool.cpp:3195
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
const a2dDoMu & GetSnapGridX() const
Get horizontal center snapping distance (zero if disabled)
Definition: restrict.h:153
void SetSpline(bool spline)
certain drawing tools like polygon drawing use this setting
Definition: sttool.cpp:4295
a2dAffineMatrix m_transform
old transform
Definition: sttool.h:1066
void SetPosXY12(double x1, double y1, double x2, double y2, bool afterinversion=true)
sets both positions of line
Definition: canprim.cpp:3932
double GetNormalizeScale()
Normalize objects ( defined in coordinates -1 to 1 ranges ) will be multiplied by this factor...
Definition: drawing.h:693
a2dPinClass * m_pinClassStartWire
required pin class at start of wire
Definition: sttool.h:1979
virtual void SetBegin(a2dCanvasObject *begin)
dummies to be compatible with a2dEndsLine
Definition: canprim.h:1084
const a2dDoMu & GetContourWidth() const
get the Contour width of shapes in meters
Definition: canglob.h:872
void OnMouseEvent(wxMouseEvent &event)
Definition: sttool.cpp:3808
bool GetSelectionStateUndo() const
set if selection state of tools object is set during undo.
Definition: sttool.h:682
a2dCommand * GetCommand()
the command ( if there was one ) that did it.
Definition: comevt.h:759
Interactive drawing of a circular arc.
Definition: sttool.h:1641
a2dSmrtPtr< a2dObject > m_eventHandler
when set called before own event handler
Definition: tools.h:787
set cursor
Definition: drawing.h:4227
void SetRadius(double radius)
set radius
Definition: canprim.h:578
a2dObjectEditTool * StartEditTool(a2dCanvasObject *objecttoedit)
to start editing tool when wanted
Definition: sttool.cpp:1632
virtual void GenerateAnotation()
to display a string along with a tool drawing.
Definition: sttool.cpp:4059
virtual void AbortBusyMode()
Called when the user aborts editing a distinct object */.
Definition: sttool.cpp:3644
void SetFill(const a2dFill &fill)
set fill if used inside a tool
Definition: tools.cpp:812
void RemoveAllDecorations()
remove all object that were added as decorations.
Definition: tools.cpp:944
double m_contourwidth
if != 0 the polygon is contoured at distance m_contourwidth/2
Definition: tools.h:829
int m_x
x of mouse in device
Definition: sttool.h:352
double GetHitMargin()
Definition: tools.cpp:983
a2dDrawingPart * m_drawingPart
a2dDrawingPart where tool is plugged into
Definition: tools.h:306
bool m_splitAtEnd
if set, end of wire splits connecting wire.
Definition: sttool.h:1985
virtual void OpenCommandGroup(bool restart)
called when starting an editing operation (e.g. on mouse down)
Definition: tools.cpp:852
void SetSelected2(bool selected)
Set the object selected2 flag if allowed.
Definition: canobj.h:1639
a2dCanvasObjectPtr m_original
This is the original object selected for editing.
Definition: sttool.h:388
Cubic Bezier curve.
Definition: polyver.h:1045
void AddDecorationObject(a2dCanvasObject *object)
Add a decoration object to be rendered by the tool.
Definition: tools.cpp:932
bool Zoom(double x1, double y1, double x2, double y2, bool upp)
Zoom to this rectangle, or Upp at x1, y1.
Definition: drawing.cpp:6123
double m_startMousex
hold start of drag
Definition: sttool.h:1166
a2dPin is used in a2dCanvasObject to add pins to it.
Definition: canpin.h:233
no snap to modes specified
Definition: restrict.h:103
double m_contrmid_y
previous y
Definition: sttool.h:2477
polygon defined with list of points.
Definition: polygon.h:45
bool GetAllowModifyTemplate()
template adepts to style change from outside or not
Definition: sttool.h:440
used to add points to polygon objects
Definition: drawing.h:1959
wxFont & GetFont(void)
wxFont in case of a2dFONT_WXDC
Definition: stylebase.cpp:3030
static a2dPropertyIdVoidPtr * PROPID_ToolObject
set for objects that act as tool object, when a tool is in action.
Definition: canobj.h:2678
a2dSmrtPtr< a2dSLine > m_templateObject
object to clone to use as start
Definition: sttool.h:1505
bool EliminateMatrix()
reduce matrix to identity without replacing object
Definition: vpath.cpp:532
~a2dDragTool()
destructor
Definition: sttool.cpp:2927
Ref Counted base object.
Definition: gen.h:1045
virtual void AdjustRenderOptions()
Adjust the rendering options to the needs of this tool.
Definition: sttool.cpp:9879
void SetTransformMatrix(const a2dAffineMatrix &mat=a2dIDENTITY_MATRIX)
Returns the matrix used to position the object.
Definition: canobj.h:509
bool Rotate(double angle)
Rotate clockwise by the given number of degrees:
Definition: afmatrix.cpp:432
snap segments of other objects in a2dCanvasObject::RestrictToObject()
Definition: restrict.h:120
a2dDrawing * GetRoot() const
get a2dCanvasDocument of the object.
Definition: canobj.h:952
bool m_wasMayConnect
allow connecting to othere object when placed
Definition: sttool.h:1150
proptype * GetPropertyListOnly(const a2dObject *obj) const
Get the property from the list in obj ( no members, not cloned )
Definition: id.inl:318
The a2dStTool is used to derive tools from.
Definition: sttool.h:115
bool GetSelectAtEnd() const
set tool object as selected at end of action
Definition: sttool.h:687
virtual void SetContourWidth(double width)
set the Contour width of the shape
Definition: canobj.h:1408
#define EVT_DO(func)
event sent from a2DocumentCommandProcessor when a command is initially done
Definition: comevt.h:795
virtual void FinishBusyMode(bool closeCommandGroup=true)
Called when the user finishes editing a distinct object */.
Definition: sttool.cpp:3223
void SetNextLineDirection(bool up)
next line is higher in Y if true or lower if false
Definition: cantext.cpp:497
void FinishBusyMode(bool closeCommandGroup=true)
Called when the user finishes editing a distinct object */.
Definition: sttool.cpp:2719
virtual void FinishBusyMode(bool closeCommandGroup=true)
Called when the user finishes editing a distinct object */.
Definition: sttool.cpp:5096
void SetEndScaleX(double xs)
scaling in X for begin and end objects of lines and polylines
Definition: sttool.cpp:4695
double GetRadius() const
get radius of the Arc
Definition: canprim.cpp:3001
double GetBboxMinY()
get minimum Y of the boundingbox in world coordinates relative to its parents
Definition: canobj.h:682
a2dObject * Clone(CloneOptions options, a2dRefMap *refs=NULL) const
create an exact copy of this property
Definition: gen.cpp:1199
void SetOneShot()
Only one action of the tool, after that it will ask the controller to stop this tool.
Definition: tools.h:430
a2dSmrtPtr< a2dBaseTool > m_toolForZoom
tool used for zooming
Definition: sttool.h:773
used to add objects to a a2dCanvasDocument in the current parent
Definition: drawing.h:4315
double m_startObjectx
hold start of drag
Definition: sttool.h:1084
virtual void AbortBusyMode()
Called when the user aborts editing a distinct object */.
Definition: sttool.cpp:8158
virtual void Render()
implement rendering
Definition: sttool.cpp:1402
generate pins, given Connect/wire pinclass
Definition: connectgen.h:48
a2dDrawingPart * GetDrawingPart()
Access to the tool controllers drawer.
Definition: tools.h:632
wxZoomList & GetZoomList()
Get zoom stack list, that is use to store zooming areas.
Definition: sttool.h:616
int m_dragstarty
y of mouse in device at start drag
Definition: sttool.h:371
store a menu Id generated by XRCID( menuIdString ) plus a menustring and helpstring ...
Definition: comevt.h:1563
a2dCanvasObject * GetLineBegin()
get current line begin object for line and polyline drawing tools.
Definition: sttool.h:1842
virtual bool Update(UpdateMode mode)
Update the state of the object according to its current position etc.
Definition: canobj.cpp:5149
void SetSpline(bool on)
set to true, the polygon will be drawn as a spline
Definition: polygon.h:232
used to connect two pins
Definition: drawing.h:2411
double DeviceToWorldYRel(double y) const
convert y relative from device to world coordinates
Definition: drawer2d.h:449
Simple canvas using a whole view for all of the scrolled window.
Definition: cansim.h:54
virtual bool RestrictCanvasObjectAtVertexes(a2dCanvasObject *object, a2dPoint2D &point, double &dx, double &dy, wxUint32 sourceRequired=snapToAll, bool ignoreEngine=false)
return the clossest vertex which can be snapped if any.
Definition: restrict.cpp:685
void OnKeyUp(wxKeyEvent &event)
called on key up events
Definition: sttool.cpp:1550
double m_y3
control point 2
Definition: polyver.h:1100
void SetChord(bool chord)
if true draw as a chord ( no fill end no lines to center )
Definition: canprim.cpp:2357
void ConnectEvent(wxEventType type, wxEvtHandler *eventSink)
Definition: gen.cpp:876
virtual bool EnterBusyMode()
starts a new action (e.g drawing something ) in a tool that is already pushed.
Definition: sttool.cpp:7682
wxString & GetUndoMenuLabel()
by default this is a2dCommandProcessor::GetUndoMenuLabel()
Definition: comevt.h:762
void AdjustShift(double *x, double *y)
This is overriden by copy tools to have a minimum distance between original and copy.
Definition: sttool.cpp:8373
a2dVpathSegment * m_segment
last point
Definition: sttool.h:2487
virtual void OpenCommandGroupNamed(const wxString &name)
called when starting an editing operation with another than the default name
Definition: tools.cpp:876
a2dOpaqueMode m_useEditOpaque
when true editcopies are using a half transparent cloned style.
Definition: sttool.h:415
bool EliminateMatrix()
reduce matrix to identity without replacing object
Definition: canprim.cpp:3885
bool IsIdentity(void) const
Is the matrix the identity matrix?
Definition: afmatrix.h:147
void Zoomin2()
zoom in two half the current visible area
Definition: sttool.cpp:406
Defines a font to be set to a2dDrawer2D or stored in a2dCanvsObject etc.
Definition: stylebase.h:779
double m_x3
control point 2
Definition: polyver.h:1098
Interactive Zooming.
Definition: sttool.h:849
a2dStToolContr * m_stcontroller
controller for canvas
Definition: sttool.h:391
wxUint16 GetLayer()
layer set for new objects.
Definition: tools.h:557
void SetChord(bool chord)
if true draw as a chord ( no fill end no lines to center )
Definition: canprim.cpp:3006
virtual void AdjustRenderOptions()
Adjust the rendering options to the needs of this tool.
Definition: sttool.cpp:8126
snap to pins in other objects when not connected
Definition: restrict.h:112
double m_startObjecty
hold start of drag
Definition: sttool.h:2077
a2dZoomTool(a2dStToolContr *controller)
constructor
Definition: sttool.cpp:1934
a2dDrawing * GetDrawing()
Returns a pointer to the drawing.
Definition: tools.cpp:969
void SetStroke(const a2dStroke &stroke)
used for new objects etc. to set the stroke
Definition: canglob.cpp:939
if set, clone childs, otherwise ref-copy them
Definition: gen.h:1207
a2dPATH_END_TYPE GetPathType()
get when m_contourwidth != 0 what is the end of the line looks like.
Definition: canglob.h:878
wxString m_anotation
anotation string, which is in general modified by the tools to display position etc.
Definition: sttool.h:340
void Update(unsigned int how=(a2dCANVIEW_UPDATE_ALL|a2dCANVIEW_UPDATE_BLIT), wxObject *hintObject=NULL)
see OnUpdate
Definition: drawer.cpp:1744
a command processor specially designed to work with a a2dCanvasDocument
Definition: drawing.h:1046
bool m_anotate
when true anotation will be shown, if used inside a tool
Definition: tools.h:839
virtual void SetPending(bool pending)
set this object pending for update
Definition: canobj.cpp:2585
#define EVT_REDO(func)
event sent from a2DocumentCommandProcessor when a command is redone
Definition: comevt.h:799
void ZoomIn2AtMouse()
zoom in two half the current visible area at mouse position
Definition: sttool.cpp:431
bool GetYaxis() const
get y axis orientation
Definition: drawer2d.h:280
virtual void FinishBusyMode(bool closeCommandGroup=true)
Called when the user finishes editing a distinct object */.
Definition: tools.cpp:755
virtual void CleanupToolObjects()
Cleanup the editcopy other tool objects (e.g. decorations)
Definition: sttool.cpp:3707
void SetEndScaleX(double xs)
scaling in X for begin and end objects of lines and polylines
Definition: sttool.cpp:6717
void RemoveRedundantPoints(a2dCanvasObject *sendCommandsTo=NULL)
remove all points that are redundant
Definition: polygon.cpp:2022
void SetZoomFirst(bool zoomfirst)
first tool on the tool stack is the zoom tool.
Definition: sttool.cpp:293
a2dRectC is a centered rectangle
Definition: canprim.h:99
bool m_active
tool is operational
Definition: tools.h:777
a2dPin * IsConnectedTo(a2dPin *pin=a2dAnyPin) const
Return the pin to which this pin is connected.
Definition: canpin.cpp:751
int m_dragstartx
x of mouse in device at start drag
Definition: sttool.h:369
double m_ywprev
y world coordinates old or new value of mouse
Definition: sttool.h:366
virtual void FinishBusyMode(bool closeCommandGroup=true)
Called when the user finishes editing a distinct object */.
Definition: sttool.cpp:1737
void Zoomout2Menu(wxCommandEvent &)
zoom out two times the current visible area
Definition: sttool.cpp:335
void SetFilename(const wxString filename, wxBitmapType type, bool doread=true)
set filename and type of image for saving.
Definition: canimage.cpp:249
int m_mouse_yprev
previous y of mouse in device
Definition: sttool.h:744
wxUint8 GetOpacityFactorEditcopy()
see SetOpacityFactorEditcopy()
Definition: sttool.h:658
void ActivateTop(bool active)
(de)activate the first tool in the list.
Definition: tools.cpp:141
void OnIdle(wxIdleEvent &event)
handler for idle events
Definition: sttool.cpp:1370
void SetActive(bool active)
set the tool active or inactive.
Definition: sttool.cpp:5880
void OnEnter(wxMouseEvent &event)
when dragging an object from another window into the tool its window, this window wants to have the f...
Definition: sttool.cpp:9810
a2dFont GetTextFont() const
get current font active text font ( like used in text tool ).
Definition: canglob.cpp:1039
void ZoomOut2AtMouse()
zoom out two times the current visible area at mouse position
Definition: sttool.cpp:417
virtual void FinishBusyMode(bool closeCommandGroup=true)
Called when the user finishes editing a distinct object */.
Definition: sttool.cpp:1161
double GetWidth() const
return width
Definition: canprim.h:337
double GetBboxMinX()
get minimum X of the boundingbox in world coordinates relative to its parents
Definition: canobj.h:676
a2dCanvasObject * GetEnd()
dummies to be compatible with a2dEndsLine
Definition: canprim.h:1206
void AbortBusyMode()
Called when the user aborts editing a distinct object */.
Definition: sttool.cpp:6948
bool GetFlag(const a2dCanvasObjectFlagsMask which) const
get specific bitflag value
Definition: canobj.cpp:2655
bool m_noStatusEvent
if set no event is send to m_where, instead a statusbar text is set directly
Definition: sttool.h:719
void SetLineBegin(a2dCanvasObject *begin)
defines line begin object for line and polyline drawing tools
Definition: sttool.cpp:6706
void SetPending(bool pending=true)
a tool is set pending when it needs to be redrawn.
Definition: tools.h:615
a2dCanvasObject * GetLineBegin() const
get current line begin object for line and polyline.
Definition: canglob.h:828
a2dCanvasObjectList m_objects
the list of selected objects
Definition: sttool.h:2070
a2dCanvasObject is the base class for Canvas Objects.
Definition: canobj.h:371
a2dPinClass * m_pinClassEndWire
required pin class at start of wire
Definition: sttool.h:1982
bool GetRouteWhenDrag()
route also while dragging object
Definition: connectgen.h:341
new object added or object edited gets tool style
Definition: sttool.h:2320
a2dPropertyId * m_id
id of property to set
Definition: sttool.h:2264
bool m_chord
draw just a cord object, not filled.
Definition: sttool.h:1618
double m_y2
control point 1
Definition: polyver.h:1095
property to hold a a2dObjectPtr smart pointer type variable to be associated with a a2dObject ...
Definition: gen.h:2199
void SetEndScaleY(double ys)
scaling in Y for begin and end objects of lines and polylines
Definition: sttool.cpp:4701
draw a rectangle the size of the bounding box of the object draged.
Definition: sttool.h:79
void SetFixedStyleStroke(const a2dStroke &fixStroke)
set a2dStroke to use when RenderFIX_STYLE is set.
Definition: drawer.h:845
bool m_renderEditcopyOnTop
if yes, the editcopy is rendered on top in usual style
Definition: sttool.h:402
void SetCurrentCanvasObject(a2dCanvasObject *currentcanvasobject, bool takeOverProperties=true)
set the current canvas object, which gets the change in style etc
Definition: drawing.cpp:6315
wxZoomList m_zoomstack
zoom stack containing previous zooms
Definition: sttool.h:729
no special flags set
Definition: id.h:161
a2dCanvas * GetCanvas() const
Get the Display window of the a2dView. But casted to a a2dCanvas.
Definition: drawer.h:525
virtual bool EnterBusyMode()
starts a new action (e.g drawing something ) in a tool that is already pushed.
Definition: sttool.cpp:5091
a2dDrawingPart * GetDrawingPart()
Get the a2dDrawingPart object that the controller is plugged into.
Definition: tools.h:104
void CaptureMouse()
redirect all mouse events for the canvas to this object
Definition: sttool.cpp:7756
bool m_mousecaptured
is mouse captured during drag
Definition: sttool.h:1075
virtual void GenerateAnotation()
to display a string along with a tool drawing.
Definition: sttool.cpp:2470
void Zoomout()
show all on canvas
Definition: sttool.cpp:378
void ZoomWindow()
start one shot zoomtool from popup menu (used while another tool is active)
Definition: sttool.cpp:345
bool m_lateconnect
connect when released
Definition: sttool.h:1072
double m_start_y
start y
Definition: sttool.h:1615
for changing boolean values inside canvas objects
Definition: drawing.h:1585
virtual void SetParent(a2dCanvasObject *parent)
set parent object of the pin
Definition: canpin.cpp:932
void SetX1(double x1)
Set X1 of arc being begin point of arc.
Definition: canprim.h:882
Interactive rotate an object.
Definition: sttool.h:1295
bool SetContext(a2dIterC &ic, a2dCanvasObject *startObject=NULL)
defines the context, relative to which this tools works.
Definition: sttool.cpp:1052
void ZoomoutMenu(wxCommandEvent &)
show all on canvas
Definition: sttool.cpp:330
wxMenu * GetMousePopupMenu()
to get the current mouse menu of the controller
Definition: sttool.h:509
virtual bool CreateToolObjects()
Create the editcopy and other tool objects (e.g. decorations)
Definition: sttool.cpp:1711
property to hold a byte integer type vector to be associated with a a2dObject
Definition: canprop.h:526
Interactive drawing of a Rectangle.
Definition: sttool.h:807
virtual a2dObject * GetRefObject() const
when a2dProperty, return its value else assert
Definition: gen.cpp:1976
void SetWidth(double w)
set width of rectangle
Definition: canprim.h:328
a2dPinClass * CanConnectTo(a2dPinClass *other=NULL) const
searches in the connection list for a given pin class
Definition: canpin.cpp:499
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
#define EVT_MENUSTRINGS(func)
event sent to a2dCommandProcessorEvents to adjust menu strings (e.g. for current undo/redo command) ...
Definition: comevt.h:801
void SetPathType(a2dPATH_END_TYPE pathtype)
Set when m_contourwidth != 0 what is the end of the line should be.
Definition: sttool.cpp:6728
void TransformPoint(double x, double y, double &tx, double &ty) const
Transform a point.
Definition: afmatrix.cpp:559
virtual void SetPinsToEndState(a2dCanvasObject *root, a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::VISIBLE)
set end state of pins after tool is finsihed
double m_start_x
start x
Definition: sttool.h:1689
virtual void GenerateAnotation()
to display a string along with a tool drawing.
Definition: sttool.cpp:5954
a2dDrawPolygonLTool(a2dStToolContr *controller, a2dPolygonL *templateObject=NULL)
constructor
Definition: sttool.cpp:4263
void SetFill(const a2dFill &fill)
used for new objects etc. to set the fill
Definition: canglob.cpp:955
static const a2dSignal sig_toolComEventSetEditObject
Definition: sttool.h:124
bool GetSelected() const
is the object selected flag set
Definition: canobj.h:1603
void SetSelected(bool selected)
Set the object selected flag if allowed.
Definition: canobj.h:1620
bool ProcessEvent(wxEvent &event)
process an event for the object, if the event is not handled by
Definition: tools.cpp:249
bool GetShiftKeyDown() const
some snapping may depend on shift key being down
Definition: restrict.h:393
virtual bool CreateToolObjects()
Create the editcopy and other tool objects (e.g. decorations)
Definition: sttool.cpp:3687
bool m_lateconnect
allow connecting to other obejcts
Definition: sttool.h:2084
bool GetSpline() const
certain drawing tools like polygon drawing use this setting
Definition: canglob.h:822
void SetEndScaleY(double ys)
scaling in Y for begin and end objects of lines and polylines
Definition: canglob.h:844
bool m_deleteonoutsidedrop
if true, the dragged object is deleted, if it is dropped outside of the window
Definition: sttool.h:1159
void SetEvtHandler(a2dObject *handler)
to reroute events to this event handler
Definition: tools.h:402
bool m_takeToolstyleToCmdhOnPush
can be used to take over style from the a2dCentralCanvasCommandProcessor
Definition: sttool.h:2403
a2dPATH_END_TYPE GetPathType()
get when m_contourwidth != 0 what is the end of the line looks like.
Definition: polygon.h:404
bool m_shift_is_add
false: shift key will unselect, true: shift will add to selection
Definition: sttool.h:934
double GetBboxWidth()
get width of the boundingbox in world coordinates relative to its parents
Definition: canobj.h:700
a2dStroke m_stroke
stroke for new object
Definition: tools.h:826
bool m_renderEditcopyRectangle
if yes, the editcopy is rendered on top as bounding box rectangle
Definition: sttool.h:406
a2dSmrtPtr< a2dEllipticArc > m_templateobject
object to clone to use as start
Definition: sttool.h:1605
bool m_withUndo
undoable or not
Definition: sttool.h:2267
double GetStart()
return start angle
Definition: canprim.h:733
bool EnterBusyMode()
starts a new action (e.g drawing something ) in a tool that is already pushed.
Definition: sttool.cpp:1731
Interactive Insertion of an a2dImage Object.
Definition: sttool.h:950
void SetBin(bool bin)
general flag use at will.
Definition: canobj.h:2259
void ReWireConnected(a2dCanvasObject *parent, bool undo=false)
rewire the object to keep connection or to make connection with other objects
Definition: canobj.cpp:7163
bool ProcessEvent(wxEvent &event)
events recieved from controller processed here
Definition: tools.cpp:668
used to change style of canvas objects in a a2dCanvasDocument
Definition: drawing.h:2201
double m_startMousexw
hold start of drag
Definition: sttool.h:2079
void SetContourWidth(double width)
set the Contour width of the shape
Definition: polygon.h:237
void OnMouseEvent(wxMouseEvent &event)
Definition: sttool.cpp:3512
a2dSnapToWhatMask GetSnapTargetFeatures() const
Definition: restrict.h:249
void OnKeyDown(wxKeyEvent &event)
called on key down events
Definition: sttool.cpp:1512
a2dFont GetFont() const
get font for text
Definition: cantext.h:251
virtual bool EnterBusyMode()
Called when the user selects a distinct object for editing */.
Definition: tools.cpp:724
a2dVpath * m_vpath
points sofar
Definition: sttool.h:2484
void OnMouseEvent(wxMouseEvent &event)
called on mouse events
Definition: sttool.cpp:1203
void Zoomout2()
zoom out two times the current visible area
Definition: sttool.cpp:395
void RotateRouteMethod()
cycle through routing methods
Definition: connectgen.cpp:74
void OnComEvent(a2dComEvent &event)
handler for this event
Definition: sttool.cpp:492
static a2dPropertyIdRefObject * PROPID_ViewSpecific
Definition: canobj.h:2691
void SetContourWidthInDataBaseUnits(double width)
set the Contour width of shapes defined in database units
Definition: canglob.cpp:1047
void SetCaretShow(bool visible=true)
set caret on or off
Definition: cantext.cpp:517
void ZoomUndo()
go to previous zoom area (used while another tool is active)
Definition: sttool.cpp:362
wxUint64 a2dCanvasObjectFlagsMask
mask flags for a2dCanvasObject
Definition: candefs.h:152
void SetInternal(bool internal)
set when pin is within the border of its parent
Definition: canpin.h:444
void SetMappingShowAll(bool centre=true)
use the boundingbox of the ShowObject to set the mapping such that it will be displayed completely...
Definition: canvas.cpp:548
void SetZoomTool(a2dBaseTool *toolForZoom)
for zooming purposes this tool wil be used
Definition: sttool.cpp:309
a2dNextSeg GetEndSegmentMode()
a2dDrawWirePolylineLTool segment mode initilization
Definition: canglob.h:962
int WorldToDeviceYRel(double y) const
convert y relative from world to device coordinates
Definition: drawer2d.h:465
void SetHeight(double h)
set height of rectangle
Definition: canprim.h:334
static const a2dCanvasObjectFlagsMask PENDING
Definition: candefs.h:194
Interactive delete an object.
Definition: sttool.h:1353
a2dWirePolylineL is a polyline that adjusts itself when the objects it connects move ...
Definition: wire.h:42
double m_startMousey
hold start of drag
Definition: sttool.h:1168
If no other snap point was closer, force to grid, even if not within threshold.
Definition: restrict.h:141
snap to other objects its vertexes, which are decided in a2dCanvasObject::RestrictToObject() ...
Definition: restrict.h:116
void ReleaseMouse()
release the mouse capture for this object
Definition: sttool.cpp:7234
static const a2dCanvasObjectFlagsMask normalized
Definition: candefs.h:217
Interactive edit properties of an object.
Definition: sttool.h:2240
void EditProperties(wxCommandEvent &)
default implementation for property editing
Definition: sttool.cpp:263
void ZoomPanMenu(wxCommandEvent &)
zoompan from popup menu (used while another tool is active)
Definition: sttool.cpp:320
a2dDrawer2D * GetDrawer2D()
Access to the tool controllers drawers drawer2d.
Definition: tools.cpp:959
a2dText is an abstract base class.
Definition: cantext.h:93
void OnChar(wxKeyEvent &event)
called on key events
Definition: sttool.cpp:536
used to change a property on objects
Definition: drawing.h:2244
void SetTemporaryPin(bool temporaryPin)
Definition: canpin.h:437
void Redo(wxCommandEvent &)
redirect to command processor of document
Definition: sttool.cpp:250
void OnMouseEvent(wxMouseEvent &event)
Definition: sttool.cpp:3058
void ConnectTo(a2dPin *connectto)
connect this pin to the given pin
Definition: canpin.cpp:918
base for tools that draw and are stack based.
Definition: sttool.h:427
void SetPathType(a2dPATH_END_TYPE pathtype)
Set when m_contourwidth != 0 what is the end of the line should be.
Definition: polygon.h:401
virtual void FinishBusyMode(bool closeCommandGroup=true)
Called when the user finishes editing a distinct object */.
Definition: sttool.cpp:9915
bool GetValid() const
returns true if boundingbox is calculated properly and therefore its valid flag is set...
Definition: bbox.cpp:299
void Expand(const a2dPoint2D &, const a2dPoint2D &)
expand boundingbox width two points
Definition: bbox.cpp:155
double GetMinX() const
get minimum X of the boundingbox
Definition: bbox.cpp:304
virtual void Render()
render in drag style
Definition: sttool.cpp:7853
double GetLength() const
Returns length of line.
Definition: canprim.cpp:3893
void CaptureMouse()
redirect all mouse events for the canvas to this object
Definition: sttool.cpp:3567
void Render()
implement rendering
Definition: sttool.cpp:3016
command on selected objects
Definition: drawing.h:2471
a2dCommandGroup * GetCommandgroup()
return the command group that is open else NULL.
Definition: tools.h:664
a2dFill m_fill
fill for new object
Definition: tools.h:823
void AddPendingUpdateArea(a2dCanvasObject *obj, wxUint8 id=0, bool refsalso=true)
add pending update for the area that is the boundingbox of the given object
Definition: drawer.cpp:2891
a2dSmrtPtr< a2dPin > m_dragPinObjPin
the pin on the dummy object that is dragged
Definition: sttool.h:2587
void AddAnotationToPendingUpdateArea()
after calculating anotation position and string, extend the boundingbox of the tools with it...
Definition: sttool.cpp:1358
static const a2dSignal sig_changedShowObject
Definition: drawer.h:1513
Interactive drag an object.
Definition: sttool.h:1012
void Transform(const a2dAffineMatrix &tworld)
transform the object using the given matrix
Definition: canobj.h:577
virtual bool EnterBusyMode()
starts a new action (e.g drawing something ) in a tool that is already pushed.
Definition: sttool.cpp:2420
void SetFont(const a2dFont &font, double lineSpaceFactor=0.1)
set font for text
Definition: cantext.cpp:527
void ZoomWindowMenu(wxCommandEvent &)
start one shot zoomtool from popup menu (used while another tool is active)
Definition: sttool.cpp:315
const a2dStroke & GetStroke() const
get the current stroke
Definition: canglob.h:797
void SetParentSnapObjects(a2dCanvasObject *obj)
parent object of objects that need to be snapped to
Definition: restrict.h:380
a2dSmrtPtr< a2dPolygonL > m_templateObject
object to clone to use as start
Definition: sttool.h:1772
a2dStToolContr * m_stcontroller
tools using this controller
Definition: sttool.h:2400
a2dDrawVPathTool(a2dStToolContr *controller, a2dVectorPath *templateObject=NULL)
constructor
Definition: sttool.cpp:9387
a2dEllipse centered at x,y.
Definition: canprim.h:635
polyline defined with list of points.
Definition: polygon.h:332
void Reset()
set invalid
Definition: bbox.cpp:394
The a2dStToolContr is a Tool Controller specialized for working with a2dCanvasView.
Definition: sttool.h:485
void SetPropertyToObject(a2dObject *obj, const basetype &value, SetFlags setflags=set_none) const
Set the property in obj to value.
Definition: id.inl:238
void SetDrawPatternOnTop(bool drawPatternOnTop)
Sets if the pattern (a rectangle) will be drawn on top of this image.
Definition: canimage.cpp:265
wxWindow * GetDisplayWindow()
Access to the tool controllers drawers canvas.
Definition: tools.cpp:964
double GetEndScaleY()
get scaling in Y for begin and end objects of lines and polylines
Definition: sttool.h:1475
bool GetSnapTo() const
is snap_to flag set?
Definition: canobj.h:1707
void AddOverlayObject(a2dCanvasObject *obj)
add to list of overlay objects (must be children of m_top)
Definition: drawer.cpp:973
a2dHandle * GetHandle()
get default handle for editing
Definition: canglob.cpp:740
double GetPosX() const
get x position from affine matrix
Definition: canobj.h:527
#define EVT_COM_EVENT(func)
static wxEvtHandler for communication event
Definition: gen.h:564
void SetFixedStyleFill(const a2dFill &fixFill)
set a2dFill to use when RenderFIX_STYLE is set.
Definition: drawer.h:842
bool ScrollWindowConstrained(double dx, double dy)
scroll the window in world coordinates
Definition: canvas.cpp:1278
static const a2dSignal sig_toolStartEditObject
when starting editing an object, this event is sent to tool
Definition: edit.h:83
bool m_editatend
when drawing something editing must follow, using the a2dRecursiveEditTool
Definition: sttool.h:409
const long TC_UNDO
zoom menu
Interactive drawing of a Circle.
Definition: sttool.h:1392
const a2dCommandId * GetCommandId()
a specific id for this command.
Definition: comevt.h:179
double m_arcstart
start arc
Definition: sttool.h:1684
wxCursor m_toolBusyCursor
cursor to use when the tool is busy doing something.
Definition: tools.h:771
wxMenu * m_mousemenu
popup menu
Definition: sttool.h:732
Normal straight line segment in a2dVpath.
Definition: polyver.h:878
#define wxStaticCast(obj, className)
The wxWindows 2.4.2 wxStaticCast is buggy. It evaluates its argument twice.
Definition: gen.h:123
a2dVertexListPtr GetSegments()
Get the list of points ( this is not a copy! )
Definition: polygon.h:219
Interactive drawing of a polyline wire.
Definition: sttool.h:1930
can be used to take over style from the a2dCentralCanvasCommandProcessor
Definition: sttool.h:2303
static const a2dSignal sig_toolPushed
sent to new first tool when tool was pushed
Definition: tools.h:384
void StopAllTools(bool abort=true)
all tools currently on the tool stack will be terminated and poped ( forced )
Definition: tools.cpp:123
a2dCanvasObject * GetShowObject() const
return pointer of then currently shown object on the drawer.
Definition: drawer.h:680
a2dImage (will scale/rotate image when needed)
Definition: canimage.h:33
bool m_oneshot
do it only once
Definition: tools.h:817
double wxRadToDeg(double rad)
conversion from radians to degrees
Definition: artglob.cpp:31
Normal straight line segment in a2dVertexList and a2dVertexArray.
Definition: polyver.h:163
double m_contrmid_x
previous x
Definition: sttool.h:2475
void SetMappingShowAll(bool centre=true)
use the boundingbox of the ShowObject to set the mapping such that it will be displayed completely...
Definition: cansim.cpp:378
double m_startObjecty
hold start of drag
Definition: sttool.h:1086
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
wxMenu * m_mousemenu
popup menu
Definition: tools.h:851
int m_yanotation
y position of anotation text
Definition: sttool.h:346
void SetEndScaleY(double ys)
scale begin and end object with this factor in Y
Definition: polygon.h:395
void OnChar(wxKeyEvent &event)
called on key events
Definition: sttool.cpp:1568
a2dSLine
Definition: canprim.h:987
DRAGMODE GetDragMode()
Returns drag mode.
Definition: sttool.h:567
bool ToolsProcessEvent(wxEvent &event)
Event not handled in this class are redirected to the chain of tools.
Definition: tools.cpp:289
bool m_mousecaptured
is mosue captured when dragging
Definition: sttool.h:1156
void SetSnapSourceFeatures(wxUint32 snapSourceFeatures)
Definition: restrict.h:215
bool m_zoomoutCentered
when true zoom out and center to middle of the view
Definition: sttool.h:758
A2DGENERALDLLEXP a2dSmrtPtr< a2dGeneralGlobal > a2dGeneralGlobals
a global pointer to get to global instance of important classes.
Definition: comevt.cpp:1148
virtual bool CreateToolObjects()
Create the editcopy and other tool objects (e.g. decorations)
Definition: sttool.cpp:7865
int m_mouse_xprev
previous x of mouse in device
Definition: sttool.h:741
int m_mode
general operation mode setting for a tool.
Definition: tools.h:845
void OnSetmenuStrings(a2dCommandProcessorEvent &event)
how to set mouse menu undo/redo
Definition: sttool.cpp:271
void Translate(double x, double y)
relative translate the object to position x,y in world coordinates
Definition: canobj.h:569
void SetUpdatesPending(bool onoff)
Tells the document that an object has changed.
Definition: drawing.cpp:405
virtual bool DisConnectAt(a2dPin *pin, bool undo=false)
Do Disconnect from another a2dCanvasObject by pin pointer.
Definition: canobj.cpp:7134
void SetUseOpaqueEditcopy(a2dOpaqueMode editOpaque)
When set true, instead of using a special style for editcopies, a clone of the.
Definition: sttool.h:211
virtual bool Undo()
Undo one command or command group.
Definition: drawing.cpp:6023
de-select objects in a rectangle area
Definition: drawing.h:2489
void SetTopTool(a2dBaseTool *toolOnTop)
when all tools are poped, this tool will be pushed.
Definition: sttool.cpp:302
Restriction engine for editing restrictions like snapping.
Definition: restrict.h:88
~a2dStToolContr()
destructor
Definition: sttool.cpp:209
wxUint16 GetLayer() const
Returns the layer index where this object is drawn upon.
Definition: canobj.h:2368
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 EnterBusyMode()
starts a new action (e.g drawing something ) in a tool that is already pushed.
Definition: sttool.cpp:2700
int WorldToDeviceX(double x) const
convert x from world to device coordinates
Definition: drawer2d.h:453
Hint to clone enough of the object to do proper dragging in graphics.
Definition: gen.h:1221
a2dDrawer2D * GetDrawer2D()
get the internal m_drawer2D that is used for rendering the document
Definition: drawer.h:1125
This tool does do a hit test on objects to edit, and then starts editing the object.
Definition: edit.h:226
bool HasPins(bool realcheck=false)
are there a2dPin derived children
Definition: canobj.cpp:6414
void SetLayer(wxUint16 layer)
layer set for the object that is drawn using a tool
Definition: tools.cpp:827
Drag Selected canvasObjects.
Definition: sttool.h:2021
bool CheckMask(a2dCanvasObjectFlagsMask mask) const
Compares all flags in object to the given mask and return true is the same.
Definition: canobj.cpp:2665
if set, respect layer order, hit testing is done per layer from the top.
Definition: canobj.h:82
static const a2dCanvasObjectFlagsMask SELECTED
Definition: candefs.h:180
bool IsSelected() const
Is the object selected flag set.
Definition: canobj.h:1610
wxRect GetAbsoluteArea(a2dCanvasObject *object)
area occupied by this object
Definition: sttool.cpp:1061
bool m_reverse
end to begin wire.
Definition: sttool.h:1786
a2dAffineMatrix m_transform
old transform
Definition: sttool.h:1147
~a2dZoomTool()
destructor
Definition: sttool.cpp:1974
bool RotateObject90LeftRight(bool Right)
rotate object of first tool on the stack, when appropriate.
Definition: sttool.cpp:953
void SetBegin(a2dCanvasObject *begin)
set object to draw as begin point
Definition: polygon.cpp:1832
bool CanRedo()
by default this is a2dCommandProcessor::CanRedo()
Definition: comevt.h:768
bool m_deleteonoutsidedrop
if true, the dragged object is deleted, if it is dropped outside of the window
Definition: sttool.h:1078
void RemovePins(bool NotConnected=false, bool onlyTemporary=false, bool now=false)
Remove all a2dPin children.
Definition: canobj.cpp:6504
void Render()
implement rendering
Definition: sttool.cpp:3470
bool TriggerReStartEdit(wxUint16 editmode)
when edit tool is firsttool, restart it.
Definition: sttool.cpp:942
Remove from property in a hierarchy of a canvas document.
Definition: algos.h:188
bool GetSpline()
Get the polygon spline setting.
Definition: polygon.h:235
void OnKeyDown(wxKeyEvent &event)
called on keydown events
Definition: sttool.cpp:556
virtual bool EnterBusyMode()
starts a new action (e.g drawing something ) in a tool that is already pushed.
Definition: sttool.cpp:3897
void OnChar(wxKeyEvent &event)
character handling
Definition: sttool.cpp:1997
virtual bool EnterBusyMode()
starts a new action (e.g drawing something ) in a tool that is already pushed.
Definition: sttool.cpp:3205
set a2dCanvasObjects flags in a hierarchy of a a2dCanvasDocument
Definition: algos.h:486
void OnKeyUp(wxKeyEvent &event)
called on key up events
Definition: sttool.cpp:1793
wxUint32 a2dSnapToWhatMask
mask for a2dSnapToWhat flags
Definition: restrict.h:26
a2dCorridor m_corridor
Definition: tools.h:795
virtual a2dCanvasObject * GetEnd()
dummies to be compatible with a2dEndsLine
Definition: canprim.h:1092
virtual a2dCanvasObject * CreateConnectObject(a2dCanvasObject *parent, a2dPin *pinThis, a2dPin *pinOther, bool undo=false) const
generates a connection object with pins and all.
Definition: canobj.cpp:3169
This tool is for editing a single object.
Definition: edit.h:73
Each a2dCommand is given a command id at construction.
Definition: comevt.h:99
double m_startMousex
hold start of drag
Definition: sttool.h:1088
used to add object to a a2dCanvasDocument in the current parent
Definition: drawing.h:1403
a2dFill GetTextFill() const
get the current text fill
Definition: canglob.cpp:1032
corridor as a direct event path to a a2dCanvasObject
Definition: objlist.h:313
defines common settinsg for a habitat for a set of a2dCameleons.
Definition: canglob.h:439
double m_x2
control point 1
Definition: polyver.h:1093
void SetVisible(bool visible)
set if this object will visible (be rendered or not)
Definition: canobj.h:1303
double GetContourWidth() const
get the Contour width of the shape
Definition: polygon.h:240
Drag and Copy Selected canvasObjects.
Definition: sttool.h:2148
void CaptureMouse()
redirect all mouse events for the canvas to this object
Definition: sttool.cpp:3188
bool IsTemporaryPin() const
return true if this pin is a temporary pin
Definition: canpin.h:433
void SetLastXyEntry(double x, double y)
set last mouse X position in world coordinates, as set by tools.
Definition: canglob.h:774
void SetEndSegmentMode(a2dNextSeg mode)
Definition: sttool.cpp:5117
virtual void FinishBusyMode(bool closeCommandGroup=true)
Called when the user finishes editing a distinct object */.
Definition: sttool.cpp:3602
void SetLineEnd(a2dCanvasObject *end)
defines line end object for line and polyline drawing tools
Definition: sttool.cpp:6711
void SetSnapTo(bool snap)
Sets snap_to flag.
Definition: canobj.h:1704
A 2x3 affine matrix class for 2D transformations.
Definition: afmatrix.h:53
a2dPoint2D GetPosXY() const
get position of object
Definition: canobj.h:533
unsigned int m_defaultBehavior
control the default behavior
Definition: sttool.h:767
virtual a2dCanvasObject * GetBegin()
dummies to be compatible with a2dEndsLine
Definition: canprim.h:1089
bool EnterBusyMode()
starts a new action (e.g drawing something ) in a tool that is already pushed.
Definition: sttool.cpp:6934
makes a tool fixed in style.
Definition: sttool.h:2369
virtual void SetEnd(a2dCanvasObject *end)
dummies to be compatible with a2dEndsLine
Definition: canprim.h:1086
virtual bool RotateObject90LeftRight(bool right)
rotate object of first tool on the stack, when appropriate.
Definition: tools.h:729
double m_xwprev
x world coordinates old or new value of mouse
Definition: sttool.h:363
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
To implement behaviour on a set of tools.
Definition: tools.h:884
double GetMaxX() const
get maximum X of the boundingbox
Definition: bbox.cpp:316
bool Start(a2dCanvasObject *object)
Definition: algos.cpp:318
a2dCanvas is used to display one of the a2dCanvasObjects which are part of a a2dCanvasDocument object...
Definition: canvas.h:68
void SetPathType(a2dPATH_END_TYPE pathtype)
Set when m_contourwidth != 0 what is the end of the line should be.
Definition: canglob.cpp:1057
bool DoConnect()
if return true, connection with other object on this object its pins is allowed.
Definition: canobj.h:1845
virtual void AbortBusyMode()
Called when the user aborts editing a distinct object */.
Definition: sttool.cpp:7746
void SetLineBegin(a2dCanvasObject *begin)
defines line begin object for line and polyline drawing tools
Definition: sttool.cpp:4685
virtual void GenerateAnotation()
to display a string along with a tool drawing.
Definition: sttool.cpp:1832
a2dPin * HasPinNamed(const wxString pinName, bool NotConnected=false)
are there a2dPin derived children which matches the given pin name?
Definition: canobj.cpp:6436
virtual void ReStart()
sets the m_toptool (if set ) as first tool.
Definition: sttool.cpp:227
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
void Zoomin2Menu(wxCommandEvent &)
zoom in two half the current visible area
Definition: sttool.cpp:340
bool m_stop
stop the tool
Definition: tools.h:820
object stay in document and it is redrawn while dragging, and so are all objects above and below it...
Definition: sttool.h:83
virtual void FinishBusyMode(bool closeCommandGroup=true)
Called when the user finishes editing a distinct object */.
Definition: sttool.cpp:6942
void AddPropertyId(a2dPropertyId *id)
add a a2dPropertyId to the list
Definition: algos.cpp:312
virtual void AbortBusyMode()
Called when the user aborts editing a distinct object */.
Definition: sttool.cpp:1178
virtual a2dLineSegment * Clone()
create exact copy
Definition: polyver.cpp:250
virtual void AbortBusyMode()
Called when the user aborts editing a distinct object */.
Definition: sttool.cpp:9954
virtual double GetContourWidth() const
get the Contour width of the shape
Definition: canobj.h:1411
Interactive drawing of a EllipticArc.
Definition: sttool.h:1569
Interactive copy an object.
Definition: sttool.h:1253
while iterating a a2dCanvasDocument, this holds the context.
Definition: canobj.h:3212
snap segments middle of other objects in a2dCanvasObject::RestrictToObject()
Definition: restrict.h:118
void ResetContext()
context like corridor and parentobject are reset
Definition: tools.cpp:619
double m_x
x endpoint of line
Definition: polyver.h:232
void SetLineEnd(a2dCanvasObject *end)
defines line end object for line and polyline drawing tools
Definition: sttool.cpp:4690
bool CanUndo()
by default this is a2dCommandProcessor::CanUndo()
Definition: comevt.h:766
double GetEndScaleY()
get scaling in Y for begin and end objects of lines and polylines
Definition: sttool.h:1857
bool m_halted
if a tool is deactivated while m_busy is true, this flag is set
Definition: tools.h:810
a2dCanvasObject * AddCurrent(a2dCanvasObject *objectToAdd, bool withUndo=false, a2dPropertyIdList *setStyles=NULL, a2dCanvasObject *parentObject=NULL)
add the current canvas object to parent as child
Definition: drawing.cpp:6290
int m_mode2
mode to change what is drawn
Definition: sttool.h:1621
All updates of these modes force an update (e.g. update non-pending valid bounding boxes) ...
Definition: canobj.h:1107
a2dLineSegment * AddPoint(double x, double y, a2dLineSegmentPtr seg=NULL, bool afterinversion=true)
add point/segment after a segment.
Definition: polygon.cpp:356
double GetEndScaleY() const
get scaling in Y for begin and end objects of lines and polylines
Definition: canglob.h:850
bool GetUseOpaqueEditcopy()
see SetUseOpaqueEditcopy()
Definition: sttool.h:669
a2dCommandProcessor * GetCommandProcessor() const
Returns a pointer to the command processor associated with this document.
Definition: drawing.h:549
const a2dStroke & GetStroke() const
get the current stroke
Definition: tools.h:551
a2dLineSegment * m_point
last point
Definition: sttool.h:1783
~a2dStToolFixedToolStyleEvtHandler()
destructor
Definition: sttool.cpp:9238
const a2dFill & GetFill() const
get the current fill
Definition: canglob.h:804
a2dConnectionGenerator * GetConnectionGenerator() const
Get class for generating new connection objects between object and pins.
Definition: canglob.h:601
double m_y
y endpoint of line
Definition: polyver.h:235
virtual bool Submit(a2dCommand *command, bool storeIt=true)
Definition: drawing.cpp:5966
virtual void DoStopTool(bool abort)
to do tool specific stuff to stop a tool. Called from StopTool().
Definition: sttool.cpp:9887
virtual void AdjustRenderOptions()
Adjust the rendering options to the needs of this tool.
Definition: sttool.cpp:3875
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
int TakeOverFrom(a2dCanvasObjectList *total, const wxString &type=wxT(""), a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::ALL, const a2dPropertyId *id=NULL)
Move objects fitting the given filter from the total list to this list.
Definition: objlist.cpp:724
void Scale(double scalex, double scaley)
Scale in x and y ( &gt; zero)
Definition: canobj.cpp:2633
used to release object from a a2dCanvasDocument in the current parent
Definition: drawing.h:1437
void SetReleaseSnap(bool releaseSnap)
do not snap if set
Definition: restrict.h:396
static const a2dCanvasObjectFlagsMask VISIBLE
Definition: candefs.h:186
virtual void FinishBusyMode(bool closeCommandGroup=true)
Called when the user finishes editing a distinct object */.
Definition: sttool.cpp:8167
static const a2dSignal sig_toolPoped
sent to new first tool when last first tool was poped
Definition: tools.h:386
void SetMode(int mode)
general integer to set operation modes for a tool (e.g the way it draws)
Definition: sttool.cpp:5999
void ClearStateStrings()
set all state string to empty.
Definition: sttool.cpp:742
a2dCanvasObjectPtr m_parentAddedTo
This is the parent, to which the temporary object was added.
Definition: sttool.h:1235
int m_y
y of mouse in device
Definition: sttool.h:354
double m_startMousey
hold start of drag
Definition: sttool.h:1090
void DuplicateConnectedPins(a2dPin *other, bool undo=false)
pins connected to given other pin, will become part of this pin.
Definition: canpin.cpp:864
const a2dAffineMatrix & GetTransform() const
Get the accumulated transform up to and including m_lworld of the current object. ...
Definition: objlist.h:341
void SetCorridor(const a2dCorridor &corridor)
set a corridor from a list of objects
Definition: tools.cpp:900
Interactive drawing of a polygon.
Definition: sttool.h:1715
bool GetSpline()
certain drawing tools like polygon drawing use this setting
Definition: sttool.h:1750
a2dRestrictionEngine * GetRestrictionEngine()
Get restriction engine (grid snapping)
Definition: canglob.cpp:934
void AdjustRenderOptions()
Adjust the rendering options to the needs of this tool.
Definition: sttool.cpp:4879
static const a2dSignal sig_toolBeforePush
Definition: tools.h:389
virtual bool CreateToolObjects()
Create the editcopy and other tool objects (e.g. decorations)
Definition: sttool.cpp:1260
virtual bool EditProperties(const a2dPropertyId *id, bool withUndo)
edit properties of the object
Definition: canobj.cpp:2722
double m_arcend
end arc
Definition: sttool.h:1686
double m_prev_y
previous y
Definition: sttool.h:1777
double GetUnitsScale()
this is the number that defines the physical dimension in meters / inch/ etc.
Definition: drawing.h:676
virtual void AbortBusyMode()
Called when the user aborts editing a distinct object */.
Definition: sttool.cpp:3297
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
bool GetRelease() const
get release flag
Definition: gen.h:1350
editing tool for a2dCanvasObject&#39;s
Interactive drawing a text object.
Definition: sttool.h:2191
a2dSnapToWhatMask m_snapTargetFeatures
set to the a2dSnapToWhat target features enabled by the engine and/or snap source object ...
Definition: sttool.h:337
bool m_reverse
end to begin wire.
Definition: sttool.h:2491
double m_y1
y endpoint of line
Definition: polyver.h:922
void AbortBusyMode()
Called when the user aborts editing a distinct object */.
Definition: sttool.cpp:1763
void Undo(wxCommandEvent &)
redirect to command processor of document
Definition: sttool.cpp:244
Interactive drawing of a EllipticArc.
Definition: sttool.h:1436
void SetShiftKeyDown(bool shiftDown)
some snapping may depend on shift key being down
Definition: restrict.h:390
virtual void CleanupToolObjects()
Cleanup the editcopy other tool objects (e.g. decorations)
Definition: sttool.cpp:1265
a2dEndsLine with begin and/or end object.
Definition: canprim.h:1174
a2dCanvasObject * GetBegin()
dummies to be compatible with a2dEndsLine
Definition: canprim.h:1201
Interactive drag a a2dPin on a wire.
Definition: sttool.h:2547
const a2dFont & GetFont() const
get current font active font.
Definition: canglob.h:884
bool IsDraggable() const
get if the object can be dragged
Definition: canobj.h:1683
void CaptureMouse()
redirect all mouse events for the canvas to this object
Definition: sttool.cpp:7228
double GetMaxY() const
get maximum Y of the boundingbox
Definition: bbox.cpp:322
double GetWidth() const
returns width of the boundingbox
Definition: bbox.cpp:328
a2dCanvasObject * GetParentObject()
parent object relative to which the actions take place.
Definition: tools.h:684
An object of this class will update a a2dIterC with the required information.
Definition: canobj.h:3123
void OnEnter(wxMouseEvent &event)
when dragging an object from another window into the tool its window, this window wants to have the f...
Definition: sttool.cpp:8016
void SetY2(double y2)
Set Y2 of arc being end point of arc.
Definition: canprim.h:888
void SetStroke(const a2dStroke &stroke)
set stroke if used inside a tool
Definition: tools.cpp:817
void SetPathType(a2dPATH_END_TYPE pathtype)
Set when m_contourwidth != 0 what is the end of the line should be.
Definition: sttool.cpp:4672
virtual void DeviceDrawAnnotation(const wxString &text, wxCoord x, wxCoord y, const wxFont &font)
text drawn in device coordinates
Definition: drawer2d.h:672
a2dBaseTool * GetFirstTool() const
get currently used eventhandler (always the first in the list)
Definition: tools.cpp:91
double m_arcend
end arc
Definition: sttool.h:1610
bool m_draggingCanvas
used to indicate that dragging canvas is in action.
Definition: sttool.h:747
virtual void SetEndScaleX(double xs)
dummies to be compatible with a2dEndsLine
Definition: canprim.h:1095
void SetMode(int mode)
mode of drawing, can be swicthed with Tab key.
Definition: sttool.cpp:4471
virtual ~a2dStDrawTool()
destructor
Definition: sttool.cpp:1707
select objects in a rectangle area
Definition: drawing.h:2488
a2dConnectionGenerator * m_connectionGenerator
Use this connection generator for wires and pins.
Definition: sttool.h:394
void OnMouseEvent(wxMouseEvent &event)
called on mouse events
Definition: sttool.cpp:809
void SetEndScaleY(double ys)
scaling in Y for begin and end objects of lines and polylines
Definition: sttool.cpp:6723
void SetPosXY(double x, double y, bool restrict=false)
set position to x,y
Definition: canobj.cpp:1624
a2dCanvasObject * IsHitWorld(double x, double y, int layer=wxLAYER_ALL, a2dHitOption option=a2dCANOBJHITOPTION_NONE, bool filterSelectableLayers=false)
do a hittest on the view at coordinates x,y
Definition: drawer.cpp:1565
void SetFont(const a2dFont &font)
used for to set the font for non Text objects
Definition: canglob.cpp:971
bool Start(a2dCanvasObject *object, bool setTo)
start removing properties from the object given, and down.
Definition: algos.cpp:784
bool Translate(double x, double y)
Translate by dx, dy:
Definition: afmatrix.cpp:420
virtual void AbortBusyMode()
Called when the user aborts editing a distinct object */.
Definition: tools.cpp:770
void OnKeyUp(wxKeyEvent &event)
called on keyup events
Definition: sttool.cpp:685
void SetPathType(a2dPATH_END_TYPE pathtype)
Set when m_contourwidth != 0 what is the end of the line should be.
Definition: canprim.h:1111
double m_start_y
start y
Definition: sttool.h:1691
void SetLineBegin(a2dCanvasObject *begin)
set current line begin object for line and polyline.
Definition: canglob.h:835
const a2dFill & GetFill() const
get the current fill
Definition: tools.h:542
virtual void GenerateAnotation()
to display a string along with a tool drawing.
Definition: sttool.cpp:6149
const a2dStroke * a2dTRANSPARENT_STROKE
global a2dStroke stock object for TRANSPARENT stroking
int m_dragstartx
x of mouse in device at start drag
Definition: sttool.h:753
double GetBboxHeight()
get height of the boundingbox in world coordinates relative to its parents
Definition: canobj.h:706
wxString & GetRedoMenuLabel()
by default this is a2dCommandProcessor::GetRedoMenuLabel()
Definition: comevt.h:764
wxUint8 m_editOpacityFactor
when using cloned style for editcopy, use this opacity.
Definition: sttool.h:412
a2dStTool(a2dStToolContr *controller)
Definition: sttool.cpp:982
Event sent to a2dCommandProcessor.
Definition: comevt.h:701
a2dVertexList * m_points
points sofar
Definition: sttool.h:1780
virtual bool EliminateMatrix()
reduce matrix to identity
Definition: canobj.cpp:6191
perform snapping to snapping vector path returned by a2dCanvasObject::GetSnapVpath() ...
Definition: restrict.h:139
void Add(a2dVpathSegment *item)
Append a new segment, which is owned by this class now.
Definition: vpath.h:123
void SetToolWantsEventToContinue(bool continueEvent=true)
if tool want an event to be handled by the view, even if already processed.
Definition: drawer.h:1219
if set, clone members (e.g. line end styles), otherwise ref-copy them
Definition: gen.h:1203
void ZoomPan()
zoompan from popup menu (used while another tool is active)
Definition: sttool.cpp:352
void OnPaint(wxPaintEvent &event)
handler for paint event
Definition: sttool.cpp:1387
see a2dComEvent
Definition: gen.h:371
a2dSmrtPtr< a2dVectorPath > m_templateObject
object to clone to use as start
Definition: sttool.h:2466
a2dCanvasObject * Find(a2dCanvasObject *obj) const
return the object if it is part of the list
Definition: objlist.cpp:553
int m_dragstarty
y of mouse in device at start drag
Definition: sttool.h:755
void RenderAnotation()
to render the tools its anotation text.
Definition: sttool.cpp:1479
void RemoveOverlayObject(a2dCanvasObject *obj)
remove from the list of overlay objects (must be children of m_top)
Definition: drawer.cpp:979
double GetContourWidthInDataBaseUnits() const
get the Contour width of shapes in the document its units
Definition: canglob.cpp:1052
virtual bool OnPushNewTool(a2dBaseTool *newtool)
halts the tool is busy
Definition: sttool.cpp:1076
void GetTextExtent(const wxString &string, wxCoord *w, wxCoord *h, wxCoord *descent=NULL, wxCoord *externalLeading=NULL)
return text extends of string
Definition: sttool.cpp:1069
bool RotateObject90LeftRight(bool right)
rotate object of first tool on the stack, when appropriate.
Definition: sttool.cpp:3734
virtual bool PushTool(a2dBaseTool *handler)
push/pop tool:
Definition: tools.cpp:335
double GetEndScaleX()
scale begin and end object with this factor in X
Definition: polygon.h:389
void SetMode(int mode)
general integer to set operation modes for a tool (e.g the way it draws)
Definition: sttool.cpp:4127
a2dRect
Definition: canprim.h:440
a2dCanvasObject * IsHitWorld(a2dIterC &ic, a2dHitEvent &hitEvent)
If the position (x,y) is within the object return this.
Definition: canobj.cpp:3415
static const wxEventType sm_showCursor
Definition: sttool.h:791
void OnComEvent(a2dComEvent &event)
called when a tool has changed (fill stroke layer spline )
Definition: sttool.cpp:1497
The a2dBoundingBox class stores one a2dBoundingBox of a a2dCanvasObject.
Definition: bbox.h:39
bool Invert(void)
Invert matrix.
Definition: afmatrix.cpp:197
wxFont m_annotateFont
font to use for anotation
Definition: tools.h:842
void AssertUnique()
Check if all objects are only once in the list.
Definition: objlist.cpp:729
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 SetX2(double x2)
Set X2 of arc being end point of arc.
Definition: canprim.h:886
double m_arcstart
start arc
Definition: sttool.h:1608
virtual a2dVpathSegment * Clone()
create exact copy
Definition: polyver.cpp:3554
void SetMode(int mode)
general integer to set operation modes for a tool (e.g the way it draws)
Definition: sttool.cpp:6497
virtual bool RemoveProperty(const a2dPropertyId *id, bool all=true)
This function is called by a2dPropertyId to remove a property from the list.
Definition: gen.cpp:1573
bool m_boxCenterDrag
drag from origin of object or center of bbox
Definition: sttool.h:1238
void SetRouteWhenDrag(bool routeWhenDrag)
route also while dragging object
Definition: connectgen.h:338
virtual void TriggerReStartEdit(wxUint16 editmode)
trigger restart editing (after undo event or when changing editing mode )
Definition: edit.cpp:1879
double GetEnd()
return end angle
Definition: canprim.h:743
void OnEnter(wxMouseEvent &event)
when dragging an object from another window into the tool its window, this window wants to have the f...
Definition: sttool.cpp:3779
double m_startObjectx
hold start of drag
Definition: sttool.h:2075
double GetMinY() const
get minimum Y of the boundingbox
Definition: bbox.cpp:310
void SetMode(int mode)
mode of drawing, can be swicthed with Tab key.
Definition: sttool.cpp:9483
virtual void SetStateString(const wxString &message=wxEmptyString, size_t field=3)
function called at mouse events, the default displays cursor in statusbar.
Definition: sttool.cpp:753
double m_startObjecty
hold start of drag
Definition: sttool.h:1164
virtual void AdjustShift(double *x, double *y)
This is overriden by copy tools to have a minimum distance between original and copy.
Definition: sttool.cpp:3478
a2dDrawing * GetDrawing() const
get drawing via top object
Definition: drawer.cpp:726
void DuplicateConnectedToOtherPins(bool undo=false)
all connections to this pins, will become available in those connected pins too.
Definition: canpin.cpp:836
virtual bool CreateToolObjects()
Create the editcopy and other tool objects (e.g. decorations)
Definition: sttool.cpp:2433
virtual bool EnterBusyMode()
starts a new action (e.g drawing something ) in a tool that is already pushed.
Definition: sttool.cpp:9901
virtual void AdjustShift(double *x, double *y)
This is overriden by copy tools to have a minimum distance between original and copy.
Definition: sttool.cpp:2863
a2dArc centered at x,y
Definition: canprim.h:823
bool AddPendingUpdatesOldNew()
adds current and future boundingbox of the objects with pending flag set, to the pendinglist of all a...
Definition: drawing.cpp:525
virtual bool EnterBusyMode()
starts a new action (e.g drawing something ) in a tool that is already pushed.
Definition: sttool.cpp:1147
double m_x1
x endpoint of line
Definition: polyver.h:919
a2dCanvasObjectPtr m_dragPinObj
dummy object that is dragged
Definition: sttool.h:2585
virtual bool PopTool(a2dSmrtPtr< a2dBaseTool > &poped, bool force=true)
specialize to keep m_topTool tool active
Definition: sttool.cpp:461
void SetCaptured(a2dCanvasObject *captured)
set the object that is captured for events in the a2dDrawing.
Definition: drawer.h:638
void SetCaret(int position)
set position of caret (-1 means off)
Definition: cantext.h:254
basetype GetPropertyValue(const a2dObject *obj) const
Get the property value in obj.
Definition: id.inl:325
a2dVpath * GetSegments()
modify point at index to x,y
Definition: vpath.h:117
static a2dPinClass * Any
used to ask for a new default pin on an object.
Definition: canpin.h:763
void SetStart(double start)
set start angle
Definition: canprim.h:730
void OnDoEvent(a2dCommandProcessorEvent &event)
handler for Do event
Definition: sttool.cpp:1492
a2dCanvasGlobal * a2dCanvasGlobals
global a2dCanvasGlobal to have easy access to global settings
Definition: canglob.cpp:1234
virtual bool Redo()
Redo one command or command group.
Definition: drawing.cpp:6029
all headers of the canvas module
void OnKeyDown(wxKeyEvent &event)
called on key down events
Definition: sttool.cpp:1769
#define EVT_UNDO(func)
event sent from a2DocumentCommandProcessor when a command is undone
Definition: comevt.h:797
static a2dPropertyIdBool * PROPID_ToolDecoration
set for objects that act as tool decorations, when a tool is in action.
Definition: canobj.h:2675
a2dCanvasObject for a Vector Path
Definition: vpath.h:55
size_t GetNumberOfSegments()
get the number of points in the pointlist
Definition: polygon.h:229
void OnChar(wxKeyEvent &event)
called on key events
Definition: sttool.cpp:1798
a clone is created which is draged in an outline mode, original stays at position until drag is finis...
Definition: sttool.h:85
virtual void DoStopTool(bool abort)
to do tool specific stuff to stop a tool. Called from StopTool().
Definition: sttool.cpp:8134
The a2dToolContr is the base class for Tool controller classes.
Definition: tools.h:87
a2dSnapToWhatMask GetSnapSourceFeatures() const
Definition: restrict.h:227
void SetMode2(int mode)
change mode of drawing
Definition: sttool.cpp:6255
void MouseToToolWorld(int x, int y, double &xWorldLocal, double &yWorldLocal)
calculate world coordinates from devide coordinates
Definition: sttool.cpp:1622
virtual bool StartEditingObject(a2dCanvasObject *objectToEdit)
start editing this object
Definition: sttool.cpp:926
virtual bool EnterBusyMode()
starts a new action (e.g drawing something ) in a tool that is already pushed.
Definition: sttool.cpp:8148
This template class is for property ids with a known data type.
Definition: id.h:477
Drag and Copy Selected canvasObjects.
Definition: sttool2.h:274
Vector Path.
Definition: polyver.h:1211
static a2dPropertyIdTagVec * PROPID_Tags
used in tool when grouping using tags
Definition: canobj.h:2721
void AddCurrent(a2dCanvasObject *objectToAdd)
add the current canvas object to parent as child
Definition: sttool.cpp:1087
void SetMode(int mode)
general integer to set operation modes for a tool (e.g the way it draws)
Definition: sttool.cpp:6194
bool GetBusy()
Check if the tool is busy editing a distinct object */.
Definition: tools.h:513
a2dSnapToWhatMask m_snapSourceFeatures
set to the a2dSnapToWhat features enabled by the engine for the source object
Definition: sttool.h:334
void AdjustRenderOptions()
Adjust the rendering options to the needs of this tool.
Definition: sttool.cpp:1807
Interactive drawing of a polyline.
Definition: sttool.h:1806
virtual void RenderTopObject(wxUint32 documentDrawStyle, wxUint8 id)
does render the top object in the given style.
Definition: drawer.cpp:2306
void EndTool(wxCommandEvent &)
End the current active tool if not busy.
Definition: sttool.cpp:256
Interactive drawing of a polygon.
Definition: sttool.h:2426
double GetEndScaleX()
get scaling in X for begin and end objects of lines and polylines
Definition: sttool.h:1854
a2dCanvasObject * GetLineEnd()
get current line end object for line and polyline drawing tools
Definition: sttool.h:1846
int CollectObjects(a2dCanvasObjectList *total, const wxString &classname=wxT(""), a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::ALL, const a2dPropertyId *id=0, const a2dBoundingBox &bbox=wxNonValidBbox) const
Copy objects with the right conditions to the total list.
Definition: canobj.cpp:4495
a2dStToolContr * m_stcontroller
tools using this controller
Definition: sttool.h:2350
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
virtual void FinishBusyMode(bool closeCommandGroup=true)
Called when the user finishes editing a distinct object */.
Definition: sttool.cpp:7690
virtual void CleanupToolObjects()
Cleanup the editcopy other tool objects (e.g. decorations)
Definition: sttool.cpp:3389
double m_startMouseyw
hold start of drag
Definition: sttool.h:2081
void Append(a2dCanvasObject *obj)
append a a2dCanvasObject to the childobjects
Definition: canobj.cpp:6224
a2dSmrtPtr< a2dText > m_templateObject
object to clone to use as start
Definition: sttool.h:2223
void OnComEvent(a2dComEvent &event)
Definition: sttool.cpp:8759
double GetHeight() const
return height
Definition: canprim.h:339
virtual void DragAbsolute(double x, double y)
called when dragging is in progress
Definition: sttool.cpp:3651
virtual void SetActive(bool active=true)
set the tool active or inactive.
Definition: tools.cpp:648
a2dCanvasObject * GetParent() const
get parent object of the pin
Definition: canpin.h:295
virtual void AdjustShift(double *x, double *y)
This is overriden by copy tools to have a minimum distance between original and copy.
Definition: sttool.cpp:3024
virtual ~a2dStTool()
destructor
Definition: sttool.cpp:1043
void PopCursor()
pop a cursor from the cursor stack, and set display cursor to back
Definition: drawer.cpp:1059
virtual void SetLayer(wxUint16 layer)
set layer index where this object is drawn upon.
Definition: canobj.cpp:5920
bool m_renderOriginal
if yes, the original object is rendered in place
Definition: sttool.h:397
void SetEnd(a2dCanvasObject *end)
set object to draw as end point
Definition: polygon.cpp:1840
void SetMode2(int mode)
change mode of drawing
Definition: sttool.cpp:6570
Interactive Selection of an Object.
Definition: sttool.h:898
virtual bool CreateToolObjects()
Create the editcopy and other tool objects (e.g. decorations)
Definition: sttool.cpp:3362
void SetOpacityFactor(wxUint8 OpacityFactor)
when enabling m_useOpacityFactor, this is how transparent
Definition: drawer2d.cpp:550
const a2dDoMu & GetSnapGridY() const
Get vertical center snapping distance (zero if disabled)
Definition: restrict.h:156
stack based tools controller and tools for drawing and editing.
void ReleaseMouse()
release the mouse capture for this object
Definition: sttool.cpp:7763
seperate the object from the document, and layer, so it will be draged on top of all other objects...
Definition: sttool.h:81
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
void SetMousePopupMenu(wxMenu *mousemenu)
to set the current mouse menu of the controller
Definition: sttool.cpp:237
virtual bool LinkReferences(bool ignoreNonResolved=false)
link references to their destination
Definition: gen.cpp:4862
Interactive drawing of a Ellipse.
Definition: sttool.h:1523
int m_xanotation
x position of anotation text
Definition: sttool.h:343
virtual void GenerateAnotation()
to display a string along with a tool drawing.
Definition: sttool.cpp:2169
~a2dStToolEvtHandler()
destructor
Definition: sttool.cpp:8623
virtual void GenerateAnotation()
to display a string along with a tool drawing.
Definition: sttool.cpp:1346
void SetRestrictPoint(double xSnap, double ySnap)
sets the point for snapping to
Definition: restrict.h:337
void StopTool(bool abort=false)
call to stop a tool, internal and external.
Definition: tools.cpp:785
for changing boolean select flag values inside canvas objects
Definition: drawing.h:1715
a2dPin * FindPin(a2dCanvasObject *root, double x, double y)
Helper function to find a pin in a DIRECT child object of the given root object.
Definition: sttool.cpp:4895
void MouseToToolWorld(int x, int y, double &xWorldLocal, double &yWorldLocal)
Definition: drawer.cpp:1097
virtual bool CreateToolObjects()
Create the editcopy and other tool objects (e.g. decorations)
Definition: sttool.cpp:2688
void SetImageType(wxBitmapType type)
set type of image for saving
Definition: canimage.h:142
void SetY1(double y1)
Set Y1 of arc being begin point of arc.
Definition: canprim.h:884
int m_mode2
way of drawing
Definition: sttool.h:1680
double m_prev_x
previous x
Definition: sttool.h:1775
virtual void SetActive(bool active=true)
set the tool active or inactive.
Definition: sttool.cpp:1099
CloneOptions
options for cloning
Definition: gen.h:1200
double DeviceToWorldXRel(double x) const
convert x relative from device to world coordinates
Definition: drawer2d.h:444
bool DisconnectEvent(wxEventType type, wxEvtHandler *eventSink)
Definition: gen.cpp:902
bool GetDraggable() const
get if the object can be dragged
Definition: canobj.h:1676
behaviour model of a2dStTool tools
Definition: sttool.h:2287
virtual void CloseCommandGroup()
called when ending an editing operation (e.g. mouse up)
Definition: tools.cpp:883
virtual void GenerateAnotation()
to display a string along with a tool drawing.
Definition: sttool.cpp:6413
a2dBoundingBox & GetBbox()
get boundingbox in world coordinates exclusive stroke width relative to its parent ...
Definition: canobj.cpp:3175
Contain one drawing as hierarchical tree of a2dCanvasObject&#39;s.
Definition: drawing.h:434
a2dText * GetTemplateObject() const
set template for line object
Definition: sttool.h:2209
wxFrame * m_where
statusbar frame
Definition: sttool.h:722
virtual bool RestrictPoint(double &x, double &y, wxUint32 sourceRequired=snapToAll, bool ignoreEngine=false)
Restrict a single point of a line or polyline.
Definition: restrict.cpp:227
void SetRadius(double radius)
set radius of the Arc
Definition: canprim.cpp:2971
void ZoomUndoMenu(wxCommandEvent &)
go to previous zoom area (used while another tool is active)
Definition: sttool.cpp:325
double GetEndScaleX() const
get scaling in X for begin and end objects of lines and polylines
Definition: canglob.h:847
const double wxPI
defines PI
Definition: artglob.cpp:28
void SetFill(const a2dFill &fill)
Set a fill for the object which will be used instead of the layer fill.
Definition: canobj.cpp:2874
double m_startObjectx
hold start of drag
Definition: sttool.h:1162
virtual void GenerateAnotation()
to display a string along with a tool drawing.
Definition: sttool.cpp:6747
a2dEllipticArc centered at x,y
Definition: canprim.h:697
snap to pins in other objects
Definition: restrict.h:111
void StartToEdit(a2dCanvasObject *startObject)
start editing this object
Definition: edit.cpp:1445
virtual void AdjustShift(double *x, double *y)
This is overriden by copy tools to have a minimum distance between original and copy.
Definition: sttool.cpp:7861
static void SetIgnoreAllSetpending(bool value=true)
set static IgnoreAllSetpending flag
Definition: canobj.h:2307
bool EliminateMatrix()
reduce matrix to identity without replacing object
Definition: polygon.cpp:812
const a2dFill * a2dTRANSPARENT_FILL
global a2dFill stock object for TRANSPARENT filling
void SetEnd(double end)
set end angle
Definition: canprim.h:740
virtual bool PopTool(a2dBaseToolPtr &poped, bool force=true)
remove first tool on the tool stack
Definition: tools.cpp:364
#define a2dREFOBJECTPTR_KEEPALIVE
Definition: gen.h:1631
a2dPATH_END_TYPE GetPathType()
get when m_contourwidth != 0 what is the end of the line looks like.
Definition: canprim.h:1114
sttool.cpp Source File -- Sun Oct 12 2014 17:04:25 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation