wxArt2D
mastertoolgroups4.cpp
1 /*! \file editor/src/mastertoolgroups4.cpp
2  \author Klaas Holwerda
3  \date Created 15/02/2013
4 
5  Copyright: 2012-2012 (c) Klaas Holwerda
6 
7  Licence: wxWidgets Licence
8 
9  RCS-ID: $Id: mastertoolgroups4.cpp,v 1.13 2009/04/23 19:35:23 titato Exp $
10 */
11 
12 #include "a2dprec.h"
13 
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17 
18 #ifndef WX_PRECOMP
19 #include "wx/wx.h"
20 #endif
21 
22 #include "wx/canvas/canmod.h"
23 //#include "wx/filename.h"
24 
25 #include <float.h>
26 #include "wx/canvas/sttool.h"
27 #include "wx/canvas/sttool2.h"
29 
30 //----------------------------------------------------------------------------
31 // a2dMasterTagGroups33
32 //----------------------------------------------------------------------------
33 
34 bool a2dMasterTagGroups33::m_selectMoreAtShift = false;
35 
36 IMPLEMENT_CLASS( a2dMasterTagGroups33 , a2dMasterDrawBase )
37 
38 BEGIN_EVENT_TABLE( a2dMasterTagGroups33 , a2dMasterDrawBase )
39  EVT_MOUSE_EVENTS( a2dMasterTagGroups33 ::OnMouseEvent )
40  EVT_CHAR( a2dMasterTagGroups33 ::OnChar )
41  EVT_KEY_DOWN( a2dMasterTagGroups33 ::OnKeyDown )
42  EVT_KEY_UP( a2dMasterTagGroups33 ::OnKeyUp )
43  EVT_COM_EVENT( a2dMasterTagGroups33::OnComEvent )
44  EVT_TIMER( -1, a2dMasterTagGroups33::OnTimer )
45 END_EVENT_TABLE()
46 
47 a2dMasterTagGroups33 ::a2dMasterTagGroups33 ( a2dStToolContr* controller ):
48  m_timer( this ),
49  m_selectionIfNoDoubleClick( false ),
50  m_drawWireIfNoDoubleClick( false ),
51  m_AllowDoubleClickModifier( false ),
52  m_editIfDelayed( false ),
53  m_startEditIfDelayed( true ),
54  m_AllowDelayedEdit( false ),
55  m_shiftWasDown( false ),
56  m_ctrlWasDown( false ),
57  m_altWasDown( false ),
58 
59  a2dMasterDrawBase( controller )
60 {
61  controller->SetDefaultBehavior( controller->GetDefaultBehavior() | wxTC_NoDefaultKeys | wxTC_NoDefaultMouseActions );
62  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_Select );
63  m_drawWire = false;
64  a2dCanvasGlobals->ConnectEvent( a2dEVT_COM_EVENT, this );
65 }
66 
67 a2dMasterTagGroups33 ::~a2dMasterTagGroups33 ()
68 {
69  a2dCanvasGlobals->DisconnectEvent( a2dEVT_COM_EVENT, this );
70 }
71 
72 wxString a2dMasterTagGroups33 ::GetToolString() const
73 {
74  wxString str = GetClassInfo()->GetClassName();
75  if ( m_drawWire )
76  return str + " Wires";
77  if ( m_dlgOrEdit )
78  return str + " Dlg";
79  return str;
80 }
81 
83 {
84 }
85 
87 {
89  m_toolBusy = false;
90 }
91 
93 {
95 
96  if ( selected )
97  {
98  DeselectAll();
99  }
100  if( GetBusy() && m_dragStarted )
101  {
102  switch( m_mode )
103  {
104  case mode_zoom:
105  case mode_select:
106  case mode_cntrlselect:
107  {
108  break;
109  }
110  default:
111  break;
112  }
113  }
114 
116 }
117 
119 {
120  a2dStTool::SetActive( active );
121  m_pending = true;
122 
123  if ( active )
124  {
125  SetToolMode( false, false, false );
126  }
127 }
128 
129 void a2dMasterTagGroups33::OnComEvent( a2dComEvent& event )
130 {
131  if ( GetEvtHandlerEnabled() )
132  {
133  a2dSignal comId = event.GetId();
134 
135  if ( event.GetId() == a2dBaseTool::sig_toolPoped )
136  {
137  }
138 
140  if ( tool && tool->GetActive() && tool->GetEvtHandlerEnabled() && tool->GetDrawingPart() )
141  {
142  bool OnSelected = false;
143 
144  if ( !m_dlgOrEditModal )
145  {
146  a2dCanvasObjectList objects;
148  if ( objects.size() > 0 )
149  OnSelected = true;
150  }
151  else
152  {
153  if ( /*IsShown_styleDlg &&*/ m_modehit && m_modehit->GetSelected() )
154  {
155  a2dCanvasObjectList objects;
157  if ( objects.size() > 0 )
158  OnSelected = true;
159  }
160  }
161  if ( !OnSelected )
162  {
163  //m_styleDlg->GetFill()
164  //m_styleDlg->GetStroke()
165 
167  a2dFill f = GetDrawing()->GetHabitat()->GetFill();
168  if ( comId == a2dHabitat::sig_changedFill && ! tool->GetFill().IsSameAs( f ) )
169  {
170  if ( m_modehit )
171  docCmdh->Submit( new a2dCommand_ChangeCanvasObjectStyle( m_modehit, f ) );
172  }
173  a2dStroke s = GetDrawing()->GetHabitat()->GetStroke();
174  if ( comId == a2dHabitat::sig_changedStroke && ! tool->GetStroke().IsSameAs( s ) )
175  {
176  if ( m_modehit )
177  docCmdh->Submit( new a2dCommand_ChangeCanvasObjectStyle( m_modehit, s ) );
178  }
179  }
180  else
181  {
182  if (
183  comId == a2dHabitat::sig_changedFill ||
184  comId == a2dHabitat::sig_changedStroke ||
185  comId == a2dHabitat::sig_changedLayer
186  )
187  {
189  a2dFill f = GetDrawing()->GetHabitat()->GetFill();
190  if ( comId == a2dHabitat::sig_changedFill )
191  {
192  docCmdh->Submit( new a2dCommand_SetFillStrokeMask( tool->GetDrawingPart()->GetShowObject() ) );
193  }
194  a2dStroke s = GetDrawing()->GetHabitat()->GetStroke();
195  if ( comId == a2dHabitat::sig_changedStroke )
196  {
197  docCmdh->Submit( new a2dCommand_SetFillStrokeMask( tool->GetDrawingPart()->GetShowObject() ) );
198  }
199  wxUint16 layer = GetDrawing()->GetHabitat()->GetLayer();
200  if ( comId == a2dHabitat::sig_changedLayer )
201  {
202  docCmdh->Submit( new a2dCommand_SetLayerMask( tool->GetDrawingPart()->GetShowObject(), layer ) );
203  }
204  }
205  }
206  }
207  }
208 
209 
210  event.Skip();
211 }
212 
213 void a2dMasterTagGroups33::OnChar( wxKeyEvent& event )
214 {
215  //wxLogDebug(wxT("key %d"), event.GetKeyCode());
217 
219 
220  if ( selected )
221  {
222  event.Skip();
223  }
224  else if( GetBusy() && m_dragStarted )
225  {
226  switch( m_mode )
227  {
228  case mode_zoom:
229  case mode_select:
230  case mode_cntrlselect:
231  {
232  break;
233  }
234  default:
235  event.Skip();
236  break;
237  }
238  }
239  else
240  event.Skip();
241 }
242 
243 void a2dMasterTagGroups33 ::OnKeyDown( wxKeyEvent& event )
244 {
245  if ( !m_active )
246  {
247  event.Skip();
248  return;
249  }
250 
251  switch( event.GetKeyCode() )
252  {
253  case 'w':
254  case 'W':
255  {
256  m_drawWire = !m_drawWire;
257  SetToolMode( event.m_controlDown, event.m_shiftDown, event.AltDown() );
258  break;
259  }
260  default:
261  if ( event.m_controlDown || event.m_shiftDown || event.AltDown() )
262  SetToolMode( event.m_controlDown, event.m_shiftDown, event.AltDown() );
263  event.Skip();
264  }
265 }
266 
267 void a2dMasterTagGroups33 ::OnKeyUp( wxKeyEvent& event )
268 {
269  if ( !m_active )
270  {
271  event.Skip();
272  return;
273  }
274 
275  switch( event.GetKeyCode() )
276  {
277  case 'w':
278  case 'W':
279  {
280  SetToolMode( event.m_controlDown, event.m_shiftDown, event.AltDown() );
281  break;
282  }
283  default:
284  if ( !event.m_controlDown || !event.m_shiftDown || !event.AltDown() )
285  SetToolMode( event.m_controlDown, event.m_shiftDown, event.AltDown() );
286  event.Skip();
287  }
288 }
289 
290 bool a2dMasterTagGroups33::SetWireCursor( a2dWirePolylineL* wire, const a2dHitEvent& hitinfo, bool ctrl, bool shift, bool alt )
291 {
292  a2dHit how2;
293  int i;
294  float minDist = FLT_MAX;
295  for( i = 0; i < hitinfo.m_extended.size(); i++ )
296  {
297  a2dWirePolylineL* wire2 = wxDynamicCast( hitinfo.m_extended[i].GetObject(), a2dWirePolylineL );
298  if( wire2 && hitinfo.m_extended[i].GetHitType().m_distance < minDist && hitinfo.m_extended[i].GetHitType().IsStrokeHit() )
299  //if( wire2 && hitinfo.m_extended[i].GetHitType().m_distance < minDist && hitinfo.m_extended[i].GetHitType().IsDirectStrokeHit() )
300  {
301  wire = wire2;
302  how2 = hitinfo.m_extended[i].GetHitType();
303  minDist = how2.m_distance;
304  }
305  }
306 
307  if ( wire )
308  {
309  // wire editing mode
310  // check, where the wire was hit:
311  m_modehit = wire;
312  m_modehitinfo = how2;
313  if ( !alt )
314  {
315  switch( how2.m_stroke2 )
316  {
317  case a2dHit::stroke2_vertex:
318  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireVertex ) );
319  SetStateString( _("drag to move vertex on the wire"), STAT_toolHelp );
320  m_mode = mode_editwire_vertex;
321  break;
322  case a2dHit::stroke2_edgehor:
323  case a2dHit::stroke2_edgevert:
324  case a2dHit::stroke2_edgeother:
325  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_WireSegmentInsert ) );
326  SetStateString( _("drag to insert vertex on the wire"), STAT_toolHelp );
327  m_mode = mode_editwire_segmentinsert;
328  break;
329  default:
330  m_modehit = NULL;
331  m_modehitinfo = a2dHit();
332  }
333  }
334  else
335  {
336  switch( how2.m_stroke2 )
337  {
338  case a2dHit::stroke2_vertex:
339  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireDeleteVertex ) );
340  SetStateString( _("click to remove vertex from wire"), STAT_toolHelp );
341  m_mode = mode_editwire_vertex;
342  break;
343  case a2dHit::stroke2_edgehor:
344  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireSegmentHorizontal ) );
345  SetStateString( _("drag to move segment of the wire"), STAT_toolHelp );
346  m_mode = mode_editwire_segmenthorizontal;
347  break;
348  case a2dHit::stroke2_edgevert:
349  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireSegmentVertical ) );
350  SetStateString( _("drag to move segment of the wire"), STAT_toolHelp );
351  m_mode = mode_editwire_segmentvertical;
352  break;
353  case a2dHit::stroke2_edgeother:
354  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireSegment ) );
355  SetStateString( _("drag to move segment, Alt key to insert a vertex on wire"), STAT_toolHelp );
356  m_mode = mode_editwire_segment;
357  break;
358  default:
359  m_modehit = NULL;
360  m_modehitinfo = a2dHit();
361  }
362  }
363  }
364  return true;
365 }
366 
367 void a2dMasterTagGroups33::SetToolMode( bool ctrl, bool shift, bool alt )
368 {
369  a2dCanvasObject* hit = m_modehit;
370  if ( !m_dragStarted )
371  {
372  //GetDrawingPart()->Update( a2dCANVIEW_UPDATE_PENDING );
373  a2dIterC ic( GetDrawingPart() );
374  ic.SetLayer( wxLAYER_ALL );
375  ic.SetObjectFilter( new a2dCanvasObjectFilterLayerMask( wxLAYER_ALL, a2dCanvasOFlags::VISIBLE | a2dCanvasOFlags::SELECTABLE ) );
376  m_hitinfo = a2dHitEvent( m_xwprev, m_ywprev, false, a2dCANOBJHITOPTION_NONE, true );
378  //at the top level the group its matrix is to be ignored.
379  //Since it is normally NOT ignored within a2dCanvasObject, force an inverse.
380  m_hitinfo.m_xyRelToChildren = true;
381 
382  m_mode = mode_none;
383  m_modehit = 0;
384  m_modehitinfo = a2dHit();
385  hit = GetDrawingPart()->GetShowObject()->ChildIsHitWorld( ic, m_hitinfo, true );
386  GetDrawing()->GetHabitat()->GetConnectionGenerator()->SetPinsToBeginState( GetDrawingPart()->GetShowObject() );
387  }
388  a2dPin* pin = NULL;
389  if ( hit )
390  {
391  pin = wxDynamicCast( hit, a2dPin );
392  if ( pin )
393  pin = wxDynamicCast( hit, a2dPin );
394  }
395 
396  if ( !pin && !ctrl && shift )
397  {
398  if ( hit )
399  {
400  m_modehit = hit;
401  SetStateString( _("drag to move object, double click to edit"), STAT_toolHelp );
402  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
403  }
404  else
405  {
406  m_modehit = NULL;
407  SetStateString( _("move to object and click to select"), STAT_toolHelp );
408  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_ARROW ) );
409  }
410  m_mode = mode_select;
411  }
412  /*
413  else if ( !pin && ctrl && shift )
414  {
415  if ( hit )
416  {
417  m_modehit = hit;
418  SetStateString( _("click to select"), STAT_toolHelp );
419  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
420  }
421  else
422  {
423  m_modehit = NULL;
424  SetStateString( _("move to object and click to select"), STAT_toolHelp );
425  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_ARROW ) );
426  }
427  m_mode = mode_cntrlselect;
428  }
429  */
430  else
431  {
432  if ( hit )
433  {
434  // Check if there is pin
435  // This has highest priority
436  a2dHit how2;
437 
439 
440  if ( wire && wire->GetSelected() && m_drawWire )
441  {
442  SetWireCursor( wire, m_hitinfo, ctrl, shift, alt );
443  }
444  else if ( wire )
445  {
446  if ( m_drawWire || ( !m_drawWire && ctrl ) )
447  {
448  GetDrawing()->GetHabitat()->GetConnectionGenerator()->
450  }
451  else
452  wire->RemovePins( true, true );
453 
454 
455  //we did hit a wire, still a pin at this location, can be on a wire or any other object, depending on drawing order.
456  pin = GetDrawing()->GetHabitat()->GetConnectionGenerator()->
457  SearchPinForStartWire( GetDrawingPart()->GetShowObject(), m_xwprev, m_ywprev, a2dPinClass::Any, GetHitMargin() );
458 
459  if( pin )
460  {
461  // if in draw wire mode, we must be able to start a wire on a pin
462  // Else we just drag pins, if not connected to a normal object ( so a wire to wire pin ).
463  if ( m_dragStarted && !pin->IsTemporaryPin() )
464  {
465  if ( !( m_drawWire || ( !m_drawWire && ctrl ) ) &&
466  ( pin->GetParent()->IsConnect() && !pin->FindNonWirePin() )
467  )
468  {
469  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Drag ) );
470  SetStateString( _("drag the pin and reroute wires"), STAT_toolHelp );
471  m_mode = mode_move_pin;
472  m_modehit = pin;
473  }
474  if ( !( m_drawWire || ( !m_drawWire && ctrl ) ) &&
475  ( ( pin->GetParent()->IsConnect() && pin->FindNonWirePin() ) || !pin->GetParent()->IsConnect() )
476  )
477  {
478  if ( pin->GetConnectedPinsNr() <= 1 )
479  {
480  // wire drawing mode
481  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
482  SetStateString( _("drag to rewire"), STAT_toolHelp );
483  m_mode = mode_rewire_pin;
484  if ( !pin->GetParent()->IsConnect() )
485  m_modehit = pin->FindWirePin();
486  }
487  else
488  {
489  // wire drawing mode
490  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
491  SetStateString( _("draw a wire from pin"), STAT_toolHelp );
492  m_mode = mode_drawwire;
493  m_modehit = pin;
494  }
495  }
496  }
497  // If we know we are on an object pin, or at least a wire pin on that location, we can
498  // start a wire without extra Ctrl or special m_drawWire mode.
499  // So we can start multiple wires on a normal pin.
500  else if ( !pin->IsTemporaryPin() &&
501  ( ( pin->GetParent()->IsConnect() && pin->FindNonWirePin() ) || !pin->GetParent()->IsConnect() )
502  )
503  {
504  if ( pin->GetConnectedPinsNr() <= 1 )
505  {
506  // wire drawing mode
507  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
508  SetStateString( _("draw a wire from pin, or drag to rewire"), STAT_toolHelp );
509  m_mode = mode_drawwire;
510  }
511  else
512  {
513  // wire drawing mode
514  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
515  SetStateString( _("draw a wire from pin"), STAT_toolHelp );
516  m_mode = mode_drawwire;
517  }
518  m_modehit = pin;
519  }
520  else if (!m_dragStarted && !( m_drawWire || ( !m_drawWire && ctrl ) ) )
521  {
522  // wire drawing mode
523  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
524  SetStateString( _("Drag the pin or start a wire with a click"), STAT_toolHelp );
525  m_mode = mode_drawwire;
526  m_modehit = pin;
527  }
528  else if ( m_drawWire || ( !m_drawWire && ctrl ) || !m_dragStarted )
529  {
530  // wire drawing mode
531  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
532  SetStateString( _("start a wire with a click"), STAT_toolHelp );
533  m_mode = mode_drawwire;
534  m_modehit = pin;
535  }
536  }
537  else
538  {
539  if ( m_drawWire || ( !m_drawWire && ctrl ) )
540  {
541  // wire drawing mode
542  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
543  SetStateString( _("draw a wire"), STAT_toolHelp );
544  m_mode = mode_drawwire;
545  m_modehit = pin;
546  }
547  else
548  {
549  // a wire is not draggabble, but it might be editable, in that case we can drag segments and vertexes.
550  if( hit->GetEditable() )
551  {
552  SetWireCursor( wire, m_hitinfo, ctrl, shift, alt );
553 /* We do not really want to drag wire do we, anyway connect object are !GetDraggable()?
554  if ( hit->GetSelected() )
555  {
556  m_modehit = hit;
557  if ( event.ControlDown() && event.ShiftDown() )
558  {
559  m_mode = mode_copymulti;
560  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Copy ) );
561  }
562  else //no shift no control
563  {
564  m_mode = mode_dragmulti;
565  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Drag ) );
566  }
567  }
568  else
569  {
570  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
571  m_mode = mode_select;
572  m_modehit = hit;
573  }
574 */
575  }
576  else
577  {
578  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
579  SetStateString( _("click to select object"), STAT_toolHelp );
580  m_mode = mode_select;
581  m_modehit = hit;
582  }
583  }
584  }
585 
586  }
587  else //not a wire
588  {
589  if ( !pin && !shift && !ctrl )
590  {
591  //While moving event, there is no wire nor pin yet, therefore we can just feedback possible pin connection, based on the
592  // m_connectionGenerator.
593  GetDrawing()->GetHabitat()->GetConnectionGenerator()->
595 
596  pin = GetDrawing()->GetHabitat()->GetConnectionGenerator()->
597  SearchPinForStartWire( GetDrawingPart()->GetShowObject(), m_xwprev, m_ywprev, a2dPinClass::Any, GetHitMargin() );
598 
599  if ( pin )
600  {
602  if ( wire && wire->GetSelected() )
603  pin = NULL;
604  }
605  }
606 
607  // if not editing a wire, if pin start a wire draw
608  if( pin )
609  {
610  if ( m_dragStarted && !pin->IsTemporaryPin() )
611  {
612  if ( !( m_drawWire || ( !m_drawWire && ctrl ) ) &&
613  ( pin->GetParent()->IsConnect() && !pin->FindNonWirePin() ) )
614  {
615  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Drag ) );
616  m_mode = mode_move_pin;
617  SetStateString( _("drag the pin and reroute wires"), STAT_toolHelp );
618  m_modehit = pin;
619  }
620  else if ( pin->GetParent()->IsConnect() && !pin->IsConnectedTo() )
621  {
622  // rewire pin mode
623  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
624  SetStateString( _("Rewire this pin"), STAT_toolHelp );
625  m_mode = mode_rewire_pin;
626  m_modehit = pin;
627  }
628  else if ( pin->GetParent()->IsConnect() && !pin->FindNonWirePin() )
629  {
630  // wire drawing mode
631  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
632  SetStateString( _("draw a wire from this pin"), STAT_toolHelp );
633  m_mode = mode_drawwire;
634  m_modehit = pin;
635  }
636  else if ( !pin->GetParent()->IsConnect() && pin->IsConnectedTo() )
637  {
638  // rewire pin mode
639  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
640  SetStateString( _("Rewire this pin"), STAT_toolHelp );
641  m_mode = mode_rewire_pin;
642  m_modehit = pin;
643  }
644  else
645  {
646  m_mode = mode_drawwire;
647  m_modehit = pin;
648  }
649  }
650  else if ( !m_dragStarted && !pin->IsTemporaryPin() )
651  {
652  // wire drawing mode
653  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
654  SetStateString( _("draw a wire from this pin"), STAT_toolHelp );
655  m_mode = mode_drawwire;
656  m_modehit = pin;
657  }
658  }
659  else
660  {
661  if( hit->GetDraggable() )
662  {
663  if ( hit->GetSelected() )
664  {
665  m_modehit = hit;
666  if ( ctrl && shift )
667  {
668  m_mode = mode_copymulti;
669  SetStateString( _("drag to copy selected objects"), STAT_toolHelp );
670  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Copy ) );
671  }
672  else //no shift no control
673  {
674  SetStateString( _("drag to move selected objects"), STAT_toolHelp );
675  m_mode = mode_dragmulti;
676  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Drag ) );
677  }
678  }
679  else
680  {
681  if ( !m_dragStarted )
682  {
683  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
684  SetStateString( _("click to select object, double click to edit"), STAT_toolHelp );
685  m_mode = mode_select;
686  m_modehit = hit;
687  }
688  else
689  {
690  m_mode = mode_drag;
691  m_modehit = hit;
692  SetStateString( _("drag to move object"), STAT_toolHelp );
693  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Drag ) );
694  }
695  }
696  }
697  else
698  {
699  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
700  SetStateString( _("can not drag this object, double click to edit"), STAT_toolHelp );
701  m_mode = mode_select;
702  m_modehit = hit;
703  }
704  }
705  }
706  }
707  else
708  {
709  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_ARROW ) );
710  SetStateString( _("click on object, drag rectangle to select objects"), STAT_toolHelp );
711  m_mode = mode_select;
712  m_modehit = hit;
713  }
714  }
715 }
716 
717 void a2dMasterTagGroups33::OnTimer(wxTimerEvent& event)
718 {
719  if ( m_startEditIfDelayed )
720  m_editIfDelayed = true;
721  if ( m_hadDoubleClick )
722  {
723  m_hadDoubleClick = false;
724  //wxLogDebug( "time DC" );
725  m_selectionIfNoDoubleClick = false;
726  m_drawWireIfNoDoubleClick = false;
727  }
728  else
729  {
730  if ( m_drawWireIfNoDoubleClick )
731  {
732  m_toolBusy = false;
733  m_drawWireIfNoDoubleClick = false;
734 
735  //When pin was generated on a wire at mouse moving), use it here.
736  a2dPin* pin = wxDynamicCast( m_modehit, a2dPin );
737  // if in draw wire mode, we must be able to start a wire on a pin
738  if( pin )
739  {
740  // wire drawing mode
741  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
742  m_mode = mode_drawwire;
743  m_modehit = pin;
744  PushDrawWireTool( m_modehit );
745 
746  wxMouseEvent mouseevent( wxEVT_LEFT_DOWN );
747  mouseevent.m_x = m_dragstartx;
748  mouseevent.m_y = m_dragstarty;
749  mouseevent.m_controlDown = true;
750  mouseevent.m_leftDown = true;
751  mouseevent.SetEventObject(this);
752  mouseevent.SetId( GetDrawingPart()->GetDisplayWindow()->GetId() );
753  m_stcontroller->GetFirstTool()->ProcessEvent( mouseevent );
754 
755  wxMouseEvent mouseevent2( wxEVT_LEFT_UP );
756  mouseevent2.m_x = m_dragstartx;
757  mouseevent2.m_y = m_dragstarty;
758  mouseevent2.m_controlDown = true;
759  mouseevent2.m_leftDown = true;
760  mouseevent2.SetEventObject(this);
761  mouseevent2.SetId( GetDrawingPart()->GetDisplayWindow()->GetId() );
762  m_stcontroller->GetFirstTool()->ProcessEvent( mouseevent2 );
763  }
764  }
765 
766 
767 /* wait and see
768  {
769  if ( !m_modehit )
770  DeselectAll();
771  else
772  {
773  if ( m_modehit->GetSelected() )
774  {
775  if ( m_mode == mode_none && m_modehit->GetSelectable() )
776  m_modehit->SetSelected( ! m_modehit->GetSelected() );
777  }
778  else
779  {
780  if ( m_mode == mode_none && m_modehit->GetSelectable() )
781  {
782  a2dCanvasObject* selected = m_parentobject->GetChildObjectList()->Find( "", "", a2dCanvasOFlags::SELECTED );
783  if ( selected )
784  {
785  DeselectAll();
786  m_modehit->SetSelected( true );
787  }
788  else
789  {
790  m_modehit->SetSelected( true );
791  }
792  }
793  }
794  }
795  }
796 */
797 
798  if ( m_selectionIfNoDoubleClick )
799  {
800  m_toolBusy = false;
801  m_selectionIfNoDoubleClick = false;
802  if ( m_shiftWasDown )
803  {
804  if ( m_modehit && m_modehit->GetSelectable() )
805  {
806  if ( m_modehit->IsSelected() )
807  m_modehit->SetSelected( false );
808  else
809  m_modehit->SetSelected( true );
810  }
811  }
812  else
813  {
814  if ( m_selectMoreAtShift )
815  DeselectAll();
816  else if ( !m_modehit )
817  DeselectAll();
818  if ( m_modehit && m_modehit->GetSelectable() )
819  {
820  if ( m_drawWire )
821  m_modehit->SetSelected( true );
822  else //is conflicting with starting a wire
823  m_modehit->SetSelected( !m_modehitLastSelectState );
824  }
825  }
826  }
827  //wxLogDebug( "time");
828  }
829 }
830 
831 void a2dMasterTagGroups33::OnMouseEvent( wxMouseEvent& event )
832 {
833  //MouseDump( event, "OnM " );
834  //wxLogDebug( "%d %d %d %d ", m_x, m_y, m_dragstartx, m_dragstarty );
835 
836  m_shiftWasDown = event.ShiftDown();
837  m_ctrlWasDown = event.ControlDown();
838  m_altWasDown = event.AltDown();
839 
840  if ( !m_active )
841  {
842  event.Skip();
843  return;
844  }
845  m_x = event.GetX();
846  m_y = event.GetY();
847 
849 
850  if ( event.LeftDClick() &&
851  !m_toolBusy //&&
852  //no need !( event.ControlDown() || event.ShiftDown() )
853  )
854  {
855  m_hadDoubleClick = true;
856  a2dPin* pin = wxDynamicCast( m_modehit, a2dPin );
857  // if in draw wire mode a double click is on a pin, but edit style should be on wire.
858  if( pin )
859  m_modehit = pin->GetParent();
860 
861  EditDlgOrHandles( m_modehit, m_AllowDoubleClickModifier ? m_shiftWasDown: false, m_drawWire );
862  }
863  else if ( event.Dragging() && m_toolBusy && !m_dragStarted )
864  {
865  //we assume dragging starts for real if 5 pixels shift.
866  if ( abs( m_x - m_dragstartx ) >= 5 || abs( m_y - m_dragstarty ) >= 5 )
867  {
868  m_dragStarted = true;
869  SetToolMode( m_ctrlWasDown, m_shiftWasDown, m_altWasDown );
870  m_toolBusy = false;
871  switch( m_mode )
872  {
873  case mode_none:
874  {
875  m_dragStarted = false;
876  m_toolBusy = false;
877  break;
878  }
879  case mode_drawwire:
880  {
881  m_dragStarted = false;
882  m_toolBusy = false;
883  break;
884  }
885  case mode_cntrlselect:
886  DeselectAll();
887  m_toolBusy = true;
888  event.Skip();
889  break;
890  case mode_select:
891  break;
892  case mode_dragmulti:
893  {
894  m_dragStarted = false;
895  PushDragMultiTool( m_modehit );
896  //event.Skip();
897  break;
898  }
899  case mode_copymulti:
900  {
901  m_dragStarted = false;
902  PushCopyMultiTool( m_modehit );
903  //event.Skip();
904  break;
905  }
906  case mode_drag:
907  {
908  m_dragStarted = false;
909  PushDragTool( m_modehit );
910  //event.Skip();
911  break;
912  }
913  case mode_copy:
914  {
915  m_dragStarted = false;
916  PushCopyTool( m_modehit );
917  //event.Skip();
918  break;
919  }
920  case mode_move_pin:
921  {
922  m_dragStarted = false;
923  PushMovePinTool( m_modehit );
924  wxMouseEvent mouseevent( wxEVT_LEFT_DOWN );
925  InitMouseEvent( mouseevent, m_dragstartx, m_dragstarty, event );
926  m_stcontroller->GetFirstTool()->ProcessEvent( mouseevent );
927  break;
928  }
929  case mode_rewire_pin:
930  {
931  m_dragStarted = false;
932  PushRewirePinTool( m_modehit );
933  wxMouseEvent mouseevent( wxEVT_LEFT_DOWN );
934  InitMouseEvent( mouseevent, m_dragstartx, m_dragstarty, event );
935  m_stcontroller->GetFirstTool()->ProcessEvent( mouseevent );
936  break;
937  }
938  case mode_editwire_vertex:
939  {
940  m_dragStarted = false;
941  PushEditWireVertexTool( m_modehit, m_modehitinfo.m_index );
942  wxMouseEvent mouseevent( wxEVT_LEFT_DOWN );
943  InitMouseEvent( mouseevent, m_dragstartx, m_dragstarty, event );
944  m_stcontroller->GetFirstTool()->ProcessEvent( mouseevent );
945  break;
946  }
947  case mode_editwire_segmenthorizontal:
948  {
949  m_dragStarted = false;
950  PushEditWireSegmentHorizontalTool( m_modehit, m_modehitinfo.m_index );
951  wxMouseEvent mouseevent( wxEVT_LEFT_DOWN );
952  InitMouseEvent( mouseevent, m_dragstartx, m_dragstarty, event );
953  m_stcontroller->GetFirstTool()->ProcessEvent( mouseevent );
954  break;
955  }
956  case mode_editwire_segmentvertical:
957  {
958  m_dragStarted = false;
959  PushEditWireSegmentVerticalTool( m_modehit, m_modehitinfo.m_index );
960  wxMouseEvent mouseevent( wxEVT_LEFT_DOWN );
961  InitMouseEvent( mouseevent, m_dragstartx, m_dragstarty, event );
962  m_stcontroller->GetFirstTool()->ProcessEvent( mouseevent );
963  break;
964  }
965  case mode_editwire_segmentinsert:
966  {
967  m_dragStarted = false;
968  PushEditWireSegmentInsertTool( m_modehit, m_modehitinfo.m_index );
969  wxMouseEvent mouseevent( wxEVT_LEFT_DOWN );
970  InitMouseEvent( mouseevent, m_dragstartx, m_dragstarty, event );
971  m_stcontroller->GetFirstTool()->ProcessEvent( mouseevent );
972  break;
973  }
974  case mode_editwire_segment:
975  {
976  m_dragStarted = false;
977  PushEditSegmentTool( m_modehit, m_modehitinfo.m_index );
978  wxMouseEvent mouseevent( wxEVT_LEFT_DOWN );
979  InitMouseEvent( mouseevent, m_dragstartx, m_dragstarty, event );
980  m_stcontroller->GetFirstTool()->ProcessEvent( mouseevent );
981  break;
982  }
983 
984  default:
985  m_toolBusy = true;
986  break;
987  }
988  }
989  }
990  else if ( event.Dragging() && m_toolBusy && m_dragStarted )
991  {
992  }
993  else if ( event.Moving() && !m_toolBusy && !m_selectionIfNoDoubleClick && !m_drawWireIfNoDoubleClick )
994  {
995  SetToolMode( m_ctrlWasDown, m_shiftWasDown, m_altWasDown );
996  event.Skip();
997  }
998  else if( event.LeftDown() && !m_toolBusy )
999  {
1000  //detect Double Click
1001  m_selectionIfNoDoubleClick = false;
1002  m_drawWireIfNoDoubleClick = false;
1003  m_editIfDelayed = false;
1004 
1005  SetStateString( "" );
1006  m_dragStarted = false;
1007  m_xprev = m_x;
1008  m_yprev = m_y;
1009  m_dragstartx = m_x;
1010  m_dragstarty = m_y;
1011 
1012  if( !m_modehit )
1013  {
1014  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
1015  m_mode = mode_select;
1016  event.Skip();
1017  m_toolBusy = false;
1018  return;
1019  }
1020 
1021  switch( m_mode )
1022  {
1023  case mode_select:
1024  m_toolBusy = true;
1025  break;
1026  case mode_move_pin:
1027  m_toolBusy = true;
1028  break;
1029  case mode_rewire_pin:
1030  m_toolBusy = true;
1031  break;
1032  case mode_drawwire:
1033  m_toolBusy = true;
1034  break;
1035  case mode_editwire_vertex:
1036  {
1037  if ( m_altWasDown )
1038  {
1039  PushEditWireVertexTool( m_modehit, m_modehitinfo.m_index );
1040  event.Skip();
1041  }
1042  else
1043  {
1044  m_toolBusy = true;
1045  }
1046  break;
1047  }
1048  case mode_editwire_segmenthorizontal:
1049  case mode_editwire_segmentvertical:
1050  case mode_editwire_segmentinsert:
1051  case mode_editwire_segment:
1052  m_toolBusy = true;
1053  break;
1054  default:
1055  // not know until a drag started or not.
1056  m_mode = mode_none;
1057  m_toolBusy = true;
1058  event.Skip();
1059  }
1060  }
1061  else if( event.LeftUp() && m_toolBusy && m_dragStarted )
1062  {
1063  m_toolBusy = false;
1064  m_dragStarted = false; //end of drag
1065  m_mode = mode_none;
1066  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
1067  }
1068  else if( event.LeftUp() && m_toolBusy )
1069  {
1070  m_timer.Start( a2dDoubleClickWait, true );
1071  m_toolBusy = false;
1072  m_dragStarted = false; //never started but still
1073 
1074  //reserve for double click if it happens
1075  m_modehitLastSelectState = false;
1076  if ( m_modehit )
1077  m_modehitLastSelectState = m_modehit->GetSelected();
1078 
1079  if ( m_AllowDelayedEdit && m_editIfDelayed ) //set by timer if it arrived there first, meaning LeftUp was delayed.
1080  {
1081  m_editIfDelayed = false;
1082  EditDlgOrHandles( m_modehit, m_AllowDoubleClickModifier ? m_shiftWasDown: false, m_drawWire ); //reuse from the LeftDown event.
1083  }
1084  if ( !m_ctrlWasDown )
1085  {
1086  m_selectionIfNoDoubleClick = true; //canceled by/in timer if double click came within time.
1087  }
1088  if ( m_mode == mode_drawwire )
1089  {
1090  m_drawWireIfNoDoubleClick = true; //canceled by/in timer if double click came within time.
1091  }
1092  m_mode = mode_none;
1093  }
1094  else if( event.RightDown() && !GetBusy() )
1095  {
1096  PushZoomTool();
1097  event.Skip();
1098  }
1099  else
1100  {
1101  event.Skip();
1102  }
1103 }
1104 
1105 //----------------------------------------------------------------------------
1106 // a2dMasterTagGroups4
1107 //----------------------------------------------------------------------------
1108 
1109 bool a2dMasterTagGroups4::m_selectMoreAtShift = false;
1110 
1111 IMPLEMENT_CLASS( a2dMasterTagGroups4 , a2dMasterDrawBase )
1112 
1113 BEGIN_EVENT_TABLE( a2dMasterTagGroups4 , a2dMasterDrawBase )
1114  EVT_MOUSE_EVENTS( a2dMasterTagGroups4 ::OnMouseEvent )
1115  EVT_CHAR( a2dMasterTagGroups4 ::OnChar )
1116  EVT_KEY_DOWN( a2dMasterTagGroups4 ::OnKeyDown )
1117  EVT_KEY_UP( a2dMasterTagGroups4 ::OnKeyUp )
1118  EVT_COM_EVENT( a2dMasterTagGroups4::OnComEvent )
1119  EVT_TIMER( -1, a2dMasterTagGroups4::OnTimer )
1120 END_EVENT_TABLE()
1121 
1122 a2dMasterTagGroups4 ::a2dMasterTagGroups4 ( a2dStToolContr* controller ):
1123  m_timer( this ),
1124  m_selectionIfNoDoubleClick( false ),
1125  m_drawWireIfNoDoubleClick( false ),
1126  m_editIfDelayed( false ),
1127  m_startEditIfDelayed( true ),
1128  a2dMasterDrawBase( controller )
1129 {
1130  controller->SetDefaultBehavior( controller->GetDefaultBehavior() | wxTC_NoDefaultKeys | wxTC_NoDefaultMouseActions );
1131  m_toolcursor = a2dCanvasGlobals->GetCursor( a2dCURSOR_Select );
1132  m_drawWire = false;
1133  a2dCanvasGlobals->ConnectEvent( a2dEVT_COM_EVENT, this );
1134 }
1135 
1136 a2dMasterTagGroups4 ::~a2dMasterTagGroups4 ()
1137 {
1138  a2dCanvasGlobals->DisconnectEvent( a2dEVT_COM_EVENT, this );
1139 }
1140 
1141 wxString a2dMasterTagGroups4 ::GetToolString() const
1142 {
1143  wxString str = GetClassInfo()->GetClassName();
1144  if ( m_drawWire )
1145  return str + " Wires";
1146  if ( m_dlgOrEdit )
1147  return str + " Dlg";
1148  return str;
1149 }
1150 
1152 {
1153 }
1154 
1156 {
1158  m_toolBusy = false;
1159 }
1160 
1162 {
1164 
1165  if ( selected )
1166  {
1167  DeselectAll();
1168  }
1169  if( GetBusy() && m_dragStarted )
1170  {
1171  switch( m_mode )
1172  {
1173  case mode_zoom:
1174  case mode_select:
1175  case mode_cntrlselect:
1176  {
1177  break;
1178  }
1179  default:
1180  break;
1181  }
1182  }
1183 
1185 }
1186 
1188 {
1189  a2dStTool::SetActive( active );
1190  m_pending = true;
1191 
1192  if ( active )
1193  {
1194  SetToolMode( false, false, false );
1195  }
1196 }
1197 
1198 void a2dMasterTagGroups4::OnComEvent( a2dComEvent& event )
1199 {
1200  if ( GetEvtHandlerEnabled() )
1201  {
1202  a2dSignal comId = event.GetId();
1203 
1204  if ( event.GetId() == a2dBaseTool::sig_toolPoped )
1205  {
1206  }
1207 
1209  if ( tool && tool->GetActive() && tool->GetEvtHandlerEnabled() && tool->GetDrawingPart() )
1210  {
1211  bool OnSelected = false;
1212 
1213  if ( m_modehit )
1214  {
1215  a2dCanvasObjectList objects;
1216  m_parentobject->CollectObjects( &objects, wxT( "" ), a2dCanvasOFlags::SELECTED );
1217  if ( objects.size() > 0 )
1218  OnSelected = true;
1219  }
1220  if ( !OnSelected )
1221  {
1222  //m_styleDlg->GetFill()
1223  //m_styleDlg->GetStroke()
1224 
1226  a2dFill f = GetDrawing()->GetHabitat()->GetFill();
1227  if ( comId == a2dHabitat::sig_changedFill && ! tool->GetFill().IsSameAs( f ) )
1228  {
1229  if ( m_modehit )
1230  docCmdh->Submit( new a2dCommand_ChangeCanvasObjectStyle( m_modehit, f ) );
1231  }
1232  a2dStroke s = GetDrawing()->GetHabitat()->GetStroke();
1233  if ( comId == a2dHabitat::sig_changedStroke && ! tool->GetStroke().IsSameAs( s ) )
1234  {
1235  if ( m_modehit )
1236  docCmdh->Submit( new a2dCommand_ChangeCanvasObjectStyle( m_modehit, s ) );
1237  }
1238  }
1239  else
1240  {
1241  if (
1242  comId == a2dHabitat::sig_changedFill ||
1243  comId == a2dHabitat::sig_changedStroke ||
1244  comId == a2dHabitat::sig_changedLayer
1245  )
1246  {
1248  a2dFill f = GetDrawing()->GetHabitat()->GetFill();
1249  if ( comId == a2dHabitat::sig_changedFill )
1250  {
1251  docCmdh->Submit( new a2dCommand_SetFillStrokeMask( tool->GetDrawingPart()->GetShowObject() ) );
1252  }
1253  a2dStroke s = GetDrawing()->GetHabitat()->GetStroke();
1254  if ( comId == a2dHabitat::sig_changedStroke )
1255  {
1256  docCmdh->Submit( new a2dCommand_SetFillStrokeMask( tool->GetDrawingPart()->GetShowObject() ) );
1257  }
1258  wxUint16 layer = GetDrawing()->GetHabitat()->GetLayer();
1259  if ( comId == a2dHabitat::sig_changedLayer )
1260  {
1261  docCmdh->Submit( new a2dCommand_SetLayerMask( tool->GetDrawingPart()->GetShowObject(), layer ) );
1262  }
1263  }
1264  }
1265  }
1266  }
1267 
1268 
1269  event.Skip();
1270 }
1271 
1272 void a2dMasterTagGroups4::OnChar( wxKeyEvent& event )
1273 {
1274  //wxLogDebug(wxT("key %d"), event.GetKeyCode());
1276 
1278 
1279  if ( selected )
1280  {
1281  event.Skip();
1282  }
1283  else if( GetBusy() && m_dragStarted )
1284  {
1285  switch( m_mode )
1286  {
1287  case mode_zoom:
1288  case mode_select:
1289  case mode_cntrlselect:
1290  {
1291  break;
1292  }
1293  default:
1294  event.Skip();
1295  break;
1296  }
1297  }
1298  else
1299  event.Skip();
1300 }
1301 
1302 void a2dMasterTagGroups4 ::OnKeyDown( wxKeyEvent& event )
1303 {
1304  if ( !m_active )
1305  {
1306  event.Skip();
1307  return;
1308  }
1309 
1310  switch( event.GetKeyCode() )
1311  {
1312  case 'w':
1313  case 'W':
1314  {
1315  m_drawWire = !m_drawWire;
1316  SetToolMode( event.m_controlDown, event.m_shiftDown, event.AltDown() );
1317  break;
1318  }
1319  default:
1320  if ( event.m_controlDown || event.m_shiftDown || event.AltDown() )
1321  SetToolMode( event.m_controlDown, event.m_shiftDown, event.AltDown() );
1322  event.Skip();
1323  }
1324 }
1325 
1326 void a2dMasterTagGroups4 ::OnKeyUp( wxKeyEvent& event )
1327 {
1328  if ( !m_active )
1329  {
1330  event.Skip();
1331  return;
1332  }
1333 
1334  switch( event.GetKeyCode() )
1335  {
1336  case 'w':
1337  case 'W':
1338  {
1339  SetToolMode( event.m_controlDown, event.m_shiftDown, event.AltDown() );
1340  break;
1341  }
1342  default:
1343  if ( !event.m_controlDown || !event.m_shiftDown || !event.AltDown() )
1344  SetToolMode( event.m_controlDown, event.m_shiftDown, event.AltDown() );
1345  event.Skip();
1346  }
1347 }
1348 
1349 bool a2dMasterTagGroups4::SetWireCursor( a2dWirePolylineL* wire, const a2dHitEvent& hitinfo, bool ctrl, bool shift, bool alt )
1350 {
1351  a2dHit how2;
1352  int i;
1353  float minDist = FLT_MAX;
1354  for( i = 0; i < hitinfo.m_extended.size(); i++ )
1355  {
1356  a2dWirePolylineL* wire2 = wxDynamicCast( hitinfo.m_extended[i].GetObject(), a2dWirePolylineL );
1357  if( wire2 && hitinfo.m_extended[i].GetHitType().m_distance < minDist && hitinfo.m_extended[i].GetHitType().IsStrokeHit() )
1358  //if( wire2 && hitinfo.m_extended[i].GetHitType().m_distance < minDist && hitinfo.m_extended[i].GetHitType().IsDirectStrokeHit() )
1359  {
1360  wire = wire2;
1361  how2 = hitinfo.m_extended[i].GetHitType();
1362  minDist = how2.m_distance;
1363  }
1364  }
1365 
1366  if ( wire )
1367  {
1368  // wire editing mode
1369  // check, where the wire was hit:
1370  m_modehit = wire;
1371  m_modehitinfo = how2;
1372  if ( !alt )
1373  {
1374  switch( how2.m_stroke2 )
1375  {
1376  case a2dHit::stroke2_vertex:
1377  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireVertex ) );
1378  SetStateString( _("drag to move vertex on the wire"), STAT_toolHelp );
1379  m_mode = mode_editwire_vertex;
1380  break;
1381  case a2dHit::stroke2_edgehor:
1382  case a2dHit::stroke2_edgevert:
1383  case a2dHit::stroke2_edgeother:
1384  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_WireSegmentInsert ) );
1385  SetStateString( _("drag to insert vertex on the wire"), STAT_toolHelp );
1386  m_mode = mode_editwire_segmentinsert;
1387  break;
1388  default:
1389  m_modehit = NULL;
1390  m_modehitinfo = a2dHit();
1391  }
1392  }
1393  else
1394  {
1395  switch( how2.m_stroke2 )
1396  {
1397  case a2dHit::stroke2_vertex:
1398  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireDeleteVertex ) );
1399  SetStateString( _("click to remove vertex from wire"), STAT_toolHelp );
1400  m_mode = mode_editwire_vertex;
1401  break;
1402  case a2dHit::stroke2_edgehor:
1403  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireSegmentHorizontal ) );
1404  SetStateString( _("drag to move segment of the wire"), STAT_toolHelp );
1405  m_mode = mode_editwire_segmenthorizontal;
1406  break;
1407  case a2dHit::stroke2_edgevert:
1408  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireSegmentVertical ) );
1409  SetStateString( _("drag to move segment of the wire"), STAT_toolHelp );
1410  m_mode = mode_editwire_segmentvertical;
1411  break;
1412  case a2dHit::stroke2_edgeother:
1413  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireSegment ) );
1414  SetStateString( _("drag to move segment, Alt key to insert a vertex on wire"), STAT_toolHelp );
1415  m_mode = mode_editwire_segment;
1416  break;
1417  default:
1418  m_modehit = NULL;
1419  m_modehitinfo = a2dHit();
1420  }
1421  }
1422  }
1423  return true;
1424 }
1425 
1426 void a2dMasterTagGroups4::SetToolMode( bool ctrl, bool shift, bool alt )
1427 {
1428  a2dCanvasObject* hit = m_modehit;
1429  if ( !m_dragStarted )
1430  {
1431  //GetDrawingPart()->Update( a2dCANVIEW_UPDATE_PENDING );
1432  a2dIterC ic( GetDrawingPart() );
1433  ic.SetLayer( wxLAYER_ALL );
1434  ic.SetObjectFilter( new a2dCanvasObjectFilterLayerMask( wxLAYER_ALL, a2dCanvasOFlags::VISIBLE | a2dCanvasOFlags::SELECTABLE ) );
1435  m_hitinfo = a2dHitEvent( m_xwprev, m_ywprev, false, a2dCANOBJHITOPTION_NONE, true );
1436  m_hitinfo.m_option = a2dCANOBJHITOPTION_LAYERS;
1437  //at the top level the group its matrix is to be ignored.
1438  //Since it is normally NOT ignored within a2dCanvasObject, force an inverse.
1439  m_hitinfo.m_xyRelToChildren = true;
1440 
1441  m_mode = mode_none;
1442  m_modehit = 0;
1443  m_modehitinfo = a2dHit();
1444  hit = GetDrawingPart()->GetShowObject()->ChildIsHitWorld( ic, m_hitinfo, true );
1445  GetDrawing()->GetHabitat()->GetConnectionGenerator()->SetPinsToBeginState( GetDrawingPart()->GetShowObject() );
1446  }
1447  a2dPin* pin = NULL;
1448  if ( hit )
1449  {
1450  pin = wxDynamicCast( hit, a2dPin );
1451  if ( pin )
1452  pin = wxDynamicCast( hit, a2dPin );
1453  }
1454 
1455  if ( !pin && !ctrl && shift )
1456  {
1457  if ( hit )
1458  {
1459  m_modehit = hit;
1460  SetStateString( _("drag to move object, double click to edit"), STAT_toolHelp );
1461  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
1462  }
1463  else
1464  {
1465  m_modehit = NULL;
1466  SetStateString( _("move to object and click to select"), STAT_toolHelp );
1467  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_ARROW ) );
1468  }
1469  m_mode = mode_select;
1470  }
1471  /*
1472  else if ( !pin && ctrl && shift )
1473  {
1474  if ( hit )
1475  {
1476  m_modehit = hit;
1477  SetStateString( _("click to select"), STAT_toolHelp );
1478  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
1479  }
1480  else
1481  {
1482  m_modehit = NULL;
1483  SetStateString( _("move to object and click to select"), STAT_toolHelp );
1484  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_ARROW ) );
1485  }
1486  m_mode = mode_cntrlselect;
1487  }
1488  */
1489  else
1490  {
1491  if ( hit )
1492  {
1493  // Check if there is pin
1494  // This has highest priority
1495  a2dHit how2;
1496 
1498 
1499  if ( wire && wire->GetSelected() && m_drawWire )
1500  {
1501  SetWireCursor( wire, m_hitinfo, ctrl, shift, alt );
1502  }
1503  else if ( wire )
1504  {
1505  if ( m_drawWire || ( !m_drawWire && ctrl ) )
1506  {
1507  GetDrawing()->GetHabitat()->GetConnectionGenerator()->
1508  GeneratePinsToConnect( GetDrawingPart(), wire, a2dPinClass::Any, a2d_GeneratePinsForStartWire, m_xwprev, m_ywprev );
1509  }
1510  else
1511  wire->RemovePins( true, true );
1512 
1513 
1514  //we did hit a wire, still a pin at this location, can be on a wire or any other object, depending on drawing order.
1515  pin = GetDrawing()->GetHabitat()->GetConnectionGenerator()->
1516  SearchPinForStartWire( GetDrawingPart()->GetShowObject(), m_xwprev, m_ywprev, a2dPinClass::Any, GetHitMargin() );
1517 
1518  if( pin )
1519  {
1520  // if in draw wire mode, we must be able to start a wire on a pin
1521  // Else we just drag pins, if not connected to a normal object ( so a wire to wire pin ).
1522  if ( m_dragStarted && !pin->IsTemporaryPin() )
1523  {
1524  if ( !( m_drawWire || ( !m_drawWire && ctrl ) ) &&
1525  ( pin->GetParent()->IsConnect() && !pin->FindNonWirePin() )
1526  )
1527  {
1528  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Drag ) );
1529  SetStateString( _("drag the pin and reroute wires"), STAT_toolHelp );
1530  m_mode = mode_move_pin;
1531  m_modehit = pin;
1532  }
1533  if ( !( m_drawWire || ( !m_drawWire && ctrl ) ) &&
1534  ( ( pin->GetParent()->IsConnect() && pin->FindNonWirePin() ) || !pin->GetParent()->IsConnect() )
1535  )
1536  {
1537  if ( pin->GetConnectedPinsNr() <= 1 )
1538  {
1539  // wire drawing mode
1540  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
1541  SetStateString( _("drag to rewire"), STAT_toolHelp );
1542  m_mode = mode_rewire_pin;
1543  if ( !pin->GetParent()->IsConnect() )
1544  m_modehit = pin->FindWirePin();
1545  }
1546  else
1547  {
1548  // wire drawing mode
1549  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
1550  SetStateString( _("draw a wire from pin"), STAT_toolHelp );
1551  m_mode = mode_drawwire;
1552  m_modehit = pin;
1553  }
1554  }
1555  }
1556  // If we know we are on an object pin, or at least a wire pin on that location, we can
1557  // start a wire without extra Ctrl or special m_drawWire mode.
1558  // So we can start multiple wires on a normal pin.
1559  else if ( !pin->IsTemporaryPin() &&
1560  ( ( pin->GetParent()->IsConnect() && pin->FindNonWirePin() ) || !pin->GetParent()->IsConnect() )
1561  )
1562  {
1563  if ( pin->GetConnectedPinsNr() <= 1 )
1564  {
1565  // wire drawing mode
1566  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
1567  SetStateString( _("draw a wire from pin, or drag to rewire"), STAT_toolHelp );
1568  m_mode = mode_drawwire;
1569  }
1570  else
1571  {
1572  // wire drawing mode
1573  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
1574  SetStateString( _("draw a wire from pin"), STAT_toolHelp );
1575  m_mode = mode_drawwire;
1576  }
1577  m_modehit = pin;
1578  }
1579  else if (!m_dragStarted && !( m_drawWire || ( !m_drawWire && ctrl ) ) )
1580  {
1581  // wire drawing mode
1582  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
1583  SetStateString( _("Drag the pin or start a wire with a click"), STAT_toolHelp );
1584  m_mode = mode_drawwire;
1585  m_modehit = pin;
1586  }
1587  else if ( m_drawWire || ( !m_drawWire && ctrl ) || !m_dragStarted )
1588  {
1589  // wire drawing mode
1590  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
1591  SetStateString( _("start a wire with a click"), STAT_toolHelp );
1592  m_mode = mode_drawwire;
1593  m_modehit = pin;
1594  }
1595  }
1596  else
1597  {
1598  if ( m_drawWire || ( !m_drawWire && ctrl ) )
1599  {
1600  // wire drawing mode
1601  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
1602  SetStateString( _("draw a wire"), STAT_toolHelp );
1603  m_mode = mode_drawwire;
1604  m_modehit = pin;
1605  }
1606  else
1607  {
1608  // a wire is not draggabble, but it might be editable, in that case we can drag segments and vertexes.
1609  if( hit->GetEditable() )
1610  {
1611  SetWireCursor( wire, m_hitinfo, ctrl, shift, alt );
1612 /* We do not really want to drag wire do we, anyway connect object are !GetDraggable()?
1613  if ( hit->GetSelected() )
1614  {
1615  m_modehit = hit;
1616  if ( event.ControlDown() && event.ShiftDown() )
1617  {
1618  m_mode = mode_copymulti;
1619  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Copy ) );
1620  }
1621  else //no shift no control
1622  {
1623  m_mode = mode_dragmulti;
1624  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Drag ) );
1625  }
1626  }
1627  else
1628  {
1629  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
1630  m_mode = mode_select;
1631  m_modehit = hit;
1632  }
1633 */
1634  }
1635  else
1636  {
1637  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
1638  SetStateString( _("click to select object"), STAT_toolHelp );
1639  m_mode = mode_select;
1640  m_modehit = hit;
1641  }
1642  }
1643  }
1644 
1645  }
1646  else //not a wire
1647  {
1648  if ( !pin && !shift && !ctrl )
1649  {
1650  //While moving event, there is no wire nor pin yet, therefore we can just feedback possible pin connection, based on the
1651  // m_connectionGenerator.
1652  GetDrawing()->GetHabitat()->GetConnectionGenerator()->
1654 
1655  pin = GetDrawing()->GetHabitat()->GetConnectionGenerator()->
1656  SearchPinForStartWire( GetDrawingPart()->GetShowObject(), m_xwprev, m_ywprev, a2dPinClass::Any, GetHitMargin() );
1657 
1658  if ( pin )
1659  {
1661  if ( wire && wire->GetSelected() )
1662  pin = NULL;
1663  }
1664  }
1665 
1666  // if not editing a wire, if pin start a wire draw
1667  if( pin )
1668  {
1669  if ( m_dragStarted && !pin->IsTemporaryPin() )
1670  {
1671  if ( !( m_drawWire || ( !m_drawWire && ctrl ) ) &&
1672  ( pin->GetParent()->IsConnect() && !pin->FindNonWirePin() ) )
1673  {
1674  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Drag ) );
1675  m_mode = mode_move_pin;
1676  SetStateString( _("drag the pin and reroute wires"), STAT_toolHelp );
1677  m_modehit = pin;
1678  }
1679  else if ( pin->GetParent()->IsConnect() && !pin->FindNonWirePin() )
1680  {
1681  // wire drawing mode
1682  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
1683  SetStateString( _("draw a wire from this pin"), STAT_toolHelp );
1684  m_mode = mode_drawwire;
1685  m_modehit = pin;
1686  }
1687  else if ( !pin->GetParent()->IsConnect() )
1688  {
1689  // rewire pin mode
1690  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
1691  SetStateString( _("Rewire this pin"), STAT_toolHelp );
1692  m_mode = mode_rewire_pin;
1693  m_modehit = pin;
1694  }
1695  }
1696  else if ( !m_dragStarted && !pin->IsTemporaryPin() )
1697  {
1698  // wire drawing mode
1699  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
1700  SetStateString( _("draw a wire from this pin"), STAT_toolHelp );
1701  m_mode = mode_drawwire;
1702  m_modehit = pin;
1703  }
1704  }
1705  else
1706  {
1707  if( hit->GetDraggable() )
1708  {
1709  if ( hit->GetSelected() )
1710  {
1711  m_modehit = hit;
1712  if ( ctrl && shift )
1713  {
1714  m_mode = mode_copymulti;
1715  SetStateString( _("drag to copy selected objects"), STAT_toolHelp );
1716  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Copy ) );
1717  }
1718  else //no shift no control
1719  {
1720  SetStateString( _("drag to move selected objects"), STAT_toolHelp );
1721  m_mode = mode_dragmulti;
1722  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Drag ) );
1723  }
1724  }
1725  else
1726  {
1727  if ( !m_dragStarted )
1728  {
1729  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
1730  SetStateString( _("click to select object, double click to edit"), STAT_toolHelp );
1731  m_mode = mode_select;
1732  m_modehit = hit;
1733  }
1734  else
1735  {
1736  m_mode = mode_drag;
1737  m_modehit = hit;
1738  SetStateString( _("drag to move object"), STAT_toolHelp );
1739  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Drag ) );
1740  }
1741  }
1742  }
1743  else
1744  {
1745  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
1746  SetStateString( _("can not drag this object, double click to edit"), STAT_toolHelp );
1747  m_mode = mode_select;
1748  m_modehit = hit;
1749  }
1750  }
1751  }
1752  }
1753  else
1754  {
1755  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_ARROW ) );
1756  SetStateString( _("click on object, drag rectangle to select objects"), STAT_toolHelp );
1757  m_mode = mode_select;
1758  m_modehit = hit;
1759  }
1760  }
1761 }
1762 
1763 void a2dMasterTagGroups4::EditDlgOrHandles( a2dCanvasObject* hit, bool modifier, bool noHandleEditForWire )
1764 {
1765  if ( hit )
1766  {
1767  //if ( m_mode == mode_drawwire )
1768  {
1769  a2dWirePolylineL* wire = wxDynamicCast( m_modehit, a2dWirePolylineL );
1770  a2dPin* pin = wxDynamicCast( m_modehit, a2dPin );
1771  if ( pin )
1772  {
1773  hit = m_modehit = m_modehit->GetParent();
1774  m_modehit->RemovePins( true, true );
1775  }
1776 
1777  }
1778 
1779  if ( m_dlgOrEdit && ! hit->GetFixedStyle() && !modifier )
1780  {
1781  if ( !m_dlgOrEditModal )
1783  else
1784  {
1785  a2dStyleDialog styleDlg( GetDrawing()->GetHabitat(), NULL, wxDEFAULT_DIALOG_STYLE | wxDIALOG_NO_PARENT | wxMINIMIZE_BOX | wxMAXIMIZE_BOX, true );
1786  styleDlg.SetFill( hit->GetFill() );
1787  styleDlg.SetStroke( hit->GetStroke() );
1788  if ( styleDlg.ShowModal() == wxID_OK )
1789  {
1790  if ( !hit->GetSelected() )
1791  {
1792  hit->SetFill( styleDlg.GetFill() );
1793  hit->SetStroke( styleDlg.GetStroke() );
1794  }
1795  else
1797  }
1798  }
1799  }
1800  else
1801  {
1803  m_modehit = hit;
1804 
1805  if ( (wire && wire->GetSelected() ) || (wire && !noHandleEditForWire ) || !wire )
1806  {
1807  hit->SetSelected( m_modehitLastSelectState );
1808  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
1809  m_mode = mode_edit;
1810  PushEditTool( m_modehit );
1811  }
1812  }
1813  }
1814 }
1815 
1816 void a2dMasterTagGroups4::OnTimer(wxTimerEvent& event)
1817 {
1818  if ( m_startEditIfDelayed )
1819  m_editIfDelayed = true;
1820  if ( m_hadDoubleClick )
1821  {
1822  m_hadDoubleClick = false;
1823  //wxLogDebug( "time DC" );
1824  m_selectionIfNoDoubleClick = false;
1825  m_drawWireIfNoDoubleClick = false;
1826  }
1827  else
1828  {
1829  if ( m_drawWireIfNoDoubleClick && m_mode == mode_drawwire )
1830  {
1831  //When pin was generated on a wire at mouse moving), use it here.
1832  a2dPin* pin = wxDynamicCast( m_modehit, a2dPin );
1833  // if in draw wire mode, we must be able to start a wire on a pin
1834  if( pin )
1835  {
1836  // wire drawing mode
1837  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_DrawWire ) );
1838  m_mode = mode_drawwire;
1839  m_modehit = pin;
1840  PushDrawWireTool( m_modehit );
1841 
1842  wxMouseEvent mouseevent( wxEVT_LEFT_DOWN );
1843  mouseevent.m_x = m_dragstartx;
1844  mouseevent.m_y = m_dragstarty;
1845  mouseevent.m_controlDown = true;
1846  mouseevent.m_leftDown = true;
1847  mouseevent.SetEventObject(this);
1848  mouseevent.SetId( GetDrawingPart()->GetDisplayWindow()->GetId() );
1849  m_stcontroller->GetFirstTool()->ProcessEvent( mouseevent );
1850 
1851  wxMouseEvent mouseevent2( wxEVT_LEFT_UP );
1852  mouseevent2.m_x = m_dragstartx;
1853  mouseevent2.m_y = m_dragstarty;
1854  mouseevent2.m_controlDown = true;
1855  mouseevent2.m_leftDown = true;
1856  mouseevent2.SetEventObject(this);
1857  mouseevent2.SetId( GetDrawingPart()->GetDisplayWindow()->GetId() );
1858  m_stcontroller->GetFirstTool()->ProcessEvent( mouseevent2 );
1859  }
1860  m_drawWireIfNoDoubleClick = false;
1861  }
1862 
1863  if ( m_selectionIfNoDoubleClick )
1864  {
1865  if ( m_selectMoreAtShift )
1866  DeselectAll();
1867  else if ( !m_modehit )
1868  DeselectAll();
1869  if ( m_modehit && m_modehit->GetSelectable() )
1870  {
1871  if ( m_drawWire )
1872  m_modehit->SetSelected( true );
1873  else //is conflicting with starting a wire
1874  m_modehit->SetSelected( !m_modehitLastSelectState );
1875  }
1876  m_selectionIfNoDoubleClick = false;
1877  }
1878  //wxLogDebug( "time");
1879  }
1880 }
1881 
1882 void a2dMasterTagGroups4::OnMouseEvent( wxMouseEvent& event )
1883 {
1884  //MouseDump( event, "OnM " );
1885 
1886  if ( !m_active )
1887  {
1888  event.Skip();
1889  return;
1890  }
1891  m_x = event.GetX();
1892  m_y = event.GetY();
1893 
1895 
1896  if ( event.LeftDClick() &&
1897  !m_toolBusy //&&
1898  //no need !( event.ControlDown() || event.ShiftDown() )
1899  )
1900  {
1901  m_hadDoubleClick = true;
1902  EditDlgOrHandles( m_modehit, event.ControlDown(), m_drawWire );
1903  }
1904  else if ( event.Dragging() && m_toolBusy && !m_dragStarted )
1905  {
1906  //we assume dragging starts for real if 5 pixels shift.
1907  if ( abs( m_x - m_dragstartx ) >= 5 || abs( m_y - m_dragstarty ) >= 5 )
1908  {
1909  m_dragStarted = true;
1910  SetToolMode( event.ControlDown(), event.ShiftDown(), event.AltDown() );
1911  m_toolBusy = false;
1912  switch( m_mode )
1913  {
1914  case mode_cntrlselect:
1915  DeselectAll();
1916  m_toolBusy = true;
1917  event.Skip();
1918  break;
1919  case mode_select:
1920  break;
1921  case mode_dragmulti:
1922  {
1923  m_dragStarted = false;
1924  PushDragMultiTool( m_modehit );
1925  //event.Skip();
1926  break;
1927  }
1928  case mode_copymulti:
1929  {
1930  m_dragStarted = false;
1931  PushCopyMultiTool( m_modehit );
1932  //event.Skip();
1933  break;
1934  }
1935  case mode_drag:
1936  {
1937  m_dragStarted = false;
1938  PushDragTool( m_modehit );
1939  //event.Skip();
1940  break;
1941  }
1942  case mode_copy:
1943  {
1944  m_dragStarted = false;
1945  PushCopyTool( m_modehit );
1946  //event.Skip();
1947  break;
1948  }
1949  case mode_move_pin:
1950  {
1951  m_dragStarted = false;
1952  PushMovePinTool( m_modehit );
1953  wxMouseEvent mouseevent( wxEVT_LEFT_DOWN );
1954  InitMouseEvent( mouseevent, m_dragstartx, m_dragstarty, event );
1955  m_stcontroller->GetFirstTool()->ProcessEvent( mouseevent );
1956  break;
1957  }
1958  case mode_rewire_pin:
1959  {
1960  m_dragStarted = false;
1961  PushRewirePinTool( m_modehit );
1962  wxMouseEvent mouseevent( wxEVT_LEFT_DOWN );
1963  InitMouseEvent( mouseevent, m_dragstartx, m_dragstarty, event );
1964  m_stcontroller->GetFirstTool()->ProcessEvent( mouseevent );
1965  break;
1966  }
1967  default:
1968  m_toolBusy = true;
1969  break;
1970  }
1971  }
1972  }
1973  else if ( event.Dragging() && m_toolBusy && m_dragStarted )
1974  {
1975  }
1976  else if ( event.Moving() && !m_toolBusy )
1977  {
1978  SetToolMode( event.ControlDown(), event.ShiftDown(), event.AltDown() );
1979  event.Skip();
1980  }
1981  else if( event.LeftDown() && !m_toolBusy )
1982  {
1983  //detect Double Click
1984  m_timer.Start( 280, true );
1985  m_editIfDelayed = false;
1986 
1987  SetStateString( "" );
1988  m_dragStarted = false;
1989  m_xprev = m_x;
1990  m_yprev = m_y;
1991  m_dragstartx = m_x;
1992  m_dragstarty = m_y;
1993 
1994  if( !m_modehit )
1995  {
1996  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
1997  m_mode = mode_select;
1998  event.Skip();
1999  m_toolBusy = false;
2000  return;
2001  }
2002 
2003  switch( m_mode )
2004  {
2005  case mode_select:
2006  m_toolBusy = true;
2007  break;
2008  case mode_move_pin:
2009  m_toolBusy = true;
2010  break;
2011  case mode_rewire_pin:
2012  m_toolBusy = true;
2013  break;
2014  case mode_drawwire:
2015  m_toolBusy = true;
2016  break;
2017  case mode_editwire_vertex:
2018  case mode_editwire_segmenthorizontal:
2019  case mode_editwire_segmentvertical:
2020  case mode_editwire_segmentinsert:
2021  case mode_editwire_segment:
2022  event.Skip();
2023  break;
2024  default:
2025  // not know until a drag started or not.
2026  m_mode = mode_none;
2027  m_toolBusy = true;
2028  event.Skip();
2029  }
2030  }
2031  else if( event.LeftUp() && m_toolBusy && m_dragStarted )
2032  {
2033  m_toolBusy = false;
2034  m_dragStarted = false; //end of drag
2035  m_mode = mode_none;
2036  GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Select ) );
2037  }
2038  else if( event.LeftUp() && m_toolBusy )
2039  {
2040  m_toolBusy = false;
2041  m_dragStarted = false; //never started but still
2042 
2043  //reserve for double click if it happens
2044  m_modehitLastSelectState = false;
2045  if ( m_modehit )
2046  m_modehitLastSelectState = m_modehit->GetSelected();
2047 
2048  if ( m_editIfDelayed ) //set by timer if it arrived there first, meaning LeftUp was delayed.
2049  {
2050  m_editIfDelayed = false;
2051  EditDlgOrHandles( m_modehit, event.ControlDown(), m_drawWire ); //reuse from the LeftDown event.
2052  }
2053  if ( !event.ControlDown() && !event.ShiftDown() )
2054  {
2055  m_selectionIfNoDoubleClick = true; //canceled by/in timer if double click came within time.
2056  }
2057  if ( event.ControlDown() )
2058  {
2059  m_drawWireIfNoDoubleClick = true; //canceled by/in timer if double click came within time.
2060  }
2061  else if ( event.ShiftDown() )
2062  {
2063  if ( m_modehit && m_modehit->GetSelectable() )
2064  {
2065  if ( m_modehit->IsSelected() )
2066  m_modehit->SetSelected( false );
2067  else
2068  m_modehit->SetSelected( true );
2069  }
2070  }
2071  m_mode = mode_none;
2072 
2073  SetToolMode( event.ControlDown(), event.ShiftDown(), event.AltDown() );
2074  }
2075  else if( event.RightDown() && !GetBusy() )
2076  {
2077  PushZoomTool();
2078  event.Skip();
2079  }
2080  else
2081  {
2082  event.Skip();
2083  }
2084 }
2085 
2086 
a2dPin * FindNonWirePin(a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::ALL)
Definition: canpin.cpp:1012
void AbortBusyMode()
Called when the user aborts editing a distinct object */.
#define wxDynamicCast(obj, className)
Define wxDynamicCast so that it will give a compiler error for unrelated types.
Definition: gen.h:75
Base class for all types of strokes, understood by a2dDrawer2D classes.
Definition: stylebase.h:378
wxUint16 GetLayer() const
layer set for new objects.
Definition: canglob.h:930
unsigned int m_index
For edge/vertex hits the index of the edge / vertex.
Definition: polyver.h:89
a2dCanvasObjectPtr m_parentobject
( if needed ) parent a2dCanvasObject relative to which the tool actions take place.
Definition: tools.h:854
void Render()
implement rendering
void Render()
implement rendering
bool m_dragStarted
used to indicate that a first drag event has arrived.
Definition: sttool.h:374
static const a2dSignal sig_changedFill
when active drawing is set, this signal is send to the drawing.
Definition: canglob.h:1187
bool m_pending
set when tool needs an redraw (after a a2dCanvas Repaint etc.)
Definition: tools.h:814
bool GetActive()
is the tool active?
Definition: tools.h:497
a2dCanvasCommandProcessor * GetCanvasCommandProcessor()
Returns a pointer to the command processor associated with this document.
Definition: tools.cpp:976
bool GetEditable() const
get if the object may be edited
Definition: canobj.h:1584
The a2dBaseTool is used to derive tools from that are controlled by.
Definition: tools.h:379
no special options
Definition: canobj.h:79
virtual void DoStopTool(bool abort)
to do tool specific stuff to stop a tool. Called from StopTool().
Definition: mastertool.cpp:900
int m_x
x of mouse in device
Definition: sttool.h:352
double GetHitMargin()
Definition: tools.cpp:983
a2dPin is used in a2dCanvasObject to add pins to it.
Definition: canpin.h:233
stack based tools for drawing and editing in a faster manner, but with less document feedback...
The a2dStTool is used to derive tools from.
Definition: sttool.h:115
generate pins, given Connect/wire pinclass
Definition: connectgen.h:48
a2dDrawingPart * GetDrawingPart()
Access to the tool controllers drawer.
Definition: tools.h:632
int m_dragstarty
y of mouse in device at start drag
Definition: sttool.h:371
void ConnectEvent(wxEventType type, wxEvtHandler *eventSink)
Definition: gen.cpp:876
a2dStToolContr * m_stcontroller
controller for canvas
Definition: sttool.h:391
a2dDrawing * GetDrawing()
Returns a pointer to the drawing.
Definition: tools.cpp:969
a command processor specially designed to work with a a2dCanvasDocument
Definition: drawing.h:1046
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
float m_distance
For margin hits, the distance from the stroke center in fractions of the margin.
Definition: polyver.h:93
set layer of objects which fit the mask
Definition: drawing.h:2891
void DoStopTool(bool abort)
to do tool specific stuff to stop a tool. Called from StopTool().
a2dCanvasObject is the base class for Canvas Objects.
Definition: canobj.h:371
wxUint32 GetConnectedPinsNr() const
Get the number of connected pins.
Definition: canpin.cpp:738
a2dPin * FindWirePin(a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::ALL)
Definition: canpin.cpp:1029
a2dCanvasObjectList * GetChildObjectList()
get the list where the child objects are stored in.
Definition: canobj.cpp:2551
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
virtual a2dCanvasObject * GetParent() const
Definition: canobj.h:2126
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
master tool using tags to groups object
general style dialog to edit a2dCanvasObject style
Definition: styledialg.h:60
a2dWirePolylineL is a polyline that adjusts itself when the objects it connects move ...
Definition: wire.h:42
bool m_xyRelToChildren
is set, m_x and m_y are supplied relative to the child objects ( object matrix m_world already applie...
Definition: canobj.h:297
wxUint32 m_option
the way to hit/traverse the document.
Definition: canobj.h:299
a2dExtendedResult m_extended
extended result information with e.g path to lead to the nested object hit
Definition: canobj.h:303
const a2dStroke & GetStroke() const
get the current stroke
Definition: canglob.h:797
The a2dStToolContr is a Tool Controller specialized for working with a2dCanvasView.
Definition: sttool.h:485
wxWindow * GetDisplayWindow()
Access to the tool controllers drawers canvas.
Definition: tools.cpp:964
static const a2dCanvasObjectFlagsMask SELECTABLE
Definition: candefs.h:182
#define EVT_COM_EVENT(func)
static wxEvtHandler for communication event
Definition: gen.h:564
a2dCanvasObject * GetShowObject() const
return pointer of then currently shown object on the drawer.
Definition: drawer.h:680
objects which fit the mask are given a new fill and stroke style
Definition: drawing.h:3480
int m_yprev
previous y of mouse in device
Definition: sttool.h:360
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
void RemovePins(bool NotConnected=false, bool onlyTemporary=false, bool now=false)
Remove all a2dPin children.
Definition: canobj.cpp:6504
Master tool for objects graphics slecting and dragging.
a2dCanvasObject * ChildIsHitWorld(a2dIterC &ic, a2dHitEvent &hitEvent, bool filterSelectableLayers=false)
Do hittest on children.
Definition: canobj.cpp:3289
bool IsTemporaryPin() const
return true if this pin is a temporary pin
Definition: canpin.h:433
double m_xwprev
x world coordinates old or new value of mouse
Definition: sttool.h:363
void InitMouseEvent(wxMouseEvent &eventnew, int x, int y, wxMouseEvent &event)
Definition: mastertool.cpp:370
bool GetFixedStyle() const
Get object fixed style setting.
Definition: canobj.h:1590
bool ShowDlgStyle(bool onOff)
show style dialog or not, return true of changed from previous state
Definition: drawing.cpp:6095
common stuff for several master tools
Definition: mastertool.h:167
virtual void AbortBusyMode()
Called when the user aborts editing a distinct object */.
Definition: sttool.cpp:1178
while iterating a a2dCanvasDocument, this holds the context.
Definition: canobj.h:3212
struct for how a single object on one layer was hit
Definition: polyver.h:38
const a2dStroke & GetStroke() const
get the current stroke
Definition: tools.h:551
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
virtual bool Submit(a2dCommand *command, bool storeIt=true)
Definition: drawing.cpp:5966
virtual void SetActive(bool active=true)
set the tool active or inactive.
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
static const a2dCanvasObjectFlagsMask VISIBLE
Definition: candefs.h:186
static const a2dSignal sig_toolPoped
sent to new first tool when last first tool was poped
Definition: tools.h:386
int m_y
y of mouse in device
Definition: sttool.h:354
a2dCanvasCommandProcessor * GetCanvasCommandProcessor()
get a pointer to the command processor
Definition: drawing.cpp:375
a2dBaseTool * GetFirstTool() const
get currently used eventhandler (always the first in the list)
Definition: tools.cpp:91
void DoStopTool(bool abort)
to do tool specific stuff to stop a tool. Called from StopTool().
const a2dFill & GetFill() const
get the current fill
Definition: tools.h:542
void AbortBusyMode()
Called when the user aborts editing a distinct object */.
a2dStTool(a2dStToolContr *controller)
Definition: sttool.cpp:982
see a2dComEvent
Definition: gen.h:371
a2dCanvasObject * Find(a2dCanvasObject *obj) const
return the object if it is part of the list
Definition: objlist.cpp:553
bool GetSelectable() const
is the object selectable flag set
Definition: canobj.h:1648
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 ...
static a2dPinClass * Any
used to ask for a new default pin on an object.
Definition: canpin.h:763
a2dCanvasGlobal * a2dCanvasGlobals
global a2dCanvasGlobal to have easy access to global settings
Definition: canglob.cpp:1234
all headers of the canvas module
filter on this layer and mask.
Definition: canobj.h:2780
void MouseToToolWorld(int x, int y, double &xWorldLocal, double &yWorldLocal)
calculate world coordinates from devide coordinates
Definition: sttool.cpp:1622
bool GetBusy()
Check if the tool is busy editing a distinct object */.
Definition: tools.h:513
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
a2dCanvasObject * GetParent() const
get parent object of the pin
Definition: canpin.h:295
int m_xprev
previous x of mouse in device
Definition: sttool.h:357
stack based tools controller and tools for drawing and editing.
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
virtual void SetActive(bool active=true)
set the tool active or inactive.
Definition: sttool.cpp:1099
bool DisconnectEvent(wxEventType type, wxEvtHandler *eventSink)
Definition: gen.cpp:902
bool GetDraggable() const
get if the object can be dragged
Definition: canobj.h:1676
structure to give as parameter to member functions of a2dCanvasObject
Definition: canobj.h:252
void SetFill(const a2dFill &fill)
Set a fill for the object which will be used instead of the layer fill.
Definition: canobj.cpp:2874
virtual void SetActive(bool active=true)
set the tool active or inactive.
mastertoolgroups4.cpp Source File -- Sun Oct 12 2014 17:04:22 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation