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-2021 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_sheet_pin.h>
62 #include <sch_text.h>
63 #include <schematic.h>
64 #include <ee_actions.h>
65 #include <ee_grid_helper.h>
66 #include <ee_selection.h>
67 #include <ee_selection_tool.h>
68 
70 {
71 public:
73  ACTION_MENU( true ),
74  m_showTitle( false )
75  {
77  SetTitle( _( "Unfold from Bus" ) );
78  }
79 
80  void SetShowTitle()
81  {
82  m_showTitle = true;
83  }
84 
85  bool PassHelpTextToHandler() override { return true; }
86 
87 protected:
88  ACTION_MENU* create() const override
89  {
90  return new BUS_UNFOLD_MENU();
91  }
92 
93 private:
94  void update() override
95  {
98  KICAD_T busType[] = { SCH_LINE_LOCATE_BUS_T, EOT };
99  EE_SELECTION& selection = selTool->RequestSelection( busType );
100  SCH_LINE* bus = (SCH_LINE*) selection.Front();
101 
102  Clear();
103 
104  // TODO(JE) remove once real-time is enabled
105  if( !ADVANCED_CFG::GetCfg().m_RealTimeConnectivity || !CONNECTION_GRAPH::m_allowRealTime )
106  {
108 
109  // Pick up the pointer again because it may have been changed by SchematicCleanUp
110  selection = selTool->RequestSelection( busType );
111  bus = (SCH_LINE*) selection.Front();
112  }
113 
114  if( !bus )
115  {
116  Append( ID_POPUP_SCH_UNFOLD_BUS, _( "No bus selected" ), wxEmptyString );
117  Enable( ID_POPUP_SCH_UNFOLD_BUS, false );
118  return;
119  }
120 
121  SCH_CONNECTION* connection = bus->Connection();
122 
123  if( !connection || !connection->IsBus() || connection->Members().empty() )
124  {
125  Append( ID_POPUP_SCH_UNFOLD_BUS, _( "Bus has no members" ), wxEmptyString );
126  Enable( ID_POPUP_SCH_UNFOLD_BUS, false );
127  return;
128  }
129 
130  int idx = 0;
131 
132  if( m_showTitle )
133  {
134  Append( ID_POPUP_SCH_UNFOLD_BUS, _( "Unfold from Bus" ), wxEmptyString );
135  Enable( ID_POPUP_SCH_UNFOLD_BUS, false );
136  }
137 
138  for( const std::shared_ptr<SCH_CONNECTION>& member : connection->Members() )
139  {
140  int id = ID_POPUP_SCH_UNFOLD_BUS + ( idx++ );
141  wxString name = member->FullLocalName();
142 
143  if( member->Type() == CONNECTION_TYPE::BUS )
144  {
145  ACTION_MENU* submenu = new ACTION_MENU( true, m_tool );
146  AppendSubMenu( submenu, SCH_CONNECTION::PrintBusForUI( name ), name );
147 
148  for( const std::shared_ptr<SCH_CONNECTION>& 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  {
290  grid.SetSnap( !aEvent.Modifier( MD_SHIFT ) );
291  grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !aEvent.DisableGridSnapping() );
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_SIDE::UNDEFINED;
424 
425  if( force == SHEET_SIDE::LEFT || force == SHEET_SIDE::RIGHT )
426  {
427  if( aPosition.x == connectedPin->GetPosition().x ) // push outside sheet boundary
428  {
429  int direction = ( force == SHEET_SIDE::LEFT ) ? -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;
473 
474  auto setCursor =
475  [&]()
476  {
477  if( aType == LAYER_WIRE )
479  else if( aType == LAYER_BUS )
481  else if( aType == LAYER_NOTES )
483  else
485  };
486 
487  auto cleanup =
488  [&] ()
489  {
491 
492  for( SCH_LINE* wire : m_wires )
493  delete wire;
494 
495  m_wires.clear();
496  segment = nullptr;
497 
498  if( m_busUnfold.entry )
500 
503 
506 
507  delete m_busUnfold.entry;
508  delete m_busUnfold.label;
509  m_busUnfold = {};
510 
511  m_view->ClearPreview();
512  m_view->ShowPreview( false );
513  };
514 
515  controls->ShowCursor( true );
516 
517  Activate();
518 
519  // Add the new label to the selection so the rotate command operates on it
520  if( m_busUnfold.label )
522 
523  // Continue the existing wires if we've started (usually by immediate action preference)
524  if( !m_wires.empty() )
525  segment = m_wires.back();
526 
527  // Set initial cursor
528  setCursor();
529 
530  wxPoint contextMenuPos;
531 
532  // Main loop: keep receiving events
533  while( TOOL_EVENT* evt = Wait() )
534  {
535  setCursor();
536  grid.SetMask( GRID_HELPER::ALL );
537  grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
538  grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
539 
540  if( segment )
541  {
542  if( segment->GetStartPoint().x == segment->GetEndPoint().x )
543  grid.ClearMaskFlag( GRID_HELPER::VERTICAL );
544 
545  if( segment->GetStartPoint().y == segment->GetEndPoint().y )
546  grid.ClearMaskFlag( GRID_HELPER::HORIZONTAL );
547  }
548 
549  wxPoint cursorPos = static_cast<wxPoint>( evt->HasPosition() ?
550  evt->Position() :
551  controls->GetMousePosition() );
552 
553  cursorPos = (wxPoint) grid.BestSnapAnchor( cursorPos, LAYER_CONNECTABLE, segment );
554  controls->ForceCursorPosition( true, cursorPos );
555 
556  bool forceHV = m_frame->eeconfig()->m_Drawing.hv_lines_only;
557 
558  //------------------------------------------------------------------------
559  // Handle cancel:
560  //
561  if( evt->IsCancelInteractive() )
562  {
563  if( segment || m_busUnfold.in_progress )
564  {
565  cleanup();
566  }
567  else
568  {
569  m_frame->PopTool( aTool );
570  break;
571  }
572  }
573  else if( evt->IsActivate() )
574  {
575  if( segment || m_busUnfold.in_progress )
576  {
577  m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel drawing." ) );
578  evt->SetPassEvent( false );
579  continue;
580  }
581 
582  if( evt->IsMoveTool() )
583  {
584  // leave ourselves on the stack so we come back after the move
585  break;
586  }
587  else
588  {
589  m_frame->PopTool( aTool );
590  break;
591  }
592  }
593  //------------------------------------------------------------------------
594  // Handle finish:
595  //
596  else if( evt->IsAction( &EE_ACTIONS::finishLineWireOrBus )
597  || evt->IsAction( &EE_ACTIONS::finishWire )
598  || evt->IsAction( &EE_ACTIONS::finishBus )
599  || evt->IsAction( &EE_ACTIONS::finishLine ) )
600  {
601  if( segment || m_busUnfold.in_progress )
602  {
603  finishSegments();
604  segment = nullptr;
605 
606  if( aQuitOnDraw )
607  {
608  m_frame->PopTool( aTool );
609  break;
610  }
611  }
612  }
613  //------------------------------------------------------------------------
614  // Handle click:
615  //
616  else if( evt->IsClick( BUT_LEFT ) || ( segment && evt->IsDblClick( BUT_LEFT ) ) )
617  {
618  // First click when unfolding places the label and wire-to-bus entry
620  {
621  wxASSERT( aType == LAYER_WIRE );
622 
623  m_frame->AddToScreen( m_busUnfold.label, screen );
625  m_busUnfold.label_placed = true;
626  }
627 
628  if( !segment )
629  {
630  segment = startSegments( aType, VECTOR2D( cursorPos ) );
631  }
632  // Create a new segment if we're out of previously-created ones
633  else if( !segment->IsNull() || ( forceHV && !m_wires[ m_wires.size() - 2 ]->IsNull() ) )
634  {
635  // Terminate the command if the end point is on a pin, junction, label, or another
636  // wire or bus.
637  if( screen->IsTerminalPoint( cursorPos, segment->GetLayer() ) )
638  {
639  finishSegments();
640  segment = nullptr;
641 
642  if( aQuitOnDraw )
643  {
644  m_frame->PopTool( aTool );
645  break;
646  }
647  }
648  else
649  {
650  segment->SetEndPoint( cursorPos );
651 
652  // Create a new segment, and chain it after the current segment.
653  segment = new SCH_LINE( *segment );
654  segment->SetFlags( IS_NEW | IS_MOVING );
655  segment->SetStartPoint( cursorPos );
656  m_wires.push_back( segment );
657 
658  m_selectionTool->AddItemToSel( segment, true /*quiet mode*/ );
659  }
660  }
661 
662  if( evt->IsDblClick( BUT_LEFT ) && segment )
663  {
664  if( forceHV && m_wires.size() >= 2 )
665  computeBreakPoint( { m_wires[ m_wires.size() - 2 ], segment }, cursorPos );
666 
667  finishSegments();
668  segment = nullptr;
669 
670  if( aQuitOnDraw )
671  {
672  m_frame->PopTool( aTool );
673  break;
674  }
675  }
676  }
677  //------------------------------------------------------------------------
678  // Handle motion:
679  //
680  else if( evt->IsMotion() || evt->IsAction( &ACTIONS::refreshPreview ) )
681  {
682  m_view->ClearPreview();
683 
684  // Update the bus unfold posture based on the mouse movement
686  {
687  wxPoint cursor_delta = cursorPos - m_busUnfold.origin;
689 
690  bool flipX = ( cursor_delta.x < 0 );
691  bool flipY = ( cursor_delta.y < 0 );
692 
693  // Erase and redraw if necessary
694  if( flipX != m_busUnfold.flipX || flipY != m_busUnfold.flipY )
695  {
696  wxSize size = entry->GetSize();
697  int ySign = flipY ? -1 : 1;
698  int xSign = flipX ? -1 : 1;
699 
700  size.x = std::abs( size.x ) * xSign;
701  size.y = std::abs( size.y ) * ySign;
702  entry->SetSize( size );
703 
704  m_busUnfold.flipY = flipY;
705  m_busUnfold.flipX = flipX;
706 
707  m_frame->UpdateItem( entry );
708  m_wires.front()->SetStartPoint( entry->GetEnd() );
709  }
710 
711  // Update the label "ghost" position
712  m_busUnfold.label->SetPosition( cursorPos );
714 
715  // Ensure segment is non-null at the start of bus unfold
716  if( !segment )
717  segment = m_wires.back();
718  }
719 
720  if( segment )
721  {
722  // Coerce the line to vertical or horizontal if necessary
723  if( forceHV && m_wires.size() >= 2 )
724  computeBreakPoint( { m_wires[ m_wires.size() - 2 ], segment }, cursorPos );
725  else
726  segment->SetEndPoint( cursorPos );
727  }
728 
729  for( SCH_LINE* wire : m_wires )
730  {
731  if( !wire->IsNull() )
732  m_view->AddToPreview( wire->Clone() );
733  }
734  }
735  //------------------------------------------------------------------------
736  // Handle context menu:
737  //
738  else if( evt->IsClick( BUT_RIGHT ) )
739  {
740  // Warp after context menu only if dragging...
741  if( !segment )
743 
744  contextMenuPos = cursorPos;
746  }
747  else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
748  {
749  if( evt->GetCommandId().get() >= ID_POPUP_SCH_UNFOLD_BUS
750  && evt->GetCommandId().get() <= ID_POPUP_SCH_UNFOLD_BUS_END )
751  {
752  wxASSERT_MSG( !segment, "Bus unfold event received when already drawing!" );
753 
754  aType = LAYER_WIRE;
755  wxString net = *evt->Parameter<wxString*>();
756  segment = doUnfoldBus( net, contextMenuPos );
757  }
758  }
759  else if( evt->IsAction( &ACTIONS::doDelete ) )
760  {
761  if( segment || m_busUnfold.in_progress )
762  cleanup();
763  }
764  else
765  {
766  evt->SetPassEvent();
767  }
768 
769  // Enable autopanning and cursor capture only when there is a segment to be placed
770  controls->SetAutoPan( segment != nullptr );
771  controls->CaptureCursor( segment != nullptr );
772  }
773 
774  controls->SetAutoPan( false );
775  controls->CaptureCursor( false );
777  controls->ForceCursorPosition( false );
778  return 0;
779 }
780 
781 
783 {
784  SCH_LINE* segment = nullptr;
785 
786  switch ( aType )
787  {
788  default: segment = new SCH_LINE( aPos, LAYER_NOTES ); break;
789  case LAYER_WIRE: segment = new SCH_LINE( aPos, LAYER_WIRE ); break;
790  case LAYER_BUS: segment = new SCH_LINE( aPos, LAYER_BUS ); break;
791  }
792 
793  // Give segments a parent so they find the default line/wire/bus widths
794  segment->SetParent( &m_frame->Schematic() );
795  segment->SetFlags( IS_NEW | IS_MOVING );
796  m_wires.push_back( segment );
797 
798  m_selectionTool->AddItemToSel( segment, true /*quiet mode*/ );
799 
800  // We need 2 segments to go from a given start pin to an end point when the
801  // horizontal and vertical lines only switch is on.
803  {
804  segment = new SCH_LINE( *segment );
805  segment->SetFlags( IS_NEW | IS_MOVING );
806  m_wires.push_back( segment );
807 
808  m_selectionTool->AddItemToSel( segment, true /*quiet mode*/ );
809  }
810 
811  return segment;
812 }
813 
814 
829 {
830  for( auto it = m_wires.begin(); it != m_wires.end(); )
831  {
832  SCH_LINE* line = *it;
833 
834  if( line->IsNull() )
835  {
836  delete line;
837  it = m_wires.erase( it );
838  continue;
839  }
840 
841  auto next_it = it;
842  ++next_it;
843 
844  if( next_it == m_wires.end() )
845  break;
846 
847  SCH_LINE* next_line = *next_it;
848 
849  if( SCH_LINE* merged = line->MergeOverlap( m_frame->GetScreen(), next_line, false ) )
850  {
851  delete line;
852  delete next_line;
853  it = m_wires.erase( it );
854  *it = merged;
855  }
856 
857  ++it;
858  }
859 }
860 
861 
863 {
864  // Clear selection when done so that a new wire can be started.
865  // NOTE: this must be done before simplifyWireList is called or we might end up with
866  // freed selected items.
868 
869  SCH_SCREEN* screen = m_frame->GetScreen();
870  PICKED_ITEMS_LIST itemList;
871 
872  // Remove segments backtracking over others
874 
875  // Collect the possible connection points for the new lines
876  std::vector< wxPoint > connections = m_frame->GetSchematicConnections();
877  std::vector< wxPoint > new_ends;
878 
879  // Check each new segment for possible junctions and add/split if needed
880  for( SCH_LINE* wire : m_wires )
881  {
882  if( wire->HasFlag( SKIP_STRUCT ) )
883  continue;
884 
885  std::vector<wxPoint> tmpends = wire->GetConnectionPoints();
886 
887  new_ends.insert( new_ends.end(), tmpends.begin(), tmpends.end() );
888 
889  for( const wxPoint& pt : connections )
890  {
891  if( IsPointOnSegment( wire->GetStartPoint(), wire->GetEndPoint(), pt ) )
892  new_ends.push_back( pt );
893  }
894  itemList.PushItem( ITEM_PICKER( screen, wire, UNDO_REDO::NEWITEM ) );
895  }
896 
898  {
899  wxASSERT( m_busUnfold.entry && m_busUnfold.label );
900 
901  itemList.PushItem( ITEM_PICKER( screen, m_busUnfold.entry, UNDO_REDO::NEWITEM ) );
902  itemList.PushItem( ITEM_PICKER( screen, m_busUnfold.label, UNDO_REDO::NEWITEM ) );
904  }
905 
906  // Get the last non-null wire (this is the last created segment).
907  if( !m_wires.empty() )
909 
910  // Add the new wires
911  for( SCH_LINE* wire : m_wires )
912  {
913  wire->ClearFlags( IS_NEW | IS_MOVING );
914  m_frame->AddToScreen( wire, screen );
915  }
916 
917  m_wires.clear();
918  m_view->ClearPreview();
919  m_view->ShowPreview( false );
920 
921  getViewControls()->CaptureCursor( false );
922  getViewControls()->SetAutoPan( false );
923 
924  m_frame->SaveCopyInUndoList( itemList, UNDO_REDO::NEWITEM, false );
925 
926  // Correct and remove segments that need to be merged.
928 
929  std::vector<SCH_ITEM*> symbols;
930 
931  for( SCH_ITEM* symbol : m_frame->GetScreen()->Items().OfType( SCH_SYMBOL_T ) )
932  symbols.push_back( symbol );
933 
934  for( SCH_ITEM* symbol : symbols )
935  {
936  std::vector<wxPoint> pts = symbol->GetConnectionPoints();
937 
938  if( pts.size() > 2 )
939  continue;
940 
941  for( auto pt = pts.begin(); pt != pts.end(); pt++ )
942  {
943  for( auto secondPt = pt + 1; secondPt != pts.end(); secondPt++ )
944  m_frame->TrimWire( *pt, *secondPt );
945  }
946  }
947 
948  for( const wxPoint& pt : new_ends )
949  {
950  if( m_frame->GetScreen()->IsJunctionNeeded( pt, true ) )
951  m_frame->AddJunction( m_frame->GetScreen(), pt, true, false );
952  }
953 
955  m_busUnfold = {};
956 
959 
960  m_frame->OnModify();
961 }
962 
963 
965 {
966  EE_SELECTION* aSelection = aEvent.Parameter<EE_SELECTION*>();
967 
968  std::vector<wxPoint> pts;
969  std::vector<wxPoint> connections = m_frame->GetSchematicConnections();
970 
971  for( unsigned ii = 0; ii < aSelection->GetSize(); ii++ )
972  {
973  SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aSelection->GetItem( ii ) );
974 
975  if( !item || !item->IsConnectable() )
976  continue;
977 
978  std::vector<wxPoint> new_pts = item->GetConnectionPoints();
979  pts.insert( pts.end(), new_pts.begin(), new_pts.end() );
980 
981  // If the item is a line, we also add any connection points from the rest of the schematic
982  // that terminate on the line after it is moved.
983  if( item->Type() == SCH_LINE_T )
984  {
985  SCH_LINE* line = (SCH_LINE*) item;
986 
987  for( const wxPoint& pt : connections )
988  {
989  if( IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), pt ) )
990  pts.push_back( pt );
991  }
992  }
993  else
994  {
995  // Clean up any wires that short non-wire connections in the list
996  for( auto pt = new_pts.begin(); pt != new_pts.end(); pt++ )
997  {
998  for( auto secondPt = pt + 1; secondPt != new_pts.end(); secondPt++ )
999  m_frame->TrimWire( *pt, *secondPt );
1000  }
1001  }
1002  }
1003 
1004  // We always have some overlapping connection points. Drop duplicates here
1005  std::sort( pts.begin(), pts.end(),
1006  []( const wxPoint& a, const wxPoint& b ) -> bool
1007  {
1008  return a.x < b.x || ( a.x == b.x && a.y < b.y );
1009  } );
1010 
1011  pts.erase( unique( pts.begin(), pts.end() ), pts.end() );
1012 
1013  for( const wxPoint& point : pts )
1014  {
1015  if( m_frame->GetScreen()->IsJunctionNeeded( point, true ) )
1016  m_frame->AddJunction( m_frame->GetScreen(), point, true, false );
1017  }
1018 
1019  return 0;
1020 }
1021 
1022 
1024 {
1029 
1031 }
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:216
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:453
bool SchematicCleanUp(SCH_SCREEN *aScreen=nullptr)
Perform routine schematic cleaning including breaking wire and buses and deleting identical objects s...
bool IsCurrentTool(const TOOL_ACTION &aAction) const
TOOL_MENU m_menu
The functions below are not yet implemented - their interface may change.
virtual bool IsConnectable() const
Definition: sch_item.h:362
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...
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
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:377
static TOOL_ACTION breakBus
Definition: ee_actions.h:131
void RecalculateConnections(SCH_CLEANUP_FLAGS aCleanupFlags)
Generate the connection data for the entire schematic hierarchy.
wxPoint GetStartPoint() const
Definition: sch_line.h:90
void SetSize(const wxSize &aSize)
Definition: sch_bus_entry.h:64
#define IS_NEW
New item, just created.
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:48
static TOOL_ACTION doDelete
Definition: actions.h:72
void SetIcon(BITMAPS aIcon)
Assign an icon for the entry.
Definition: action_menu.cpp:73
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:1548
bool IsTerminalPoint(const wxPoint &aPosition, int aLayer) const
Test if aPosition is a connection point on aLayer.
Definition: sch_screen.cpp:473
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:84
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:214
static TOOL_ACTION placeJunction
Definition: ee_actions.h:80
static TOOL_ACTION selectConnection
If current selection is a wire or bus, expand to entire connection.
Definition: ee_actions.h:50
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:78
static TOOL_ACTION finishLineWireOrBus
Definition: ee_actions.h:90
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:153
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:143
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,...
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).
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:204
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:116
static TOOL_ACTION breakWire
Definition: ee_actions.h:130
static TOOL_ACTION finishLine
Definition: ee_actions.h:93
void SetEndPoint(const wxPoint &aPosition)
Definition: sch_line.h:94
void SetTool(TOOL_INTERACTIVE *aTool)
Set a tool that is the creator of the menu.
bool IsNew() const
Definition: eda_item.h:119
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:1562
static TOOL_ACTION leaveSheet
Definition: ee_actions.h:181
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:66
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.
void ShowInfoBarMsg(const wxString &aMsg, bool aShowCloseButton=false)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an info icon on the left of...
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: sch_text.cpp:819
#define IS_MOVING
Item being moved.
wxPoint origin
Origin (on the bus) of the unfold.
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:76
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:88
T Parameter() const
Return a non-standard parameter assigned to the event.
Definition: tool_event.h:427
void SetStartPoint(const wxPoint &aPosition)
Definition: sch_line.h:91
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.
Generic, UI-independent tool event.
Definition: tool_event.h:152
void SaveCopyForRepeatItem(const SCH_ITEM *aItem)
Clone aItem and owns that clone in this container.
void ClearPreview()
Definition: view.cpp:1526
SCHEMATIC & Schematic() const
std::vector< wxPoint > GetSchematicConnections()
Collect 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,...
#define _(s)
EE_SELECTION_TOOL * m_selectionTool
Definition: ee_tool_base.h:177
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:183
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:65
bool DisableGridSnapping() const
Definition: tool_event.h:336
static TOOL_ACTION clearSelection
Clears the current selection.
Definition: ee_actions.h:53
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:72
wxString net_name
Net label for the unfolding operation.
wxPoint GetPosition() const override
Definition: sch_text.h:237
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:260
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:77
EE_TYPE Overlapping(const EDA_RECT &aRect) const
Definition: sch_rtree.h:221
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:54
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition: selection.h:87
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition: sch_item.h:272
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:184
int Modifier(int aMask=MD_MODIFIER_MASK) const
Definition: tool_event.h:331
static bool m_allowRealTime
static TOOL_ACTION placeLabel
Definition: ee_actions.h:82
int RemoveItemFromSel(const TOOL_EVENT &aEvent)
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:455
static bool IsDrawingLineWireOrBus(const SELECTION &aSelection)
TOOLS_HOLDER * GetToolHolder() const
Definition: tool_manager.h:294
wxSize GetSize() const
Definition: sch_bus_entry.h:63
SCH_SHEET & Root() const
Definition: schematic.h:92
void SetTitle(const wxString &aTitle) override
Set title for the menu.
Definition: action_menu.cpp:91
Board layer functions and definitions.
#define SKIP_STRUCT
flag indicating that the structure should be ignored
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
virtual KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
Definition: selection.cpp:52
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.
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:102
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:422
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:46
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:70
These settings were stored in SCH_BASE_FRAME previously.
bool IsJunctionNeeded(const wxPoint &aPosition, bool aNew=false) const
Test if a junction is required for the items at aPosition on the screen.
Definition: sch_screen.cpp:390
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()
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:49
bool HasPosition() const
Definition: tool_event.h:240
SHEET_SIDE
Define the edge of the sheet that the sheet pin is positioned.
Definition: sch_sheet_pin.h:45
static TOOL_ACTION drawLines
Definition: ee_actions.h:88
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
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:317
bool IsBus() const
static TOOL_ACTION placeGlobalLabel
Definition: ee_actions.h:83
void ClearEditFlags()
Definition: eda_item.h:172
static TOOL_ACTION finishBus
Definition: ee_actions.h:92
void SetPosition(const wxPoint &aPosition) override
Definition: sch_text.h:238
void PostEvent(const TOOL_EVENT &aEvent)
Put an event to the event queue to be processed at the end of event processing cycle.
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:197
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)
static TOOL_ACTION finishWire
Definition: ee_actions.h:91
const VECTOR2D Position() const
Returns the point where dragging has started.
Definition: tool_event.h:263
BUS_UNFOLDING_T m_busUnfold
Data related to bus unfolding tool.
static TOOL_ACTION refreshPreview
Definition: actions.h:106
This item represents a bus vector.
EDA_ITEM * Front() const
Definition: selection.h:144
bool in_progress
True if bus unfold operation is running.
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113
wxPoint GetEnd() const
wxPoint GetEndPoint() const
Definition: sch_line.h:93