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 
25 #include "sch_drawing_tools.h"
26 #include "ee_selection_tool.h"
27 #include "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 <kicad_string.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_inPlaceSymbol( false ),
66  m_inPlaceImage( false ),
67  m_inSingleClickPlace( false ),
68  m_inTwoClickPlace( false ),
69  m_inDrawSheet( false )
70 {
71 }
72 
73 
75 {
77 
78  auto belowRootSheetCondition =
79  [&]( const SELECTION& aSel )
80  {
81  return m_frame->GetCurrentSheet().Last() != &m_frame->Schematic().Root();
82  };
83 
84  CONDITIONAL_MENU& ctxMenu = m_menu.GetMenu();
85  ctxMenu.AddItem( EE_ACTIONS::leaveSheet, belowRootSheetCondition, 2 );
86 
87  return true;
88 }
89 
90 
92 {
93  // calculate thearea of the canvas in pixels that create no autopan when
94  // is inside this area the mouse cursor
95  wxSize canvas_size = m_frame->GetCanvas()->GetSize();
96  EDA_RECT canvas_area( wxPoint( 0, 0 ), canvas_size );
97  const KIGFX::VC_SETTINGS& v_settings = getViewControls()->GetSettings();
98 
99  if( v_settings.m_autoPanEnabled )
100  canvas_area.Inflate( - v_settings.m_autoPanMargin );
101 
102  // Gives a margin of 2 pixels
103  canvas_area.Inflate( -2 );
104 
105  return canvas_area;
106 }
107 
108 
110 {
111  SCH_SYMBOL* symbol = aEvent.Parameter<SCH_SYMBOL*>();
113  std::vector<PICKED_SYMBOL>* historyList = nullptr;
114 
115  if( m_inPlaceSymbol )
116  return 0;
117  else
118  m_inPlaceSymbol = true;
119 
120  if( aEvent.IsAction( &EE_ACTIONS::placeSymbol ) )
121  {
122  historyList = &m_symbolHistoryList;
123  }
124  else if (aEvent.IsAction( &EE_ACTIONS::placePower ) )
125  {
126  historyList = &m_powerHistoryList;
127  filter.FilterPowerSymbols( true );
128  }
129  else
130  {
131  wxFAIL_MSG( "PlaceSymbol(): unexpected request" );
132  }
133 
134  getViewControls()->ShowCursor( true );
135 
136  std::string tool = aEvent.GetCommandStr().get();
137  m_frame->PushTool( tool );
138  Activate();
139 
140  auto addSymbol =
141  [&]( SCH_SYMBOL* aSymbol )
142  {
143  m_frame->SaveCopyForRepeatItem( aSymbol );
144 
146  m_selectionTool->AddItemToSel( aSymbol );
147 
148  aSymbol->SetParent( m_frame->GetScreen() );
149  aSymbol->SetFlags( IS_NEW | IS_MOVING );
150  m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), aSymbol, false );
151 
152  // Set IS_MOVING again, as AddItemToScreenAndUndoList() will have cleared it.
153  aSymbol->SetFlags( IS_MOVING );
155  };
156 
157  auto setCursor =
158  [&]()
159  {
162  };
163 
164  auto cleanup =
165  [&] ()
166  {
169  symbol = nullptr;
170  };
171 
172  // Prime the pump
173  if( symbol )
174  {
175  addSymbol( symbol );
176  getViewControls()->WarpCursor( getViewControls()->GetMousePosition( false ) );
177  }
178  else if( !aEvent.IsReactivate() )
179  {
181  }
182 
183  // Set initial cursor
184  setCursor();
185 
186  // Main loop: keep receiving events
187  while( TOOL_EVENT* evt = Wait() )
188  {
189  setCursor();
190  VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
191 
192  if( evt->IsCancelInteractive() )
193  {
194  if( symbol )
195  {
196  cleanup();
197  }
198  else
199  {
200  m_frame->PopTool( tool );
201  break;
202  }
203  }
204  else if( evt->IsActivate() )
205  {
206  if( symbol && evt->IsMoveTool() )
207  {
208  // we're already moving our own item; ignore the move tool
209  evt->SetPassEvent( false );
210  continue;
211  }
212 
213  if( symbol )
214  {
215  m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel symbol creation." ) );
216  evt->SetPassEvent( false );
217  continue;
218  }
219 
220  if( evt->IsMoveTool() )
221  {
222  // leave ourselves on the stack so we come back after the move
223  break;
224  }
225  else
226  {
227  m_frame->PopTool( tool );
228  break;
229  }
230  }
231  else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
232  {
233  if( !symbol )
234  {
236 
237  // Store the mouse position: if it is outside the canvas,
238  // (happens when clicking on a toolbar tool) one cannot
239  // use the last stored cursor position to place the new symbol
240  // (Current mouse pos after closing the dialog will be used)
242  VECTOR2D initialMousePos = controls->GetMousePosition(false);
243  // Build the rectangle area acceptable to move the cursor without
244  // having an auto-pan
245  EDA_RECT canvas_area = GetCanvasFreeAreaPixels();
246 
247  // Pick the footprint to be placed
248  bool footprintPreviews = m_frame->eeconfig()->m_Appearance.footprint_preview;
249  PICKED_SYMBOL sel = m_frame->PickSymbolFromLibTree( &filter, *historyList, true,
250  1, 1, footprintPreviews );
251  // Restore cursor position after closing the dialog,
252  // but only if it has meaning (i.e inside the canvas)
253  VECTOR2D newMousePos = controls->GetMousePosition(false);
254 
255  if( canvas_area.Contains( wxPoint( initialMousePos ) ) )
256  controls->WarpCursor( controls->GetCursorPosition(), true );
257  else if( !canvas_area.Contains( wxPoint( newMousePos ) ) )
258  // The mouse is outside the canvas area, after closing the dialog,
259  // thus can creating autopan issues. Warp the mouse to the canvas centre
260  controls->WarpCursor( canvas_area.Centre(), false );
261 
262  LIB_SYMBOL* libSymbol = sel.LibId.IsValid() ?
263  m_frame->GetLibSymbol( sel.LibId ) : nullptr;
264 
265  if( !libSymbol )
266  continue;
267 
268  wxPoint pos( cursorPos );
269  symbol = new SCH_SYMBOL( *libSymbol, &m_frame->GetCurrentSheet(), sel, pos );
270  addSymbol( symbol );
271 
272  // Update cursor now that we have a symbol
273  setCursor();
274  }
275  else
276  {
278  symbol->AutoplaceFields( /* aScreen */ NULL, /* aManual */ false );
279 
280  symbol->ClearEditFlags();
281 
284 
285  m_view->Update( symbol );
286  m_frame->GetScreen()->Update( symbol );
287  m_frame->OnModify();
288 
289  SCH_SYMBOL* nextSymbol = nullptr;
290 
293  {
294  int new_unit = symbol->GetUnit();
295 
297  && symbol->GetUnit() < symbol->GetUnitCount() )
298  {
299  new_unit++;
300  }
301  else
302  {
303  new_unit = 1;
304  }
305 
306  // We are either stepping to the next unit or next symbol
307  if( m_frame->eeconfig()->m_SymChooserPanel.keep_symbol || new_unit > 1 )
308  {
309  nextSymbol = static_cast<SCH_SYMBOL*>( symbol->Duplicate() );
310  nextSymbol->SetUnit( new_unit );
311  nextSymbol->SetUnitSelection( new_unit );
312 
313  addSymbol( nextSymbol );
314  }
315  }
316 
317  symbol = nextSymbol;
318  }
319  }
320  else if( evt->IsClick( BUT_RIGHT ) )
321  {
322  // Warp after context menu only if dragging...
323  if( !symbol )
325 
327  }
328  else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
329  {
330  if( evt->GetCommandId().get() >= ID_POPUP_SCH_SELECT_UNIT_CMP
331  && evt->GetCommandId().get() <= ID_POPUP_SCH_SELECT_UNIT_SYM_MAX )
332  {
333  int unit = evt->GetCommandId().get() - ID_POPUP_SCH_SELECT_UNIT_CMP;
334 
335  if( symbol )
336  {
337  m_frame->SelectUnit( symbol, unit );
339  }
340  }
341  }
342  else if( symbol && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
343  {
344  symbol->SetPosition( (wxPoint)cursorPos );
345  m_view->Update( symbol );
346  }
347  else if( symbol && evt->IsAction( &ACTIONS::doDelete ) )
348  {
349  cleanup();
350  }
351  else
352  {
353  evt->SetPassEvent();
354  }
355 
356  // Enable autopanning and cursor capture only when there is a symbol to be placed
357  getViewControls()->SetAutoPan( symbol != nullptr );
358  getViewControls()->CaptureCursor( symbol != nullptr );
359  }
360 
361  getViewControls()->SetAutoPan( false );
362  getViewControls()->CaptureCursor( false );
364  m_inPlaceSymbol = false;
365  return 0;
366 }
367 
368 
370 {
371  SCH_BITMAP* image = aEvent.Parameter<SCH_BITMAP*>();
372  bool immediateMode = image;
373  VECTOR2I cursorPos = getViewControls()->GetCursorPosition();
374 
375  if( m_inPlaceImage )
376  return 0;
377  else
378  m_inPlaceImage = true;
379 
381  getViewControls()->ShowCursor( true );
382 
383  // Add all the drawable symbols to preview
384  if( image )
385  {
386  image->SetPosition( (wxPoint)cursorPos );
387  m_view->ClearPreview();
388  m_view->AddToPreview( image->Clone() );
389  }
390 
391  std::string tool = aEvent.GetCommandStr().get();
392  m_frame->PushTool( tool );
393  Activate();
394 
395  auto setCursor =
396  [&]()
397  {
398  if( image )
400  else
402  };
403 
404  auto cleanup =
405  [&] ()
406  {
408  m_view->ClearPreview();
409  delete image;
410  image = nullptr;
411  };
412 
413  // Prime the pump
414  if( image )
416  else if( !aEvent.IsReactivate() )
418 
419  // Set initial cursor
420  setCursor();
421 
422  // Main loop: keep receiving events
423  while( TOOL_EVENT* evt = Wait() )
424  {
425  setCursor();
426  cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
427 
428  if( evt->IsCancelInteractive() )
429  {
430  if( image )
431  {
432  cleanup();
433  }
434  else
435  {
436  m_frame->PopTool( tool );
437  break;
438  }
439 
440  if( immediateMode )
441  {
442  m_frame->PopTool( tool );
443  break;
444  }
445  }
446  else if( evt->IsActivate() )
447  {
448  if( image && evt->IsMoveTool() )
449  {
450  // we're already moving our own item; ignore the move tool
451  evt->SetPassEvent( false );
452  continue;
453  }
454 
455  if( image )
456  {
457  m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel image creation." ) );
458  evt->SetPassEvent( false );
459  continue;
460  }
461 
462  if( evt->IsMoveTool() )
463  {
464  // leave ourselves on the stack so we come back after the move
465  break;
466  }
467  else
468  {
469  m_frame->PopTool( tool );
470  break;
471  }
472  }
473  else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
474  {
475  if( !image )
476  {
478 
479  // Store the mouse position: if it is outside the canvas,
480  // (happens when clicking on a toolbar tool) one cannot
481  // use the last stored cursor position to place the new symbol
482  // (Current mouse pos after closing the dialog will be used)
484  VECTOR2D initialMousePos = controls->GetMousePosition(false);
485  // Build the rectangle area acceptable to move the cursor without
486  // having an auto-pan
487  EDA_RECT canvas_area = GetCanvasFreeAreaPixels();
488 
489  wxFileDialog dlg( m_frame, _( "Choose Image" ), wxEmptyString, wxEmptyString,
490  _( "Image Files" ) + wxS( " " ) + wxImage::GetImageExtWildcard(),
491  wxFD_OPEN );
492 
493  if( dlg.ShowModal() != wxID_OK )
494  continue;
495 
496  // Restore cursor position after closing the dialog,
497  // but only if it has meaning (i.e inside the canvas)
498  VECTOR2D newMousePos = controls->GetMousePosition( false );
499 
500  if( canvas_area.Contains( wxPoint( initialMousePos ) ) )
501  controls->WarpCursor( controls->GetCursorPosition(), true );
502  else if( !canvas_area.Contains( wxPoint( newMousePos ) ) )
503  // The mouse is outside the canvas area, after closing the dialog,
504  // thus can creating autopan issues. Warp the mouse to the canvas centre
505  controls->WarpCursor( canvas_area.Centre(), false );
506 
507  cursorPos = controls->GetMousePosition( true );
508 
509  wxString fullFilename = dlg.GetPath();
510 
511  if( wxFileExists( fullFilename ) )
512  image = new SCH_BITMAP( (wxPoint)cursorPos );
513 
514  if( !image || !image->ReadImageFile( fullFilename ) )
515  {
516  wxMessageBox( _( "Couldn't load image from \"%s\"" ), fullFilename );
517  delete image;
518  image = nullptr;
519  continue;
520  }
521 
522  image->SetFlags( IS_NEW | IS_MOVING );
523 
525 
526  m_view->ClearPreview();
527  m_view->AddToPreview( image->Clone() );
528  m_view->RecacheAllItems(); // Bitmaps are cached in Opengl
529 
531 
532  getViewControls()->SetCursorPosition( cursorPos, false );
533  setCursor();
534  }
535  else
536  {
538  image = nullptr;
540 
541  m_view->ClearPreview();
542 
543  if( immediateMode )
544  {
545  m_frame->PopTool( tool );
546  break;
547  }
548  }
549  }
550  else if( evt->IsClick( BUT_RIGHT ) )
551  {
552  // Warp after context menu only if dragging...
553  if( !image )
555 
557  }
558  else if( image && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
559  {
560  image->SetPosition( (wxPoint)cursorPos );
561  m_view->ClearPreview();
562  m_view->AddToPreview( image->Clone() );
563  m_view->RecacheAllItems(); // Bitmaps are cached in Opengl
564  }
565  else if( image && evt->IsAction( &ACTIONS::doDelete ) )
566  {
567  cleanup();
568  }
569  else
570  {
571  evt->SetPassEvent();
572  }
573 
574  // Enable autopanning and cursor capture only when there is an image to be placed
575  getViewControls()->SetAutoPan( image != nullptr );
576  getViewControls()->CaptureCursor( image != nullptr );
577  }
578 
579  getViewControls()->SetAutoPan( false );
580  getViewControls()->CaptureCursor( false );
582  m_inPlaceImage = false;
583  return 0;
584 }
585 
586 
588 {
589  wxPoint cursorPos;
590  KICAD_T type = aEvent.Parameter<KICAD_T>();
593  SCH_ITEM* previewItem;
594  bool loggedInfoBarError = false;
595 
597  return 0;
598 
599  if( type == SCH_JUNCTION_T && aEvent.HasPosition() )
600  {
601  EE_SELECTION& selection = m_selectionTool->GetSelection();
602  SCH_LINE* wire = dynamic_cast<SCH_LINE*>( selection.Front() );
603 
604  if( wire )
605  {
606  SEG seg( wire->GetStartPoint(), wire->GetEndPoint() );
607  VECTOR2I nearest = seg.NearestPoint( getViewControls()->GetCursorPosition() );
608  getViewControls()->SetCrossHairCursorPosition( nearest, false );
609  getViewControls()->WarpCursor( getViewControls()->GetCursorPosition(), true );
610  }
611  }
612 
613  switch( type )
614  {
615  case SCH_NO_CONNECT_T:
616  previewItem = new SCH_NO_CONNECT( cursorPos );
617  previewItem->SetParent( m_frame->GetScreen() );
618  break;
619 
620  case SCH_JUNCTION_T:
621  previewItem = new SCH_JUNCTION( cursorPos );
622  previewItem->SetParent( m_frame->GetScreen() );
623  break;
624 
626  previewItem = new SCH_BUS_WIRE_ENTRY( cursorPos );
627  previewItem->SetParent( m_frame->GetScreen() );
628  break;
629 
630  case SCH_SHEET_PIN_T:
631  {
632  EE_SELECTION& selection = m_selectionTool->GetSelection();
633  SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( selection.Front() );
634 
635  if( !sheet )
636  return 0;
637 
638  SCH_HIERLABEL* label = importHierLabel( sheet );
639 
640  if( !label )
641  {
642  m_statusPopup.reset( new STATUS_TEXT_POPUP( m_frame ) );
643  m_statusPopup->SetText( _( "No new hierarchical labels found." ) );
644  m_statusPopup->Move( wxGetMousePosition() + wxPoint( 20, 20 ) );
645  m_statusPopup->PopupFor( 2000 );
646  return 0;
647  }
648 
649  previewItem = createSheetPin( sheet, label );
650  }
651  break;
652 
653  default:
654  wxASSERT_MSG( false, "Unknown item type in SCH_DRAWING_TOOLS::SingleClickPlace" );
655  return 0;
656  }
657 
658  m_inSingleClickPlace = true;
659 
661  getViewControls()->ShowCursor( true );
662 
663  cursorPos = static_cast<wxPoint>( aEvent.HasPosition() ?
664  aEvent.Position() :
665  controls->GetMousePosition() );
666 
667  std::string tool = aEvent.GetCommandStr().get();
668  m_frame->PushTool( tool );
669  Activate();
670 
671  m_view->ClearPreview();
672  m_view->AddToPreview( previewItem->Clone() );
673 
674  // Prime the pump
675  if( aEvent.HasPosition() && type != SCH_SHEET_PIN_T )
677  else
679 
680  auto setCursor =
681  [&]()
682  {
684  };
685 
686  // Set initial cursor
687  setCursor();
688 
689  // Main loop: keep receiving events
690  while( TOOL_EVENT* evt = Wait() )
691  {
692  setCursor();
693  grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
694  grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
695 
696  cursorPos = evt->IsPrime() ? (wxPoint) evt->Position()
697  : (wxPoint) controls->GetMousePosition();
698 
699  cursorPos = wxPoint( grid.BestSnapAnchor( cursorPos, LAYER_CONNECTABLE, nullptr ) );
700  controls->ForceCursorPosition( true, cursorPos );
701 
702  if( evt->IsCancelInteractive() )
703  {
704  m_frame->PopTool( tool );
705  break;
706  }
707  else if( evt->IsActivate() )
708  {
709  if( evt->IsMoveTool() )
710  {
711  // leave ourselves on the stack so we come back after the move
712  break;
713  }
714  else
715  {
716  m_frame->PopTool( tool );
717  break;
718  }
719  }
720  else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
721  {
722  if( !m_frame->GetScreen()->GetItem( cursorPos, 0, type ) )
723  {
724  if( type == SCH_JUNCTION_T )
725  {
726  if( !m_frame->GetScreen()->IsJunctionNeeded( cursorPos ) )
727  {
728  m_frame->ShowInfoBarError( _( "Junction location contains no joinable "
729  "wires and/or pins." ) );
730  loggedInfoBarError = true;
731  continue;
732  }
733  else if( loggedInfoBarError )
734  {
735  m_frame->GetInfoBar()->Dismiss();
736  }
737  }
738 
739  SCH_ITEM* newItem = static_cast<SCH_ITEM*>( previewItem->Clone() );
740  newItem->SetPosition( cursorPos );
741  newItem->SetFlags( IS_NEW );
742 
743  m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), newItem, false );
744 
745  if( type == SCH_JUNCTION_T )
747  else
749 
750  m_frame->OnModify();
751  }
752 
753  if( evt->IsDblClick( BUT_LEFT ) || type == SCH_SHEET_PIN_T ) // Finish tool.
754  {
755  m_frame->PopTool( tool );
756  break;
757  }
758  }
759  else if( evt->IsClick( BUT_RIGHT ) )
760  {
762  }
763  else if( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() )
764  {
765  previewItem->SetPosition( (wxPoint)cursorPos );
766  m_view->ClearPreview();
767  m_view->AddToPreview( previewItem->Clone() );
768  }
769  else if( evt->Category() == TC_COMMAND )
770  {
771  if( ( type == SCH_BUS_WIRE_ENTRY_T )
772  && ( evt->IsAction( &EE_ACTIONS::rotateCW )
773  || evt->IsAction( &EE_ACTIONS::rotateCCW )
774  || evt->IsAction( &EE_ACTIONS::mirrorV )
775  || evt->IsAction( &EE_ACTIONS::mirrorH ) ) )
776  {
777  SCH_BUS_ENTRY_BASE* busItem = static_cast<SCH_BUS_ENTRY_BASE*>( previewItem );
778 
779  // The bus entries only rotate in one direction
780  if( evt->IsAction( &EE_ACTIONS::rotateCW )
781  || evt->IsAction( &EE_ACTIONS::rotateCCW ) )
782  {
783  busItem->Rotate( busItem->GetPosition() );
784  }
785  else if( evt->IsAction( &EE_ACTIONS::mirrorV ) )
786  {
787  busItem->MirrorVertically( busItem->GetPosition().x );
788  }
789  else if( evt->IsAction( &EE_ACTIONS::mirrorH ) )
790  {
791  busItem->MirrorHorizontally( busItem->GetPosition().y );
792  }
793 
794  m_view->ClearPreview();
795  m_view->AddToPreview( previewItem->Clone() );
796  }
797  else if( evt->IsAction( &EE_ACTIONS::properties ) )
798  {
799  switch( type )
800  {
802  {
803  std::deque<SCH_ITEM*> strokeItems;
804  strokeItems.push_back( previewItem );
805 
806  DIALOG_EDIT_LINE_STYLE dlg( m_frame, strokeItems );
807 
808  if( dlg.ShowModal() == wxID_OK )
809  {
811  m_frame->OnModify();
812  }
813  }
814  break;
815 
816  case SCH_JUNCTION_T:
817  {
818  std::deque<SCH_JUNCTION*> junctions;
819  junctions.push_back( static_cast<SCH_JUNCTION*>( previewItem ) );
820 
821  DIALOG_JUNCTION_PROPS dlg( m_frame, junctions );
822 
823  if( dlg.ShowModal() == wxID_OK )
824  {
826  m_frame->OnModify();
827  }
828  }
829  break;
830  default:
831  // Do nothing
832  break;
833  }
834 
835  m_view->ClearPreview();
836  m_view->AddToPreview( previewItem->Clone() );
837  }
838  else
839  {
840  evt->SetPassEvent();
841  }
842  }
843  else
844  {
845  evt->SetPassEvent();
846  }
847  }
848 
849  delete previewItem;
850  m_view->ClearPreview();
851 
853  controls->ForceCursorPosition( false );
854  m_inSingleClickPlace = false;
855  return 0;
856 }
857 
858 
859 SCH_TEXT* SCH_DRAWING_TOOLS::createNewText( const VECTOR2I& aPosition, int aType )
860 {
861  SCHEMATIC* schematic = getModel<SCHEMATIC>();
862  SCHEMATIC_SETTINGS& settings = schematic->Settings();
863  SCH_TEXT* textItem = nullptr;
864 
865  switch( aType )
866  {
867  case LAYER_NOTES:
868  textItem = new SCH_TEXT( (wxPoint) aPosition );
869  break;
870 
871  case LAYER_LOCLABEL:
872  textItem = new SCH_LABEL( (wxPoint) aPosition );
873  break;
874 
875  case LAYER_HIERLABEL:
876  textItem = new SCH_HIERLABEL( (wxPoint) aPosition );
877  textItem->SetShape( m_lastGlobalLabelShape );
878  break;
879 
880  case LAYER_GLOBLABEL:
881  textItem = new SCH_GLOBALLABEL( (wxPoint) aPosition );
882  textItem->SetShape( m_lastGlobalLabelShape );
883 
884  if( settings.m_IntersheetRefsShow )
885  static_cast<SCH_GLOBALLABEL*>( textItem )->GetIntersheetRefs()->SetVisible( true );
886  break;
887 
888  default:
889  wxFAIL_MSG( "SCH_EDIT_FRAME::CreateNewText() unknown layer type" );
890  return nullptr;
891  }
892 
893  textItem->SetParent( schematic );
894  textItem->SetBold( m_lastTextBold );
895  textItem->SetItalic( m_lastTextItalic );
897  textItem->SetTextSize( wxSize( settings.m_DefaultTextSize, settings.m_DefaultTextSize ) );
898  textItem->SetFlags( IS_NEW | IS_MOVING );
899 
900  DIALOG_LABEL_EDITOR dlg( m_frame, textItem );
901 
902  // Must be quasi modal for syntax help
903  if( dlg.ShowQuasiModal() != wxID_OK || NoPrintableChars( textItem->GetText() ) )
904  {
905  delete textItem;
906  return nullptr;
907  }
908 
909  m_lastTextBold = textItem->IsBold();
910  m_lastTextItalic = textItem->IsItalic();
912 
913  if( textItem->Type() == SCH_GLOBAL_LABEL_T || textItem->Type() == SCH_HIER_LABEL_T )
914  m_lastGlobalLabelShape = textItem->GetShape();
915 
916  return textItem;
917 }
918 
919 
921 {
922  if( !aSheet->GetScreen() )
923  return nullptr;
924 
925  for( EDA_ITEM* item : aSheet->GetScreen()->Items().OfType( SCH_HIER_LABEL_T ) )
926  {
927  SCH_HIERLABEL* label = static_cast<SCH_HIERLABEL*>( item );
928 
929  /* A global label has been found: check if there a corresponding sheet label. */
930  if( !aSheet->HasPin( label->GetText() ) )
931  return label;
932  }
933 
934  return nullptr;
935 }
936 
937 
939 {
940  SCHEMATIC_SETTINGS& settings = aSheet->Schematic()->Settings();
941  wxString text;
942  SCH_SHEET_PIN* sheetPin;
943 
944  if( aLabel )
945  {
946  text = aLabel->GetText();
947  m_lastSheetPinType = aLabel->GetShape();
948  }
949 
950  sheetPin = new SCH_SHEET_PIN( aSheet, wxPoint( 0, 0 ), text );
951  sheetPin->SetFlags( IS_NEW );
952  sheetPin->SetTextSize( wxSize( settings.m_DefaultTextSize, settings.m_DefaultTextSize ) );
953  sheetPin->SetShape( m_lastSheetPinType );
954 
955  if( !aLabel )
956  {
957  DIALOG_SHEET_PIN_PROPERTIES dlg( m_frame, sheetPin );
958 
959  if( dlg.ShowModal() != wxID_OK || NoPrintableChars( sheetPin->GetText() ) )
960  {
961  delete sheetPin;
962  return nullptr;
963  }
964  }
965 
966  m_lastSheetPinType = sheetPin->GetShape();
967 
968  sheetPin->SetPosition( (wxPoint) getViewControls()->GetCursorPosition() );
969 
970  return sheetPin;
971 }
972 
973 
975 {
976  SCH_ITEM* item = nullptr;
979 
980  if( m_inTwoClickPlace )
981  return 0;
982  else
983  m_inTwoClickPlace = true;
984 
985  bool isText = aEvent.IsAction( &EE_ACTIONS::placeSchematicText );
986  bool isGlobalLabel = aEvent.IsAction( &EE_ACTIONS::placeGlobalLabel );
987  bool isHierLabel = aEvent.IsAction( &EE_ACTIONS::placeHierLabel );
988  bool isNetLabel = aEvent.IsAction( &EE_ACTIONS::placeLabel );
989  bool isSheetPin = aEvent.IsAction( &EE_ACTIONS::importSheetPin );
990  int snapLayer = isText ? LAYER_GRAPHICS : LAYER_CONNECTABLE;
991 
993  controls->ShowCursor( true );
994 
995  std::string tool = aEvent.GetCommandStr().get();
996  m_frame->PushTool( tool );
997  Activate();
998 
999  auto setCursor =
1000  [&]()
1001  {
1002  if( item )
1004  else if( isText )
1006  else if( isGlobalLabel )
1008  else if( isNetLabel )
1010  else if( isHierLabel )
1012  else
1014  };
1015 
1016  auto updatePreview =
1017  [&]()
1018  {
1019  m_view->ClearPreview();
1020  m_view->AddToPreview( item->Clone() );
1021  item->RunOnChildren( [&]( SCH_ITEM* aChild )
1022  {
1023  m_view->AddToPreview( aChild->Clone() );
1024  } );
1025  };
1026 
1027  auto cleanup =
1028  [&]()
1029  {
1031  m_view->ClearPreview();
1032  delete item;
1033  item = nullptr;
1034  };
1035 
1036  // Prime the pump
1037  // If the tool isn't being re-activated
1038  if( aEvent.HasPosition() || ( !aEvent.IsReactivate()
1039  && ( isText || isGlobalLabel || isHierLabel || isNetLabel ) ) )
1040  {
1042  }
1043 
1044  // Set initial cursor
1045  setCursor();
1046 
1047  // Main loop: keep receiving events
1048  while( TOOL_EVENT* evt = Wait() )
1049  {
1050  setCursor();
1051  grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1052  grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1053 
1054  VECTOR2I cursorPos = evt->IsPrime() ? evt->Position() : controls->GetMousePosition();
1055  cursorPos = grid.BestSnapAnchor( cursorPos, snapLayer, item );
1056  controls->ForceCursorPosition( true, cursorPos );
1057 
1058  if( evt->IsCancelInteractive() )
1059  {
1060  if( item )
1061  {
1062  cleanup();
1063  }
1064  else
1065  {
1066  m_frame->PopTool( tool );
1067  break;
1068  }
1069  }
1070  else if( evt->IsActivate() )
1071  {
1072  if( item && evt->IsMoveTool() )
1073  {
1074  // we're already moving our own item; ignore the move tool
1075  evt->SetPassEvent( false );
1076  continue;
1077  }
1078 
1079  if( item )
1080  {
1081  m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel item creation." ) );
1082  evt->SetPassEvent( false );
1083  continue;
1084  }
1085 
1086  if( evt->IsPointEditor() )
1087  {
1088  // don't exit (the point editor runs in the background)
1089  }
1090  else if( evt->IsMoveTool() )
1091  {
1092  break;
1093  }
1094  else
1095  {
1096  m_frame->PopTool( tool );
1097  break;
1098  }
1099  }
1100  else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
1101  {
1102  // First click creates...
1103  if( !item )
1104  {
1106 
1107  if( isText )
1108  {
1109  item = createNewText( cursorPos, LAYER_NOTES );
1110  }
1111  else if( isGlobalLabel )
1112  {
1113  item = createNewText( cursorPos, LAYER_GLOBLABEL );
1114  }
1115  else if( isHierLabel )
1116  {
1117  item = createNewText( cursorPos, LAYER_HIERLABEL );
1118  }
1119  else if( isNetLabel )
1120  {
1121  item = createNewText( cursorPos, LAYER_LOCLABEL );
1122  }
1123  else if( isSheetPin )
1124  {
1125  EDA_ITEM* i;
1126  SCH_HIERLABEL* label = nullptr;
1127  SCH_SHEET* sheet = nullptr;
1128 
1129  if( m_selectionTool->SelectPoint( cursorPos, EE_COLLECTOR::SheetsOnly, &i ) )
1130  sheet = dynamic_cast<SCH_SHEET*>( i );
1131 
1133 
1134  if( !sheet )
1135  {
1136  m_statusPopup.reset( new STATUS_TEXT_POPUP( m_frame ) );
1137  m_statusPopup->SetText( _( "Click over a sheet." ) );
1138  m_statusPopup->Move( wxGetMousePosition() + wxPoint( 20, 20 ) );
1139  m_statusPopup->PopupFor( 2000 );
1140  item = nullptr;
1141  }
1142  else
1143  {
1144  label = importHierLabel( sheet );
1145 
1146  if( !label )
1147  {
1148  m_statusPopup.reset( new STATUS_TEXT_POPUP( m_frame ) );
1149  m_statusPopup->SetText( _( "No new hierarchical labels found." ) );
1150  m_statusPopup->Move( wxGetMousePosition() + wxPoint( 20, 20 ) );
1151  m_statusPopup->PopupFor( 2000 );
1152  item = nullptr;
1153  }
1154  else
1155  {
1156  item = createSheetPin( sheet, label );
1157  }
1158  }
1159  }
1160 
1161  // Restore cursor after dialog
1162  controls->WarpCursor( controls->GetCursorPosition(), true );
1163 
1164  if( item )
1165  {
1166  item->SetFlags( IS_NEW | IS_MOVING );
1167  item->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
1168  updatePreview();
1169 
1170  m_selectionTool->AddItemToSel( item );
1171 
1172  // update the cursor so it looks correct before another event
1173  setCursor();
1174  }
1175 
1176  controls->SetCursorPosition( cursorPos, false );
1177  }
1178 
1179  // ... and second click places:
1180  else
1181  {
1182  item->ClearFlags( IS_MOVING );
1184  false );
1185  item = nullptr;
1186 
1187  m_view->ClearPreview();
1188  }
1189  }
1190  else if( evt->IsClick( BUT_RIGHT ) )
1191  {
1192  // Warp after context menu only if dragging...
1193  if( !item )
1195 
1197  }
1198  else if( item && evt->IsSelectionEvent() )
1199  {
1200  // This happens if our text was replaced out from under us by ConvertTextType()
1201  EE_SELECTION& selection = m_selectionTool->GetSelection();
1202 
1203  if( selection.GetSize() == 1 )
1204  {
1205  item = (SCH_ITEM*) selection.Front();
1206  updatePreview();
1207  }
1208  else
1209  {
1210  item = nullptr;
1211  }
1212  }
1213  else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
1214  {
1215  item->SetPosition( (wxPoint) cursorPos );
1216  item->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
1217  updatePreview();
1218  }
1219  else if( item && evt->IsAction( &ACTIONS::doDelete ) )
1220  {
1221  cleanup();
1222  }
1223  else
1224  {
1225  evt->SetPassEvent();
1226  }
1227 
1228  // Enable autopanning and cursor capture only when there is an item to be placed
1229  controls->SetAutoPan( item != nullptr );
1230  controls->CaptureCursor( item != nullptr );
1231  }
1232 
1233  controls->SetAutoPan( false );
1234  controls->CaptureCursor( false );
1235  controls->ForceCursorPosition( false );
1237  m_inTwoClickPlace = false;
1238  return 0;
1239 }
1240 
1241 
1243 {
1244  SCH_SHEET* sheet = nullptr;
1245 
1246  if( m_inDrawSheet )
1247  return 0;
1248  else
1249  m_inDrawSheet = true;
1250 
1252  getViewControls()->ShowCursor( true );
1253 
1254  std::string tool = aEvent.GetCommandStr().get();
1255  m_frame->PushTool( tool );
1256  Activate();
1257 
1258  auto setCursor =
1259  [&]()
1260  {
1262  };
1263 
1264  auto cleanup =
1265  [&] ()
1266  {
1268  m_view->ClearPreview();
1269  delete sheet;
1270  sheet = nullptr;
1271  };
1272 
1273  // Prime the pump
1274  if( aEvent.HasPosition() )
1276 
1277  // Set initial cursor
1278  setCursor();
1279 
1280  // Main loop: keep receiving events
1281  while( TOOL_EVENT* evt = Wait() )
1282  {
1283  setCursor();
1284 
1285  VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
1286 
1287  if( evt->IsCancelInteractive() )
1288  {
1289  if( sheet )
1290  {
1291  cleanup();
1292  }
1293  else
1294  {
1295  m_frame->PopTool( tool );
1296  break;
1297  }
1298  }
1299  else if( evt->IsActivate() )
1300  {
1301  if( sheet && evt->IsMoveTool() )
1302  {
1303  // we're already drawing our own item; ignore the move tool
1304  evt->SetPassEvent( false );
1305  continue;
1306  }
1307 
1308  if( sheet )
1309  {
1310  m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel sheet creation." ) );
1311  evt->SetPassEvent( false );
1312  continue;
1313  }
1314 
1315  if( evt->IsPointEditor() )
1316  {
1317  // don't exit (the point editor runs in the background)
1318  }
1319  else if( evt->IsMoveTool() )
1320  {
1321  // leave ourselves on the stack so we come back after the move
1322  break;
1323  }
1324  else
1325  {
1326  m_frame->PopTool( tool );
1327  break;
1328  }
1329  }
1330  else if( !sheet && ( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) ) )
1331  {
1333 
1335 
1336  sheet = new SCH_SHEET( m_frame->GetCurrentSheet().Last(),
1337  static_cast<wxPoint>( cursorPos ) );
1338  sheet->SetFlags( IS_NEW | IS_RESIZING );
1339  sheet->SetScreen( NULL );
1343  sheet->GetFields()[ SHEETNAME ].SetText( "Untitled Sheet" );
1344  sheet->GetFields()[ SHEETFILENAME ].SetText( "untitled." + KiCadSchematicFileExtension );
1345  sizeSheet( sheet, cursorPos );
1346 
1347  m_view->ClearPreview();
1348  m_view->AddToPreview( sheet->Clone() );
1349  }
1350  else if( sheet && ( evt->IsClick( BUT_LEFT )
1351  || evt->IsDblClick( BUT_LEFT )
1352  || evt->IsAction( &EE_ACTIONS::finishSheet ) ) )
1353  {
1354  m_view->ClearPreview();
1355  getViewControls()->SetAutoPan( false );
1356  getViewControls()->CaptureCursor( false );
1357 
1358  // Find the list of paths in the hierarchy that refer to the destination sheet where
1359  // the new sheet will be drawn
1360  SCH_SCREEN* currentScreen = m_frame->GetCurrentSheet().LastScreen();
1361  SCH_SHEET_LIST hierarchy = m_frame->Schematic().GetSheets();
1362  SCH_SHEET_LIST instances = hierarchy.FindAllSheetsForScreen( currentScreen );
1363  instances.SortByPageNumbers();
1364 
1365  int pageNum = static_cast<int>( hierarchy.size() ) + 1;
1366 
1367  // Set a page number for all the instances of the new sheet in the hierarchy
1368  for( SCH_SHEET_PATH& instance : instances )
1369  {
1370  SCH_SHEET_PATH sheetPath = instance;
1371  sheetPath.push_back( sheet );
1372  sheet->AddInstance( sheetPath.Path() );
1373  sheet->SetPageNumber( sheetPath, wxString::Format( "%d", pageNum++ ) );
1374  }
1375 
1376  if( m_frame->EditSheetProperties( static_cast<SCH_SHEET*>( sheet ),
1377  &m_frame->GetCurrentSheet(), nullptr ) )
1378  {
1379  sheet->AutoplaceFields( /* aScreen */ NULL, /* aManual */ false );
1380 
1381  m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), sheet, false );
1383  m_selectionTool->AddItemToSel( sheet );
1384  }
1385  else
1386  {
1387  delete sheet;
1388  }
1389 
1390  sheet = nullptr;
1391  }
1392  else if( sheet && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
1393  {
1394  sizeSheet( sheet, cursorPos );
1395  m_view->ClearPreview();
1396  m_view->AddToPreview( sheet->Clone() );
1397  }
1398  else if( evt->IsClick( BUT_RIGHT ) )
1399  {
1400  // Warp after context menu only if dragging...
1401  if( !sheet )
1403 
1405  }
1406  else
1407  {
1408  evt->SetPassEvent();
1409  }
1410 
1411  // Enable autopanning and cursor capture only when there is a sheet to be placed
1412  getViewControls()->SetAutoPan( sheet != nullptr );
1413  getViewControls()->CaptureCursor( sheet != nullptr );
1414  }
1415 
1416  getViewControls()->SetAutoPan( false );
1417  getViewControls()->CaptureCursor( false );
1419  m_inDrawSheet = false;
1420  return 0;
1421 }
1422 
1423 
1425 {
1426  wxPoint pos = aSheet->GetPosition();
1427  wxPoint size = (wxPoint) aPos - pos;
1428 
1429  size.x = std::max( size.x, MIN_SHEET_WIDTH );
1430  size.y = std::max( size.y, MIN_SHEET_HEIGHT );
1431 
1432  wxPoint grid = m_frame->GetNearestGridPosition( pos + size );
1433  aSheet->Resize( wxSize( grid.x - pos.x, grid.y - pos.y ) );
1434 }
1435 
1436 
1438 {
1452 }
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:216
bool IsBold() const
Definition: eda_text.h:190
static TOOL_ACTION properties
Definition: ee_actions.h:117
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:94
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:642
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:321
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:253
int GetUnitCount() const
Return the number of units per package of the symbol.
Definition: sch_symbol.cpp:360
void AddToPreview(EDA_ITEM *aItem, bool aTakeOwnership=true)
Definition: view.cpp:1548
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
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:129
static TOOL_ACTION placeHierLabel
Definition: ee_actions.h:84
void SetItalic(bool isItalic)
Definition: eda_text.h:186
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:214
static TOOL_ACTION placeJunction
Definition: ee_actions.h:80
void RecacheAllItems()
Rebuild GAL display lists.
Definition: view.cpp:1381
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:157
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:97
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:153
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:143
bool m_lastTextItalic
Re-entrancy guards.
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:81
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:244
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
void SelectUnit(SCH_SYMBOL *aSymbol, int aUnit)
Definition: getpart.cpp:198
static const KICAD_T SheetsOnly[]
Definition: ee_collectors.h:49
static TOOL_ACTION mirrorH
Definition: ee_actions.h:116
wxPoint GetNearestGridPosition(const wxPoint &aPosition) const
Return the nearest aGridSize location to aPosition.
static TOOL_ACTION importSingleSheetPin
Definition: ee_actions.h:184
bool IsValid() const
Check if this LID_ID is valid.
Definition: lib_id.h:168
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:103
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:537
void SetPageNumber(const SCH_SHEET_PATH &aInstance, const wxString &aPageNumber)
Set the page number for the sheet instance aInstance.
Definition: sch_sheet.cpp:1136
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
#define MIN_SHEET_WIDTH
Definition: sch_sheet.h:37
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:116
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:115
static TOOL_ACTION rotateCW
Definition: ee_actions.h:113
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:181
void SetBorderWidth(int aWidth)
Definition: sch_sheet.h:109
bool NoPrintableChars(const wxString &aString)
Return true if the string is empty or contains only whitespace.
Definition: string.cpp:455
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:187
EE_SELECTION & GetSelection()
Return the set of currently selected items.
EESCHEMA_SETTINGS * eeconfig() const
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:88
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
static TOOL_ACTION drawSheet
Definition: ee_actions.h:85
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:453
virtual void WarpCursor(const VECTOR2D &aPosition, bool aWorldCoordinates=false, bool aWarpView=false)=0
If enabled (.
static TOOL_ACTION rotateCCW
Definition: ee_actions.h:114
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: infobar.cpp:176
int PlaceSymbol(const TOOL_EVENT &aEvent)
AUTOPLACE_FIELDS m_AutoplaceFields
void SetBackgroundColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:115
static TOOL_ACTION placePower
Definition: ee_actions.h:75
#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:78
#define NULL
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: getpart.cpp:88
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:427
virtual void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual)
Definition: sch_item.h:451
static TOOL_ACTION placeSchematicText
Definition: ee_actions.h:87
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:89
void ClearPreview()
Definition: view.cpp:1526
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:329
SCHEMATIC & Schematic() const
void UpdateHierarchyNavigator(bool aForceUpdate=false)
Run the Hierarchy Navigator dialog.
void SetBorderColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:112
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:154
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.
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:86
static TOOL_ACTION clearSelection
Clears the current selection.
Definition: ee_actions.h:53
static TOOL_ACTION placeSymbol
Definition: ee_actions.h:74
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:72
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:87
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:82
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:455
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:151
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
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()
Definition: sch_screen.h:102
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:79
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:100
#define MIN_SHEET_HEIGHT
Definition: sch_sheet.h:38
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
void ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an error icon on the left o...
wxPoint Centre() const
Definition: eda_rect.h:55
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:458
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:253
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual) override
Definition: sch_sheet.cpp:516
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:195
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 HasPin(const wxString &aName) const
Checks if the sheet already has a sheet pin named aName.
Definition: sch_sheet.cpp:328
static TOOL_ACTION placeGlobalLabel
Definition: ee_actions.h:83
void ClearEditFlags()
Definition: eda_item.h:172
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:189
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
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
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:133
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:144
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:1504
bool AddInstance(const KIID_PATH &aInstance)
Add a new instance aSheetPath to the instance list.
Definition: sch_sheet.cpp:1094
PINSHEETLABEL_SHAPE GetShape() const
Definition: sch_text.h:161
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113
void Resize(const wxSize &aSize)
Resize this sheet to aSize and adjust all of the labels accordingly.
Definition: sch_sheet.cpp:804
void sizeSheet(SCH_SHEET *aSheet, VECTOR2I aPos)
Set up handlers for various events.
wxPoint GetPosition() const override
wxPoint GetEndPoint() const
Definition: sch_line.h:93
std::unique_ptr< STATUS_TEXT_POPUP > m_statusPopup