KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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-2023 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 <memory>
26
27#include <kiplatform/ui.h>
33#include <ee_actions.h>
34#include <sch_edit_frame.h>
35#include <pgm_base.h>
36#include <eeschema_id.h>
37#include <confirm.h>
38#include <view/view_controls.h>
39#include <view/view.h>
40#include <sch_symbol.h>
41#include <sch_no_connect.h>
42#include <sch_line.h>
43#include <sch_junction.h>
44#include <sch_bus_entry.h>
45#include <sch_text.h>
46#include <sch_textbox.h>
47#include <sch_sheet.h>
48#include <sch_sheet_pin.h>
49#include <sch_bitmap.h>
50#include <schematic.h>
51#include <sch_commit.h>
53#include <eeschema_settings.h>
55#include <dialogs/dialog_text_properties.h>
58#include <string_utils.h>
60#include <wx/filedlg.h>
61
63 EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.InteractiveDrawing" ),
64 m_lastSheetPinType( LABEL_FLAG_SHAPE::L_INPUT ),
65 m_lastGlobalLabelShape( LABEL_FLAG_SHAPE::L_INPUT ),
66 m_lastNetClassFlagShape( LABEL_FLAG_SHAPE::F_ROUND ),
67 m_lastTextOrientation( SPIN_STYLE::RIGHT ),
68 m_lastTextBold( false ),
69 m_lastTextItalic( false ),
70 m_lastTextAngle( ANGLE_0 ),
71 m_lastTextJust( GR_TEXT_H_ALIGN_LEFT ),
72 m_lastFillStyle( FILL_T::NO_FILL ),
73 m_lastTextboxFillStyle( FILL_T::NO_FILL ),
74 m_lastFillColor( COLOR4D::UNSPECIFIED ),
75 m_lastTextboxFillColor( COLOR4D::UNSPECIFIED ),
76 m_lastStroke( 0, PLOT_DASH_TYPE::DEFAULT, COLOR4D::UNSPECIFIED ),
77 m_lastTextboxStroke( 0, PLOT_DASH_TYPE::DEFAULT, COLOR4D::UNSPECIFIED ),
78 m_mruPath( wxEmptyString ),
79 m_lastAutoLabelRotateOnPlacement( false ),
80 m_inPlaceSymbol( false ),
81 m_inDrawShape( false ),
82 m_inPlaceImage( false ),
83 m_inSingleClickPlace( false ),
84 m_inTwoClickPlace( false ),
85 m_inDrawSheet( false )
86{
87}
88
89
91{
93
94 auto belowRootSheetCondition =
95 [&]( const SELECTION& aSel )
96 {
97 return m_frame->GetCurrentSheet().Last() != &m_frame->Schematic().Root();
98 };
99
100 CONDITIONAL_MENU& ctxMenu = m_menu.GetMenu();
101 ctxMenu.AddItem( EE_ACTIONS::leaveSheet, belowRootSheetCondition, 2 );
102
103 return true;
104}
105
106
108{
109 SCH_SYMBOL* symbol = aEvent.Parameter<SCH_SYMBOL*>();
111 std::vector<PICKED_SYMBOL>* historyList = nullptr;
112 bool ignorePrimePosition = false;
113 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
114 SCH_SCREEN* screen = m_frame->GetScreen();
115
116 if( m_inPlaceSymbol )
117 return 0;
118
120
123 VECTOR2I cursorPos;
124
125 // First we need to get all instances of this sheet so we can annotate
126 // whatever symbols we place on all copies
127 SCH_SHEET_LIST hierarchy = m_frame->Schematic().GetSheets();
128 SCH_SHEET_LIST newInstances =
130 newInstances.SortByPageNumbers();
131
132 // Get a list of all references in the schematic to avoid duplicates wherever
133 // they're placed
134 SCH_REFERENCE_LIST existingRefs;
135 hierarchy.GetSymbols( existingRefs );
136 existingRefs.SortByReferenceOnly();
137
138 if( aEvent.IsAction( &EE_ACTIONS::placeSymbol ) )
139 {
140 historyList = &m_symbolHistoryList;
141 }
142 else if (aEvent.IsAction( &EE_ACTIONS::placePower ) )
143 {
144 historyList = &m_powerHistoryList;
145 filter.FilterPowerSymbols( true );
146 }
147 else
148 {
149 wxFAIL_MSG( "PlaceSymbol(): unexpected request" );
150 }
151
152 m_frame->PushTool( aEvent );
153
154 auto addSymbol =
155 [this]( SCH_SYMBOL* aSymbol )
156 {
158 m_selectionTool->AddItemToSel( aSymbol );
159
160 aSymbol->SetFlags( IS_NEW | IS_MOVING );
161
163 m_view->AddToPreview( aSymbol, false ); // Add, but not give ownership
164
165 // Set IS_MOVING again, as AddItemToCommitAndScreen() will have cleared it.
166 aSymbol->SetFlags( IS_MOVING );
168 };
169
170 auto setCursor =
171 [&]()
172 {
173 m_frame->GetCanvas()->SetCurrentCursor( symbol ? KICURSOR::MOVING
174 : KICURSOR::COMPONENT );
175 };
176
177 auto cleanup =
178 [&]()
179 {
182 delete symbol;
183 symbol = nullptr;
184
185 existingRefs.Clear();
186 hierarchy.GetSymbols( existingRefs );
187 existingRefs.SortByReferenceOnly();
188 };
189
190 auto annotate =
191 [&]()
192 {
194
195 // Then we need to annotate all instances by sheet
196 for( SCH_SHEET_PATH& instance : newInstances )
197 {
198 SCH_REFERENCE newReference( symbol, symbol->GetLibSymbolRef().get(), instance );
200 refs.AddItem( newReference );
201
202 if( cfg->m_AnnotatePanel.automatic || newReference.AlwaysAnnotate() )
203 {
207 existingRefs, false, &hierarchy );
208
209 refs.UpdateAnnotation();
210
211 // Update existing refs for next iteration
212 for( size_t i = 0; i < refs.GetCount(); i++ )
213 existingRefs.AddItem( refs[i] );
214 }
215 }
216
218 };
219
220 Activate();
221
222 // Must be done after Activate() so that it gets set into the correct context
223 getViewControls()->ShowCursor( true );
224
225 // Set initial cursor
226 setCursor();
227
228 // Prime the pump
229 if( symbol )
230 {
231 addSymbol( symbol );
232 annotate();
233 getViewControls()->WarpMouseCursor( getViewControls()->GetMousePosition( false ) );
234 }
235 else if( aEvent.HasPosition() )
236 {
237 m_toolMgr->PrimeTool( aEvent.Position() );
238 }
239 else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() )
240 {
241 m_toolMgr->PrimeTool( { 0, 0 } );
242 ignorePrimePosition = true;
243 }
244
245 // Main loop: keep receiving events
246 while( TOOL_EVENT* evt = Wait() )
247 {
248 setCursor();
249 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
250 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
251
252 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
253 controls->ForceCursorPosition( true, cursorPos );
254
255 // The tool hotkey is interpreted as a click when drawing
256 bool isSyntheticClick = symbol && evt->IsActivate() && evt->HasPosition()
257 && evt->Matches( aEvent );
258
259 if( evt->IsCancelInteractive() || ( symbol && evt->IsAction( &ACTIONS::undo ) ) )
260 {
262
263 if( symbol )
264 {
265 cleanup();
266 }
267 else
268 {
269 m_frame->PopTool( aEvent );
270 break;
271 }
272 }
273 else if( evt->IsActivate() && !isSyntheticClick )
274 {
275 if( symbol && evt->IsMoveTool() )
276 {
277 // we're already moving our own item; ignore the move tool
278 evt->SetPassEvent( false );
279 continue;
280 }
281
282 if( symbol )
283 {
284 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel symbol creation." ) );
285 evt->SetPassEvent( false );
286 continue;
287 }
288
289 if( evt->IsMoveTool() )
290 {
291 // leave ourselves on the stack so we come back after the move
292 break;
293 }
294 else
295 {
296 m_frame->PopTool( aEvent );
297 break;
298 }
299 }
300 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) || isSyntheticClick )
301 {
302 if( !symbol )
303 {
305
306 // Pick the symbol to be placed
307 bool footprintPreviews = m_frame->eeconfig()->m_Appearance.footprint_preview;
308 PICKED_SYMBOL sel = m_frame->PickSymbolFromLibTree( &filter, *historyList, true,
309 1, 1, footprintPreviews );
310
311 LIB_SYMBOL* libSymbol = sel.LibId.IsValid() ? m_frame->GetLibSymbol( sel.LibId )
312 : nullptr;
313
314 if( !libSymbol )
315 continue;
316
317 // If we started with a hotkey which has a position then warp back to that.
318 // Otherwise update to the current mouse position pinned inside the autoscroll
319 // boundaries.
320 if( evt->IsPrime() && !ignorePrimePosition )
321 {
322 cursorPos = grid.Align( evt->Position(), GRID_HELPER_GRIDS::GRID_CONNECTABLE );
323 getViewControls()->WarpMouseCursor( cursorPos, true );
324 }
325 else
326 {
328 cursorPos = grid.Align( getViewControls()->GetMousePosition(),
329 GRID_HELPER_GRIDS::GRID_CONNECTABLE );
330 }
331
332 symbol = new SCH_SYMBOL( *libSymbol, &m_frame->GetCurrentSheet(), sel, cursorPos,
333 &m_frame->Schematic() );
334 addSymbol( symbol );
335 annotate();
336
337 // Update the list of references for the next symbol placement.
338 SCH_REFERENCE placedSymbolReference( symbol, symbol->GetLibSymbolRef().get(),
340 existingRefs.AddItem( placedSymbolReference );
341 existingRefs.SortByReferenceOnly();
342
344 symbol->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
345
346 // Update cursor now that we have a symbol
347 setCursor();
348 }
349 else
350 {
352 m_frame->AddToScreen( symbol, screen );
353
355 symbol->AutoplaceFields( screen, false /* aManual */ );
356
358
359 SCH_COMMIT commit( m_toolMgr );
360 commit.Added( symbol, screen );
361
363 lwbTool->TrimOverLappingWires( &commit, &m_selectionTool->GetSelection() );
364 lwbTool->AddJunctionsIfNeeded( &commit, &m_selectionTool->GetSelection() );
365
366 commit.Push( _( "Add Symbol" ) );
367
368 SCH_SYMBOL* nextSymbol = nullptr;
369
372 {
373 int new_unit = symbol->GetUnit();
374
376 && symbol->GetUnit() < symbol->GetUnitCount() )
377 {
378 new_unit++;
379 }
380 else
381 {
382 new_unit = 1;
383 }
384
385 // We are either stepping to the next unit or next symbol
386 if( m_frame->eeconfig()->m_SymChooserPanel.keep_symbol || new_unit > 1 )
387 {
388 nextSymbol = static_cast<SCH_SYMBOL*>( symbol->Duplicate() );
389 nextSymbol->SetUnit( new_unit );
390 nextSymbol->SetUnitSelection( new_unit );
391
392 // Start new annotation sequence at first unit
393 if( new_unit == 1 )
394 nextSymbol->ClearAnnotation( nullptr, false );
395
396 addSymbol( nextSymbol );
397 symbol = nextSymbol;
398 annotate();
399
400 // Update the list of references for the next symbol placement.
401 SCH_REFERENCE placedSymbolReference( symbol,
402 symbol->GetLibSymbolRef().get(),
404 existingRefs.AddItem( placedSymbolReference );
405 existingRefs.SortByReferenceOnly();
406 }
407 }
408
409 symbol = nextSymbol;
410 }
411 }
412 else if( evt->IsClick( BUT_RIGHT ) )
413 {
414 // Warp after context menu only if dragging...
415 if( !symbol )
417
419 }
420 else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
421 {
422 if( *evt->GetCommandId() >= ID_POPUP_SCH_SELECT_UNIT
423 && *evt->GetCommandId() <= ID_POPUP_SCH_SELECT_UNIT_END )
424 {
425 int unit = *evt->GetCommandId() - ID_POPUP_SCH_SELECT_UNIT;
426
427 if( symbol )
428 {
429 m_frame->SelectUnit( symbol, unit );
431 }
432 }
433 }
434 else if( evt->IsAction( &ACTIONS::duplicate ) )
435 {
436 if( symbol )
437 {
438 // This doesn't really make sense; we'll just end up dragging a stack of
439 // objects so we ignore the duplicate and just carry on.
440 wxBell();
441 continue;
442 }
443
444 // Exit. The duplicate will run in its own loop.
445 m_frame->PopTool( aEvent );
446 break;
447 }
448 else if( symbol && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
449 {
450 symbol->SetPosition( cursorPos );
452 m_view->AddToPreview( symbol, false ); // Add, but not give ownership
453 m_frame->SetMsgPanel( symbol );
454 }
455 else if( symbol && evt->IsAction( &ACTIONS::doDelete ) )
456 {
457 cleanup();
458 }
459 else if( symbol && evt->IsAction( &ACTIONS::redo ) )
460 {
461 wxBell();
462 }
463 else
464 {
465 evt->SetPassEvent();
466 }
467
468 // Enable autopanning and cursor capture only when there is a symbol to be placed
469 getViewControls()->SetAutoPan( symbol != nullptr );
470 getViewControls()->CaptureCursor( symbol != nullptr );
471 }
472
473 getViewControls()->SetAutoPan( false );
474 getViewControls()->CaptureCursor( false );
475 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
476
477 return 0;
478}
479
480
482{
483 SCH_BITMAP* image = aEvent.Parameter<SCH_BITMAP*>();
484 bool immediateMode = image != nullptr;
485 bool ignorePrimePosition = false;
486 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
487
488 if( m_inPlaceImage )
489 return 0;
490
492
495 VECTOR2I cursorPos;
496
498
499 // Add all the drawable symbols to preview
500 if( image )
501 {
502 image->SetPosition( getViewControls()->GetCursorPosition() );
504 m_view->AddToPreview( image, false ); // Add, but not give ownership
505 }
506
507 m_frame->PushTool( aEvent );
508
509 auto setCursor =
510 [&]()
511 {
512 if( image )
513 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::MOVING );
514 else
515 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
516 };
517
518 auto cleanup =
519 [&] ()
520 {
524 delete image;
525 image = nullptr;
526 };
527
528 Activate();
529
530 // Must be done after Activate() so that it gets set into the correct context
531 getViewControls()->ShowCursor( true );
532
533 // Set initial cursor
534 setCursor();
535
536 // Prime the pump
537 if( image )
538 {
540 }
541 else if( aEvent.HasPosition() )
542 {
543 m_toolMgr->PrimeTool( aEvent.Position() );
544 }
545 else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() )
546 {
547 m_toolMgr->PrimeTool( { 0, 0 } );
548 ignorePrimePosition = true;
549 }
550
551 // Main loop: keep receiving events
552 while( TOOL_EVENT* evt = Wait() )
553 {
554 setCursor();
555 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
556 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
557
558 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
559 controls->ForceCursorPosition( true, cursorPos );
560
561 // The tool hotkey is interpreted as a click when drawing
562 bool isSyntheticClick = image && evt->IsActivate() && evt->HasPosition()
563 && evt->Matches( aEvent );
564
565 if( evt->IsCancelInteractive() || ( image && evt->IsAction( &ACTIONS::undo ) ) )
566 {
568
569 if( image )
570 {
571 cleanup();
572 }
573 else
574 {
575 m_frame->PopTool( aEvent );
576 break;
577 }
578
579 if( immediateMode )
580 {
581 m_frame->PopTool( aEvent );
582 break;
583 }
584 }
585 else if( evt->IsActivate() && !isSyntheticClick )
586 {
587 if( image && evt->IsMoveTool() )
588 {
589 // we're already moving our own item; ignore the move tool
590 evt->SetPassEvent( false );
591 continue;
592 }
593
594 if( image )
595 {
596 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel image creation." ) );
597 evt->SetPassEvent( false );
598 continue;
599 }
600
601 if( evt->IsMoveTool() )
602 {
603 // leave ourselves on the stack so we come back after the move
604 break;
605 }
606 else
607 {
608 m_frame->PopTool( aEvent );
609 break;
610 }
611 }
612 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) || isSyntheticClick )
613 {
614 if( !image )
615 {
617
618 wxFileDialog dlg( m_frame, _( "Choose Image" ), m_mruPath, wxEmptyString,
619 _( "Image Files" ) + wxS( " " ) + wxImage::GetImageExtWildcard(),
620 wxFD_OPEN );
621
622 if( dlg.ShowModal() != wxID_OK )
623 continue;
624
625 // If we started with a hotkey which has a position then warp back to that.
626 // Otherwise update to the current mouse position pinned inside the autoscroll
627 // boundaries.
628 if( evt->IsPrime() && !ignorePrimePosition )
629 {
630 cursorPos = grid.Align( evt->Position() );
631 getViewControls()->WarpMouseCursor( cursorPos, true );
632 }
633 else
634 {
636 cursorPos = getViewControls()->GetMousePosition();
637 }
638
639 wxString fullFilename = dlg.GetPath();
640 m_mruPath = wxPathOnly( fullFilename );
641
642 if( wxFileExists( fullFilename ) )
643 image = new SCH_BITMAP( cursorPos );
644
645 if( !image || !image->ReadImageFile( fullFilename ) )
646 {
647 wxMessageBox( _( "Could not load image from '%s'." ), fullFilename );
648 delete image;
649 image = nullptr;
650 continue;
651 }
652
653 image->SetFlags( IS_NEW | IS_MOVING );
654
656
658 m_view->AddToPreview( image, false ); // Add, but not give ownership
659 m_view->RecacheAllItems(); // Bitmaps are cached in Opengl
660
662
663 getViewControls()->SetCursorPosition( cursorPos, false );
664 setCursor();
665 }
666 else
667 {
668 SCH_COMMIT commit( m_toolMgr );
669 commit.Add( image, m_frame->GetScreen() );
670 commit.Push( _( "Add Image" ) );
671
672 image = nullptr;
674
676
677 if( immediateMode )
678 {
679 m_frame->PopTool( aEvent );
680 break;
681 }
682 }
683 }
684 else if( evt->IsClick( BUT_RIGHT ) )
685 {
686 // Warp after context menu only if dragging...
687 if( !image )
689
691 }
692 else if( image && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
693 {
694 image->SetPosition( cursorPos );
696 m_view->AddToPreview( image, false ); // Add, but not give ownership
697 m_view->RecacheAllItems(); // Bitmaps are cached in Opengl
699 }
700 else if( image && evt->IsAction( &ACTIONS::doDelete ) )
701 {
702 cleanup();
703 }
704 else if( image && evt->IsAction( &ACTIONS::redo ) )
705 {
706 wxBell();
707 }
708 else
709 {
710 evt->SetPassEvent();
711 }
712
713 // Enable autopanning and cursor capture only when there is an image to be placed
714 getViewControls()->SetAutoPan( image != nullptr );
715 getViewControls()->CaptureCursor( image != nullptr );
716 }
717
718 getViewControls()->SetAutoPan( false );
719 getViewControls()->CaptureCursor( false );
720 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
721
722 return 0;
723}
724
725
727{
728 VECTOR2I cursorPos;
729 KICAD_T type = aEvent.Parameter<KICAD_T>();
732 SCH_ITEM* previewItem;
733 bool loggedInfoBarError = false;
734 wxString description;
735 SCH_SCREEN* screen = m_frame->GetScreen();
736 bool allowRepeat = false; // Set to true to allow new item repetition
737
739 return 0;
740
742
743 if( type == SCH_JUNCTION_T && aEvent.HasPosition() )
744 {
746 SCH_LINE* wire = dynamic_cast<SCH_LINE*>( selection.Front() );
747
748 if( wire )
749 {
750 SEG seg( wire->GetStartPoint(), wire->GetEndPoint() );
751 VECTOR2I nearest = seg.NearestPoint( getViewControls()->GetCursorPosition() );
752 getViewControls()->SetCrossHairCursorPosition( nearest, false );
753 getViewControls()->WarpMouseCursor( getViewControls()->GetCursorPosition(), true );
754 }
755 }
756
757 switch( type )
758 {
759 case SCH_NO_CONNECT_T:
760 previewItem = new SCH_NO_CONNECT( cursorPos );
761 previewItem->SetParent( screen );
762 description = _( "Add No Connect Flag" );
763 allowRepeat = true;
764 break;
765
766 case SCH_JUNCTION_T:
767 previewItem = new SCH_JUNCTION( cursorPos );
768 previewItem->SetParent( screen );
769 description = _( "Add Junction" );
770 break;
771
773 previewItem = new SCH_BUS_WIRE_ENTRY( cursorPos );
774 previewItem->SetParent( screen );
775 description = _( "Add Wire to Bus Entry" );
776 allowRepeat = true;
777 break;
778
779 default:
780 wxASSERT_MSG( false, "Unknown item type in SCH_DRAWING_TOOLS::SingleClickPlace" );
781 return 0;
782 }
783
785
786 cursorPos = aEvent.HasPosition() ? aEvent.Position() : controls->GetMousePosition();
787
788 m_frame->PushTool( aEvent );
789
790 auto setCursor =
791 [&]()
792 {
793 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PLACE );
794 };
795
796 Activate();
797
798 // Must be done after Activate() so that it gets set into the correct context
799 getViewControls()->ShowCursor( true );
800
801 // Set initial cursor
802 setCursor();
803
805 m_view->AddToPreview( previewItem->Clone() );
806
807 // Prime the pump
808 if( aEvent.HasPosition() && type != SCH_SHEET_PIN_T )
809 m_toolMgr->PrimeTool( aEvent.Position() );
810 else
812
813 // Main loop: keep receiving events
814 while( TOOL_EVENT* evt = Wait() )
815 {
816 setCursor();
817 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
818 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
819
820 cursorPos = evt->IsPrime() ? evt->Position() : controls->GetMousePosition();
821 cursorPos = grid.BestSnapAnchor( cursorPos, grid.GetItemGrid( previewItem ), nullptr );
822 controls->ForceCursorPosition( true, cursorPos );
823
824 if( evt->IsCancelInteractive() )
825 {
826 m_frame->PopTool( aEvent );
827 break;
828 }
829 else if( evt->IsActivate() )
830 {
831 if( evt->IsMoveTool() )
832 {
833 // leave ourselves on the stack so we come back after the move
834 break;
835 }
836 else
837 {
838 m_frame->PopTool( aEvent );
839 break;
840 }
841 }
842 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
843 {
844 if( !screen->GetItem( cursorPos, 0, type ) )
845 {
846 if( type == SCH_JUNCTION_T )
847 {
848 if( !screen->IsExplicitJunctionAllowed( cursorPos ) )
849 {
850 m_frame->ShowInfoBarError( _( "Junction location contains no joinable "
851 "wires and/or pins." ) );
852 loggedInfoBarError = true;
853 continue;
854 }
855 else if( loggedInfoBarError )
856 {
858 }
859 }
860
861 SCH_ITEM* newItem = static_cast<SCH_ITEM*>( previewItem->Clone() );
862 const_cast<KIID&>( newItem->m_Uuid ) = KIID();
863 newItem->SetPosition( cursorPos );
864 newItem->SetFlags( IS_NEW );
865 m_frame->AddToScreen( newItem, screen );
866
867 if( allowRepeat )
868 m_frame->SaveCopyForRepeatItem( newItem );
869
870 SCH_COMMIT commit( m_toolMgr );
871 commit.Added( newItem, screen );
872
873 m_frame->SchematicCleanUp( &commit );
874
875 commit.Push( description );
876 }
877
878 if( evt->IsDblClick( BUT_LEFT ) || type == SCH_SHEET_PIN_T ) // Finish tool.
879 {
880 m_frame->PopTool( aEvent );
881 break;
882 }
883 }
884 else if( evt->IsClick( BUT_RIGHT ) )
885 {
887 }
888 else if( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() )
889 {
890 previewItem->SetPosition( cursorPos );
892 m_view->AddToPreview( previewItem->Clone() );
893 m_frame->SetMsgPanel( previewItem );
894 }
895 else if( evt->Category() == TC_COMMAND )
896 {
897 if( ( type == SCH_BUS_WIRE_ENTRY_T ) && ( evt->IsAction( &EE_ACTIONS::rotateCW )
898 || evt->IsAction( &EE_ACTIONS::rotateCCW )
899 || evt->IsAction( &EE_ACTIONS::mirrorV )
900 || evt->IsAction( &EE_ACTIONS::mirrorH ) ) )
901 {
902 SCH_BUS_ENTRY_BASE* busItem = static_cast<SCH_BUS_ENTRY_BASE*>( previewItem );
903
904 // The bus entries only rotate in one direction
905 if( evt->IsAction( &EE_ACTIONS::rotateCW )
906 || evt->IsAction( &EE_ACTIONS::rotateCCW ) )
907 {
908 busItem->Rotate( busItem->GetPosition() );
909 }
910 else if( evt->IsAction( &EE_ACTIONS::mirrorV ) )
911 {
912 busItem->MirrorVertically( busItem->GetPosition().y );
913 }
914 else if( evt->IsAction( &EE_ACTIONS::mirrorH ) )
915 {
916 busItem->MirrorHorizontally( busItem->GetPosition().x );
917 }
918
920 m_view->AddToPreview( previewItem->Clone() );
921 }
922 else if( evt->IsAction( &EE_ACTIONS::properties ) )
923 {
924 switch( type )
925 {
927 {
928 std::deque<SCH_ITEM*> strokeItems;
929 strokeItems.push_back( previewItem );
930
931 DIALOG_WIRE_BUS_PROPERTIES dlg( m_frame, strokeItems );
932 }
933 break;
934
935 case SCH_JUNCTION_T:
936 {
937 std::deque<SCH_JUNCTION*> junctions;
938 junctions.push_back( static_cast<SCH_JUNCTION*>( previewItem ) );
939
940 DIALOG_JUNCTION_PROPS dlg( m_frame, junctions );
941 }
942 break;
943 default:
944 // Do nothing
945 break;
946 }
947
949 m_view->AddToPreview( previewItem->Clone() );
950 }
951 else
952 {
953 evt->SetPassEvent();
954 }
955 }
956 else
957 {
958 evt->SetPassEvent();
959 }
960 }
961
962 delete previewItem;
964
965 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
966 controls->ForceCursorPosition( false );
967
968 return 0;
969}
970
971
973{
974 for( SCH_ITEM* item : m_frame->GetScreen()->Items().Overlapping( SCH_LINE_T, aPosition ) )
975 {
976 SCH_LINE* line = static_cast<SCH_LINE*>( item );
977
978 if( line->GetEditFlags() & STRUCT_DELETED )
979 continue;
980
981 if( line->IsWire() )
982 return line;
983 }
984
985 return nullptr;
986}
987
988
990{
991 SCHEMATIC* schematic = getModel<SCHEMATIC>();
992 SCHEMATIC_SETTINGS& settings = schematic->Settings();
993 SCH_TEXT* textItem = nullptr;
994 SCH_LABEL_BASE* labelItem = nullptr;
995 wxString netName;
996
997 switch( aType )
998 {
999 case LAYER_NOTES:
1000 textItem = new SCH_TEXT( aPosition );
1001 break;
1002
1003 case LAYER_LOCLABEL:
1004 labelItem = new SCH_LABEL( aPosition );
1005 textItem = labelItem;
1006
1007 if( SCH_LINE* wire = findWire( aPosition ) )
1008 netName = wire->GetNetname( m_frame->GetCurrentSheet() );
1009
1010 break;
1011
1013 labelItem = new SCH_DIRECTIVE_LABEL( aPosition );
1014 labelItem->SetShape( m_lastNetClassFlagShape );
1015 labelItem->GetFields().emplace_back( SCH_FIELD( {0,0}, 0, labelItem, wxT( "Netclass" ) ) );
1016 labelItem->GetFields().back().SetItalic( true );
1017 labelItem->GetFields().back().SetVisible( true );
1018 textItem = labelItem;
1019 break;
1020
1021 case LAYER_HIERLABEL:
1022 labelItem = new SCH_HIERLABEL( aPosition );
1023 labelItem->SetShape( m_lastGlobalLabelShape );
1025 textItem = labelItem;
1026 break;
1027
1028 case LAYER_GLOBLABEL:
1029 labelItem = new SCH_GLOBALLABEL( aPosition );
1030 labelItem->SetShape( m_lastGlobalLabelShape );
1031 labelItem->GetFields()[0].SetVisible( settings.m_IntersheetRefsShow );
1033 textItem = labelItem;
1034
1035 if( SCH_LINE* wire = findWire( aPosition ) )
1036 netName = wire->GetNetname( m_frame->GetCurrentSheet() );
1037
1038 break;
1039
1040 default:
1041 wxFAIL_MSG( "SCH_EDIT_FRAME::CreateNewText() unknown layer type" );
1042 return nullptr;
1043 }
1044
1045 textItem->SetParent( schematic );
1046
1047 if( aType != LAYER_NETCLASS_REFS )
1048 {
1049 textItem->SetBold( m_lastTextBold );
1050 textItem->SetItalic( m_lastTextItalic );
1051 }
1052
1053 if( labelItem )
1054 labelItem->SetSpinStyle( m_lastTextOrientation );
1055
1056 textItem->SetTextSize( VECTOR2I( settings.m_DefaultTextSize, settings.m_DefaultTextSize ) );
1057 textItem->SetFlags( IS_NEW | IS_MOVING );
1058
1059 if( !labelItem )
1060 {
1061 DIALOG_TEXT_PROPERTIES dlg( m_frame, textItem );
1062
1063 // QuasiModal required for syntax help and Scintilla auto-complete
1064 if( dlg.ShowQuasiModal() != wxID_OK )
1065 {
1066 delete textItem;
1067 return nullptr;
1068 }
1069 }
1070 else if( !netName.IsEmpty() )
1071 {
1072 // Auto-create from attached wire
1073 textItem->SetText( netName );
1074 }
1075 else
1076 {
1077 DIALOG_LABEL_PROPERTIES dlg( m_frame, static_cast<SCH_LABEL_BASE*>( textItem ) );
1078
1079 // Must be quasi modal for syntax help
1080 if( dlg.ShowQuasiModal() != wxID_OK )
1081 {
1082 delete labelItem;
1083 return nullptr;
1084 }
1085 }
1086
1087 wxString text = textItem->GetText();
1088
1089 if( textItem->Type() != SCH_DIRECTIVE_LABEL_T && NoPrintableChars( text ) )
1090 {
1091 delete textItem;
1092 return nullptr;
1093 }
1094
1095 if( aType != LAYER_NETCLASS_REFS )
1096 {
1097 m_lastTextBold = textItem->IsBold();
1098 m_lastTextItalic = textItem->IsItalic();
1099 }
1100
1101 if( labelItem )
1102 m_lastTextOrientation = labelItem->GetSpinStyle();
1103
1104 if( aType == LAYER_GLOBLABEL || aType == LAYER_HIERLABEL )
1105 {
1106 m_lastGlobalLabelShape = labelItem->GetShape();
1108 }
1109 else if( aType == LAYER_NETCLASS_REFS )
1110 {
1111 m_lastNetClassFlagShape = labelItem->GetShape();
1112 }
1113
1114 return textItem;
1115}
1116
1117
1119{
1120 if( !aSheet->GetScreen() )
1121 return nullptr;
1122
1123 for( EDA_ITEM* item : aSheet->GetScreen()->Items().OfType( SCH_HIER_LABEL_T ) )
1124 {
1125 SCH_HIERLABEL* label = static_cast<SCH_HIERLABEL*>( item );
1126
1127 /* A global label has been found: check if there a corresponding sheet label. */
1128 if( !aSheet->HasPin( label->GetText() ) )
1129 return label;
1130 }
1131
1132 return nullptr;
1133}
1134
1135
1137 const VECTOR2I& aPosition )
1138{
1139 SCHEMATIC_SETTINGS& settings = aSheet->Schematic()->Settings();
1140 SCH_SHEET_PIN* pin = new SCH_SHEET_PIN( aSheet );
1141
1142 pin->SetFlags( IS_NEW | IS_MOVING );
1143 pin->SetText( aLabel->GetText() );
1144 pin->SetTextSize( VECTOR2I( settings.m_DefaultTextSize, settings.m_DefaultTextSize ) );
1145 pin->SetShape( aLabel->GetShape() );
1146 pin->SetPosition( aPosition );
1147 pin->ClearSelected();
1148
1149 m_lastSheetPinType = pin->GetShape();
1150
1151 return pin;
1152}
1153
1154
1156{
1157 SCH_ITEM* item = nullptr;
1160 bool ignorePrimePosition = false;
1161 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
1162 SCH_SHEET* sheet = nullptr;
1163 wxString description;
1164
1165 if( m_inTwoClickPlace )
1166 return 0;
1167
1169
1170 bool isText = aEvent.IsAction( &EE_ACTIONS::placeSchematicText );
1171 bool isGlobalLabel = aEvent.IsAction( &EE_ACTIONS::placeGlobalLabel );
1172 bool isHierLabel = aEvent.IsAction( &EE_ACTIONS::placeHierLabel );
1173 bool isClassLabel = aEvent.IsAction( &EE_ACTIONS::placeClassLabel );
1174 bool isNetLabel = aEvent.IsAction( &EE_ACTIONS::placeLabel );
1175 bool isSheetPin = aEvent.IsAction( &EE_ACTIONS::importSheetPin );
1176
1177 GRID_HELPER_GRIDS snapGrid = isText ? GRID_TEXT : GRID_CONNECTABLE;
1178
1179 // If we have a selected sheet use it, otherwise try to get one under the cursor
1180 if( isSheetPin )
1181 sheet = dynamic_cast<SCH_SHEET*>( m_selectionTool->GetSelection().Front() );
1182
1184
1185 m_frame->PushTool( aEvent );
1186
1187 auto setCursor =
1188 [&]()
1189 {
1190 if( item )
1191 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PLACE );
1192 else if( isText )
1193 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::TEXT );
1194 else if( isGlobalLabel )
1195 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_GLOBAL );
1196 else if( isNetLabel )
1197 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_NET );
1198 else if( isClassLabel )
1199 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_NET ); // JEY TODO: netclass directive cursor
1200 else if( isHierLabel )
1201 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_HIER );
1202 else
1203 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
1204 };
1205
1206 auto updatePreview =
1207 [&]()
1208 {
1210 m_view->AddToPreview( item->Clone() );
1211 item->RunOnChildren( [&]( SCH_ITEM* aChild )
1212 {
1213 m_view->AddToPreview( aChild->Clone() );
1214 } );
1215 m_frame->SetMsgPanel( item );
1216 };
1217
1218 auto cleanup =
1219 [&]()
1220 {
1223 delete item;
1224 item = nullptr;
1225 };
1226
1227 Activate();
1228
1229 // Must be done after Activate() so that it gets set into the correct context
1230 controls->ShowCursor( true );
1231
1232 // Set initial cursor
1233 setCursor();
1234
1235 if( aEvent.HasPosition() )
1236 {
1237 m_toolMgr->PrimeTool( aEvent.Position() );
1238 }
1239 else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate()
1240 && ( isText || isGlobalLabel || isHierLabel || isClassLabel || isNetLabel ) )
1241 {
1242 m_toolMgr->PrimeTool( { 0, 0 } );
1243 ignorePrimePosition = true;
1244 }
1245
1246 // Main loop: keep receiving events
1247 while( TOOL_EVENT* evt = Wait() )
1248 {
1249 setCursor();
1250 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1251 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1252
1253 VECTOR2I cursorPos = controls->GetMousePosition();
1254 cursorPos = grid.BestSnapAnchor( cursorPos, snapGrid, item );
1255 controls->ForceCursorPosition( true, cursorPos );
1256
1257 // The tool hotkey is interpreted as a click when drawing
1258 bool isSyntheticClick = item && evt->IsActivate() && evt->HasPosition()
1259 && evt->Matches( aEvent );
1260
1261 if( evt->IsCancelInteractive() || evt->IsAction( &ACTIONS::undo ) )
1262 {
1264
1265 if( item )
1266 {
1267 cleanup();
1268 }
1269 else
1270 {
1271 m_frame->PopTool( aEvent );
1272 break;
1273 }
1274 }
1275 else if( evt->IsActivate() && !isSyntheticClick )
1276 {
1277 if( item && evt->IsMoveTool() )
1278 {
1279 // we're already moving our own item; ignore the move tool
1280 evt->SetPassEvent( false );
1281 continue;
1282 }
1283
1284 if( item )
1285 {
1286 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel item creation." ) );
1287 evt->SetPassEvent( false );
1288 continue;
1289 }
1290
1291 if( evt->IsPointEditor() )
1292 {
1293 // don't exit (the point editor runs in the background)
1294 }
1295 else if( evt->IsMoveTool() )
1296 {
1297 // leave ourselves on the stack so we come back after the move
1298 break;
1299 }
1300 else
1301 {
1302 m_frame->PopTool( aEvent );
1303 break;
1304 }
1305 }
1306 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) || isSyntheticClick )
1307 {
1308 // First click creates...
1309 if( !item )
1310 {
1312
1313 if( isText )
1314 {
1315 item = createNewText( cursorPos, LAYER_NOTES );
1316 description = _( "Add Text" );
1317 }
1318 else if( isHierLabel )
1319 {
1320 item = createNewText( cursorPos, LAYER_HIERLABEL );
1321 description = _( "Add Hierarchical Label" );
1322 }
1323 else if( isNetLabel )
1324 {
1325 item = createNewText( cursorPos, LAYER_LOCLABEL );
1326 description = _( "Add Label" );
1327 }
1328 else if( isGlobalLabel )
1329 {
1330 item = createNewText( cursorPos, LAYER_GLOBLABEL );
1331 description = _( "Add Label" );
1332 }
1333 else if( isClassLabel )
1334 {
1335 item = createNewText( cursorPos, LAYER_NETCLASS_REFS );
1336 description = _( "Add Label" );
1337 }
1338 else if( isSheetPin )
1339 {
1340 EDA_ITEM* i = nullptr;
1341
1342 // If we didn't have a sheet selected, try to find one under the cursor
1343 if( !sheet && m_selectionTool->SelectPoint( cursorPos, { SCH_SHEET_T }, &i ) )
1344 sheet = dynamic_cast<SCH_SHEET*>( i );
1345
1346 if( !sheet )
1347 {
1348 m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( m_frame );
1349 m_statusPopup->SetText( _( "Click over a sheet." ) );
1351 + wxPoint( 20, 20 ) );
1352 m_statusPopup->PopupFor( 2000 );
1353 item = nullptr;
1354 }
1355 else
1356 {
1357 SCH_HIERLABEL* label = importHierLabel( sheet );
1358
1359 if( !label )
1360 {
1361 m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( m_frame );
1362 m_statusPopup->SetText( _( "No new hierarchical labels found." ) );
1364 + wxPoint( 20, 20 ) );
1365 m_statusPopup->PopupFor( 2000 );
1366 item = nullptr;
1367
1368 m_frame->PopTool( aEvent );
1369 break;
1370 }
1371
1372 item = createNewSheetPin( sheet, label, cursorPos );
1373 }
1374
1375 description = _( "Add Sheet Pin" );
1376 }
1377
1378 // If we started with a hotkey which has a position then warp back to that.
1379 // Otherwise update to the current mouse position pinned inside the autoscroll
1380 // boundaries.
1381 if( evt->IsPrime() && !ignorePrimePosition )
1382 {
1383 cursorPos = grid.Align( evt->Position() );
1384 getViewControls()->WarpMouseCursor( cursorPos, true );
1385 }
1386 else
1387 {
1389 cursorPos = getViewControls()->GetMousePosition();
1390 cursorPos = grid.BestSnapAnchor( cursorPos, snapGrid, item );
1391 }
1392
1393 if( item )
1394 {
1395 item->SetPosition( cursorPos );
1396
1397 item->SetFlags( IS_NEW | IS_MOVING );
1398 item->AutoplaceFields( nullptr, false /* aManual */ );
1399 updatePreview();
1400
1401 if( item->Type() != SCH_SHEET_PIN_T )
1403
1405
1406 // update the cursor so it looks correct before another event
1407 setCursor();
1408 }
1409
1410 controls->SetCursorPosition( cursorPos, false );
1411 }
1412 else // ... and second click places:
1413 {
1414 SCH_COMMIT commit( m_toolMgr );
1415
1416 item->ClearFlags( IS_MOVING );
1417
1418 if( item->IsConnectable() )
1420
1421 if( isSheetPin )
1422 {
1423 // Sheet pins are owned by their parent sheet.
1424 commit.Modify( sheet, m_frame->GetScreen() );
1425 sheet->AddPin( (SCH_SHEET_PIN*) item );
1426 }
1427 else
1428 {
1430 m_frame->AddToScreen( item, m_frame->GetScreen() );
1431 commit.Added( item, m_frame->GetScreen() );
1432 }
1433
1434 item->AutoplaceFields( m_frame->GetScreen(), false /* aManual */ );
1435
1436 commit.Push( description );
1437
1438 item = nullptr;
1440
1441 if( isSheetPin )
1442 {
1443 SCH_HIERLABEL* label = importHierLabel( sheet );
1444
1445 if( !label )
1446 {
1447 m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( m_frame );
1448 m_statusPopup->SetText( _( "No new hierarchical labels found." ) );
1450 + wxPoint( 20, 20 ) );
1451 m_statusPopup->PopupFor( 2000 );
1452 item = nullptr;
1453
1454 m_frame->PopTool( aEvent );
1455 break;
1456 }
1457
1458 item = createNewSheetPin( sheet, label, cursorPos );
1459 }
1460 }
1461 }
1462 else if( evt->IsClick( BUT_RIGHT ) )
1463 {
1464 // Warp after context menu only if dragging...
1465 if( !item )
1467
1469 }
1470 else if( item && evt->IsSelectionEvent() )
1471 {
1472 // This happens if our text was replaced out from under us by ConvertTextType()
1474
1475 if( selection.GetSize() == 1 )
1476 {
1477 item = (SCH_ITEM*) selection.Front();
1478 updatePreview();
1479 }
1480 else
1481 {
1482 item = nullptr;
1483 }
1484 }
1485 else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
1486 {
1487 item->SetPosition( cursorPos );
1488 item->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
1489 updatePreview();
1490 }
1491 else if( item && evt->IsAction( &ACTIONS::doDelete ) )
1492 {
1493 cleanup();
1494 }
1495 else if( evt->IsAction( &ACTIONS::redo ) )
1496 {
1497 wxBell();
1498 }
1499 else
1500 {
1501 evt->SetPassEvent();
1502 }
1503
1504 // Enable autopanning and cursor capture only when there is an item to be placed
1505 controls->SetAutoPan( item != nullptr );
1506 controls->CaptureCursor( item != nullptr );
1507 }
1508
1509 controls->SetAutoPan( false );
1510 controls->CaptureCursor( false );
1511 controls->ForceCursorPosition( false );
1512 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1513 return 0;
1514}
1515
1516
1518{
1519 SCHEMATIC* schematic = getModel<SCHEMATIC>();
1520 SCHEMATIC_SETTINGS& sch_settings = schematic->Settings();
1521 SCH_SHAPE* item = nullptr;
1522 bool isTextBox = aEvent.IsAction( &EE_ACTIONS::drawTextBox );
1523 SHAPE_T type = aEvent.Parameter<SHAPE_T>();
1524 wxString description;
1525
1526 if( m_inDrawShape )
1527 return 0;
1528
1530
1533 VECTOR2I cursorPos;
1534
1535 // We might be running as the same shape in another co-routine. Make sure that one
1536 // gets whacked.
1538
1540
1541 m_frame->PushTool( aEvent );
1542
1543 auto setCursor =
1544 [&]()
1545 {
1546 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
1547 };
1548
1549 auto cleanup =
1550 [&] ()
1551 {
1554 delete item;
1555 item = nullptr;
1556 };
1557
1558 Activate();
1559
1560 // Must be done after Activate() so that it gets set into the correct context
1561 getViewControls()->ShowCursor( true );
1562
1563 // Set initial cursor
1564 setCursor();
1565
1566 if( aEvent.HasPosition() )
1567 m_toolMgr->PrimeTool( aEvent.Position() );
1568
1569 // Main loop: keep receiving events
1570 while( TOOL_EVENT* evt = Wait() )
1571 {
1572 setCursor();
1573 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1574 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1575
1576 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
1577 controls->ForceCursorPosition( true, cursorPos );
1578
1579 // The tool hotkey is interpreted as a click when drawing
1580 bool isSyntheticClick = item && evt->IsActivate() && evt->HasPosition()
1581 && evt->Matches( aEvent );
1582
1583 if( evt->IsCancelInteractive() || ( item && evt->IsAction( &ACTIONS::undo ) ) )
1584 {
1585 if( item )
1586 {
1587 cleanup();
1588 }
1589 else
1590 {
1591 m_frame->PopTool( aEvent );
1592 break;
1593 }
1594 }
1595 else if( evt->IsActivate() && !isSyntheticClick )
1596 {
1597 if( item && evt->IsMoveTool() )
1598 {
1599 // we're already drawing our own item; ignore the move tool
1600 evt->SetPassEvent( false );
1601 continue;
1602 }
1603
1604 if( item )
1605 cleanup();
1606
1607 if( evt->IsPointEditor() )
1608 {
1609 // don't exit (the point editor runs in the background)
1610 }
1611 else if( evt->IsMoveTool() )
1612 {
1613 // leave ourselves on the stack so we come back after the move
1614 break;
1615 }
1616 else
1617 {
1618 m_frame->PopTool( aEvent );
1619 break;
1620 }
1621 }
1622 else if( evt->IsClick( BUT_LEFT ) && !item )
1623 {
1625
1626 if( isTextBox )
1627 {
1628 SCH_TEXTBOX* textbox = new SCH_TEXTBOX( 0, m_lastTextboxFillStyle );
1629
1630 textbox->SetBold( m_lastTextBold );
1631 textbox->SetItalic( m_lastTextItalic );
1632 textbox->SetTextSize( VECTOR2I( sch_settings.m_DefaultTextSize,
1633 sch_settings.m_DefaultTextSize ) );
1634 textbox->SetTextAngle( m_lastTextAngle );
1635 textbox->SetHorizJustify( m_lastTextJust );
1636 textbox->SetStroke( m_lastTextboxStroke );
1638 textbox->SetParent( schematic );
1639
1640 item = textbox;
1641 description = _( "Add Text Box" );
1642 }
1643 else
1644 {
1645 item = new SCH_SHAPE( type, 0, m_lastFillStyle );
1646
1647 item->SetStroke( m_lastStroke );
1649 item->SetParent( schematic );
1650 description = wxString::Format( _( "Add %s" ), item->EDA_SHAPE::GetFriendlyName() );
1651 }
1652
1653 item->SetFlags( IS_NEW );
1654 item->BeginEdit( cursorPos );
1655
1657 m_view->AddToPreview( item->Clone() );
1658 }
1659 else if( item && ( evt->IsClick( BUT_LEFT )
1660 || evt->IsDblClick( BUT_LEFT )
1661 || isSyntheticClick
1662 || evt->IsAction( &EE_ACTIONS::finishDrawing ) ) )
1663 {
1664 if( evt->IsDblClick( BUT_LEFT )
1665 || evt->IsAction( &EE_ACTIONS::finishDrawing )
1666 || !item->ContinueEdit( cursorPos ) )
1667 {
1668 item->EndEdit();
1669 item->ClearEditFlags();
1670 item->SetFlags( IS_NEW );
1671
1672 if( isTextBox )
1673 {
1674 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( item );
1675 DIALOG_TEXT_PROPERTIES dlg( m_frame, textbox );
1676
1677 getViewControls()->SetAutoPan( false );
1678 getViewControls()->CaptureCursor( false );
1679
1680 // QuasiModal required for syntax help and Scintilla auto-complete
1681 if( dlg.ShowQuasiModal() != wxID_OK )
1682 {
1683 cleanup();
1684 continue;
1685 }
1686
1687 m_lastTextBold = textbox->IsBold();
1688 m_lastTextItalic = textbox->IsItalic();
1689 m_lastTextAngle = textbox->GetTextAngle();
1690 m_lastTextJust = textbox->GetHorizJustify();
1691 m_lastTextboxStroke = textbox->GetStroke();
1694 }
1695 else
1696 {
1697 m_lastStroke = item->GetStroke();
1698 m_lastFillStyle = item->GetFillMode();
1699 m_lastFillColor = item->GetFillColor();
1700 }
1701
1702 SCH_COMMIT commit( m_toolMgr );
1703 commit.Add( item, m_frame->GetScreen() );
1704 commit.Push( wxString::Format( _( "Draw %s" ), item->GetClass() ) );
1705
1707 item = nullptr;
1708
1711 }
1712 }
1713 else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
1714 {
1715 item->CalcEdit( cursorPos );
1717 m_view->AddToPreview( item->Clone() );
1718 m_frame->SetMsgPanel( item );
1719 }
1720 else if( evt->IsDblClick( BUT_LEFT ) && !item )
1721 {
1723 }
1724 else if( evt->IsClick( BUT_RIGHT ) )
1725 {
1726 // Warp after context menu only if dragging...
1727 if( !item )
1729
1731 }
1732 else if( item && evt->IsAction( &ACTIONS::redo ) )
1733 {
1734 wxBell();
1735 }
1736 else
1737 {
1738 evt->SetPassEvent();
1739 }
1740
1741 // Enable autopanning and cursor capture only when there is a shape being drawn
1742 getViewControls()->SetAutoPan( item != nullptr );
1743 getViewControls()->CaptureCursor( item != nullptr );
1744 }
1745
1746 getViewControls()->SetAutoPan( false );
1747 getViewControls()->CaptureCursor( false );
1748 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1749 return 0;
1750}
1751
1752
1754{
1755 SCH_SHEET* sheet = nullptr;
1756
1757 if( m_inDrawSheet )
1758 return 0;
1759
1761
1764 VECTOR2I cursorPos;
1765
1767
1768 m_frame->PushTool( aEvent );
1769
1770 auto setCursor =
1771 [&]()
1772 {
1773 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
1774 };
1775
1776 auto cleanup =
1777 [&] ()
1778 {
1781 delete sheet;
1782 sheet = nullptr;
1783 };
1784
1785 Activate();
1786
1787 // Must be done after Activate() so that it gets set into the correct context
1788 getViewControls()->ShowCursor( true );
1789
1790 // Set initial cursor
1791 setCursor();
1792
1793 if( aEvent.HasPosition() )
1794 m_toolMgr->PrimeTool( aEvent.Position() );
1795
1796 // Main loop: keep receiving events
1797 while( TOOL_EVENT* evt = Wait() )
1798 {
1799 setCursor();
1800 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1801 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1802
1803 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
1804 controls->ForceCursorPosition( true, cursorPos );
1805
1806 // The tool hotkey is interpreted as a click when drawing
1807 bool isSyntheticClick = sheet && evt->IsActivate() && evt->HasPosition()
1808 && evt->Matches( aEvent );
1809
1810 if( evt->IsCancelInteractive() || ( sheet && evt->IsAction( &ACTIONS::undo ) ) )
1811 {
1813
1814 if( sheet )
1815 {
1816 cleanup();
1817 }
1818 else
1819 {
1820 m_frame->PopTool( aEvent );
1821 break;
1822 }
1823 }
1824 else if( evt->IsActivate() && !isSyntheticClick )
1825 {
1826 if( sheet && evt->IsMoveTool() )
1827 {
1828 // we're already drawing our own item; ignore the move tool
1829 evt->SetPassEvent( false );
1830 continue;
1831 }
1832
1833 if( sheet )
1834 {
1835 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel sheet creation." ) );
1836 evt->SetPassEvent( false );
1837 continue;
1838 }
1839
1840 if( evt->IsPointEditor() )
1841 {
1842 // don't exit (the point editor runs in the background)
1843 }
1844 else if( evt->IsMoveTool() )
1845 {
1846 // leave ourselves on the stack so we come back after the move
1847 break;
1848 }
1849 else
1850 {
1851 m_frame->PopTool( aEvent );
1852 break;
1853 }
1854 }
1855 else if( !sheet && ( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) ) )
1856 {
1859
1860 if( selection.Size() == 1
1861 && selection.Front()->Type() == SCH_SHEET_T
1862 && selection.Front()->GetBoundingBox().Contains( cursorPos ) )
1863 {
1864 if( evt->IsClick( BUT_LEFT ) )
1865 {
1866 // sheet already selected
1867 continue;
1868 }
1869 else if( evt->IsDblClick( BUT_LEFT ) )
1870 {
1872 break;
1873 }
1874 }
1875
1877
1878 sheet = new SCH_SHEET( m_frame->GetCurrentSheet().Last(), cursorPos );
1879 sheet->SetFlags( IS_NEW | IS_MOVING );
1880 sheet->SetScreen( nullptr );
1884 sheet->GetFields()[ SHEETNAME ].SetText( "Untitled Sheet" );
1885 sheet->GetFields()[ SHEETFILENAME ].SetText( "untitled." + KiCadSchematicFileExtension );
1886 sizeSheet( sheet, cursorPos );
1887
1889 m_view->AddToPreview( sheet->Clone() );
1890 }
1891 else if( sheet && ( evt->IsClick( BUT_LEFT )
1892 || evt->IsDblClick( BUT_LEFT )
1893 || isSyntheticClick
1894 || evt->IsAction( &EE_ACTIONS::finishSheet ) ) )
1895 {
1896 getViewControls()->SetAutoPan( false );
1897 getViewControls()->CaptureCursor( false );
1898
1899 if( m_frame->EditSheetProperties( static_cast<SCH_SHEET*>( sheet ),
1900 &m_frame->GetCurrentSheet(), nullptr ) )
1901 {
1903
1904 sheet->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
1905
1906 SCH_COMMIT commit( m_toolMgr );
1907 commit.Add( sheet, m_frame->GetScreen() );
1908 commit.Push( "Draw Sheet" );
1909
1911 m_selectionTool->AddItemToSel( sheet );
1912 }
1913 else
1914 {
1916 delete sheet;
1917 }
1918
1919 sheet = nullptr;
1920 }
1921 else if( sheet && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
1922 {
1923 sizeSheet( sheet, cursorPos );
1925 m_view->AddToPreview( sheet->Clone() );
1926 m_frame->SetMsgPanel( sheet );
1927 }
1928 else if( evt->IsClick( BUT_RIGHT ) )
1929 {
1930 // Warp after context menu only if dragging...
1931 if( !sheet )
1933
1935 }
1936 else if( sheet && evt->IsAction( &ACTIONS::redo ) )
1937 {
1938 wxBell();
1939 }
1940 else
1941 {
1942 evt->SetPassEvent();
1943 }
1944
1945 // Enable autopanning and cursor capture only when there is a sheet to be placed
1946 getViewControls()->SetAutoPan( sheet != nullptr );
1947 getViewControls()->CaptureCursor( sheet != nullptr );
1948 }
1949
1950 getViewControls()->SetAutoPan( false );
1951 getViewControls()->CaptureCursor( false );
1952 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1953
1954 return 0;
1955}
1956
1957
1959{
1960 VECTOR2I pos = aSheet->GetPosition();
1961 VECTOR2I size = aPos - pos;
1962
1963 size.x = std::max( size.x, schIUScale.MilsToIU( MIN_SHEET_WIDTH ) );
1964 size.y = std::max( size.y, schIUScale.MilsToIU( MIN_SHEET_HEIGHT ) );
1965
1967 aSheet->Resize( VECTOR2I( grid.x - pos.x, grid.y - pos.y ) );
1968}
1969
1970
1972{
1990}
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:111
static TOOL_ACTION undo
Definition: actions.h:65
static TOOL_ACTION duplicate
Definition: actions.h:73
static TOOL_ACTION activatePointEditor
Definition: actions.h:178
static TOOL_ACTION doDelete
Definition: actions.h:74
static TOOL_ACTION redo
Definition: actions.h:66
static TOOL_ACTION refreshPreview
Definition: actions.h:111
bool Contains(const Vec &aPoint) const
Definition: box2.h:142
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Create an undo entry for an item that has been already modified.
Definition: commit.h:103
COMMIT & Added(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
Definition: commit.h:84
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
Definition: commit.h:78
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.
int ShowQuasiModal()
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...
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...
WX_INFOBAR * GetInfoBar()
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
VECTOR2I GetNearestGridPosition(const VECTOR2I &aPosition) const
Return the nearest aGridSize location to aPosition.
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
virtual void SetPosition(const VECTOR2I &aPos)
Definition: eda_item.h:240
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:74
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:129
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:123
const KIID m_Uuid
Definition: eda_item.h:482
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:125
virtual bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const
Compare the item against the search criteria in aSearchData.
Definition: eda_item.h:372
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:100
virtual EDA_ITEM * Clone() const
Create a duplicate of this item with linked list members set to NULL.
Definition: eda_item.cpp:82
void ClearEditFlags()
Definition: eda_item.h:137
FILL_T GetFillMode() const
Definition: eda_shape.h:102
void SetFillColor(const COLOR4D &aColor)
Definition: eda_shape.h:107
COLOR4D GetFillColor() const
Definition: eda_shape.h:106
void SetTextSize(VECTOR2I aNewSize)
Definition: eda_text.cpp:355
bool IsItalic() const
Definition: eda_text.h:141
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:131
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:95
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition: eda_text.h:160
void SetBold(bool aBold)
Definition: eda_text.cpp:218
bool IsBold() const
Definition: eda_text.h:144
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:180
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:202
void SetItalic(bool aItalic)
Definition: eda_text.cpp:210
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition: eda_text.cpp:249
PANEL_ANNOTATE m_AnnotatePanel
PANEL_SYM_CHOOSER m_SymChooserPanel
AUTOPLACE_FIELDS m_AutoplaceFields
static TOOL_ACTION mirrorV
Definition: ee_actions.h:124
static TOOL_ACTION properties
Definition: ee_actions.h:127
static TOOL_ACTION placeSymbol
Definition: ee_actions.h:79
static TOOL_ACTION clearSelection
Clears the current selection.
Definition: ee_actions.h:56
static TOOL_ACTION placeClassLabel
Definition: ee_actions.h:88
static TOOL_ACTION drawCircle
Definition: ee_actions.h:96
static TOOL_ACTION rotateCCW
Definition: ee_actions.h:123
static TOOL_ACTION placePower
Definition: ee_actions.h:80
static TOOL_ACTION mirrorH
Definition: ee_actions.h:125
static TOOL_ACTION rotateCW
Definition: ee_actions.h:122
static TOOL_ACTION importSheetPin
Definition: ee_actions.h:92
static TOOL_ACTION leaveSheet
Definition: ee_actions.h:215
static TOOL_ACTION placeGlobalLabel
Definition: ee_actions.h:89
static TOOL_ACTION placeHierLabel
Definition: ee_actions.h:90
static TOOL_ACTION drawTextBox
Definition: ee_actions.h:94
static TOOL_ACTION drawRectangle
Definition: ee_actions.h:95
static TOOL_ACTION placeImage
Definition: ee_actions.h:99
static TOOL_ACTION enterSheet
Definition: ee_actions.h:214
static TOOL_ACTION finishSheet
Definition: ee_actions.h:106
static TOOL_ACTION placeSchematicText
Definition: ee_actions.h:93
static TOOL_ACTION finishDrawing
Definition: ee_actions.h:115
static TOOL_ACTION drawArc
Definition: ee_actions.h:97
static TOOL_ACTION drawSheet
Definition: ee_actions.h:91
static TOOL_ACTION placeLabel
Definition: ee_actions.h:87
static TOOL_ACTION placeBusWireEntry
Definition: ee_actions.h:86
static TOOL_ACTION placeJunction
Definition: ee_actions.h:85
static TOOL_ACTION placeNoConnect
Definition: ee_actions.h:84
EE_TYPE Overlapping(const BOX2I &aRect) const
Definition: sch_rtree.h:243
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:238
bool SelectPoint(const VECTOR2I &aWhere, const std::vector< KICAD_T > &aScanTypes={ SCH_LOCATE_ANY_T }, EDA_ITEM **aItem=nullptr, bool *aSelectionCancelledFlag=nullptr, bool aCheckLocked=false, bool aAdd=false, bool aSubtract=false, bool aExclusiveOr=false)
Perform a click-type selection at a point (usually the cursor position).
EE_SELECTION & GetSelection()
A foundation class for a tool operating on a schematic or symbol.
Definition: ee_tool_base.h:48
EE_SELECTION_TOOL * m_selectionTool
Definition: ee_tool_base.h:197
bool Init() override
Init() is called once upon a registration of the tool.
Definition: ee_tool_base.h:64
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
An interface for classes handling user events controlling the view behavior such as zooming,...
virtual void CaptureCursor(bool aEnabled)
Force the cursor to stay within the drawing panel area.
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Place the cursor immediately at a given point.
virtual void ShowCursor(bool aEnabled)
Enable or disables display of cursor.
virtual void WarpMouseCursor(const VECTOR2D &aPosition, bool aWorldCoordinates=false, bool aWarpView=false)=0
If enabled (.
virtual void SetCrossHairCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true)=0
Move the graphic crosshair cursor to the requested position expressed in world coordinates.
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Return the current mouse pointer position.
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.
virtual void SetAutoPan(bool aEnabled)
Turn on/off auto panning (this feature is used when there is a tool active (eg.
virtual void PinCursorInsideNonAutoscrollArea(bool aWarpMouseCursor)=0
void AddToPreview(EDA_ITEM *aItem, bool aTakeOwnership=true)
Definition: view.cpp:1652
void ClearPreview()
Definition: view.cpp:1630
void RecacheAllItems()
Rebuild GAL display lists.
Definition: view.cpp:1401
Definition: kiid.h:49
bool IsValid() const
Check if this LID_ID is valid.
Definition: lib_id.h:172
Define a library symbol object.
Definition: lib_symbol.h:99
These settings were stored in SCH_BASE_FRAME previously.
Holds all the data relating to one schematic.
Definition: schematic.h:75
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:209
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:100
SCH_SHEET & Root() const
Definition: schematic.h:105
void AddToScreen(EDA_ITEM *aItem, SCH_SCREEN *aScreen=nullptr)
Add an item to the screen (and view) aScreen is the screen the item is located on,...
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
PICKED_SYMBOL PickSymbolFromLibTree(const SYMBOL_LIBRARY_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:93
EESCHEMA_SETTINGS * eeconfig() const
LIB_SYMBOL * GetLibSymbol(const LIB_ID &aLibId, bool aUseCacheLib=false, bool aShowErrorMsg=false)
Load symbol from symbol library table.
Object to handle a bitmap image that can be inserted in a schematic.
Definition: sch_bitmap.h:41
Base class for a bus or wire entry.
Definition: sch_bus_entry.h:38
VECTOR2I GetPosition() const override
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
void Rotate(const VECTOR2I &aCenter) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
Class for a wire to bus entry.
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
Definition: sch_commit.cpp:350
STROKE_PARAMS m_lastTextboxStroke
int DrawSheet(const TOOL_EVENT &aEvent)
SPIN_STYLE m_lastTextOrientation
STROKE_PARAMS m_lastStroke
SCH_TEXT * createNewText(const VECTOR2I &aPosition, int aType)
GR_TEXT_H_ALIGN_T m_lastTextJust
std::vector< PICKED_SYMBOL > m_powerHistoryList
bool m_lastAutoLabelRotateOnPlacement
Re-entrancy guards.
int SingleClickPlace(const TOOL_EVENT &aEvent)
SCH_LINE * findWire(const VECTOR2I &aPosition)
void sizeSheet(SCH_SHEET *aSheet, const VECTOR2I &aPos)
Set up handlers for various events.
LABEL_FLAG_SHAPE m_lastGlobalLabelShape
LABEL_FLAG_SHAPE m_lastNetClassFlagShape
COLOR4D m_lastTextboxFillColor
SCH_SHEET_PIN * createNewSheetPin(SCH_SHEET *aSheet, SCH_HIERLABEL *aLabel, const VECTOR2I &aPosition)
std::unique_ptr< STATUS_TEXT_POPUP > m_statusPopup
int TwoClickPlace(const TOOL_EVENT &aEvent)
LABEL_FLAG_SHAPE m_lastSheetPinType
int DrawShape(const TOOL_EVENT &aEvent)
bool Init() override
Init() is called once upon a registration of the tool.
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
int PlaceSymbol(const TOOL_EVENT &aEvent)
int PlaceImage(const TOOL_EVENT &aEvent)
std::vector< PICKED_SYMBOL > m_symbolHistoryList
SCH_HIERLABEL * importHierLabel(SCH_SHEET *aSheet)
Schematic editor (Eeschema) main window.
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
void SchematicCleanUp(SCH_COMMIT *aCommit, SCH_SCREEN *aScreen=nullptr)
Perform routine schematic cleaning including breaking wire and buses and deleting identical objects s...
SCH_SHEET_PATH & GetCurrentSheet() const
SCHEMATIC & Schematic() const
void SelectUnit(SCH_SYMBOL *aSymbol, int aUnit)
Definition: picksymbol.cpp:241
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:533
void UpdateHierarchyNavigator()
Update the hierarchy navigation tree and history.
void AutoRotateItem(SCH_SCREEN *aScreen, SCH_ITEM *aItem)
Automatically set the rotation of an item (if the item supports it)
void SaveCopyForRepeatItem(const SCH_ITEM *aItem)
Clone aItem and owns that clone in this container.
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:52
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:150
virtual bool IsConnectable() const
Definition: sch_item.h:362
SCHEMATIC * Schematic() const
Searches the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:113
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction)
Definition: sch_item.h:463
virtual void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual)
Definition: sch_item.h:461
SCH_ITEM * Duplicate(bool doClone=false) const
Routine to create a new copy of given item.
Definition: sch_item.cpp:94
bool AutoRotateOnPlacement() const
autoRotateOnPlacement
Definition: sch_label.cpp:1316
SPIN_STYLE GetSpinStyle() const
Definition: sch_label.cpp:372
void SetShape(LABEL_FLAG_SHAPE aShape)
Definition: sch_label.h:148
LABEL_FLAG_SHAPE GetShape() const
Definition: sch_label.h:147
void SetAutoRotateOnPlacement(bool autoRotate=true)
setAutoRotateOnPlacement
Definition: sch_label.cpp:1321
std::vector< SCH_FIELD > & GetFields()
Definition: sch_label.h:167
virtual void SetSpinStyle(SPIN_STYLE aSpinStyle)
Definition: sch_label.cpp:337
Tool responsible for drawing/placing items (symbols, wires, buses, labels, etc.)
int AddJunctionsIfNeeded(SCH_COMMIT *aCommit, EE_SELECTION *aSelection)
Handle the addition of junctions to a selection of objects.
int TrimOverLappingWires(SCH_COMMIT *aCommit, EE_SELECTION *aSelection)
Logic to remove wires when overlapping correct items.
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:40
bool IsWire() const
Return true if the line is a wire.
Definition: sch_line.cpp:969
VECTOR2I GetEndPoint() const
Definition: sch_line.h:145
VECTOR2I GetStartPoint() const
Definition: sch_line.h:140
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
void SortByReferenceOnly()
Sort the list of references by reference.
void ReannotateByOptions(ANNOTATE_ORDER_T aSortOption, ANNOTATE_ALGO_T aAlgoOption, int aStartNumber, const SCH_REFERENCE_LIST &aAdditionalRefs, bool aStartAtCurrent, SCH_SHEET_LIST *aHierarchy)
Forces reannotation of the provided references.
size_t GetCount() const
void AddItem(const SCH_REFERENCE &aItem)
void UpdateAnnotation()
Update the symbol references for the schematic project (or the current sheet).
A helper to define a symbol's reference designator in a schematic.
bool AlwaysAnnotate() const
Verify the reference should always be automatically annotated.
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:109
SCH_ITEM * GetItem(const VECTOR2I &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:390
bool IsExplicitJunctionAllowed(const VECTOR2I &aPosition) const
Indicates that a juction dot may be placed at the given location.
Definition: sch_screen.cpp:704
void CalcEdit(const VECTOR2I &aPosition)
Definition: sch_shape.h:84
bool ContinueEdit(const VECTOR2I &aPosition)
Definition: sch_shape.h:83
void BeginEdit(const VECTOR2I &aStartPoint)
Definition: sch_shape.h:82
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: sch_shape.cpp:46
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: sch_shape.cpp:63
void EndEdit()
Definition: sch_shape.h:85
wxString GetClass() const override
Return the class name.
Definition: sch_shape.h:42
STROKE_PARAMS GetStroke() const override
Definition: sch_shape.h:64
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
void SortByPageNumbers(bool aUpdateVirtualPageNums=true)
Sort the list of sheets by page number.
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 GetSymbols(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void UpdateAllScreenReferences() const
Update all the symbol references for this sheet path.
SCH_SCREEN * LastScreen()
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:66
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:57
void SetBorderColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:119
void AddPin(SCH_SHEET_PIN *aSheetPin)
Add aSheetPin to the sheet.
Definition: sch_sheet.cpp:368
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: sch_sheet.cpp:155
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: sch_sheet.cpp:948
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:93
void SetBackgroundColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:122
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:110
VECTOR2I GetPosition() const override
Definition: sch_sheet.h:378
bool HasPin(const wxString &aName) const
Checks if the sheet already has a sheet pin named aName.
Definition: sch_sheet.cpp:396
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:161
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual) override
Definition: sch_sheet.cpp:605
void SetBorderWidth(int aWidth)
Definition: sch_sheet.h:116
void Resize(const VECTOR2I &aSize)
Resize this sheet to aSize and adjust all of the labels accordingly.
Definition: sch_sheet.cpp:931
Schematic symbol object.
Definition: sch_symbol.h:81
int GetUnitCount() const
Return the number of units per package of the symbol.
Definition: sch_symbol.cpp:418
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual) override
Automatically orient all the fields in the symbol.
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_symbol.h:704
int GetUnit() const
Definition: sch_symbol.h:226
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
void ClearAnnotation(const SCH_SHEET_PATH *aSheetPath, bool aResetPrefix)
Clear exiting symbol annotation.
void SetUnit(int aUnit)
Change the unit number to aUnit.
Definition: sch_symbol.cpp:387
void SetUnitSelection(const SCH_SHEET_PATH *aSheet, int aUnitSelection)
Set the selected unit of this symbol on one sheet.
Definition: sch_symbol.cpp:800
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:190
Definition: seg.h:42
const VECTOR2I NearestPoint(const VECTOR2I &aP) const
Compute a point on the segment (this) that is closest to point aP.
Definition: seg.cpp:269
int AddItemToSel(const TOOL_EVENT &aEvent)
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition: selection.h:99
EDA_ITEM * Front() const
Definition: selection.h:208
int Size() const
Returns the number of selected parts.
Definition: selection.h:115
Helper object to filter a list of libraries.
virtual void PopTool(const TOOL_EVENT &aEvent)
Pops a tool from the stack.
virtual void PushTool(const TOOL_EVENT &aEvent)
NB: the definition of "tool" is different at the user level.
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:216
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
Generic, UI-independent tool event.
Definition: tool_event.h:167
bool HasPosition() const
Definition: tool_event.h:256
const VECTOR2D Position() const
Returns the point where dragging has started.
Definition: tool_event.h:285
bool IsReactivate() const
Definition: tool_event.h:268
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:81
T Parameter() const
Return a parameter assigned to the event.
Definition: tool_event.h:461
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).
TOOL_MENU m_menu
The functions below are not yet implemented - their interface may change.
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 Activate()
Run the tool.
void DeactivateTool()
Deactivate the currently active tool.
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:145
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...
bool PostAction(const std::string &aActionName, T aParam)
Run the specified action after the current action (coroutine) ends.
Definition: tool_manager.h:230
void VetoContextMenuMouseWarp()
Disable mouse warping after the current context menu is closed.
Definition: tool_manager.h:517
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:44
void ShowContextMenu(SELECTION &aSelection)
Helper function to set and immediately show a CONDITIONAL_MENU in concert with the given SELECTION.
Definition: tool_menu.cpp:57
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: wx_infobar.cpp:187
This file is part of the common library.
#define _(s)
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:437
#define IS_NEW
New item, just created.
#define STRUCT_DELETED
flag indication structures to be erased
#define IS_MOVING
Item being moved.
SHAPE_T
Definition: eda_shape.h:42
FILL_T
Definition: eda_shape.h:55
@ ID_POPUP_SCH_SELECT_UNIT
Definition: eeschema_id.h:83
@ ID_POPUP_SCH_SELECT_UNIT_END
Definition: eeschema_id.h:87
GRID_HELPER_GRIDS
Definition: grid_helper.h:37
@ GRID_TEXT
Definition: grid_helper.h:44
@ GRID_CONNECTABLE
Definition: grid_helper.h:41
const std::string KiCadSchematicFileExtension
@ LAYER_HIERLABEL
Definition: layer_ids.h:354
@ LAYER_GLOBLABEL
Definition: layer_ids.h:353
@ LAYER_NOTES
Definition: layer_ids.h:363
@ LAYER_LOCLABEL
Definition: layer_ids.h:352
@ LAYER_NETCLASS_REFS
Definition: layer_ids.h:361
wxPoint GetMousePosition()
Returns the mouse position in screen coordinates.
Definition: gtk/ui.cpp:573
see class PGM_BASE
LABEL_FLAG_SHAPE
Definition: sch_label.h:91
@ F_ROUND
Definition: sch_label.h:100
@ L_INPUT
Definition: sch_label.h:92
ANNOTATE_ORDER_T
Schematic annotation order options.
ANNOTATE_ALGO_T
Schematic annotation type options.
@ SHEETNAME
Definition: sch_sheet.h:45
@ SHEETFILENAME
Definition: sch_sheet.h:46
#define MIN_SHEET_HEIGHT
Definition: sch_sheet.h:40
#define MIN_SHEET_WIDTH
Definition: sch_sheet.h:39
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:115
bool NoPrintableChars(const wxString &aString)
Return true if the string is empty or contains only whitespace.
PLOT_DASH_TYPE
Dashed line types.
Definition: stroke_params.h:48
constexpr int MilsToIU(int mils) const
Definition: base_units.h:94
LIB_ID LibId
Definition: sch_screen.h:80
@ GR_TEXT_H_ALIGN_LEFT
@ TA_CHOICE_MENU_CHOICE
Definition: tool_event.h:97
@ TC_COMMAND
Definition: tool_event.h:56
@ MD_SHIFT
Definition: tool_event.h:142
@ BUT_LEFT
Definition: tool_event.h:131
@ BUT_RIGHT
Definition: tool_event.h:132
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ SCH_LINE_T
Definition: typeinfo.h:145
@ SCH_NO_CONNECT_T
Definition: typeinfo.h:142
@ SCH_DIRECTIVE_LABEL_T
Definition: typeinfo.h:153
@ SCH_SHEET_T
Definition: typeinfo.h:157
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:152
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:156
@ SCH_BUS_WIRE_ENTRY_T
Definition: typeinfo.h:143
@ SCH_JUNCTION_T
Definition: typeinfo.h:141
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588
Definition of file extensions used in Kicad.