KiCad PCB EDA Suite
sch_line_wire_bus_tool.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2019 CERN
5  * Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <sch_line_wire_bus_tool.h>
26 
27 #include <wx/debug.h>
28 #include <wx/gdicmn.h>
29 #include <wx/string.h>
30 #include <wx/stringimpl.h>
31 #include <wx/translation.h>
32 #include <algorithm>
33 #include <cstdlib>
34 #include <iterator>
35 #include <memory>
36 #include <utility>
37 #include <vector>
38 
39 #include <eda_item.h>
40 #include <bitmaps.h>
41 #include <core/typeinfo.h>
43 #include <math/vector2d.h>
44 #include <advanced_config.h>
45 #include <tool/actions.h>
46 #include <tool/conditional_menu.h>
47 #include <tool/selection.h>
49 #include <tool/tool_event.h>
50 #include <trigo.h>
51 #include <undo_redo_container.h>
52 #include <connection_graph.h>
53 #include <eeschema_id.h>
54 #include <sch_bus_entry.h>
55 #include <sch_connection.h>
56 #include <sch_edit_frame.h>
57 #include <sch_item.h>
58 #include <sch_line.h>
59 #include <sch_screen.h>
60 #include <sch_sheet.h>
61 #include <sch_text.h>
62 #include <schematic.h>
63 #include <ee_actions.h>
64 #include <ee_grid_helper.h>
65 #include <ee_selection.h>
66 #include <ee_selection_tool.h>
67 
69 {
70 public:
72  ACTION_MENU( true ),
73  m_showTitle( false )
74  {
76  SetTitle( _( "Unfold from Bus" ) );
77  }
78 
79  void SetShowTitle()
80  {
81  m_showTitle = true;
82  }
83 
84  bool PassHelpTextToHandler() override { return true; }
85 
86 protected:
87  ACTION_MENU* create() const override
88  {
89  return new BUS_UNFOLD_MENU();
90  }
91 
92 private:
93  void update() override
94  {
97  KICAD_T busType[] = { SCH_LINE_LOCATE_BUS_T, EOT };
98  EE_SELECTION& selection = selTool->RequestSelection( busType );
99  SCH_LINE* bus = (SCH_LINE*) selection.Front();
100 
101  Clear();
102 
103  // TODO(JE) remove once real-time is enabled
104  if( !ADVANCED_CFG::GetCfg().m_RealTimeConnectivity || !CONNECTION_GRAPH::m_allowRealTime )
105  {
107 
108  // Pick up the pointer again because it may have been changed by SchematicCleanUp
109  selection = selTool->RequestSelection( busType );
110  bus = (SCH_LINE*) selection.Front();
111  }
112 
113  if( !bus )
114  {
115  Append( ID_POPUP_SCH_UNFOLD_BUS, _( "No bus selected" ), wxEmptyString );
116  Enable( ID_POPUP_SCH_UNFOLD_BUS, false );
117  return;
118  }
119 
120  SCH_CONNECTION* connection = bus->Connection();
121 
122  if( !connection || !connection->IsBus() || connection->Members().empty() )
123  {
124  Append( ID_POPUP_SCH_UNFOLD_BUS, _( "Bus has no members" ), wxEmptyString );
125  Enable( ID_POPUP_SCH_UNFOLD_BUS, false );
126  return;
127  }
128 
129  int idx = 0;
130 
131  if( m_showTitle )
132  {
133  Append( ID_POPUP_SCH_UNFOLD_BUS, _( "Unfold from Bus" ), wxEmptyString );
134  Enable( ID_POPUP_SCH_UNFOLD_BUS, false );
135  }
136 
137  for( const auto& member : connection->Members() )
138  {
139  int id = ID_POPUP_SCH_UNFOLD_BUS + ( idx++ );
140  wxString name = member->FullLocalName();
141 
142  if( member->Type() == CONNECTION_TYPE::BUS )
143  {
144  ACTION_MENU* submenu = new ACTION_MENU( true );
145  submenu->SetTool( m_tool );
146  AppendSubMenu( submenu, SCH_CONNECTION::PrintBusForUI( name ), name );
147 
148  for( const auto& sub_member : member->Members() )
149  {
150  id = ID_POPUP_SCH_UNFOLD_BUS + ( idx++ );
151  name = sub_member->FullLocalName();
152  submenu->Append( id, SCH_CONNECTION::PrintBusForUI( name ), name );
153  }
154  }
155  else
156  {
157  Append( id, name, wxEmptyString );
158  }
159  }
160  }
161 
163 };
164 
165 
167  EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.InteractiveDrawingLineWireBus" )
168 {
169  m_busUnfold = {};
170  m_wires.reserve( 16 );
171 }
172 
173 
175 {
176 }
177 
178 
180 {
182 
183  auto wireOrBusTool =
184  [this]( const SELECTION& aSel )
185  {
188  };
189 
190  auto lineTool =
191  [this]( const SELECTION& aSel )
192  {
194  };
195 
196  auto belowRootSheetCondition =
197  [&]( const SELECTION& aSel )
198  {
199  return m_frame->GetCurrentSheet().Last() != &m_frame->Schematic().Root();
200  };
201 
202  auto busSelection = EE_CONDITIONS::MoreThan( 0 )
204 
205  auto& ctxMenu = m_menu.GetMenu();
206 
207  // Build the tool menu
208  //
209  ctxMenu.AddItem( EE_ACTIONS::leaveSheet, belowRootSheetCondition, 2 );
210 
211  ctxMenu.AddSeparator( 10 );
212  ctxMenu.AddItem( EE_ACTIONS::drawWire, wireOrBusTool && EE_CONDITIONS::Idle, 10 );
213  ctxMenu.AddItem( EE_ACTIONS::drawBus, wireOrBusTool && EE_CONDITIONS::Idle, 10 );
214  ctxMenu.AddItem( EE_ACTIONS::drawLines, lineTool && EE_CONDITIONS::Idle, 10 );
215  ctxMenu.AddItem( EE_ACTIONS::finishWire, IsDrawingWire, 10 );
216  ctxMenu.AddItem( EE_ACTIONS::finishBus, IsDrawingBus, 10 );
217  ctxMenu.AddItem( EE_ACTIONS::finishLine, IsDrawingLine, 10 );
218 
219  std::shared_ptr<BUS_UNFOLD_MENU> busUnfoldMenu = std::make_shared<BUS_UNFOLD_MENU>();
220  busUnfoldMenu->SetTool( this );
221  m_menu.AddSubMenu( busUnfoldMenu );
222  ctxMenu.AddMenu( busUnfoldMenu.get(), EE_CONDITIONS::Idle, 10 );
223 
224  ctxMenu.AddSeparator( 100 );
225  ctxMenu.AddItem( EE_ACTIONS::placeJunction, wireOrBusTool && EE_CONDITIONS::Idle, 100 );
226  ctxMenu.AddItem( EE_ACTIONS::placeLabel, wireOrBusTool && EE_CONDITIONS::Idle, 100 );
227  ctxMenu.AddItem( EE_ACTIONS::placeGlobalLabel, wireOrBusTool && EE_CONDITIONS::Idle, 100 );
228  ctxMenu.AddItem( EE_ACTIONS::placeHierLabel, wireOrBusTool && EE_CONDITIONS::Idle, 100 );
229  ctxMenu.AddItem( EE_ACTIONS::breakWire, wireOrBusTool && EE_CONDITIONS::Idle, 100 );
230  ctxMenu.AddItem( EE_ACTIONS::breakBus, wireOrBusTool && EE_CONDITIONS::Idle, 100 );
231 
232  ctxMenu.AddSeparator( 200 );
233  ctxMenu.AddItem( EE_ACTIONS::selectNode, wireOrBusTool && EE_CONDITIONS::Idle, 200 );
234  ctxMenu.AddItem( EE_ACTIONS::selectConnection, wireOrBusTool && EE_CONDITIONS::Idle, 200 );
235 
236  // Add bus unfolding to the selection tool
237  //
239 
240  std::shared_ptr<BUS_UNFOLD_MENU> selBusUnfoldMenu = std::make_shared<BUS_UNFOLD_MENU>();
241  selBusUnfoldMenu->SetTool( m_selectionTool );
242  m_selectionTool->GetToolMenu().AddSubMenu( selBusUnfoldMenu );
243  selToolMenu.AddMenu( selBusUnfoldMenu.get(), busSelection && EE_CONDITIONS::Idle, 100 );
244 
245  return true;
246 }
247 
248 
250 {
251  static KICAD_T graphicLineType[] = { SCH_LINE_LOCATE_GRAPHIC_LINE_T, EOT };
252  return IsDrawingLineWireOrBus( aSelection ) && aSelection.Front()->IsType( graphicLineType );
253 }
254 
255 
257 {
258  static KICAD_T wireType[] = { SCH_LINE_LOCATE_WIRE_T, EOT };
259  return IsDrawingLineWireOrBus( aSelection ) && aSelection.Front()->IsType( wireType );
260 }
261 
262 
264 {
265  static KICAD_T busType[] = { SCH_LINE_LOCATE_BUS_T, EOT };
266  return IsDrawingLineWireOrBus( aSelection ) && aSelection.Front()->IsType( busType );
267 }
268 
269 
271 {
272  // NOTE: for immediate hotkeys, it is NOT required that the line, wire or bus tool
273  // be selected
274  SCH_ITEM* item = (SCH_ITEM*) aSelection.Front();
275  return item && item->IsNew() && item->Type() == SCH_LINE_T;
276 }
277 
278 
280 {
282 
283  std::string tool = aEvent.GetCommandStr().get();
284  m_frame->PushTool( tool );
286 
287  if( aEvent.HasPosition() )
288  {
289  EE_GRID_HELPER grid( m_toolMgr );
290  grid.SetSnap( !aEvent.Modifier( MD_SHIFT ) );
291  grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !aEvent.Modifier( MD_ALT ) );
292 
293  VECTOR2D cursorPos = grid.BestSnapAnchor( aEvent.Position(), LAYER_CONNECTABLE, nullptr );
294  startSegments( params->layer, cursorPos );
295  }
296 
297  return doDrawSegments( tool, params->layer, params->quitOnDraw );
298 }
299 
300 
302 {
303  wxString* netPtr = aEvent.Parameter<wxString*>();
304  wxString net;
305  SCH_LINE* segment = nullptr;
306 
307  std::string tool = aEvent.GetCommandStr().get();
308  m_frame->PushTool( tool );
309  Activate();
310 
311  if( netPtr )
312  {
313  net = *netPtr;
314  delete netPtr;
315  }
316  else
317  {
318  BUS_UNFOLD_MENU unfoldMenu;
319  unfoldMenu.SetTool( this );
320  unfoldMenu.SetShowTitle();
321 
322  SetContextMenu( &unfoldMenu, CMENU_NOW );
323 
324  while( TOOL_EVENT* evt = Wait() )
325  {
326  if( evt->Action() == TA_CHOICE_MENU_CHOICE )
327  {
328  OPT<int> id = evt->GetCommandId();
329 
330  if( id && ( *id > 0 ) )
331  net = *evt->Parameter<wxString*>();
332 
333  break;
334  }
335  else if( evt->Action() == TA_CHOICE_MENU_CLOSED )
336  {
337  break;
338  }
339  else
340  {
341  evt->SetPassEvent();
342  }
343  }
344  }
345 
346  // Break a wire for the given net out of the bus
347  if( !net.IsEmpty() )
348  segment = doUnfoldBus( net );
349 
350  // If we have an unfolded wire to draw, then draw it
351  if( segment )
352  return doDrawSegments( tool, LAYER_WIRE, false );
353  else
354  {
355  m_frame->PopTool( tool );
356  return 0;
357  }
358 }
359 
360 
361 SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::doUnfoldBus( const wxString& aNet, wxPoint aPos )
362 {
363  SCHEMATIC_SETTINGS& cfg = getModel<SCHEMATIC>()->Settings();
364 
365  if( aPos == wxDefaultPosition )
366  aPos = static_cast<wxPoint>( getViewControls()->GetCursorPosition() );
367 
369 
370  m_busUnfold.entry = new SCH_BUS_WIRE_ENTRY( aPos );
373 
379 
380  m_busUnfold.in_progress = true;
381  m_busUnfold.origin = aPos;
382  m_busUnfold.net_name = aNet;
383 
385 
387 }
388 
389 
390 const SCH_SHEET_PIN* SCH_LINE_WIRE_BUS_TOOL::getSheetPin( const wxPoint& aPosition )
391 {
392  SCH_SCREEN* screen = m_frame->GetScreen();
393 
394  for( SCH_ITEM* item : screen->Items().Overlapping( SCH_SHEET_T, aPosition ) )
395  {
396  SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
397 
398  for( SCH_SHEET_PIN* pin : sheet->GetPins() )
399  {
400  if( pin->GetPosition() == aPosition )
401  return pin;
402  }
403  }
404 
405  return nullptr;
406 }
407 
408 
409 void SCH_LINE_WIRE_BUS_TOOL::computeBreakPoint( const std::pair<SCH_LINE*, SCH_LINE*>& aSegments,
410  wxPoint& aPosition )
411 {
412  wxCHECK_RET( aSegments.first && aSegments.second,
413  wxT( "Cannot compute break point of NULL line segment." ) );
414 
415  SCH_LINE* segment = aSegments.first;
416  SCH_LINE* next_segment = aSegments.second;
417 
418  wxPoint midPoint;
419  int iDx = segment->GetEndPoint().x - segment->GetStartPoint().x;
420  int iDy = segment->GetEndPoint().y - segment->GetStartPoint().y;
421 
422  const SCH_SHEET_PIN* connectedPin = getSheetPin( segment->GetStartPoint() );
423  SHEET_SIDE force = connectedPin ? connectedPin->GetEdge() : SHEET_UNDEFINED_SIDE;
424 
425  if( force == SHEET_LEFT_SIDE || force == SHEET_RIGHT_SIDE )
426  {
427  if( aPosition.x == connectedPin->GetPosition().x ) // push outside sheet boundary
428  {
429  int direction = ( force == SHEET_LEFT_SIDE ) ? -1 : 1;
430  aPosition.x += KiROUND( getView()->GetGAL()->GetGridSize().x * direction );
431  }
432 
433  midPoint.x = aPosition.x;
434  midPoint.y = segment->GetStartPoint().y; // force horizontal
435  }
436  else if( iDy != 0 ) // keep the first segment orientation (vertical)
437  {
438  midPoint.x = segment->GetStartPoint().x;
439  midPoint.y = aPosition.y;
440  }
441  else if( iDx != 0 ) // keep the first segment orientation (horizontal)
442  {
443  midPoint.x = aPosition.x;
444  midPoint.y = segment->GetStartPoint().y;
445  }
446  else
447  {
448  if( std::abs( aPosition.x - segment->GetStartPoint().x ) <
449  std::abs( aPosition.y - segment->GetStartPoint().y ) )
450  {
451  midPoint.x = segment->GetStartPoint().x;
452  midPoint.y = aPosition.y;
453  }
454  else
455  {
456  midPoint.x = aPosition.x;
457  midPoint.y = segment->GetStartPoint().y;
458  }
459  }
460 
461  segment->SetEndPoint( midPoint );
462  next_segment->SetStartPoint( midPoint );
463  next_segment->SetEndPoint( aPosition );
464 }
465 
466 
467 int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const std::string& aTool, int aType, bool aQuitOnDraw )
468 {
469  SCH_SCREEN* screen = m_frame->GetScreen();
470  SCH_LINE* segment = nullptr;
471  EE_GRID_HELPER grid( m_toolMgr );
472 
474 
475  controls->ShowCursor( true );
476 
477  Activate();
478 
479  // Add the new label to the selection so the rotate command operates on it
480  if( m_busUnfold.label )
482 
483  // Continue the existing wires if we've started (usually by immediate action preference)
484  if( !m_wires.empty() )
485  segment = m_wires.back();
486 
487  auto setCursor =
488  [&]()
489  {
490  if( aType == LAYER_WIRE )
492  else if( aType == LAYER_BUS )
494  else if( aType == LAYER_NOTES )
496  else
498  };
499 
500  // Set initial cursor
501  setCursor();
502 
503  wxPoint contextMenuPos;
504 
505  // Main loop: keep receiving events
506  while( TOOL_EVENT* evt = Wait() )
507  {
508  setCursor();
509  grid.SetMask( GRID_HELPER::ALL );
510  grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
511  grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->Modifier( MD_ALT ) );
512 
513  if( segment )
514  {
515  if( segment->GetStartPoint().x == segment->GetEndPoint().x )
517 
518  if( segment->GetStartPoint().y == segment->GetEndPoint().y )
520  }
521 
522  wxPoint cursorPos = static_cast<wxPoint>( evt->HasPosition() ?
523  evt->Position() :
524  controls->GetMousePosition() );
525 
526  cursorPos = (wxPoint) grid.BestSnapAnchor( cursorPos, LAYER_CONNECTABLE, segment );
527  controls->ForceCursorPosition( true, cursorPos );
528 
529  bool forceHV = m_frame->eeconfig()->m_Drawing.hv_lines_only;
530 
531  auto cleanup =
532  [&] ()
533  {
535 
536  for( SCH_LINE* wire : m_wires )
537  delete wire;
538 
539  m_wires.clear();
540  segment = nullptr;
541 
542  if( m_busUnfold.entry )
544 
547 
550 
551  delete m_busUnfold.entry;
552  delete m_busUnfold.label;
553  m_busUnfold = {};
554 
555  m_view->ClearPreview();
556  m_view->ShowPreview( false );
557  };
558 
559  //------------------------------------------------------------------------
560  // Handle cancel:
561  //
562  if( evt->IsCancelInteractive() )
563  {
564  if( segment || m_busUnfold.in_progress )
565  cleanup();
566  else
567  {
568  m_frame->PopTool( aTool );
569  break;
570  }
571  }
572  else if( evt->IsActivate() )
573  {
574  if( segment || m_busUnfold.in_progress )
575  cleanup();
576 
577  if( evt->IsMoveTool() )
578  {
579  // leave ourselves on the stack so we come back after the move
580  break;
581  }
582  else
583  {
584  m_frame->PopTool( aTool );
585  break;
586  }
587  }
588  //------------------------------------------------------------------------
589  // Handle finish:
590  //
591  else if( evt->IsAction( &EE_ACTIONS::finishLineWireOrBus )
592  || evt->IsAction( &EE_ACTIONS::finishWire )
593  || evt->IsAction( &EE_ACTIONS::finishBus )
594  || evt->IsAction( &EE_ACTIONS::finishLine ) )
595  {
596  if( segment || m_busUnfold.in_progress )
597  {
598  finishSegments();
599  segment = nullptr;
600 
601  if( aQuitOnDraw )
602  {
603  m_frame->PopTool( aTool );
604  break;
605  }
606  }
607  }
608  //------------------------------------------------------------------------
609  // Handle click:
610  //
611  else if( evt->IsClick( BUT_LEFT ) || ( segment && evt->IsDblClick( BUT_LEFT ) ) )
612  {
613  // First click when unfolding places the label and wire-to-bus entry
615  {
616  wxASSERT( aType == LAYER_WIRE );
617 
618  m_frame->AddToScreen( m_busUnfold.label, screen );
620  m_busUnfold.label_placed = true;
621  }
622 
623  if( !segment )
624  {
625  segment = startSegments( aType, VECTOR2D( cursorPos ) );
626  }
627  // Create a new segment if we're out of previously-created ones
628  else if( !segment->IsNull() || ( forceHV && !m_wires[ m_wires.size() - 2 ]->IsNull() ) )
629  {
630  // Terminate the command if the end point is on a pin, junction, label, or another
631  // wire or bus.
632  if( screen->IsTerminalPoint( cursorPos, segment->GetLayer() ) )
633  {
634  finishSegments();
635  segment = nullptr;
636 
637  if( aQuitOnDraw )
638  {
639  m_frame->PopTool( aTool );
640  break;
641  }
642  }
643  else
644  {
645  segment->SetEndPoint( cursorPos );
646 
647  // Create a new segment, and chain it after the current segment.
648  segment = new SCH_LINE( *segment );
649  segment->SetFlags( IS_NEW | IS_MOVED );
650  segment->SetStartPoint( cursorPos );
651  m_wires.push_back( segment );
652 
653  m_selectionTool->AddItemToSel( segment, true /*quiet mode*/ );
654  }
655  }
656 
657  if( evt->IsDblClick( BUT_LEFT ) && segment )
658  {
659  if( forceHV && m_wires.size() >= 2 )
660  computeBreakPoint( { m_wires[ m_wires.size() - 2 ], segment }, cursorPos );
661 
662  finishSegments();
663  segment = nullptr;
664 
665  if( aQuitOnDraw )
666  {
667  m_frame->PopTool( aTool );
668  break;
669  }
670  }
671  }
672  //------------------------------------------------------------------------
673  // Handle motion:
674  //
675  else if( evt->IsMotion() || evt->IsAction( &ACTIONS::refreshPreview ) )
676  {
677  m_view->ClearPreview();
678 
679  // Update the bus unfold posture based on the mouse movement
681  {
682  wxPoint cursor_delta = cursorPos - m_busUnfold.origin;
684 
685  bool flipX = ( cursor_delta.x < 0 );
686  bool flipY = ( cursor_delta.y < 0 );
687 
688  // Erase and redraw if necessary
689  if( flipX != m_busUnfold.flipX || flipY != m_busUnfold.flipY )
690  {
691  wxSize size = entry->GetSize();
692  int ySign = flipY ? -1 : 1;
693  int xSign = flipX ? -1 : 1;
694 
695  size.x = std::abs( size.x ) * xSign;
696  size.y = std::abs( size.y ) * ySign;
697  entry->SetSize( size );
698 
699  m_busUnfold.flipY = flipY;
700  m_busUnfold.flipX = flipX;
701 
702  m_frame->UpdateItem( entry );
703  m_wires.front()->SetStartPoint( entry->GetEnd() );
704  }
705 
706  // Update the label "ghost" position
707  m_busUnfold.label->SetPosition( cursorPos );
709 
710  // Ensure segment is non-null at the start of bus unfold
711  if( !segment )
712  segment = m_wires.back();
713  }
714 
715  if( segment )
716  {
717  // Coerce the line to vertical or horizontal if necessary
718  if( forceHV && m_wires.size() >= 2 )
719  computeBreakPoint( { m_wires[ m_wires.size() - 2 ], segment }, cursorPos );
720  else
721  segment->SetEndPoint( cursorPos );
722  }
723 
724  for( SCH_LINE* wire : m_wires )
725  {
726  if( !wire->IsNull() )
727  m_view->AddToPreview( wire->Clone() );
728  }
729  }
730  //------------------------------------------------------------------------
731  // Handle context menu:
732  //
733  else if( evt->IsClick( BUT_RIGHT ) )
734  {
735  // Warp after context menu only if dragging...
736  if( !segment )
738 
739  contextMenuPos = cursorPos;
741  }
742  else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
743  {
744  if( evt->GetCommandId().get() >= ID_POPUP_SCH_UNFOLD_BUS
745  && evt->GetCommandId().get() <= ID_POPUP_SCH_UNFOLD_BUS_END )
746  {
747  wxASSERT_MSG( !segment, "Bus unfold event received when already drawing!" );
748 
749  aType = LAYER_WIRE;
750  wxString net = *evt->Parameter<wxString*>();
751  segment = doUnfoldBus( net, contextMenuPos );
752  }
753  }
754  else
755  {
756  evt->SetPassEvent();
757  }
758 
759  // Enable autopanning and cursor capture only when there is a segment to be placed
760  controls->SetAutoPan( segment != nullptr );
761  controls->CaptureCursor( segment != nullptr );
762  }
763 
765  controls->ForceCursorPosition( false );
766  return 0;
767 }
768 
769 
771 {
772  SCH_LINE* segment = nullptr;
773 
774  switch ( aType )
775  {
776  default: segment = new SCH_LINE( aPos, LAYER_NOTES ); break;
777  case LAYER_WIRE: segment = new SCH_LINE( aPos, LAYER_WIRE ); break;
778  case LAYER_BUS: segment = new SCH_LINE( aPos, LAYER_BUS ); break;
779  }
780 
781  // Give segments a parent so they find the default line/wire/bus widths
782  segment->SetParent( &m_frame->Schematic() );
783  segment->SetFlags( IS_NEW | IS_MOVED );
784  m_wires.push_back( segment );
785 
786  m_selectionTool->AddItemToSel( segment, true /*quiet mode*/ );
787 
788  // We need 2 segments to go from a given start pin to an end point when the
789  // horizontal and vertical lines only switch is on.
791  {
792  segment = new SCH_LINE( *segment );
793  segment->SetFlags( IS_NEW | IS_MOVED );
794  m_wires.push_back( segment );
795 
796  m_selectionTool->AddItemToSel( segment, true /*quiet mode*/ );
797  }
798 
799  return segment;
800 }
801 
802 
817 {
818  for( auto it = m_wires.begin(); it != m_wires.end(); )
819  {
820  SCH_LINE* line = *it;
821 
822  if( line->IsNull() )
823  {
824  delete line;
825  it = m_wires.erase( it );
826  continue;
827  }
828 
829  auto next_it = it;
830  ++next_it;
831 
832  if( next_it == m_wires.end() )
833  break;
834 
835  SCH_LINE* next_line = *next_it;
836 
837  if( SCH_LINE* merged = line->MergeOverlap( m_frame->GetScreen(), next_line, false ) )
838  {
839  delete line;
840  delete next_line;
841  it = m_wires.erase( it );
842  *it = merged;
843  }
844 
845  ++it;
846  }
847 }
848 
849 
851 {
852  // Clear selection when done so that a new wire can be started.
853  // NOTE: this must be done before simplifyWireList is called or we might end up with
854  // freed selected items.
856 
857  SCH_SCREEN* screen = m_frame->GetScreen();
858  PICKED_ITEMS_LIST itemList;
859 
860  // Remove segments backtracking over others
862 
863  // Collect the possible connection points for the new lines
864  std::vector< wxPoint > connections = m_frame->GetSchematicConnections();
865  std::vector< wxPoint > new_ends;
866 
867  // Check each new segment for possible junctions and add/split if needed
868  for( SCH_LINE* wire : m_wires )
869  {
870  if( wire->HasFlag( SKIP_STRUCT ) )
871  continue;
872 
873  std::vector<wxPoint> tmpends = wire->GetConnectionPoints();
874 
875  new_ends.insert( new_ends.end(), tmpends.begin(), tmpends.end() );
876 
877  for( const wxPoint& pt : connections )
878  {
879  if( IsPointOnSegment( wire->GetStartPoint(), wire->GetEndPoint(), pt ) )
880  new_ends.push_back( pt );
881  }
882  itemList.PushItem( ITEM_PICKER( screen, wire, UNDO_REDO::NEWITEM ) );
883  }
884 
886  {
887  wxASSERT( m_busUnfold.entry && m_busUnfold.label );
888 
889  itemList.PushItem( ITEM_PICKER( screen, m_busUnfold.entry, UNDO_REDO::NEWITEM ) );
890  itemList.PushItem( ITEM_PICKER( screen, m_busUnfold.label, UNDO_REDO::NEWITEM ) );
892  }
893 
894  // Get the last non-null wire (this is the last created segment).
895  if( !m_wires.empty() )
897 
898  // Add the new wires
899  for( SCH_LINE* wire : m_wires )
900  {
901  wire->ClearFlags( IS_NEW | IS_MOVED );
902  m_frame->AddToScreen( wire, screen );
903  }
904 
905  m_wires.clear();
906  m_view->ClearPreview();
907  m_view->ShowPreview( false );
908 
909  getViewControls()->CaptureCursor( false );
910  getViewControls()->SetAutoPan( false );
911 
912  m_frame->SaveCopyInUndoList( itemList, UNDO_REDO::NEWITEM, false );
913 
914  // Correct and remove segments that need to be merged.
916 
917  std::vector<SCH_ITEM*> components;
918 
919  for( SCH_ITEM* item : m_frame->GetScreen()->Items().OfType( SCH_COMPONENT_T ) )
920  components.push_back( item );
921 
922  for( SCH_ITEM* item : components )
923  {
924  std::vector<wxPoint> pts = item->GetConnectionPoints();
925 
926  if( pts.size() > 2 )
927  continue;
928 
929  for( auto pt = pts.begin(); pt != pts.end(); pt++ )
930  {
931  for( auto secondPt = pt + 1; secondPt != pts.end(); secondPt++ )
932  m_frame->TrimWire( *pt, *secondPt );
933  }
934  }
935 
936  for( const wxPoint& pt : new_ends )
937  {
938  if( m_frame->GetScreen()->IsJunctionNeeded( pt, true ) )
939  m_frame->AddJunction( m_frame->GetScreen(), pt, true, false );
940  }
941 
943  m_busUnfold = {};
944 
947 
948  m_frame->OnModify();
949 }
950 
951 
953 {
954  EE_SELECTION* aSelection = aEvent.Parameter<EE_SELECTION*>();
955 
956  std::vector<wxPoint> pts;
957  std::vector<wxPoint> connections = m_frame->GetSchematicConnections();
958 
959  for( unsigned ii = 0; ii < aSelection->GetSize(); ii++ )
960  {
961  SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aSelection->GetItem( ii ) );
962 
963  if( !item || !item->IsConnectable() )
964  continue;
965 
966  std::vector<wxPoint> new_pts = item->GetConnectionPoints();
967  pts.insert( pts.end(), new_pts.begin(), new_pts.end() );
968 
969  // If the item is a line, we also add any connection points from the rest of the schematic
970  // that terminate on the line after it is moved.
971  if( item->Type() == SCH_LINE_T )
972  {
973  SCH_LINE* line = (SCH_LINE*) item;
974 
975  for( const wxPoint& pt : connections )
976  {
977  if( IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), pt ) )
978  pts.push_back( pt );
979  }
980  }
981  else
982  {
983  // Clean up any wires that short non-wire connections in the list
984  for( auto pt = new_pts.begin(); pt != new_pts.end(); pt++ )
985  {
986  for( auto secondPt = pt + 1; secondPt != new_pts.end(); secondPt++ )
987  m_frame->TrimWire( *pt, *secondPt );
988  }
989  }
990  }
991 
992  // We always have some overlapping connection points. Drop duplicates here
993  std::sort( pts.begin(), pts.end(),
994  []( const wxPoint& a, const wxPoint& b ) -> bool
995  {
996  return a.x < b.x || ( a.x == b.x && a.y < b.y );
997  } );
998 
999  pts.erase( unique( pts.begin(), pts.end() ), pts.end() );
1000 
1001  for( const wxPoint& point : pts )
1002  {
1003  if( m_frame->GetScreen()->IsJunctionNeeded( point, true ) )
1004  m_frame->AddJunction( m_frame->GetScreen(), point, true, false );
1005  }
1006 
1007  return 0;
1008 }
1010 {
1015 
1017 }
static wxString PrintBusForUI(const wxString &aString)
virtual void ShowCursor(bool aEnabled)
Enable or disables display of cursor.
void AddMenu(ACTION_MENU *aMenu, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Add a submenu to the menu.
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:219
SCH_LINE * MergeOverlap(SCH_SCREEN *aScreen, SCH_LINE *aLine, bool aCheckJunctions)
Check line against aLine to see if it overlaps and merge if it does.
Definition: sch_line.cpp:450
bool SchematicCleanUp(SCH_SCREEN *aScreen=nullptr)
Performs routine schematic cleaning including breaking wire and buses and deleting identical objects ...
bool IsCurrentTool(const TOOL_ACTION &aAction) const
SHEET_SIDE
Defines the edge of the sheet that the sheet pin is positioned SHEET_LEFT_SIDE = 0: pin on left side ...
Definition: sch_sheet.h:56
TOOL_MENU m_menu
The functions below are not yet implemented - their interface may change.
virtual bool IsConnectable() const
Definition: sch_item.h:376
void UpdateItem(EDA_ITEM *aItem, bool isAddOrDelete=false)
Mark an item for refresh.
static bool IsDrawingWire(const SELECTION &aSelection)
void simplifyWireList()
Iterate over the wire list and removes the null segments and overlapping segments to create a simplif...
bool flipY
True if the bus entry should be flipped in the y-axis.
bool PassHelpTextToHandler() override
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Suspend execution of the tool until an event specified in aEventList arrives.
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Return the current mouse pointer position.
virtual std::vector< wxPoint > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition: sch_item.h:390
static TOOL_ACTION breakBus
Definition: ee_actions.h:132
void RecalculateConnections(SCH_CLEANUP_FLAGS aCleanupFlags)
Generates the connection data for the entire schematic hierarchy.
wxPoint GetStartPoint() const
Definition: sch_line.h:94
void SetSize(const wxSize &aSize)
Definition: sch_bus_entry.h:64
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:45
bool IsJunctionNeeded(const wxPoint &aPosition, bool aNew=false)
Test if a junction is required for the items at aPosition on the screen.
Definition: sch_screen.cpp:373
const BITMAP_OPAQUE add_line2bus_xpm[1]
static SELECTION_CONDITION MoreThan(int aNumber)
Create a functor that tests if the number of selected items is greater than the value given as parame...
void AddToPreview(EDA_ITEM *aItem, bool aTakeOwnership=true)
Definition: view.cpp:1552
static bool Idle(const SELECTION &aSelection)
Test if there no items selected or being edited.
std::vector< SCH_LINE * > m_wires
Storage for the line segments while drawing.
int AddJunctionsIfNeeded(const TOOL_EVENT &aEvent)
Handle the addition of junctions to a selection of objects.
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:46
static TOOL_ACTION placeHierLabel
Definition: ee_actions.h:85
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:215
static TOOL_ACTION placeJunction
Definition: ee_actions.h:81
static TOOL_ACTION selectConnection
If current selection is a wire or bus, expand to entire connection.
Definition: ee_actions.h:51
EE_TYPE Overlapping(const EDA_RECT &aRect)
Definition: sch_rtree.h:224
virtual void PushTool(const std::string &actionName)
NB: the definition of "tool" is different at the user level.
SCH_LINE * startSegments(int aType, const VECTOR2D &aPos)
static TOOL_ACTION unfoldBus
Definition: ee_actions.h:79
static TOOL_ACTION finishLineWireOrBus
Definition: ee_actions.h:91
TOOL_MENU & GetToolMenu()
bool IsPointOnSegment(const wxPoint &aSegStart, const wxPoint &aSegEnd, const wxPoint &aTestPoint)
Test if aTestPoint is on line defined by aSegStart and aSegEnd.
Definition: trigo.cpp:42
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:141
static bool IsDrawingLine(const SELECTION &aSelection)
void RemoveFromScreen(EDA_ITEM *aItem, SCH_SCREEN *aScreen)
Remove an item from the screen (and view) aScreen is the screen the item is located on,...
VECTOR2I BestSnapAnchor(const VECTOR2I &aOrigin, int aLayer, SCH_ITEM *aDraggedItem)
void PushItem(const ITEM_PICKER &aItem)
Push aItem to the top of the list.
SHEET_SIDE GetEdge() const
Schematic editor (Eeschema) main window.
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:244
void SetContextMenu(ACTION_MENU *aMenu, CONTEXT_MENU_TRIGGER aTrigger=CMENU_BUTTON)
Assign a context menu and tells when it should be activated.
void update() override
Update menu state stub.
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
int UnfoldBus(const TOOL_EVENT &aEvent)
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
void SetCurrentCursor(KICURSOR cursor)
Set the current cursor shape for this panel.
search types array terminator (End Of Types)
Definition: typeinfo.h:81
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:77
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition: actions.h:214
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:165
static TOOL_ACTION breakWire
Definition: ee_actions.h:131
void ClearMaskFlag(int aFlag)
Definition: grid_helper.h:74
static TOOL_ACTION finishLine
Definition: ee_actions.h:94
void SetEndPoint(const wxPoint &aPosition)
Definition: sch_line.h:98
void SetTool(TOOL_INTERACTIVE *aTool)
Set a tool that is the creator of the menu.
bool IsNew() const
Definition: eda_item.h:168
const SCH_SHEET_PIN * getSheetPin(const wxPoint &aPosition)
Search for a sheet pin at a location.
SCH_JUNCTION * AddJunction(SCH_SCREEN *aScreen, const wxPoint &aPos, bool aAppendToUndo, bool aFinal=true)
bool Init() override
Init() is called once upon a registration of the tool.
void ShowPreview(bool aShow=true)
Definition: view.cpp:1566
static TOOL_ACTION leaveSheet
Definition: ee_actions.h:182
SCH_CONNECTION * Connection(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve the connection associated with this object in the given sheet.
Definition: sch_item.cpp:131
bool Init() override
Init() is called once upon a registration of the tool.
Definition: ee_tool_base.h:65
EE_SELECTION & GetSelection()
Return the set of currently selected items.
EESCHEMA_SETTINGS * eeconfig() const
EE_SELECTION & RequestSelection(const KICAD_T *aFilterList=EE_COLLECTOR::AllItems)
Return either an existing selection (filtered), or the selection at the current cursor if the existin...
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: sch_text.cpp:747
wxPoint origin
Origin (on the bus) of the unfold.
void SetFlags(STATUS_FLAGS aMask)
Definition: eda_item.h:202
VECTOR2< double > VECTOR2D
Definition: vector2d.h:622
void TestDanglingEnds()
Test all of the connectable objects in the schematic for unused connection points.
static TOOL_ACTION drawWire
Definition: ee_actions.h:77
virtual void PopTool(const std::string &actionName)
virtual void CaptureCursor(bool aEnabled)
Force the cursor to stay within the drawing panel area.
bool IsNull() const
Definition: sch_line.h:92
T Parameter() const
Return a non-standard parameter assigned to the event.
Definition: tool_event.h:443
void SetStartPoint(const wxPoint &aPosition)
Definition: sch_line.h:95
SCH_LINE * doUnfoldBus(const wxString &aNet, wxPoint aPos=wxDefaultPosition)
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void SetIcon(const BITMAP_OPAQUE *aIcon)
Assign an icon for the entry.
Definition: action_menu.cpp:72
Generic, UI-independent tool event.
Definition: tool_event.h:173
void ClearPreview()
Definition: view.cpp:1530
SCHEMATIC & Schematic() const
void SaveCopyForRepeatItem(SCH_ITEM *aItem)
Clone aItem and owns that clone in this container.
std::vector< wxPoint > GetSchematicConnections()
Collects a unique list of all possible connection points in the schematic.
An interface for classes handling user events controlling the view behavior such as zooming,...
EE_SELECTION_TOOL * m_selectionTool
Definition: ee_tool_base.h:176
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Place the cursor immediately at a given point.
virtual bool IsType(const KICAD_T aScanTypes[]) const
Check whether the item is one of the listed types.
Definition: eda_item.h:232
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet.h:85
static TOOL_ACTION clearSelection
Clears the current selection.
Definition: ee_actions.h:54
virtual void SetCrossHairCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true)=0
Move the graphic crosshair cursor to the requested position expressed in world coordinates.
A holder to handle information on schematic or board items.
static TOOL_ACTION addNeededJunctions
Definition: ee_actions.h:73
wxString net_name
Net label for the unfolding operation.
virtual KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
Definition: selection.h:106
wxPoint GetPosition() const override
Definition: sch_text.h:312
#define IS_MOVED
Item being moved.
Definition: eda_item.h:105
int doDrawSegments(const std::string &aTool, int aType, bool aQuitOnDraw)
void computeBreakPoint(const std::pair< SCH_LINE *, SCH_LINE * > &aSegments, wxPoint &aPosition)
Compute the middle coordinate for 2 segments from the start point to aPosition with the segments kept...
TOOL_INTERACTIVE * m_tool
Associates tool actions with menu item IDs. Non-owning.
Definition: action_menu.h:252
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
virtual void SetAutoPan(bool aEnabled)
Turn on/off auto panning (this feature is used when there is a tool active (eg.
SCH_BUS_WIRE_ENTRY * entry
static bool IsDrawingBus(const SELECTION &aSelection)
static TOOL_ACTION drawBus
Definition: ee_actions.h:78
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:219
void SetSnap(bool aSnap)
Definition: grid_helper.h:64
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition: selection.h:101
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:287
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:365
int Modifier(int aMask=MD_MODIFIER_MASK) const
Definition: tool_event.h:352
static bool m_allowRealTime
static TOOL_ACTION placeLabel
Definition: ee_actions.h:83
int RemoveItemFromSel(const TOOL_EVENT &aEvent)
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:471
static bool IsDrawingLineWireOrBus(const SELECTION &aSelection)
TOOLS_HOLDER * GetToolHolder() const
Definition: tool_manager.h:300
wxSize GetSize() const
Definition: sch_bus_entry.h:63
SCH_SHEET & Root() const
Definition: schematic.h:116
bool IsTerminalPoint(const wxPoint &aPosition, int aLayer)
Test if aPosition is a connection point on aLayer.
Definition: sch_screen.cpp:483
void SetUseGrid(bool aSnapToGrid)
Definition: grid_helper.h:67
void SetTitle(const wxString &aTitle) override
Set title for the menu.
Definition: action_menu.cpp:90
Board layer functions and definitions.
int AddItemToSel(const TOOL_EVENT &aEvent)
const char * name
Definition: DXF_plotter.cpp:59
void AddToScreen(EDA_ITEM *aItem, SCH_SCREEN *aScreen)
Add an item to the screen (and view) aScreen is the screen the item is located on,...
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:37
ACTION_MENU(bool isContextMenu, TOOL_INTERACTIVE *aTool=nullptr)
< Default constructor
Definition: action_menu.cpp:47
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
void SaveCopyInUndoList(SCH_SCREEN *aScreen, SCH_ITEM *aItemToCopy, UNDO_REDO aTypeCommand, bool aAppend)
Create a copy of the current schematic item, and put it in the undo list.
#define _(s)
Definition: 3d_actions.cpp:33
ACTION_MENU * create() const override
< Return an instance of this class. It has to be overridden in inheriting classes.
TOOL_MANAGER * getToolManager() const
void AddSubMenu(std::shared_ptr< ACTION_MENU > aSubMenu)
Store a submenu of this menu model.
Definition: tool_menu.cpp:52
EE_RTREE & Items()
Definition: sch_screen.h:162
static SELECTION_CONDITION OnlyType(KICAD_T aType)
Create a functor that tests if the selected items are only of given type.
void VetoContextMenuMouseWarp()
Disable mouse warping after the current context menu is closed.
Definition: tool_manager.h:428
void Clear()
Remove all the entries from the menu (as well as its title).
static TOOL_ACTION selectNode
Select the junction, wire or bus segment under the cursor.
Definition: ee_actions.h:47
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
These settings were stored in SCH_BASE_FRAME previously.
boost::optional< T > OPT
Definition: optional.h:7
std::vector< std::shared_ptr< SCH_CONNECTION > > & Members()
void SetMask(int aMask)
Definition: grid_helper.h:72
Class for a wire to bus entry.
void Activate()
Run the tool.
SCH_SHEET_PATH & GetCurrentSheet() const
bool TrimWire(const wxPoint &aStart, const wxPoint &aEnd)
If any single wire passes through both points, remove the portion between the two points,...
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
A foundation class for a tool operating on a schematic or symbol.
Definition: ee_tool_base.h:48
bool HasPosition() const
Definition: tool_event.h:261
static TOOL_ACTION drawLines
Definition: ee_actions.h:89
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current screen and u...
bool label_placed
True if user has placed the net label.
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
#define SKIP_STRUCT
flag indicating that the structure should be ignored
Definition: eda_item.h:117
virtual void SetLabelSpinStyle(LABEL_SPIN_STYLE aSpinStyle)
Set a spin or rotation angle, along with specific horizontal and vertical justification styles with e...
Definition: sch_text.cpp:248
bool IsBus() const
static TOOL_ACTION placeGlobalLabel
Definition: ee_actions.h:84
void ClearEditFlags()
Definition: eda_item.h:221
static TOOL_ACTION finishBus
Definition: ee_actions.h:93
void SetPosition(const wxPoint &aPosition) override
Definition: sch_text.h:313
void PostEvent(const TOOL_EVENT &aEvent)
Put an event to the event queue to be processed at the end of event processing cycle.
Definition: tool_manager.h:267
bool flipX
True if the bus entry should be flipped in the x-axis.
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Add a menu entry to run a TOOL_ACTION on selected items.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:196
void ShowContextMenu(SELECTION &aSelection)
Helper function to set and immediately show a CONDITIONAL_MENU in concert with the given SELECTION.
Definition: tool_menu.cpp:59
int DrawSegments(const TOOL_EVENT &aEvent)
#define IS_NEW
New item, just created.
Definition: eda_item.h:106
static TOOL_ACTION finishWire
Definition: ee_actions.h:92
const VECTOR2D Position() const
Returns the point where dragging has started.
Definition: tool_event.h:284
BUS_UNFOLDING_T m_busUnfold
Data related to bus unfolding tool.
static TOOL_ACTION refreshPreview
Definition: actions.h:109
This item represents a bus vector.
EDA_ITEM * Front() const
Definition: selection.h:203
bool in_progress
True if bus unfold operation is running.
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:162
wxPoint GetEnd() const
wxPoint GetEndPoint() const
Definition: sch_line.h:97