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 
53 #include <connection_graph.h>
54 #include <eeschema_id.h>
55 #include <sch_bus_entry.h>
56 #include <sch_connection.h>
57 #include <sch_edit_frame.h>
58 #include <sch_item.h>
59 #include <sch_line.h>
60 #include <sch_screen.h>
61 #include <sch_sheet.h>
62 #include <sch_text.h>
63 #include <schematic.h>
64 
65 #include <ee_actions.h>
66 #include <ee_grid_helper.h>
67 #include <ee_point_editor.h>
68 #include <ee_selection.h>
69 #include <ee_selection_tool.h>
70 
72 {
73 public:
75  ACTION_MENU( true ),
76  m_showTitle( false )
77  {
79  SetTitle( _( "Unfold from Bus" ) );
80  }
81 
82  void SetShowTitle()
83  {
84  m_showTitle = true;
85  }
86 
87 
88 protected:
89  ACTION_MENU* create() const override
90  {
91  return new BUS_UNFOLD_MENU();
92  }
93 
94 private:
95  void update() override
96  {
99  KICAD_T busType[] = { SCH_LINE_LOCATE_BUS_T, EOT };
100  EE_SELECTION& selection = selTool->RequestSelection( busType );
101  SCH_LINE* bus = (SCH_LINE*) selection.Front();
102 
103  Clear();
104 
105  // TODO(JE) remove once real-time is enabled
106  if( !ADVANCED_CFG::GetCfg().m_RealTimeConnectivity || !CONNECTION_GRAPH::m_allowRealTime )
107  {
109 
110  // Pick up the pointer again because it may have been changed by SchematicCleanUp
111  selection = selTool->RequestSelection( busType );
112  bus = (SCH_LINE*) selection.Front();
113  }
114 
115  if( !bus )
116  {
117  Append( ID_POPUP_SCH_UNFOLD_BUS, _( "No bus selected" ), wxEmptyString );
118  Enable( ID_POPUP_SCH_UNFOLD_BUS, false );
119  return;
120  }
121 
122  SCH_CONNECTION* connection = bus->Connection();
123 
124  if( !connection || !connection->IsBus() || connection->Members().empty() )
125  {
126  Append( ID_POPUP_SCH_UNFOLD_BUS, _( "Bus has no members" ), wxEmptyString );
127  Enable( ID_POPUP_SCH_UNFOLD_BUS, false );
128  return;
129  }
130 
131  int idx = 0;
132 
133  if( m_showTitle )
134  {
135  Append( ID_POPUP_SCH_UNFOLD_BUS, _( "Unfold from Bus" ), wxEmptyString );
136  Enable( ID_POPUP_SCH_UNFOLD_BUS, false );
137  }
138 
139  for( const auto& member : connection->Members() )
140  {
141  int id = ID_POPUP_SCH_UNFOLD_BUS + ( idx++ );
142  wxString name = SCH_CONNECTION::PrintBusForUI( member->FullLocalName() );
143 
144  if( member->Type() == CONNECTION_TYPE::BUS )
145  {
146  ACTION_MENU* submenu = new ACTION_MENU( true );
147  submenu->SetTool( m_tool );
148  AppendSubMenu( submenu, name );
149 
150  for( const auto& sub_member : member->Members() )
151  {
152  id = ID_POPUP_SCH_UNFOLD_BUS + ( idx++ );
153  name = SCH_CONNECTION::PrintBusForUI( sub_member->FullLocalName() );
154  submenu->Append( id, name, wxEmptyString );
155  }
156  }
157  else
158  {
159  Append( id, name, wxEmptyString );
160  }
161  }
162  }
163 
165 };
166 
167 
169  EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.InteractiveDrawingLineWireBus" )
170 {
171  m_busUnfold = {};
172  m_wires.reserve( 16 );
173 }
174 
175 
177 {
178 }
179 
180 
182 {
184 
185  auto wireOrBusTool =
186  [this]( const SELECTION& aSel )
187  {
190  };
191 
192  auto lineTool =
193  [this]( const SELECTION& aSel )
194  {
196  };
197 
198  auto belowRootSheetCondition =
199  [&]( const SELECTION& aSel )
200  {
201  return m_frame->GetCurrentSheet().Last() != &m_frame->Schematic().Root();
202  };
203 
204  auto busSelection = EE_CONDITIONS::MoreThan( 0 )
206 
207  auto& ctxMenu = m_menu.GetMenu();
208 
209  // Build the tool menu
210  //
211  ctxMenu.AddItem( EE_ACTIONS::leaveSheet, belowRootSheetCondition, 2 );
212 
213  ctxMenu.AddSeparator( 10 );
214  ctxMenu.AddItem( EE_ACTIONS::drawWire, wireOrBusTool && EE_CONDITIONS::Idle, 10 );
215  ctxMenu.AddItem( EE_ACTIONS::drawBus, wireOrBusTool && EE_CONDITIONS::Idle, 10 );
216  ctxMenu.AddItem( EE_ACTIONS::drawLines, lineTool && EE_CONDITIONS::Idle, 10 );
217  ctxMenu.AddItem( EE_ACTIONS::finishWire, IsDrawingWire, 10 );
218  ctxMenu.AddItem( EE_ACTIONS::finishBus, IsDrawingBus, 10 );
219  ctxMenu.AddItem( EE_ACTIONS::finishLine, IsDrawingLine, 10 );
220 
221  std::shared_ptr<BUS_UNFOLD_MENU> busUnfoldMenu = std::make_shared<BUS_UNFOLD_MENU>();
222  busUnfoldMenu->SetTool( this );
223  m_menu.AddSubMenu( busUnfoldMenu );
224  ctxMenu.AddMenu( busUnfoldMenu.get(), EE_CONDITIONS::Idle, 10 );
225 
226  ctxMenu.AddSeparator( 100 );
227  ctxMenu.AddItem( EE_ACTIONS::placeJunction, wireOrBusTool && EE_CONDITIONS::Idle, 100 );
228  ctxMenu.AddItem( EE_ACTIONS::placeLabel, wireOrBusTool && EE_CONDITIONS::Idle, 100 );
229  ctxMenu.AddItem( EE_ACTIONS::placeGlobalLabel, wireOrBusTool && EE_CONDITIONS::Idle, 100 );
230  ctxMenu.AddItem( EE_ACTIONS::placeHierLabel, wireOrBusTool && EE_CONDITIONS::Idle, 100 );
231  ctxMenu.AddItem( EE_ACTIONS::breakWire, wireOrBusTool && EE_CONDITIONS::Idle, 100 );
232  ctxMenu.AddItem( EE_ACTIONS::breakBus, wireOrBusTool && EE_CONDITIONS::Idle, 100 );
233 
234  ctxMenu.AddSeparator( 200 );
235  ctxMenu.AddItem( EE_ACTIONS::selectNode, wireOrBusTool && EE_CONDITIONS::Idle, 200 );
236  ctxMenu.AddItem( EE_ACTIONS::selectConnection, wireOrBusTool && EE_CONDITIONS::Idle, 200 );
237 
238  // Add bus unfolding to the selection tool
239  //
241 
242  std::shared_ptr<BUS_UNFOLD_MENU> selBusUnfoldMenu = std::make_shared<BUS_UNFOLD_MENU>();
243  selBusUnfoldMenu->SetTool( m_selectionTool );
244  m_selectionTool->GetToolMenu().AddSubMenu( selBusUnfoldMenu );
245  selToolMenu.AddMenu( selBusUnfoldMenu.get(), busSelection && EE_CONDITIONS::Idle, 100 );
246 
247  return true;
248 }
249 
250 
252 {
253  static KICAD_T graphicLineType[] = { SCH_LINE_LOCATE_GRAPHIC_LINE_T, EOT };
254  return IsDrawingLineWireOrBus( aSelection ) && aSelection.Front()->IsType( graphicLineType );
255 }
256 
257 
259 {
260  static KICAD_T wireType[] = { SCH_LINE_LOCATE_WIRE_T, EOT };
261  return IsDrawingLineWireOrBus( aSelection ) && aSelection.Front()->IsType( wireType );
262 }
263 
264 
266 {
267  static KICAD_T busType[] = { SCH_LINE_LOCATE_BUS_T, EOT };
268  return IsDrawingLineWireOrBus( aSelection ) && aSelection.Front()->IsType( busType );
269 }
270 
271 
273 {
274  // NOTE: for immediate hotkeys, it is NOT required that the line, wire or bus tool
275  // be selected
276  SCH_ITEM* item = (SCH_ITEM*) aSelection.Front();
277  return item && item->IsNew() && item->Type() == SCH_LINE_T;
278 }
279 
280 
282 {
284 
285  if( aEvent.HasPosition() )
286  getViewControls()->WarpCursor( aEvent.Position(), true );
287 
288  std::string tool = aEvent.GetCommandStr().get();
289  m_frame->PushTool( tool );
291 
292  if( aEvent.HasPosition() )
293  {
294  VECTOR2D cursorPos = getViewControls()->GetCursorPosition( !aEvent.Modifier( MD_ALT ) );
295  startSegments( params->layer, cursorPos );
296  }
297 
298  return doDrawSegments( tool, params->layer, params->quitOnDraw );
299 }
300 
301 
303 {
304  wxString* netPtr = aEvent.Parameter<wxString*>();
305  wxString net;
306  SCH_LINE* segment = nullptr;
307 
308  std::string tool = aEvent.GetCommandStr().get();
309  m_frame->PushTool( tool );
310  Activate();
311 
312  if( netPtr )
313  {
314  net = *netPtr;
315  delete netPtr;
316  }
317  else
318  {
319  BUS_UNFOLD_MENU unfoldMenu;
320  unfoldMenu.SetTool( this );
321  unfoldMenu.SetShowTitle();
322 
323  SetContextMenu( &unfoldMenu, CMENU_NOW );
324 
325  while( TOOL_EVENT* evt = Wait() )
326  {
327  if( evt->Action() == TA_CHOICE_MENU_CHOICE )
328  {
329  OPT<int> id = evt->GetCommandId();
330 
331  if( id && ( *id > 0 ) )
332  net = *evt->Parameter<wxString*>();
333 
334  break;
335  }
336  else if( evt->Action() == TA_CHOICE_MENU_CLOSED )
337  {
338  break;
339  }
340  else
341  {
342  evt->SetPassEvent();
343  }
344  }
345  }
346 
347  // Break a wire for the given net out of the bus
348  if( !net.IsEmpty() )
349  segment = doUnfoldBus( net );
350 
351  // If we have an unfolded wire to draw, then draw it
352  if( segment )
353  return doDrawSegments( tool, LAYER_WIRE, false );
354  else
355  {
356  m_frame->PopTool( tool );
357  return 0;
358  }
359 }
360 
361 
363 {
364  SCHEMATIC_SETTINGS& cfg = getModel<SCHEMATIC>()->Settings();
365  wxPoint pos = (wxPoint) getViewControls()->GetCursorPosition();
366 
368 
369  m_busUnfold.entry = new SCH_BUS_WIRE_ENTRY( pos );
372 
378 
379  m_busUnfold.in_progress = true;
380  m_busUnfold.origin = pos;
381  m_busUnfold.net_name = aNet;
382 
384 
386 }
387 
388 
389 const SCH_SHEET_PIN* SCH_LINE_WIRE_BUS_TOOL::getSheetPin( const wxPoint& aPosition )
390 {
391  SCH_SCREEN* screen = m_frame->GetScreen();
392 
393  for( SCH_ITEM* item : screen->Items().Overlapping( SCH_SHEET_T, aPosition ) )
394  {
395  SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
396 
397  for( SCH_SHEET_PIN* pin : sheet->GetPins() )
398  {
399  if( pin->GetPosition() == aPosition )
400  return pin;
401  }
402  }
403 
404  return nullptr;
405 }
406 
407 
408 void SCH_LINE_WIRE_BUS_TOOL::computeBreakPoint( const std::pair<SCH_LINE*, SCH_LINE*>& aSegments,
409  wxPoint& aPosition )
410 {
411  wxCHECK_RET( aSegments.first && aSegments.second,
412  wxT( "Cannot compute break point of NULL line segment." ) );
413 
414  SCH_LINE* segment = aSegments.first;
415  SCH_LINE* next_segment = aSegments.second;
416 
417  wxPoint midPoint;
418  int iDx = segment->GetEndPoint().x - segment->GetStartPoint().x;
419  int iDy = segment->GetEndPoint().y - segment->GetStartPoint().y;
420 
421  const SCH_SHEET_PIN* connectedPin = getSheetPin( segment->GetStartPoint() );
422  SHEET_SIDE force = connectedPin ? connectedPin->GetEdge() : SHEET_UNDEFINED_SIDE;
423 
424  if( force == SHEET_LEFT_SIDE || force == SHEET_RIGHT_SIDE )
425  {
426  if( aPosition.x == connectedPin->GetPosition().x ) // push outside sheet boundary
427  {
428  int direction = ( force == SHEET_LEFT_SIDE ) ? -1 : 1;
429  aPosition.x += KiROUND( getView()->GetGAL()->GetGridSize().x * direction );
430  }
431 
432  midPoint.x = aPosition.x;
433  midPoint.y = segment->GetStartPoint().y; // force horizontal
434  }
435  else if( iDy != 0 ) // keep the first segment orientation (vertical)
436  {
437  midPoint.x = segment->GetStartPoint().x;
438  midPoint.y = aPosition.y;
439  }
440  else if( iDx != 0 ) // keep the first segment orientation (horizontal)
441  {
442  midPoint.x = aPosition.x;
443  midPoint.y = segment->GetStartPoint().y;
444  }
445  else
446  {
447  if( std::abs( aPosition.x - segment->GetStartPoint().x ) <
448  std::abs( aPosition.y - segment->GetStartPoint().y ) )
449  {
450  midPoint.x = segment->GetStartPoint().x;
451  midPoint.y = aPosition.y;
452  }
453  else
454  {
455  midPoint.x = aPosition.x;
456  midPoint.y = segment->GetStartPoint().y;
457  }
458  }
459 
460  segment->SetEndPoint( midPoint );
461  next_segment->SetStartPoint( midPoint );
462  next_segment->SetEndPoint( aPosition );
463 }
464 
465 
466 int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const std::string& aTool, int aType, bool aQuitOnDraw )
467 {
468  SCH_SCREEN* screen = m_frame->GetScreen();
469  SCH_LINE* segment = nullptr;
470  EE_GRID_HELPER grid( m_toolMgr );
471 
473 
474  controls->ShowCursor( true );
475 
476  Activate();
477 
478  // Add the new label to the selection so the rotate command operates on it
479  if( m_busUnfold.label )
481 
482  // Continue the existing wires if we've started (usually by immediate action preference)
483  if( !m_wires.empty() )
484  segment = m_wires.back();
485 
486  auto setCursor =
487  [&]()
488  {
489  if( aType == LAYER_WIRE )
491  else if( aType == LAYER_BUS )
493  else if( aType == LAYER_NOTES )
495  else
497  };
498 
499  // Set initial cursor
500  setCursor();
501 
502  // Main loop: keep receiving events
503  while( TOOL_EVENT* evt = Wait() )
504  {
505  setCursor();
506  grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
507  grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->Modifier( MD_ALT ) );
508 
509  wxPoint cursorPos = evt->IsPrime() ? (wxPoint) evt->Position()
510  : (wxPoint) controls->GetMousePosition();
511 
512  cursorPos = (wxPoint) grid.BestSnapAnchor( cursorPos, LAYER_CONNECTABLE, nullptr );
513  controls->ForceCursorPosition( true, cursorPos );
514 
515  bool forceHV = m_frame->eeconfig()->m_Drawing.hv_lines_only;
516 
517  auto cleanup =
518  [&] ()
519  {
521 
522  for( SCH_LINE* wire : m_wires )
523  delete wire;
524 
525  m_wires.clear();
526  segment = nullptr;
527 
528  if( m_busUnfold.entry )
530 
533 
536 
537  delete m_busUnfold.entry;
538  delete m_busUnfold.label;
539  m_busUnfold = {};
540 
541  m_view->ClearPreview();
542  m_view->ShowPreview( false );
543  };
544 
545  //------------------------------------------------------------------------
546  // Handle cancel:
547  //
548  if( evt->IsCancelInteractive() )
549  {
550  if( segment || m_busUnfold.in_progress )
551  cleanup();
552  else
553  {
554  m_frame->PopTool( aTool );
555  break;
556  }
557  }
558  else if( evt->IsActivate() )
559  {
560  if( segment || m_busUnfold.in_progress )
561  cleanup();
562 
563  if( evt->IsMoveTool() )
564  {
565  // leave ourselves on the stack so we come back after the move
566  break;
567  }
568  else
569  {
570  m_frame->PopTool( aTool );
571  break;
572  }
573  }
574  //------------------------------------------------------------------------
575  // Handle finish:
576  //
577  else if( evt->IsAction( &EE_ACTIONS::finishLineWireOrBus )
578  || evt->IsAction( &EE_ACTIONS::finishWire )
579  || evt->IsAction( &EE_ACTIONS::finishBus )
580  || evt->IsAction( &EE_ACTIONS::finishLine ) )
581  {
582  if( segment || m_busUnfold.in_progress )
583  {
584  finishSegments();
585  segment = nullptr;
586 
587  if( aQuitOnDraw )
588  {
589  m_frame->PopTool( aTool );
590  break;
591  }
592  }
593  }
594  //------------------------------------------------------------------------
595  // Handle click:
596  //
597  else if( evt->IsClick( BUT_LEFT ) || ( segment && evt->IsDblClick( BUT_LEFT ) ) )
598  {
599  // First click when unfolding places the label and wire-to-bus entry
601  {
602  wxASSERT( aType == LAYER_WIRE );
603 
604  m_frame->AddToScreen( m_busUnfold.label, screen );
606  m_busUnfold.label_placed = true;
607  }
608 
609  if( !segment )
610  {
611  segment = startSegments( aType, VECTOR2D( cursorPos ) );
612  }
613  // Create a new segment if we're out of previously-created ones
614  else if( !segment->IsNull() || ( forceHV && !m_wires[ m_wires.size() - 2 ]->IsNull() ) )
615  {
616  // Terminate the command if the end point is on a pin, junction, or another
617  // wire or bus.
619  && screen->IsTerminalPoint( cursorPos, segment->GetLayer() ) )
620  {
621  finishSegments();
622  segment = nullptr;
623 
624  if( aQuitOnDraw )
625  {
626  m_frame->PopTool( aTool );
627  break;
628  }
629  }
630  else
631  {
632  segment->SetEndPoint( cursorPos );
633 
634  // Create a new segment, and chain it after the current segment.
635  segment = new SCH_LINE( *segment );
636  segment->SetFlags( IS_NEW | IS_MOVED );
637  segment->SetStartPoint( cursorPos );
638  m_wires.push_back( segment );
639 
640  m_selectionTool->AddItemToSel( segment, true /*quiet mode*/ );
641  }
642  }
643 
644  if( evt->IsDblClick( BUT_LEFT ) && segment )
645  {
646  if( forceHV && m_wires.size() >= 2 )
647  computeBreakPoint( { m_wires[ m_wires.size() - 2 ], segment }, cursorPos );
648 
649  finishSegments();
650  segment = nullptr;
651 
652  if( aQuitOnDraw )
653  {
654  m_frame->PopTool( aTool );
655  break;
656  }
657  }
658  }
659  //------------------------------------------------------------------------
660  // Handle motion:
661  //
662  else if( evt->IsMotion() || evt->IsAction( &ACTIONS::refreshPreview ) )
663  {
664  m_view->ClearPreview();
665 
666  // Update the bus unfold posture based on the mouse movement
668  {
669  wxPoint cursor_delta = cursorPos - m_busUnfold.origin;
671 
672  bool flipX = ( cursor_delta.x < 0 );
673  bool flipY = ( cursor_delta.y < 0 );
674 
675  // Erase and redraw if necessary
676  if( flipX != m_busUnfold.flipX || flipY != m_busUnfold.flipY )
677  {
678  wxSize size = entry->GetSize();
679  int ySign = flipY ? -1 : 1;
680  int xSign = flipX ? -1 : 1;
681 
682  size.x = std::abs( size.x ) * xSign;
683  size.y = std::abs( size.y ) * ySign;
684  entry->SetSize( size );
685 
686  m_busUnfold.flipY = flipY;
687  m_busUnfold.flipX = flipX;
688 
689  m_frame->UpdateItem( entry );
690  m_wires.front()->SetStartPoint( entry->GetEnd() );
691  }
692 
693  // Update the label "ghost" position
694  m_busUnfold.label->SetPosition( cursorPos );
696 
697  // Ensure segment is non-null at the start of bus unfold
698  if( !segment )
699  segment = m_wires.back();
700  }
701 
702  if( segment )
703  {
704  // Coerce the line to vertical or horizontal if necessary
705  if( forceHV && m_wires.size() >= 2 )
706  computeBreakPoint( { m_wires[ m_wires.size() - 2 ], segment }, cursorPos );
707  else
708  segment->SetEndPoint( cursorPos );
709  }
710 
711  for( SCH_LINE* wire : m_wires )
712  {
713  if( !wire->IsNull() )
714  m_view->AddToPreview( wire->Clone() );
715  }
716  }
717  //------------------------------------------------------------------------
718  // Handle context menu:
719  //
720  else if( evt->IsClick( BUT_RIGHT ) )
721  {
722  // Warp after context menu only if dragging...
723  if( !segment )
725 
727  }
728  else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
729  {
730  if( evt->GetCommandId().get() >= ID_POPUP_SCH_UNFOLD_BUS
731  && evt->GetCommandId().get() <= ID_POPUP_SCH_UNFOLD_BUS_END )
732  {
733  wxASSERT_MSG( !segment, "Bus unfold event received when already drawing!" );
734 
735  aType = LAYER_WIRE;
736  wxString net = *evt->Parameter<wxString*>();
737  segment = doUnfoldBus( net );
738  }
739  }
740  else
741  {
742  evt->SetPassEvent();
743  }
744 
745  // Enable autopanning and cursor capture only when there is a segment to be placed
746  controls->SetAutoPan( segment != nullptr );
747  controls->CaptureCursor( segment != nullptr );
748  }
749 
751  controls->ForceCursorPosition( false );
752  return 0;
753 }
754 
755 
757 {
758  SCH_LINE* segment = nullptr;
759 
760  switch ( aType )
761  {
762  default: segment = new SCH_LINE( aPos, LAYER_NOTES ); break;
763  case LAYER_WIRE: segment = new SCH_LINE( aPos, LAYER_WIRE ); break;
764  case LAYER_BUS: segment = new SCH_LINE( aPos, LAYER_BUS ); break;
765  }
766 
767  // Give segments a parent so they find the default line/wire/bus widths
768  segment->SetParent( &m_frame->Schematic() );
769  segment->SetFlags( IS_NEW | IS_MOVED );
770  m_wires.push_back( segment );
771 
772  m_selectionTool->AddItemToSel( segment, true /*quiet mode*/ );
773 
774  // We need 2 segments to go from a given start pin to an end point when the
775  // horizontal and vertical lines only switch is on.
777  {
778  segment = new SCH_LINE( *segment );
779  segment->SetFlags( IS_NEW | IS_MOVED );
780  m_wires.push_back( segment );
781 
782  m_selectionTool->AddItemToSel( segment, true /*quiet mode*/ );
783  }
784 
785  return segment;
786 }
787 
788 
803 {
804  for( auto it = m_wires.begin(); it != m_wires.end(); )
805  {
806  SCH_LINE* line = *it;
807 
808  if( line->IsNull() )
809  {
810  delete line;
811  it = m_wires.erase( it );
812  continue;
813  }
814 
815  auto next_it = it;
816  ++next_it;
817 
818  if( next_it == m_wires.end() )
819  break;
820 
821  SCH_LINE* next_line = *next_it;
822 
823  if( SCH_LINE* merged = line->MergeOverlap( m_frame->GetScreen(), next_line, false ) )
824  {
825  delete line;
826  delete next_line;
827  it = m_wires.erase( it );
828  *it = merged;
829  }
830 
831  ++it;
832  }
833 }
834 
835 
837 {
838  // Clear selection when done so that a new wire can be started.
839  // NOTE: this must be done before simplifyWireList is called or we might end up with
840  // freed selected items.
842 
843  SCH_SCREEN* screen = m_frame->GetScreen();
844  PICKED_ITEMS_LIST itemList;
845 
846  // Remove segments backtracking over others
848 
849  // Collect the possible connection points for the new lines
850  std::vector< wxPoint > connections = m_frame->GetSchematicConnections();
851  std::vector< wxPoint > new_ends;
852 
853  // Check each new segment for possible junctions and add/split if needed
854  for( SCH_LINE* wire : m_wires )
855  {
856  if( wire->HasFlag( SKIP_STRUCT ) )
857  continue;
858 
859  std::vector<wxPoint> tmpends = wire->GetConnectionPoints();
860 
861  new_ends.insert( new_ends.end(), tmpends.begin(), tmpends.end() );
862 
863  for( const wxPoint& pt : connections )
864  {
865  if( IsPointOnSegment( wire->GetStartPoint(), wire->GetEndPoint(), pt ) )
866  new_ends.push_back( pt );
867  }
868  itemList.PushItem( ITEM_PICKER( screen, wire, UNDO_REDO::NEWITEM ) );
869  }
870 
872  {
873  wxASSERT( m_busUnfold.entry && m_busUnfold.label );
874 
875  itemList.PushItem( ITEM_PICKER( screen, m_busUnfold.entry, UNDO_REDO::NEWITEM ) );
876  itemList.PushItem( ITEM_PICKER( screen, m_busUnfold.label, UNDO_REDO::NEWITEM ) );
878  }
879 
880  // Get the last non-null wire (this is the last created segment).
881  if( !m_wires.empty() )
883 
884  // Add the new wires
885  for( SCH_LINE* wire : m_wires )
886  {
887  wire->ClearFlags( IS_NEW | IS_MOVED );
888  m_frame->AddToScreen( wire, screen );
889  }
890 
891  m_wires.clear();
892  m_view->ClearPreview();
893  m_view->ShowPreview( false );
894 
895  getViewControls()->CaptureCursor( false );
896  getViewControls()->SetAutoPan( false );
897 
898  m_frame->SaveCopyInUndoList( itemList, UNDO_REDO::NEWITEM, false );
899 
900  // Correct and remove segments that need to be merged.
902 
903  for( SCH_ITEM* item : m_frame->GetScreen()->Items().OfType( SCH_COMPONENT_T ) )
904  {
905  std::vector<wxPoint> pts = item->GetConnectionPoints();
906 
907  if( pts.size() > 2 )
908  continue;
909 
910  for( auto pt = pts.begin(); pt != pts.end(); pt++ )
911  {
912  for( auto secondPt = pt + 1; secondPt != pts.end(); secondPt++ )
913  m_frame->TrimWire( *pt, *secondPt );
914  }
915  }
916 
917  for( const wxPoint& pt : new_ends )
918  {
919  if( m_frame->GetScreen()->IsJunctionNeeded( pt, true ) )
920  m_frame->AddJunction( m_frame->GetScreen(), pt, true, false );
921  }
922 
924  m_busUnfold = {};
925 
928 
929  m_frame->OnModify();
930 }
931 
932 
934 {
935  EE_SELECTION* aSelection = aEvent.Parameter<EE_SELECTION*>();
936 
937  std::vector<wxPoint> pts;
938  std::vector<wxPoint> connections = m_frame->GetSchematicConnections();
939 
940  for( unsigned ii = 0; ii < aSelection->GetSize(); ii++ )
941  {
942  SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aSelection->GetItem( ii ) );
943 
944  if( !item || !item->IsConnectable() )
945  continue;
946 
947  std::vector<wxPoint> new_pts = item->GetConnectionPoints();
948  pts.insert( pts.end(), new_pts.begin(), new_pts.end() );
949 
950  // If the item is a line, we also add any connection points from the rest of the schematic
951  // that terminate on the line after it is moved.
952  if( item->Type() == SCH_LINE_T )
953  {
954  SCH_LINE* line = (SCH_LINE*) item;
955 
956  for( const wxPoint& pt : connections )
957  {
958  if( IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), pt ) )
959  pts.push_back( pt );
960  }
961  }
962  else
963  {
964  // Clean up any wires that short non-wire connections in the list
965  for( auto pt = new_pts.begin(); pt != new_pts.end(); pt++ )
966  {
967  for( auto secondPt = pt + 1; secondPt != new_pts.end(); secondPt++ )
968  m_frame->TrimWire( *pt, *secondPt );
969  }
970  }
971  }
972 
973  // We always have some overlapping connection points. Drop duplicates here
974  std::sort( pts.begin(), pts.end(),
975  []( const wxPoint& a, const wxPoint& b ) -> bool
976  {
977  return a.x < b.x || ( a.x == b.x && a.y < b.y );
978  } );
979 
980  pts.erase( unique( pts.begin(), pts.end() ), pts.end() );
981 
982  for( const wxPoint& point : pts )
983  {
984  if( m_frame->GetScreen()->IsJunctionNeeded( point, true ) )
985  m_frame->AddJunction( m_frame->GetScreen(), point, true, false );
986  }
987 
988  return 0;
989 }
991 {
996 
998 }
static wxString PrintBusForUI(const wxString &aString)
virtual void ShowCursor(bool aEnabled)
Function ShowCursor() Enables or disables display of cursor.
void AddMenu(ACTION_MENU *aMenu, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Adds a submenu to the menu.
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:404
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
functions below are not yet implemented - their interface may change
virtual bool IsConnectable() const
Definition: sch_item.h:383
void UpdateItem(EDA_ITEM *aItem, bool isAddOrDelete=false)
Mark an item for refresh.
static bool IsDrawingWire(const SELECTION &aSelection)
void simplifyWireList()
Iterates over the wire list and removes the null segments and overlapping segments to create a simpli...
bool flipY
True if the bus entry should be flipped in the y-axis.
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Function GetMousePosition() Returns 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:397
static TOOL_ACTION breakBus
Definition: ee_actions.h:135
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:72
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:43
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:371
const BITMAP_OPAQUE add_line2bus_xpm[1]
static SELECTION_CONDITION MoreThan(int aNumber)
Creates a functor that tests if the number of selected items is greater than the value given as param...
void AddToPreview(EDA_ITEM *aItem, bool aTakeOwnership=true)
Definition: view.cpp:1554
SCH_LINE * doUnfoldBus(const wxString &aNet)
static bool Idle(const SELECTION &aSelection)
Tests 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()
Function GetMenu.
Definition: tool_menu.cpp:46
static TOOL_ACTION placeHierLabel
Definition: ee_actions.h:87
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:219
static TOOL_ACTION placeJunction
Definition: ee_actions.h:83
static TOOL_ACTION selectConnection
If current selection is a wire or bus, expand to entire connection.
Definition: ee_actions.h:53
EE_TYPE OfType(KICAD_T aType)
Definition: sch_rtree.h:219
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:81
static TOOL_ACTION finishLineWireOrBus
Definition: ee_actions.h:94
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)
Function RunAction() Runs 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)
Function PushItem pushes aItem to the top of the list.
SHEET_SIDE GetEdge() const
Schematic editor (Eeschema) main window.
bool TestDanglingEnds()
Test all of the connectable objects in the schematic for unused connection points.
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:244
void SetContextMenu(ACTION_MENU *aMenu, CONTEXT_MENU_TRIGGER aTrigger=CMENU_BUTTON)
Function SetContextMenu()
void update() override
Update menu state stub.
void setTransitions() override
Sets up handlers for various 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))
Function Go()
void SetCurrentCursor(KICURSOR cursor)
Function SetCurrentCursor Set the current cursor shape for this panel.
search types array terminator (End Of Types)
Definition: typeinfo.h:82
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
static const TOOL_EVENT SelectedItemsModified
Definition: actions.h:218
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:184
static TOOL_ACTION breakWire
Definition: ee_actions.h:134
static TOOL_ACTION finishLine
Definition: ee_actions.h:97
void SetEndPoint(const wxPoint &aPosition)
Definition: sch_line.h:98
void SetTool(TOOL_INTERACTIVE *aTool)
Sets a tool that is the creator of the menu.
bool IsNew() const
Definition: eda_item.h:187
const SCH_SHEET_PIN * getSheetPin(const wxPoint &aPosition)
Searches for a sheet pin at a location.
SCH_JUNCTION * AddJunction(SCH_SCREEN *aScreen, const wxPoint &aPos, bool aAppendToUndo, bool aFinal=true)
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
void ShowPreview(bool aShow=true)
Definition: view.cpp:1568
static TOOL_ACTION leaveSheet
Definition: ee_actions.h:185
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
Function Init() Init() is called once upon a registration of the tool.
Definition: ee_tool_base.h:69
EE_SELECTION & GetSelection()
Function GetSelection()
EESCHEMA_SETTINGS * eeconfig() const
EE_SELECTION & RequestSelection(const KICAD_T *aFilterList=EE_COLLECTOR::AllItems)
Function RequestSelection()
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
virtual void WarpCursor(const VECTOR2D &aPosition, bool aWorldCoordinates=false, bool aWarpView=false)=0
Function WarpCursor() If enabled (.
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
Definition: sch_text.cpp:743
wxPoint origin
Origin (on the bus) of the unfold.
void SetFlags(STATUS_FLAGS aMask)
Definition: eda_item.h:220
VECTOR2< double > VECTOR2D
Definition: vector2d.h:593
static TOOL_ACTION drawWire
Definition: ee_actions.h:79
virtual void PopTool(const std::string &actionName)
virtual void CaptureCursor(bool aEnabled)
Function CaptureCursor() Forces the cursor to stay within the drawing panel area.
bool IsNull() const
Definition: sch_line.h:92
T Parameter() const
Function Parameter() Returns a non-standard parameter assigned to the event.
Definition: tool_event.h:435
void SetStartPoint(const wxPoint &aPosition)
Definition: sch_line.h:95
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void SetIcon(const BITMAP_OPAQUE *aIcon)
Assigns an icon for the entry.
Definition: action_menu.cpp:71
TOOL_EVENT.
Definition: tool_event.h:171
void ClearPreview()
Definition: view.cpp:1535
SCHEMATIC & Schematic() const
void SaveCopyInUndoList(SCH_SCREEN *aScreen, SCH_ITEM *aItemToCopy, UNDO_REDO aTypeCommand, bool aAppend, const wxPoint &aTransformPoint=wxPoint(0, 0))
Create a copy of the current schematic item, and put it in the undo list.
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.
VIEW_CONTROLS is an interface for classes handling user events controlling the view behaviour (such a...
EE_SELECTION_TOOL * m_selectionTool
Definition: ee_tool_base.h:181
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Function ForceCursorPosition() Places the cursor immediately at a given point.
virtual bool IsType(const KICAD_T aScanTypes[]) const
Function IsType Checks whether the item is one of the listed types.
Definition: eda_item.h:250
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:56
virtual void SetCrossHairCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true)=0
Moves the graphic crosshair cursor to the requested position expressed in world coordinates.
PICKED_ITEMS_LIST is a holder to handle information on schematic or board items.
static TOOL_ACTION addNeededJunctions
Definition: ee_actions.h:75
wxString net_name
Net label for the unfolding operation.
void SetUseGrid(bool aSnapToGrid)
virtual KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
Definition: selection.h:104
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)
Function ComputeBreakPoint computes the middle coordinate for 2 segments from the start point to aPos...
TOOL_INTERACTIVE * m_tool
Creator of the menu
Definition: action_menu.h:235
KIGFX::VIEW * getView() const
Function getView()
Definition: tool_base.cpp:36
virtual void SetAutoPan(bool aEnabled)
Function SetAutoPan Turns 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:80
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:219
virtual unsigned int GetSize() const override
Function GetSize() Returns the number of stored items.
Definition: selection.h:99
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:285
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:364
int Modifier(int aMask=MD_MODIFIER_MASK) const
Returns information about key modifiers state (Ctrl, Alt, etc.)
Definition: tool_event.h:342
static bool m_allowRealTime
static TOOL_ACTION placeLabel
Definition: ee_actions.h:85
int RemoveItemFromSel(const TOOL_EVENT &aEvent)
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:463
static bool IsDrawingLineWireOrBus(const SELECTION &aSelection)
TOOLS_HOLDER * GetToolHolder() const
Definition: tool_manager.h:301
wxSize GetSize() const
Definition: sch_bus_entry.h:70
SCH_SHEET & Root() const
Definition: schematic.h:102
bool IsTerminalPoint(const wxPoint &aPosition, int aLayer)
Test if aPosition is a connection point on aLayer.
Definition: sch_screen.cpp:481
void SetTitle(const wxString &aTitle) override
Sets title for the menu.
Definition: action_menu.cpp:89
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:46
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
#define _(s)
Definition: 3d_actions.cpp:33
ACTION_MENU * create() const override
Returns an instance of this class. It has to be overridden in inheriting classes.
TOOL_MANAGER * getToolManager() const
Returns an instance of TOOL_MANAGER class.
void AddSubMenu(std::shared_ptr< ACTION_MENU > aSubMenu)
Function CreateSubMenu.
Definition: tool_menu.cpp:52
EE_RTREE & Items()
Definition: sch_screen.h:159
static SELECTION_CONDITION OnlyType(KICAD_T aType)
Creates a functor that tests if the selected items are only of given type.
void VetoContextMenuMouseWarp()
Disables mouse warping after the current context menu is closed.
Definition: tool_manager.h:417
void Clear()
Removes 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:49
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()
Class for a wire to bus entry.
void Activate()
Function Activate() Runs 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.
EE_TOOL_BASE.
Definition: ee_tool_base.h:50
bool HasPosition() const
Returns if it this event has a valid position (true for mouse events and context-menu or hotkey-based...
Definition: tool_event.h:260
static TOOL_ACTION drawLines
Definition: ee_actions.h:92
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
Function getViewControls()
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
void SetSnap(bool aSnap)
bool IsBus() const
static TOOL_ACTION placeGlobalLabel
Definition: ee_actions.h:86
void ClearEditFlags()
Definition: eda_item.h:239
static TOOL_ACTION finishBus
Definition: ee_actions.h:96
void SetPosition(const wxPoint &aPosition) override
Definition: sch_text.h:313
void PostEvent(const TOOL_EVENT &aEvent)
Puts an event to the event queue to be processed at the end of event processing cycle.
Definition: tool_manager.h:274
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)
Adds 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:194
void ShowContextMenu(SELECTION &aSelection)
Function ShowContextMenu.
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:95
const VECTOR2D Position() const
Returns mouse cursor position in world coordinates.
Definition: tool_event.h:274
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.
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
EDA_ITEM * Front() const
Definition: selection.h:201
bool in_progress
True if bus unfold operation is running.
KICAD_T Type() const
Function Type()
Definition: eda_item.h:181
wxPoint GetEnd() const
wxPoint GetEndPoint() const
Definition: sch_line.h:97