KiCad PCB EDA Suite
sch_drawing_tools.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 
27 #include <tools/ee_grid_helper.h>
28 #include <ee_actions.h>
29 #include <sch_edit_frame.h>
30 #include <project.h>
31 #include <id.h>
32 #include <eeschema_id.h>
33 #include <confirm.h>
34 #include <widgets/infobar.h>
35 #include <view/view_controls.h>
36 #include <view/view.h>
37 #include <sch_symbol.h>
38 #include <sch_no_connect.h>
39 #include <sch_line.h>
40 #include <sch_junction.h>
41 #include <sch_bus_entry.h>
42 #include <sch_text.h>
43 #include <sch_sheet.h>
44 #include <sch_sheet_pin.h>
45 #include <sch_bitmap.h>
46 #include <schematic.h>
47 #include <symbol_library.h>
48 #include <eeschema_settings.h>
53 #include <string_utils.h>
55 #include <wx/filedlg.h>
56 
57 
59  EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.InteractiveDrawing" ),
60  m_lastSheetPinType( PINSHEETLABEL_SHAPE::PS_INPUT ),
61  m_lastGlobalLabelShape( PINSHEETLABEL_SHAPE::PS_INPUT ),
62  m_lastTextOrientation( LABEL_SPIN_STYLE::RIGHT ),
63  m_lastTextBold( false ),
64  m_lastTextItalic( false ),
65  m_mruPath( wxEmptyString ),
66  m_inPlaceSymbol( false ),
67  m_inPlaceImage( false ),
68  m_inSingleClickPlace( false ),
69  m_inTwoClickPlace( false ),
70  m_inDrawSheet( false )
71 {
72 }
73 
74 
76 {
78 
79  auto belowRootSheetCondition =
80  [&]( const SELECTION& aSel )
81  {
82  return m_frame->GetCurrentSheet().Last() != &m_frame->Schematic().Root();
83  };
84 
85  CONDITIONAL_MENU& ctxMenu = m_menu.GetMenu();
86  ctxMenu.AddItem( EE_ACTIONS::leaveSheet, belowRootSheetCondition, 2 );
87 
88  return true;
89 }
90 
91 
93 {
94  // calculate the area of the canvas in pixels that create no autopan when
95  // is inside this area the mouse cursor
96  wxSize canvas_size = m_frame->GetCanvas()->GetSize();
97  EDA_RECT canvas_area( wxPoint( 0, 0 ), canvas_size );
98  const KIGFX::VC_SETTINGS& v_settings = getViewControls()->GetSettings();
99 
100  if( v_settings.m_autoPanEnabled )
101  canvas_area.Inflate( - v_settings.m_autoPanMargin );
102 
103  // Gives a margin of 2 pixels
104  canvas_area.Inflate( -2 );
105 
106  return canvas_area;
107 }
108 
109 
111 {
112  SCH_SYMBOL* symbol = aEvent.Parameter<SCH_SYMBOL*>();
114  std::vector<PICKED_SYMBOL>* historyList = nullptr;
115 
116  if( m_inPlaceSymbol )
117  return 0;
118 
120 
121  if( aEvent.IsAction( &EE_ACTIONS::placeSymbol ) )
122  {
123  historyList = &m_symbolHistoryList;
124  }
125  else if (aEvent.IsAction( &EE_ACTIONS::placePower ) )
126  {
127  historyList = &m_powerHistoryList;
128  filter.FilterPowerSymbols( true );
129  }
130  else
131  {
132  wxFAIL_MSG( wxT( "PlaceSymbol(): unexpected request" ) );
133  }
134 
135  std::string tool = aEvent.GetCommandStr().get();
136  m_frame->PushTool( tool );
137 
138  auto addSymbol =
139  [&]( SCH_SYMBOL* aSymbol )
140  {
141  m_frame->SaveCopyForRepeatItem( aSymbol );
142 
144  m_selectionTool->AddItemToSel( aSymbol );
145 
146  aSymbol->SetParent( m_frame->GetScreen() );
147  aSymbol->SetFlags( IS_NEW | IS_MOVING );
148  m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), aSymbol, false );
149 
150  // Set IS_MOVING again, as AddItemToScreenAndUndoList() will have cleared it.
151  aSymbol->SetFlags( IS_MOVING );
153  };
154 
155  auto setCursor =
156  [&]()
157  {
160  };
161 
162  auto cleanup =
163  [&] ()
164  {
167  symbol = nullptr;
168  };
169 
170  Activate();
171  // Must be done after Activate() so that it gets set into the correct context
172  getViewControls()->ShowCursor( true );
173  // Set initial cursor
174  setCursor();
175 
176  // Prime the pump
177  if( symbol )
178  {
179  addSymbol( symbol );
180  getViewControls()->WarpCursor( getViewControls()->GetMousePosition( false ) );
181  }
182  else if( !aEvent.IsReactivate() )
183  {
185  }
186 
187  // Main loop: keep receiving events
188  while( TOOL_EVENT* evt = Wait() )
189  {
190  setCursor();
191  VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
192 
193  if( evt->IsCancelInteractive() )
194  {
195  m_frame->GetInfoBar()->Dismiss();
196 
197  if( symbol )
198  {
199  cleanup();
200  }
201  else
202  {
203  m_frame->PopTool( tool );
204  break;
205  }
206  }
207  else if( evt->IsActivate() )
208  {
209  if( symbol && evt->IsMoveTool() )
210  {
211  // we're already moving our own item; ignore the move tool
212  evt->SetPassEvent( false );
213  continue;
214  }
215 
216  if( symbol )
217  {
218  m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel symbol creation." ) );
219  evt->SetPassEvent( false );
220  continue;
221  }
222 
223  if( evt->IsMoveTool() )
224  {
225  // leave ourselves on the stack so we come back after the move
226  break;
227  }
228  else
229  {
230  m_frame->PopTool( tool );
231  break;
232  }
233  }
234  else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
235  {
236  if( !symbol )
237  {
239 
240  // Store the mouse position: if it is outside the canvas,
241  // (happens when clicking on a toolbar tool) one cannot
242  // use the last stored cursor position to place the new symbol
243  // (Current mouse pos after closing the dialog will be used)
245  VECTOR2D initialMousePos = controls->GetMousePosition(false);
246  // Build the rectangle area acceptable to move the cursor without
247  // having an auto-pan
248  EDA_RECT canvas_area = GetCanvasFreeAreaPixels();
249 
250  // Pick the footprint to be placed
251  bool footprintPreviews = m_frame->eeconfig()->m_Appearance.footprint_preview;
252  PICKED_SYMBOL sel = m_frame->PickSymbolFromLibTree( &filter, *historyList, true,
253  1, 1, footprintPreviews );
254  // Restore cursor position after closing the dialog,
255  // but only if it has meaning (i.e inside the canvas)
256  VECTOR2D newMousePos = controls->GetMousePosition(false);
257 
258  if( canvas_area.Contains( wxPoint( initialMousePos ) ) )
259  controls->WarpCursor( controls->GetCursorPosition(), true );
260  else if( !canvas_area.Contains( wxPoint( newMousePos ) ) )
261  // The mouse is outside the canvas area, after closing the dialog,
262  // thus can creating autopan issues. Warp the mouse to the canvas center
263  controls->WarpCursor( canvas_area.Centre(), false );
264 
265  LIB_SYMBOL* libSymbol = sel.LibId.IsValid() ?
266  m_frame->GetLibSymbol( sel.LibId ) : nullptr;
267 
268  if( !libSymbol )
269  continue;
270 
271  wxPoint pos( cursorPos );
272  symbol = new SCH_SYMBOL( *libSymbol, &m_frame->GetCurrentSheet(), sel, pos );
273  addSymbol( symbol );
274 
275  // Update cursor now that we have a symbol
276  setCursor();
277  }
278  else
279  {
281  symbol->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
282 
283  symbol->ClearEditFlags();
284  m_view->Update( symbol );
285  m_frame->GetScreen()->Update( symbol );
286 
291 
292  m_frame->OnModify();
293 
294  SCH_SYMBOL* nextSymbol = nullptr;
295 
298  {
299  int new_unit = symbol->GetUnit();
300 
302  && symbol->GetUnit() < symbol->GetUnitCount() )
303  {
304  new_unit++;
305  }
306  else
307  {
308  new_unit = 1;
309  }
310 
311  // We are either stepping to the next unit or next symbol
312  if( m_frame->eeconfig()->m_SymChooserPanel.keep_symbol || new_unit > 1 )
313  {
314  nextSymbol = static_cast<SCH_SYMBOL*>( symbol->Duplicate() );
315  nextSymbol->SetUnit( new_unit );
316  nextSymbol->SetUnitSelection( new_unit );
317 
318  addSymbol( nextSymbol );
319  }
320  }
321 
322  symbol = nextSymbol;
323  }
324  }
325  else if( evt->IsClick( BUT_RIGHT ) )
326  {
327  // Warp after context menu only if dragging...
328  if( !symbol )
330 
332  }
333  else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
334  {
335  if( evt->GetCommandId().get() >= ID_POPUP_SCH_SELECT_UNIT_CMP
336  && evt->GetCommandId().get() <= ID_POPUP_SCH_SELECT_UNIT_SYM_MAX )
337  {
338  int unit = evt->GetCommandId().get() - ID_POPUP_SCH_SELECT_UNIT_CMP;
339 
340  if( symbol )
341  {
342  m_frame->SelectUnit( symbol, unit );
344  }
345  }
346  }
347  else if( symbol && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
348  {
349  symbol->SetPosition( (wxPoint)cursorPos );
350  m_view->Update( symbol );
351  }
352  else if( symbol && evt->IsAction( &ACTIONS::doDelete ) )
353  {
354  cleanup();
355  }
356  else
357  {
358  evt->SetPassEvent();
359  }
360 
361  // Enable autopanning and cursor capture only when there is a symbol to be placed
362  getViewControls()->SetAutoPan( symbol != nullptr );
363  getViewControls()->CaptureCursor( symbol != nullptr );
364  }
365 
366  getViewControls()->SetAutoPan( false );
367  getViewControls()->CaptureCursor( false );
369 
370  return 0;
371 }
372 
373 
375 {
376  SCH_BITMAP* image = aEvent.Parameter<SCH_BITMAP*>();
377  bool immediateMode = image;
378  VECTOR2I cursorPos = getViewControls()->GetCursorPosition();
379 
380  if( m_inPlaceImage )
381  return 0;
382 
384 
386 
387  // Add all the drawable symbols to preview
388  if( image )
389  {
390  image->SetPosition( (wxPoint)cursorPos );
391  m_view->ClearPreview();
392  m_view->AddToPreview( image->Clone() );
393  }
394 
395  std::string tool = aEvent.GetCommandStr().get();
396  m_frame->PushTool( tool );
397  auto setCursor =
398  [&]()
399  {
400  if( image )
402  else
404  };
405 
406  auto cleanup =
407  [&] ()
408  {
410  m_view->ClearPreview();
411  delete image;
412  image = nullptr;
413  };
414 
415  Activate();
416  // Must be done after Activate() so that it gets set into the correct context
417  getViewControls()->ShowCursor( true );
418  // Set initial cursor
419  setCursor();
420 
421  // Prime the pump
422  if( image )
424  else if( !aEvent.IsReactivate() )
426 
427  // Main loop: keep receiving events
428  while( TOOL_EVENT* evt = Wait() )
429  {
430  setCursor();
431  cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
432 
433  if( evt->IsCancelInteractive() )
434  {
435  m_frame->GetInfoBar()->Dismiss();
436 
437  if( image )
438  {
439  cleanup();
440  }
441  else
442  {
443  m_frame->PopTool( tool );
444  break;
445  }
446 
447  if( immediateMode )
448  {
449  m_frame->PopTool( tool );
450  break;
451  }
452  }
453  else if( evt->IsActivate() )
454  {
455  if( image && evt->IsMoveTool() )
456  {
457  // we're already moving our own item; ignore the move tool
458  evt->SetPassEvent( false );
459  continue;
460  }
461 
462  if( image )
463  {
464  m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel image creation." ) );
465  evt->SetPassEvent( false );
466  continue;
467  }
468 
469  if( evt->IsMoveTool() )
470  {
471  // leave ourselves on the stack so we come back after the move
472  break;
473  }
474  else
475  {
476  m_frame->PopTool( tool );
477  break;
478  }
479  }
480  else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
481  {
482  if( !image )
483  {
485 
486  // Store the mouse position: if it is outside the canvas,
487  // (happens when clicking on a toolbar tool) one cannot
488  // use the last stored cursor position to place the new symbol
489  // (Current mouse pos after closing the dialog will be used)
491  VECTOR2D initialMousePos = controls->GetMousePosition(false);
492 
493  // Build the rectangle area acceptable to move the cursor without
494  // having an auto-pan
495  EDA_RECT canvas_area = GetCanvasFreeAreaPixels();
496 
497  wxFileDialog dlg( m_frame, _( "Choose Image" ), m_mruPath, wxEmptyString,
498  _( "Image Files" ) + wxS( " " ) + wxImage::GetImageExtWildcard(),
499  wxFD_OPEN );
500 
501  if( dlg.ShowModal() != wxID_OK )
502  continue;
503 
504  // Restore cursor position after closing the dialog,
505  // but only if it has meaning (i.e inside the canvas)
506  VECTOR2D newMousePos = controls->GetMousePosition( false );
507 
508  if( canvas_area.Contains( wxPoint( initialMousePos ) ) )
509  controls->WarpCursor( controls->GetCursorPosition(), true );
510  else if( !canvas_area.Contains( wxPoint( newMousePos ) ) )
511  // The mouse is outside the canvas area, after closing the dialog,
512  // thus can creating autopan issues. Warp the mouse to the canvas center
513  controls->WarpCursor( canvas_area.Centre(), false );
514 
515  cursorPos = controls->GetMousePosition( true );
516 
517  wxString fullFilename = dlg.GetPath();
518  m_mruPath = wxPathOnly( fullFilename );
519 
520  if( wxFileExists( fullFilename ) )
521  image = new SCH_BITMAP( (wxPoint)cursorPos );
522 
523  if( !image || !image->ReadImageFile( fullFilename ) )
524  {
525  wxMessageBox( _( "Could not load image from '%s'." ), fullFilename );
526  delete image;
527  image = nullptr;
528  continue;
529  }
530 
531  image->SetFlags( IS_NEW | IS_MOVING );
532 
534 
535  m_view->ClearPreview();
536  m_view->AddToPreview( image->Clone() );
537  m_view->RecacheAllItems(); // Bitmaps are cached in Opengl
538 
540 
541  getViewControls()->SetCursorPosition( cursorPos, false );
542  setCursor();
543  }
544  else
545  {
547  image = nullptr;
549 
550  m_view->ClearPreview();
551 
552  if( immediateMode )
553  {
554  m_frame->PopTool( tool );
555  break;
556  }
557  }
558  }
559  else if( evt->IsClick( BUT_RIGHT ) )
560  {
561  // Warp after context menu only if dragging...
562  if( !image )
564 
566  }
567  else if( image && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
568  {
569  image->SetPosition( (wxPoint)cursorPos );
570  m_view->ClearPreview();
571  m_view->AddToPreview( image->Clone() );
572  m_view->RecacheAllItems(); // Bitmaps are cached in Opengl
573  }
574  else if( image && evt->IsAction( &ACTIONS::doDelete ) )
575  {
576  cleanup();
577  }
578  else
579  {
580  evt->SetPassEvent();
581  }
582 
583  // Enable autopanning and cursor capture only when there is an image to be placed
584  getViewControls()->SetAutoPan( image != nullptr );
585  getViewControls()->CaptureCursor( image != nullptr );
586  }
587 
588  getViewControls()->SetAutoPan( false );
589  getViewControls()->CaptureCursor( false );
591 
592  return 0;
593 }
594 
595 
597 {
598  wxPoint cursorPos;
599  KICAD_T type = aEvent.Parameter<KICAD_T>();
602  SCH_ITEM* previewItem;
603  bool loggedInfoBarError = false;
604 
606  return 0;
607 
609 
610  if( type == SCH_JUNCTION_T && aEvent.HasPosition() )
611  {
612  EE_SELECTION& selection = m_selectionTool->GetSelection();
613  SCH_LINE* wire = dynamic_cast<SCH_LINE*>( selection.Front() );
614 
615  if( wire )
616  {
617  SEG seg( wire->GetStartPoint(), wire->GetEndPoint() );
618  VECTOR2I nearest = seg.NearestPoint( getViewControls()->GetCursorPosition() );
619  getViewControls()->SetCrossHairCursorPosition( nearest, false );
620  getViewControls()->WarpCursor( getViewControls()->GetCursorPosition(), true );
621  }
622  }
623 
624  switch( type )
625  {
626  case SCH_NO_CONNECT_T:
627  previewItem = new SCH_NO_CONNECT( cursorPos );
628  previewItem->SetParent( m_frame->GetScreen() );
629  break;
630 
631  case SCH_JUNCTION_T:
632  previewItem = new SCH_JUNCTION( cursorPos );
633  previewItem->SetParent( m_frame->GetScreen() );
634  break;
635 
637  previewItem = new SCH_BUS_WIRE_ENTRY( cursorPos );
638  previewItem->SetParent( m_frame->GetScreen() );
639  break;
640 
641  case SCH_SHEET_PIN_T:
642  {
643  EE_SELECTION& selection = m_selectionTool->GetSelection();
644  SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( selection.Front() );
645 
646  if( !sheet )
647  return 0;
648 
649  SCH_HIERLABEL* label = importHierLabel( sheet );
650 
651  if( !label )
652  {
653  m_statusPopup.reset( new STATUS_TEXT_POPUP( m_frame ) );
654  m_statusPopup->SetText( _( "No new hierarchical labels found." ) );
655  m_statusPopup->Move( wxGetMousePosition() + wxPoint( 20, 20 ) );
656  m_statusPopup->PopupFor( 2000 );
657  return 0;
658  }
659 
660  previewItem = createSheetPin( sheet, label );
661  }
662  break;
663 
664  default:
665  wxASSERT_MSG( false, wxT( "Unknown item type in SCH_DRAWING_TOOLS::SingleClickPlace" ) );
666  return 0;
667  }
668 
670 
671  cursorPos = static_cast<wxPoint>( aEvent.HasPosition() ?
672  aEvent.Position() :
673  controls->GetMousePosition() );
674 
675  std::string tool = aEvent.GetCommandStr().get();
676  m_frame->PushTool( tool );
677 
678  auto setCursor =
679  [&]()
680  {
682  };
683 
684  Activate();
685  // Must be done after Activate() so that it gets set into the correct context
686  getViewControls()->ShowCursor( true );
687  // Set initial cursor
688  setCursor();
689 
690  m_view->ClearPreview();
691  m_view->AddToPreview( previewItem->Clone() );
692 
693  // Prime the pump
694  if( aEvent.HasPosition() && type != SCH_SHEET_PIN_T )
696  else
698 
699  // Main loop: keep receiving events
700  while( TOOL_EVENT* evt = Wait() )
701  {
702  setCursor();
703  grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
704  grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
705 
706  cursorPos = evt->IsPrime() ? (wxPoint) evt->Position()
707  : (wxPoint) controls->GetMousePosition();
708 
709  cursorPos = wxPoint( grid.BestSnapAnchor( cursorPos, LAYER_CONNECTABLE, nullptr ) );
710  controls->ForceCursorPosition( true, cursorPos );
711 
712  if( evt->IsCancelInteractive() )
713  {
714  m_frame->PopTool( tool );
715  break;
716  }
717  else if( evt->IsActivate() )
718  {
719  if( evt->IsMoveTool() )
720  {
721  // leave ourselves on the stack so we come back after the move
722  break;
723  }
724  else
725  {
726  m_frame->PopTool( tool );
727  break;
728  }
729  }
730  else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
731  {
732  if( !m_frame->GetScreen()->GetItem( cursorPos, 0, type ) )
733  {
734  if( type == SCH_JUNCTION_T )
735  {
736  if( !m_frame->GetScreen()->IsExplicitJunctionAllowed( cursorPos ) )
737  {
738  m_frame->ShowInfoBarError( _( "Junction location contains no joinable "
739  "wires and/or pins." ) );
740  loggedInfoBarError = true;
741  continue;
742  }
743  else if( loggedInfoBarError )
744  {
745  m_frame->GetInfoBar()->Dismiss();
746  }
747  }
748 
749  SCH_ITEM* newItem = static_cast<SCH_ITEM*>( previewItem->Clone() );
750  newItem->SetPosition( cursorPos );
751  newItem->SetFlags( IS_NEW );
752 
753  m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), newItem, false );
754 
755  if( type == SCH_JUNCTION_T )
757  else
759 
760  m_frame->OnModify();
761  }
762 
763  if( evt->IsDblClick( BUT_LEFT ) || type == SCH_SHEET_PIN_T ) // Finish tool.
764  {
765  m_frame->PopTool( tool );
766  break;
767  }
768  }
769  else if( evt->IsClick( BUT_RIGHT ) )
770  {
772  }
773  else if( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() )
774  {
775  previewItem->SetPosition( (wxPoint)cursorPos );
776  m_view->ClearPreview();
777  m_view->AddToPreview( previewItem->Clone() );
778  }
779  else if( evt->Category() == TC_COMMAND )
780  {
781  if( ( type == SCH_BUS_WIRE_ENTRY_T )
782  && ( evt->IsAction( &EE_ACTIONS::rotateCW )
783  || evt->IsAction( &EE_ACTIONS::rotateCCW )
784  || evt->IsAction( &EE_ACTIONS::mirrorV )
785  || evt->IsAction( &EE_ACTIONS::mirrorH ) ) )
786  {
787  SCH_BUS_ENTRY_BASE* busItem = static_cast<SCH_BUS_ENTRY_BASE*>( previewItem );
788 
789  // The bus entries only rotate in one direction
790  if( evt->IsAction( &EE_ACTIONS::rotateCW )
791  || evt->IsAction( &EE_ACTIONS::rotateCCW ) )
792  {
793  busItem->Rotate( busItem->GetPosition() );
794  }
795  else if( evt->IsAction( &EE_ACTIONS::mirrorV ) )
796  {
797  busItem->MirrorVertically( busItem->GetPosition().x );
798  }
799  else if( evt->IsAction( &EE_ACTIONS::mirrorH ) )
800  {
801  busItem->MirrorHorizontally( busItem->GetPosition().y );
802  }
803 
804  m_view->ClearPreview();
805  m_view->AddToPreview( previewItem->Clone() );
806  }
807  else if( evt->IsAction( &EE_ACTIONS::properties ) )
808  {
809  switch( type )
810  {
812  {
813  std::deque<SCH_ITEM*> strokeItems;
814  strokeItems.push_back( previewItem );
815 
816  DIALOG_LINE_WIRE_BUS_PROPERTIES dlg( m_frame, strokeItems );
817 
818  if( dlg.ShowModal() == wxID_OK )
819  {
821  m_frame->OnModify();
822  }
823  }
824  break;
825 
826  case SCH_JUNCTION_T:
827  {
828  std::deque<SCH_JUNCTION*> junctions;
829  junctions.push_back( static_cast<SCH_JUNCTION*>( previewItem ) );
830 
831  DIALOG_JUNCTION_PROPS dlg( m_frame, junctions );
832 
833  if( dlg.ShowModal() == wxID_OK )
834  {
836  m_frame->OnModify();
837  }
838  }
839  break;
840  default:
841  // Do nothing
842  break;
843  }
844 
845  m_view->ClearPreview();
846  m_view->AddToPreview( previewItem->Clone() );
847  }
848  else
849  {
850  evt->SetPassEvent();
851  }
852  }
853  else
854  {
855  evt->SetPassEvent();
856  }
857  }
858 
859  delete previewItem;
860  m_view->ClearPreview();
861 
863  controls->ForceCursorPosition( false );
864 
865  return 0;
866 }
867 
868 
869 SCH_TEXT* SCH_DRAWING_TOOLS::createNewText( const VECTOR2I& aPosition, int aType )
870 {
871  SCHEMATIC* schematic = getModel<SCHEMATIC>();
872  SCHEMATIC_SETTINGS& settings = schematic->Settings();
873  SCH_TEXT* textItem = nullptr;
874 
875  switch( aType )
876  {
877  case LAYER_NOTES:
878  textItem = new SCH_TEXT( (wxPoint) aPosition );
879  break;
880 
881  case LAYER_LOCLABEL:
882  textItem = new SCH_LABEL( (wxPoint) aPosition );
883  break;
884 
885  case LAYER_HIERLABEL:
886  textItem = new SCH_HIERLABEL( (wxPoint) aPosition );
887  textItem->SetShape( m_lastGlobalLabelShape );
888  break;
889 
890  case LAYER_GLOBLABEL:
891  textItem = new SCH_GLOBALLABEL( (wxPoint) aPosition );
892  textItem->SetShape( m_lastGlobalLabelShape );
893 
894  if( settings.m_IntersheetRefsShow )
895  static_cast<SCH_GLOBALLABEL*>( textItem )->GetIntersheetRefs()->SetVisible( true );
896 
897  break;
898 
899  default:
900  wxFAIL_MSG( wxT( "SCH_EDIT_FRAME::CreateNewText() unknown layer type" ) );
901  return nullptr;
902  }
903 
904  textItem->SetParent( schematic );
905  textItem->SetBold( m_lastTextBold );
906  textItem->SetItalic( m_lastTextItalic );
908  textItem->SetTextSize( wxSize( settings.m_DefaultTextSize, settings.m_DefaultTextSize ) );
909  textItem->SetFlags( IS_NEW | IS_MOVING );
910 
911  DIALOG_TEXT_AND_LABEL_PROPERTIES dlg( m_frame, textItem );
912 
913  // Must be quasi modal for syntax help
914  if( dlg.ShowQuasiModal() != wxID_OK || NoPrintableChars( textItem->GetText() ) )
915  {
916  delete textItem;
917  return nullptr;
918  }
919 
920  m_lastTextBold = textItem->IsBold();
921  m_lastTextItalic = textItem->IsItalic();
923 
924  if( textItem->Type() == SCH_GLOBAL_LABEL_T || textItem->Type() == SCH_HIER_LABEL_T )
925  m_lastGlobalLabelShape = textItem->GetShape();
926 
927  return textItem;
928 }
929 
930 
932 {
933  if( !aSheet->GetScreen() )
934  return nullptr;
935 
936  for( EDA_ITEM* item : aSheet->GetScreen()->Items().OfType( SCH_HIER_LABEL_T ) )
937  {
938  SCH_HIERLABEL* label = static_cast<SCH_HIERLABEL*>( item );
939 
940  /* A global label has been found: check if there a corresponding sheet label. */
941  if( !aSheet->HasPin( label->GetText() ) )
942  return label;
943  }
944 
945  return nullptr;
946 }
947 
948 
950 {
951  SCHEMATIC_SETTINGS& settings = aSheet->Schematic()->Settings();
952  wxString text;
953  SCH_SHEET_PIN* sheetPin;
954 
955  if( aLabel )
956  {
957  text = aLabel->GetText();
958  m_lastSheetPinType = aLabel->GetShape();
959  }
960 
961  sheetPin = new SCH_SHEET_PIN( aSheet, wxPoint( 0, 0 ), text );
962  sheetPin->SetFlags( IS_NEW );
963  sheetPin->SetTextSize( wxSize( settings.m_DefaultTextSize, settings.m_DefaultTextSize ) );
964  sheetPin->SetShape( m_lastSheetPinType );
965 
966  if( !aLabel )
967  {
968  DIALOG_SHEET_PIN_PROPERTIES dlg( m_frame, sheetPin );
969 
970  if( dlg.ShowModal() != wxID_OK || NoPrintableChars( sheetPin->GetText() ) )
971  {
972  delete sheetPin;
973  return nullptr;
974  }
975  }
976 
977  m_lastSheetPinType = sheetPin->GetShape();
978 
979  sheetPin->SetPosition( (wxPoint) getViewControls()->GetCursorPosition() );
980 
981  return sheetPin;
982 }
983 
984 
986 {
987  SCH_ITEM* item = nullptr;
990  bool ignorePrimePosition = false;
991 
992  if( m_inTwoClickPlace )
993  return 0;
994 
996 
997  bool isText = aEvent.IsAction( &EE_ACTIONS::placeSchematicText );
998  bool isGlobalLabel = aEvent.IsAction( &EE_ACTIONS::placeGlobalLabel );
999  bool isHierLabel = aEvent.IsAction( &EE_ACTIONS::placeHierLabel );
1000  bool isNetLabel = aEvent.IsAction( &EE_ACTIONS::placeLabel );
1001  bool isSheetPin = aEvent.IsAction( &EE_ACTIONS::importSheetPin );
1002  int snapLayer = isText ? LAYER_GRAPHICS : LAYER_CONNECTABLE;
1003 
1005 
1006  std::string tool = aEvent.GetCommandStr().get();
1007  m_frame->PushTool( tool );
1008  auto setCursor =
1009  [&]()
1010  {
1011  if( item )
1013  else if( isText )
1015  else if( isGlobalLabel )
1017  else if( isNetLabel )
1019  else if( isHierLabel )
1021  else
1023  };
1024 
1025  auto updatePreview =
1026  [&]()
1027  {
1028  m_view->ClearPreview();
1029  m_view->AddToPreview( item->Clone() );
1030  item->RunOnChildren( [&]( SCH_ITEM* aChild )
1031  {
1032  m_view->AddToPreview( aChild->Clone() );
1033  } );
1034  };
1035 
1036  auto cleanup =
1037  [&]()
1038  {
1040  m_view->ClearPreview();
1041  delete item;
1042  item = nullptr;
1043  };
1044 
1045  Activate();
1046  // Must be done after Activate() so that it gets set into the correct context
1047  controls->ShowCursor( true );
1048  // Set initial cursor
1049  setCursor();
1050 
1051  // Prime the pump if the tool isn't being re-activated
1052  if( aEvent.HasPosition() )
1053  {
1054  m_toolMgr->PrimeTool( aEvent.Position() );
1055  }
1056  else if( !aEvent.IsReactivate() && ( isText
1057  || isGlobalLabel
1058  || isHierLabel
1059  || isNetLabel ) )
1060  {
1061  m_toolMgr->PrimeTool( { 0, 0 } );
1062  ignorePrimePosition = true;
1063  }
1064 
1065  // Main loop: keep receiving events
1066  while( TOOL_EVENT* evt = Wait() )
1067  {
1068  setCursor();
1069  grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1070  grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1071 
1072  VECTOR2I cursorPos = evt->IsPrime() ? evt->Position() : controls->GetMousePosition();
1073  cursorPos = grid.BestSnapAnchor( cursorPos, snapLayer, item );
1074  controls->ForceCursorPosition( true, cursorPos );
1075 
1076  if( evt->IsCancelInteractive() )
1077  {
1078  m_frame->GetInfoBar()->Dismiss();
1079 
1080  if( item )
1081  {
1082  cleanup();
1083  }
1084  else
1085  {
1086  m_frame->PopTool( tool );
1087  break;
1088  }
1089  }
1090  else if( evt->IsActivate() )
1091  {
1092  if( item && evt->IsMoveTool() )
1093  {
1094  // we're already moving our own item; ignore the move tool
1095  evt->SetPassEvent( false );
1096  continue;
1097  }
1098 
1099  if( item )
1100  {
1101  m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel item creation." ) );
1102  evt->SetPassEvent( false );
1103  continue;
1104  }
1105 
1106  if( evt->IsPointEditor() )
1107  {
1108  // don't exit (the point editor runs in the background)
1109  }
1110  else if( evt->IsMoveTool() )
1111  {
1112  break;
1113  }
1114  else
1115  {
1116  m_frame->PopTool( tool );
1117  break;
1118  }
1119  }
1120  else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
1121  {
1122  // First click creates...
1123  if( !item )
1124  {
1126 
1127  if( isText )
1128  {
1129  item = createNewText( cursorPos, LAYER_NOTES );
1130  }
1131  else if( isGlobalLabel )
1132  {
1133  item = createNewText( cursorPos, LAYER_GLOBLABEL );
1134  }
1135  else if( isHierLabel )
1136  {
1137  item = createNewText( cursorPos, LAYER_HIERLABEL );
1138  }
1139  else if( isNetLabel )
1140  {
1141  item = createNewText( cursorPos, LAYER_LOCLABEL );
1142  }
1143  else if( isSheetPin )
1144  {
1145  EDA_ITEM* i;
1146  SCH_HIERLABEL* label = nullptr;
1147  SCH_SHEET* sheet = nullptr;
1148 
1149  if( m_selectionTool->SelectPoint( cursorPos, EE_COLLECTOR::SheetsOnly, &i ) )
1150  sheet = dynamic_cast<SCH_SHEET*>( i );
1151 
1153 
1154  if( !sheet )
1155  {
1156  m_statusPopup.reset( new STATUS_TEXT_POPUP( m_frame ) );
1157  m_statusPopup->SetText( _( "Click over a sheet." ) );
1158  m_statusPopup->Move( wxGetMousePosition() + wxPoint( 20, 20 ) );
1159  m_statusPopup->PopupFor( 2000 );
1160  item = nullptr;
1161  }
1162  else
1163  {
1164  label = importHierLabel( sheet );
1165 
1166  if( !label )
1167  {
1168  m_statusPopup.reset( new STATUS_TEXT_POPUP( m_frame ) );
1169  m_statusPopup->SetText( _( "No new hierarchical labels found." ) );
1170  m_statusPopup->Move( wxGetMousePosition() + wxPoint( 20, 20 ) );
1171  m_statusPopup->PopupFor( 2000 );
1172  item = nullptr;
1173  }
1174  else
1175  {
1176  item = createSheetPin( sheet, label );
1177  }
1178  }
1179  }
1180 
1181  // If we started with a click on a tool button or menu then continue with the
1182  // current mouse position. Otherwise warp back to the original click position.
1183  if( evt->IsPrime() && ignorePrimePosition )
1184  cursorPos = grid.Align( controls->GetMousePosition() );
1185  else
1186  controls->WarpCursor( cursorPos, true );
1187 
1188  if( item )
1189  {
1190  item->SetPosition( (wxPoint) cursorPos );
1191 
1192  item->SetFlags( IS_NEW | IS_MOVING );
1193  item->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
1194  updatePreview();
1195 
1196  m_selectionTool->AddItemToSel( item );
1197 
1198  // update the cursor so it looks correct before another event
1199  setCursor();
1200  }
1201 
1202  controls->SetCursorPosition( cursorPos, false );
1203  }
1204  else // ... and second click places:
1205  {
1206  item->ClearFlags( IS_MOVING );
1208  false );
1209  item = nullptr;
1210 
1211  m_view->ClearPreview();
1212  }
1213  }
1214  else if( evt->IsClick( BUT_RIGHT ) )
1215  {
1216  // Warp after context menu only if dragging...
1217  if( !item )
1219 
1221  }
1222  else if( item && evt->IsSelectionEvent() )
1223  {
1224  // This happens if our text was replaced out from under us by ConvertTextType()
1225  EE_SELECTION& selection = m_selectionTool->GetSelection();
1226 
1227  if( selection.GetSize() == 1 )
1228  {
1229  item = (SCH_ITEM*) selection.Front();
1230  updatePreview();
1231  }
1232  else
1233  {
1234  item = nullptr;
1235  }
1236  }
1237  else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
1238  {
1239  item->SetPosition( (wxPoint) cursorPos );
1240  item->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
1241  updatePreview();
1242  }
1243  else if( item && evt->IsAction( &ACTIONS::doDelete ) )
1244  {
1245  cleanup();
1246  }
1247  else
1248  {
1249  evt->SetPassEvent();
1250  }
1251 
1252  // Enable autopanning and cursor capture only when there is an item to be placed
1253  controls->SetAutoPan( item != nullptr );
1254  controls->CaptureCursor( item != nullptr );
1255  }
1256 
1257  controls->SetAutoPan( false );
1258  controls->CaptureCursor( false );
1259  controls->ForceCursorPosition( false );
1261  return 0;
1262 }
1263 
1264 
1266 {
1267  SCH_SHEET* sheet = nullptr;
1268 
1269  if( m_inDrawSheet )
1270  return 0;
1271 
1272  REENTRANCY_GUARD guard( &m_inDrawSheet );
1273 
1275 
1276  std::string tool = aEvent.GetCommandStr().get();
1277  m_frame->PushTool( tool );
1278 
1279  auto setCursor =
1280  [&]()
1281  {
1283  };
1284 
1285  auto cleanup =
1286  [&] ()
1287  {
1289  m_view->ClearPreview();
1290  delete sheet;
1291  sheet = nullptr;
1292  };
1293 
1294  Activate();
1295  // Must be done after Activate() so that it gets set into the correct context
1296  getViewControls()->ShowCursor( true );
1297  // Set initial cursor
1298  setCursor();
1299 
1300  // Prime the pump
1301  if( aEvent.HasPosition() )
1303 
1304  // Main loop: keep receiving events
1305  while( TOOL_EVENT* evt = Wait() )
1306  {
1307  setCursor();
1308 
1309  VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
1310 
1311  if( evt->IsCancelInteractive() )
1312  {
1313  m_frame->GetInfoBar()->Dismiss();
1314 
1315  if( sheet )
1316  {
1317  cleanup();
1318  }
1319  else
1320  {
1321  m_frame->PopTool( tool );
1322  break;
1323  }
1324  }
1325  else if( evt->IsActivate() )
1326  {
1327  if( sheet && evt->IsMoveTool() )
1328  {
1329  // we're already drawing our own item; ignore the move tool
1330  evt->SetPassEvent( false );
1331  continue;
1332  }
1333 
1334  if( sheet )
1335  {
1336  m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel sheet creation." ) );
1337  evt->SetPassEvent( false );
1338  continue;
1339  }
1340 
1341  if( evt->IsPointEditor() )
1342  {
1343  // don't exit (the point editor runs in the background)
1344  }
1345  else if( evt->IsMoveTool() )
1346  {
1347  // leave ourselves on the stack so we come back after the move
1348  break;
1349  }
1350  else
1351  {
1352  m_frame->PopTool( tool );
1353  break;
1354  }
1355  }
1356  else if( !sheet && ( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) ) )
1357  {
1359 
1361 
1362  sheet = new SCH_SHEET( m_frame->GetCurrentSheet().Last(),
1363  static_cast<wxPoint>( cursorPos ) );
1364  sheet->SetFlags( IS_NEW | IS_RESIZING );
1365  sheet->SetScreen( nullptr );
1366  sheet->SetBorderWidth( Mils2iu( cfg->m_Drawing.default_line_thickness ) );
1369  sheet->GetFields()[ SHEETNAME ].SetText( wxT( "Untitled Sheet" ) );
1370  sheet->GetFields()[ SHEETFILENAME ].SetText( wxT( "untitled." ) + KiCadSchematicFileExtension );
1371  sizeSheet( sheet, cursorPos );
1372 
1373  m_view->ClearPreview();
1374  m_view->AddToPreview( sheet->Clone() );
1375  }
1376  else if( sheet && ( evt->IsClick( BUT_LEFT )
1377  || evt->IsDblClick( BUT_LEFT )
1378  || evt->IsAction( &EE_ACTIONS::finishSheet ) ) )
1379  {
1380  m_view->ClearPreview();
1381  getViewControls()->SetAutoPan( false );
1382  getViewControls()->CaptureCursor( false );
1383 
1384  // Find the list of paths in the hierarchy that refer to the destination sheet where
1385  // the new sheet will be drawn
1386  SCH_SCREEN* currentScreen = m_frame->GetCurrentSheet().LastScreen();
1387  SCH_SHEET_LIST hierarchy = m_frame->Schematic().GetSheets();
1388  SCH_SHEET_LIST instances = hierarchy.FindAllSheetsForScreen( currentScreen );
1389  instances.SortByPageNumbers();
1390 
1391  int pageNum = static_cast<int>( hierarchy.size() ) + 1;
1392 
1393  // Set a page number for all the instances of the new sheet in the hierarchy
1394  for( SCH_SHEET_PATH& instance : instances )
1395  {
1396  SCH_SHEET_PATH sheetPath = instance;
1397  sheetPath.push_back( sheet );
1398  sheet->AddInstance( sheetPath );
1399  sheet->SetPageNumber( sheetPath, wxString::Format( wxT( "%d" ), pageNum++ ) );
1400  }
1401 
1402  if( m_frame->EditSheetProperties( static_cast<SCH_SHEET*>( sheet ),
1403  &m_frame->GetCurrentSheet(), nullptr ) )
1404  {
1405  sheet->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
1406 
1407  m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), sheet, false );
1409  m_selectionTool->AddItemToSel( sheet );
1410  }
1411  else
1412  {
1413  delete sheet;
1414  }
1415 
1416  sheet = nullptr;
1417  }
1418  else if( sheet && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
1419  {
1420  sizeSheet( sheet, cursorPos );
1421  m_view->ClearPreview();
1422  m_view->AddToPreview( sheet->Clone() );
1423  }
1424  else if( evt->IsClick( BUT_RIGHT ) )
1425  {
1426  // Warp after context menu only if dragging...
1427  if( !sheet )
1429 
1431  }
1432  else
1433  {
1434  evt->SetPassEvent();
1435  }
1436 
1437  // Enable autopanning and cursor capture only when there is a sheet to be placed
1438  getViewControls()->SetAutoPan( sheet != nullptr );
1439  getViewControls()->CaptureCursor( sheet != nullptr );
1440  }
1441 
1442  getViewControls()->SetAutoPan( false );
1443  getViewControls()->CaptureCursor( false );
1445 
1446  return 0;
1447 }
1448 
1449 
1451 {
1452  wxPoint pos = aSheet->GetPosition();
1453  wxPoint size = (wxPoint) aPos - pos;
1454 
1455  size.x = std::max( size.x, Mils2iu( MIN_SHEET_WIDTH ) );
1456  size.y = std::max( size.y, Mils2iu( MIN_SHEET_HEIGHT ) );
1457 
1458  wxPoint grid = m_frame->GetNearestGridPosition( pos + size );
1459  aSheet->Resize( wxSize( grid.x - pos.x, grid.y - pos.y ) );
1460 }
1461 
1462 
1464 {
1478 }
virtual void ShowCursor(bool aEnabled)
Enable or disables display of cursor.
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:230
bool IsBold() const
Definition: eda_text.h:204
static TOOL_ACTION properties
Definition: ee_actions.h:121
bool SchematicCleanUp(SCH_SCREEN *aScreen=nullptr)
Perform routine schematic cleaning including breaking wire and buses and deleting identical objects s...
void SetShape(PINSHEETLABEL_SHAPE aShape)
Definition: sch_text.h:163
PINSHEETLABEL_SHAPE m_lastGlobalLabelShape
int TwoClickPlace(const TOOL_EVENT &aEvent)
TOOL_MENU m_menu
The functions below are not yet implemented - their interface may change.
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
static TOOL_ACTION finishSheet
Definition: ee_actions.h:98
bool Init() override
Init() is called once upon a registration of the tool.
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.
void SetPosition(const wxPoint &aPosition) override
Definition: sch_symbol.h:646
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Return the current mouse pointer position.
static TOOL_ACTION activatePointEditor
Definition: actions.h:168
SCH_SHEET_PIN * createSheetPin(SCH_SHEET *aSheet, SCH_HIERLABEL *aLabel)
wxPoint GetStartPoint() const
Definition: sch_line.h:90
void SetUnit(int aUnit)
Change the unit number to aUnit.
Definition: sch_symbol.cpp:354
Holds all the data relating to one schematic.
Definition: schematic.h:59
#define IS_NEW
New item, just created.
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
#define IS_RESIZING
Item being resized.
This file is part of the common library.
static TOOL_ACTION doDelete
Definition: actions.h:72
virtual void SetPosition(const wxPoint &aPos)
Definition: eda_item.h:252
int GetUnitCount() const
Return the number of units per package of the symbol.
Definition: sch_symbol.cpp:393
void AddToPreview(EDA_ITEM *aItem, bool aTakeOwnership=true)
Definition: view.cpp:1614
EDA_RECT GetCanvasFreeAreaPixels()
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
Extension of STATUS_POPUP for displaying a single line text.
Definition: status_popup.h:79
void Rotate(const wxPoint &aCenter) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:46
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:167
static TOOL_ACTION placeHierLabel
Definition: ee_actions.h:88
void SetItalic(bool isItalic)
Definition: eda_text.h:200
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:214
static TOOL_ACTION placeJunction
Definition: ee_actions.h:84
void RecacheAllItems()
Rebuild GAL display lists.
Definition: view.cpp:1385
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:175
virtual void PushTool(const std::string &actionName)
NB: the definition of "tool" is different at the user level.
SCHEMATIC * Schematic() const
Searches the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:104
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:152
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:143
void PrimeTool(const VECTOR2D &aPosition)
"Prime" a tool by sending a cursor left-click event with the mouse position set to the passed in posi...
virtual void SetCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true, bool aTriggeredByArrows=false, long aArrowCommand=0)=0
Move cursor to the requested position expressed in world coordinates.
Schematic editor (Eeschema) main window.
static TOOL_ACTION placeBusWireEntry
Definition: ee_actions.h:85
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:258
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
void SelectUnit(SCH_SYMBOL *aSymbol, int aUnit)
Definition: picksymbol.cpp:211
static const KICAD_T SheetsOnly[]
Definition: ee_collectors.h:46
static TOOL_ACTION mirrorH
Definition: ee_actions.h:120
wxPoint GetNearestGridPosition(const wxPoint &aPosition) const
Return the nearest aGridSize location to aPosition.
static TOOL_ACTION importSingleSheetPin
Definition: ee_actions.h:189
void sizeSheet(SCH_SHEET *aSheet, const VECTOR2I &aPos)
Set up handlers for various events.
bool IsValid() const
Check if this LID_ID is valid.
Definition: lib_id.h:159
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:102
Define a library symbol object.
Definition: lib_symbol.h:96
int PlaceImage(const TOOL_EVENT &aEvent)
PANEL_SYM_CHOOSER m_SymChooserPanel
std::vector< PICKED_SYMBOL > m_symbolHistoryList
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).
bool Contains(const wxPoint &aPoint) const
Definition: eda_rect.cpp:57
void SetUnitSelection(const SCH_SHEET_PATH *aSheet, int aUnitSelection)
Set the selected unit of this symbol on one sheet.
Definition: sch_symbol.cpp:570
void SetPageNumber(const SCH_SHEET_PATH &aInstance, const wxString &aPageNumber)
Set the page number for the sheet instance aInstance.
Definition: sch_sheet.cpp:1210
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:205
#define MIN_SHEET_WIDTH
Definition: sch_sheet.h:37
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:115
virtual EDA_ITEM * Clone() const
Create a duplicate of this item with linked list members set to NULL.
Definition: eda_item.cpp:83
static TOOL_ACTION mirrorV
Definition: ee_actions.h:119
static TOOL_ACTION rotateCW
Definition: ee_actions.h:117
const VC_SETTINGS & GetSettings() const
Apply VIEW_CONTROLS settings from an object.
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
Definition: tool_event.cpp:88
static TOOL_ACTION leaveSheet
Definition: ee_actions.h:186
void SetBorderWidth(int aWidth)
Definition: sch_sheet.h:108
Base class for a bus or wire entry.
Definition: sch_bus_entry.h:42
bool Init() override
Init() is called once upon a registration of the tool.
Definition: ee_tool_base.h:66
bool IsItalic() const
Definition: eda_text.h:201
EE_SELECTION & GetSelection()
Return the set of currently selected items.
EESCHEMA_SETTINGS * eeconfig() const
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:90
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
void ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false, WX_INFOBAR::MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an error icon on the left o...
static TOOL_ACTION drawSheet
Definition: ee_actions.h:89
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...
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction)
Definition: sch_item.h:444
virtual void WarpCursor(const VECTOR2D &aPosition, bool aWorldCoordinates=false, bool aWarpView=false)=0
If enabled (.
static TOOL_ACTION rotateCCW
Definition: ee_actions.h:118
static TOOL_ACTION trimOverlappingWires
Definition: ee_actions.h:76
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: infobar.cpp:175
int PlaceSymbol(const TOOL_EVENT &aEvent)
AUTOPLACE_FIELDS m_AutoplaceFields
void SetBackgroundColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:114
static TOOL_ACTION placePower
Definition: ee_actions.h:79
#define IS_MOVING
Item being moved.
SCH_ITEM * Duplicate(bool doClone=false) const
Routine to create a new copy of given item.
Definition: sch_item.cpp:85
void TestDanglingEnds()
Test all of the connectable objects in the schematic for unused connection points.
virtual void PopTool(const std::string &actionName)
virtual void CaptureCursor(bool aEnabled)
Force the cursor to stay within the drawing panel area.
PICKED_SYMBOL PickSymbolFromLibTree(const SCHLIB_FILTER *aFilter, std::vector< PICKED_SYMBOL > &aHistoryList, bool aUseLibBrowser, int aUnit, int aConvert, bool aShowFootprints, const LIB_ID *aHighlight=nullptr, bool aAllowFields=true)
Call the library viewer to select symbol to import into schematic.
Definition: picksymbol.cpp:91
int ShowQuasiModal()
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual) override
Automatically orient all the fields in the symbol.
int SingleClickPlace(const TOOL_EVENT &aEvent)
T Parameter() const
Return a non-standard parameter assigned to the event.
Definition: tool_event.h:432
virtual void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual)
Definition: sch_item.h:442
static TOOL_ACTION placeSchematicText
Definition: ee_actions.h:91
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.
static TOOL_ACTION placeImage
Definition: ee_actions.h:93
void ClearPreview()
Definition: view.cpp:1592
SCH_ITEM * GetItem(const wxPoint &aPosition, int aAccuracy=0, KICAD_T aType=SCH_LOCATE_ANY_T) const
Check aPosition within a distance of aAccuracy for items of type aFilter.
Definition: sch_screen.cpp:342
SCHEMATIC & Schematic() const
void UpdateHierarchyNavigator(bool aForceUpdate=false)
Run the Hierarchy Navigator dialog.
void SetBorderColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:111
Definition of file extensions used in Kicad.
Structure to keep VIEW_CONTROLS settings for easy store/restore operations.
Definition: view_controls.h:41
Definition for symbol library class.
An interface for classes handling user events controlling the view behavior such as zooming,...
#define _(s)
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:153
EE_SELECTION_TOOL * m_selectionTool
Definition: ee_tool_base.h:179
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Place the cursor immediately at a given point.
LABEL_SPIN_STYLE GetLabelSpinStyle() const
Definition: sch_text.h:159
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:65
static TOOL_ACTION importSheetPin
Definition: ee_actions.h:90
static TOOL_ACTION clearSelection
Clears the current selection.
Definition: ee_actions.h:56
static TOOL_ACTION placeSymbol
Definition: ee_actions.h:78
virtual void SetCrossHairCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true)=0
Move the graphic crosshair cursor to the requested position expressed in world coordinates.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
float m_autoPanMargin
How fast is panning when in auto mode.
Definition: view_controls.h:76
static TOOL_ACTION addNeededJunctions
Definition: ee_actions.h:75
wxPoint GetPosition() const override
Definition: sch_sheet.h:379
bool m_autoPanEnabled
Flag for turning on autopanning.
Definition: view_controls.h:70
Object to handle a bitmap image that can be inserted in a schematic.
Definition: sch_bitmap.h:40
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.
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:88
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
Definition: seg.h:40
std::vector< PICKED_SYMBOL > m_powerHistoryList
static TOOL_ACTION placeLabel
Definition: ee_actions.h:86
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:460
void SetPosition(const wxPoint &aPosition) override
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:87
PINSHEETLABEL_SHAPE
Definition: sch_text.h:95
SCH_SHEET & Root() const
Definition: schematic.h:92
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: sch_sheet.cpp:169
void AddItemToScreenAndUndoList(SCH_SCREEN *aScreen, SCH_ITEM *aItem, bool aUndoAppend)
Add an item to the schematic and adds the changes to the undo/redo container.
Schematic symbol object.
Definition: sch_symbol.h:78
bool IsExplicitJunctionAllowed(const wxPoint &aPosition) const
Indicates that a juction dot may be placed at the given location.
Definition: sch_screen.cpp:433
int AddItemToSel(const TOOL_EVENT &aEvent)
SCH_SCREEN * LastScreen()
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:37
bool SelectPoint(const VECTOR2I &aWhere, const KICAD_T *aFilterList=EE_COLLECTOR::AllItems, EDA_ITEM **aItem=nullptr, bool *aSelectionCancelledFlag=nullptr, bool aCheckLocked=false, bool aAdd=false, bool aSubtract=false, bool aExclusiveOr=false)
This overload of SelectPoint will create an EE_COLLECTOR and collect hits at location aWhere before c...
SCH_HIERLABEL * importHierLabel(SCH_SHEET *aSheet)
int ClearSelection(const TOOL_EVENT &aEvent)
Select all visible items in sheet.
void RollbackSchematicFromUndo()
Perform an undo of the last edit WITHOUT logging a corresponding redo.
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:110
void SortByPageNumbers(bool aUpdateVirtualPageNums=true)
Sort the list of sheets by page number.
void VetoContextMenuMouseWarp()
Disable mouse warping after the current context menu is closed.
Definition: tool_manager.h:422
SCH_TEXT * createNewText(const VECTOR2I &aPosition, int aType)
Get the next queued text item.
static TOOL_ACTION placeNoConnect
Definition: ee_actions.h:83
Handle the component boundary box.
Definition: eda_rect.h:42
const std::string KiCadSchematicFileExtension
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:99
#define MIN_SHEET_HEIGHT
Definition: sch_sheet.h:38
These settings were stored in SCH_BASE_FRAME previously.
wxPoint Centre() const
Definition: eda_rect.h:64
bool IsReactivate() const
Definition: tool_event.h:252
Class for a wire to bus entry.
bool EditSheetProperties(SCH_SHEET *aSheet, SCH_SHEET_PATH *aHierarchy, bool *aClearAnnotationNewItems)
Edit an existing sheet or add a new sheet to the schematic.
Definition: sheet.cpp:461
void Activate()
Run the tool.
WX_INFOBAR * GetInfoBar()
SCH_SHEET_PATH & GetCurrentSheet() const
PINSHEETLABEL_SHAPE m_lastSheetPinType
A foundation class for a tool operating on a schematic or symbol.
Definition: ee_tool_base.h:49
LABEL_SPIN_STYLE m_lastTextOrientation
LIB_SYMBOL * GetLibSymbol(const LIB_ID &aLibId, bool aUseCacheLib=false, bool aShowErrorMsg=false)
Load symbol from symbol library table.
bool HasPosition() const
Definition: tool_event.h:240
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current screen and u...
void Update(SCH_ITEM *aItem)
Update aItem's bounding box in the tree.
Definition: sch_screen.cpp:266
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual) override
Definition: sch_sheet.cpp:579
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
int GetUnit() const
Definition: sch_symbol.h:196
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:330
bool HasPin(const wxString &aName) const
Checks if the sheet already has a sheet pin named aName.
Definition: sch_sheet.cpp:370
static TOOL_ACTION placeGlobalLabel
Definition: ee_actions.h:87
void ClearEditFlags()
Definition: eda_item.h:171
LIB_ID LibId
Definition: sch_screen.h:82
void PostEvent(const TOOL_EVENT &aEvent)
Put an event to the event queue to be processed at the end of event processing cycle.
void SetBold(bool aBold)
Definition: eda_text.h:203
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.
wxString m_mruPath
Re-entrancy guards.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:182
SCH_SHEET_LIST FindAllSheetsForScreen(const SCH_SCREEN *aScreen) const
Return a SCH_SHEET_LIST with a copy of all the SCH_SHEET_PATH using a particular screen.
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
bool NoPrintableChars(const wxString &aString)
Return true if the string is empty or contains only whitespace.
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:154
const VECTOR2D Position() const
Returns the point where dragging has started.
Definition: tool_event.h:263
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
static TOOL_ACTION refreshPreview
Definition: actions.h:106
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
EDA_ITEM * Front() const
Definition: selection.h:145
int DrawSheet(const TOOL_EVENT &aEvent)
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Inflate the rectangle horizontally by dx and vertically by dy.
Definition: eda_rect.cpp:364
static TOOL_ACTION cursorClick
Definition: actions.h:123
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1570
PINSHEETLABEL_SHAPE GetShape() const
Definition: sch_text.h:161
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:112
bool AddInstance(const SCH_SHEET_PATH &aInstance)
Add a new instance aSheetPath to the instance list.
Definition: sch_sheet.cpp:1165
void Resize(const wxSize &aSize)
Resize this sheet to aSize and adjust all of the labels accordingly.
Definition: sch_sheet.cpp:887
wxPoint GetPosition() const override
wxPoint GetEndPoint() const
Definition: sch_line.h:93
std::unique_ptr< STATUS_TEXT_POPUP > m_statusPopup