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-2023 CERN
5 * Copyright (C) 2019-2024 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_sheet_path.h"
26#include <memory>
27
28#include <kiplatform/ui.h>
29#include <optional>
30#include <project_sch.h>
37#include <ee_actions.h>
38#include <sch_edit_frame.h>
39#include <pgm_base.h>
40#include <eeschema_id.h>
41#include <confirm.h>
42#include <view/view_controls.h>
43#include <view/view.h>
44#include <sch_symbol.h>
45#include <sch_no_connect.h>
46#include <sch_line.h>
47#include <sch_junction.h>
48#include <sch_bus_entry.h>
49#include <sch_rule_area.h>
50#include <sch_text.h>
51#include <sch_textbox.h>
52#include <sch_table.h>
53#include <sch_tablecell.h>
54#include <sch_sheet.h>
55#include <sch_sheet_pin.h>
56#include <sch_label.h>
57#include <sch_bitmap.h>
58#include <schematic.h>
59#include <sch_commit.h>
60#include <scoped_set_reset.h>
61#include <symbol_library.h>
62#include <eeschema_settings.h>
64#include <dialogs/dialog_text_properties.h>
67#include <dialogs/dialog_table_properties.h>
70#include <string_utils.h>
72#include <wx/filedlg.h>
73#include <wx/msgdlg.h>
74
76 EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.InteractiveDrawing" ),
77 m_lastSheetPinType( LABEL_FLAG_SHAPE::L_INPUT ),
78 m_lastGlobalLabelShape( LABEL_FLAG_SHAPE::L_INPUT ),
79 m_lastNetClassFlagShape( LABEL_FLAG_SHAPE::F_ROUND ),
80 m_lastTextOrientation( SPIN_STYLE::RIGHT ),
81 m_lastTextBold( false ),
82 m_lastTextItalic( false ),
83 m_lastTextAngle( ANGLE_0 ),
84 m_lastTextboxAngle( ANGLE_0 ),
85 m_lastTextHJustify( GR_TEXT_H_ALIGN_CENTER ),
86 m_lastTextVJustify( GR_TEXT_V_ALIGN_CENTER ),
87 m_lastTextboxHJustify( GR_TEXT_H_ALIGN_LEFT ),
88 m_lastTextboxVJustify( GR_TEXT_V_ALIGN_TOP ),
89 m_lastFillStyle( FILL_T::NO_FILL ),
90 m_lastTextboxFillStyle( FILL_T::NO_FILL ),
91 m_lastFillColor( COLOR4D::UNSPECIFIED ),
92 m_lastTextboxFillColor( COLOR4D::UNSPECIFIED ),
93 m_lastStroke( 0, LINE_STYLE::DEFAULT, COLOR4D::UNSPECIFIED ),
94 m_lastTextboxStroke( 0, LINE_STYLE::DEFAULT, COLOR4D::UNSPECIFIED ),
95 m_mruPath( wxEmptyString ),
96 m_lastAutoLabelRotateOnPlacement( false ),
97 m_drawingRuleArea( false ),
98 m_inDrawingTool( false )
99{
100}
101
102
104{
106
107 auto belowRootSheetCondition =
108 [&]( const SELECTION& aSel )
109 {
110 return m_frame->GetCurrentSheet().Last() != &m_frame->Schematic().Root();
111 };
112
113 auto inDrawingRuleArea =
114 [&]( const SELECTION& aSel )
115 {
116 return m_drawingRuleArea;
117 };
118
119 CONDITIONAL_MENU& ctxMenu = m_menu.GetMenu();
120 ctxMenu.AddItem( EE_ACTIONS::leaveSheet, belowRootSheetCondition, 150 );
121 ctxMenu.AddItem( EE_ACTIONS::closeOutline, inDrawingRuleArea, 200 );
122 ctxMenu.AddItem( EE_ACTIONS::deleteLastPoint, inDrawingRuleArea, 200 );
123
124 return true;
125}
126
127
129{
130 SCH_SYMBOL* symbol = aEvent.Parameter<SCH_SYMBOL*>();
132 std::vector<PICKED_SYMBOL>* historyList = nullptr;
133 bool ignorePrimePosition = false;
134 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
135 SCH_SCREEN* screen = m_frame->GetScreen();
136
137 if( m_inDrawingTool )
138 return 0;
139
141
144 VECTOR2I cursorPos;
145
146 // First we need to get all instances of this sheet so we can annotate
147 // whatever symbols we place on all copies
149 SCH_SHEET_LIST newInstances =
151 newInstances.SortByPageNumbers();
152
153 // Get a list of all references in the schematic to avoid duplicates wherever
154 // they're placed
155 SCH_REFERENCE_LIST existingRefs;
156 hierarchy.GetSymbols( existingRefs );
157 existingRefs.SortByReferenceOnly();
158
159 if( aEvent.IsAction( &EE_ACTIONS::placeSymbol ) )
160 {
161 historyList = &m_symbolHistoryList;
162 }
163 else if (aEvent.IsAction( &EE_ACTIONS::placePower ) )
164 {
165 historyList = &m_powerHistoryList;
166 filter.FilterPowerSymbols( true );
167 }
168 else
169 {
170 wxFAIL_MSG( "PlaceSymbol(): unexpected request" );
171 }
172
173 m_frame->PushTool( aEvent );
174
175 auto addSymbol =
176 [this]( SCH_SYMBOL* aSymbol )
177 {
179 m_selectionTool->AddItemToSel( aSymbol );
180
181 aSymbol->SetFlags( IS_NEW | IS_MOVING );
182
184 m_view->AddToPreview( aSymbol, false ); // Add, but not give ownership
185
186 // Set IS_MOVING again, as AddItemToCommitAndScreen() will have cleared it.
187 aSymbol->SetFlags( IS_MOVING );
189 };
190
191 auto setCursor =
192 [&]()
193 {
194 m_frame->GetCanvas()->SetCurrentCursor( symbol ? KICURSOR::MOVING
195 : KICURSOR::COMPONENT );
196 };
197
198 auto cleanup =
199 [&]()
200 {
203 delete symbol;
204 symbol = nullptr;
205
206 existingRefs.Clear();
207 hierarchy.GetSymbols( existingRefs );
208 existingRefs.SortByReferenceOnly();
209 };
210
211 auto annotate =
212 [&]()
213 {
215
216 // Then we need to annotate all instances by sheet
217 for( SCH_SHEET_PATH& instance : newInstances )
218 {
219 SCH_REFERENCE newReference( symbol, instance );
221 refs.AddItem( newReference );
222
223 if( cfg->m_AnnotatePanel.automatic || newReference.AlwaysAnnotate() )
224 {
228 existingRefs, false, &hierarchy );
229
230 refs.UpdateAnnotation();
231
232 // Update existing refs for next iteration
233 for( size_t i = 0; i < refs.GetCount(); i++ )
234 existingRefs.AddItem( refs[i] );
235 }
236 }
237
239 };
240
241 Activate();
242
243 // Must be done after Activate() so that it gets set into the correct context
244 getViewControls()->ShowCursor( true );
245
246 // Set initial cursor
247 setCursor();
248
249 // Prime the pump
250 if( symbol )
251 {
252 addSymbol( symbol );
253 annotate();
254 getViewControls()->WarpMouseCursor( getViewControls()->GetMousePosition( false ) );
255 }
256 else if( aEvent.HasPosition() )
257 {
258 m_toolMgr->PrimeTool( aEvent.Position() );
259 }
260 else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() )
261 {
262 m_toolMgr->PrimeTool( { 0, 0 } );
263 ignorePrimePosition = true;
264 }
265
266 // Main loop: keep receiving events
267 while( TOOL_EVENT* evt = Wait() )
268 {
269 setCursor();
270 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
271 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
272
273 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_CONNECTABLE );
274 controls->ForceCursorPosition( true, cursorPos );
275
276 // The tool hotkey is interpreted as a click when drawing
277 bool isSyntheticClick = symbol && evt->IsActivate() && evt->HasPosition()
278 && evt->Matches( aEvent );
279
280 if( evt->IsCancelInteractive() || ( symbol && evt->IsAction( &ACTIONS::undo ) ) )
281 {
283
284 if( symbol )
285 {
286 cleanup();
287 }
288 else
289 {
290 m_frame->PopTool( aEvent );
291 break;
292 }
293 }
294 else if( evt->IsActivate() && !isSyntheticClick )
295 {
296 if( symbol && evt->IsMoveTool() )
297 {
298 // we're already moving our own item; ignore the move tool
299 evt->SetPassEvent( false );
300 continue;
301 }
302
303 if( symbol )
304 {
305 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel symbol creation." ) );
306 evt->SetPassEvent( false );
307 continue;
308 }
309
310 if( evt->IsMoveTool() )
311 {
312 // leave ourselves on the stack so we come back after the move
313 break;
314 }
315 else
316 {
317 m_frame->PopTool( aEvent );
318 break;
319 }
320 }
321 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) || isSyntheticClick )
322 {
323 if( !symbol )
324 {
326
329
330 auto compareByLibID =
331 []( const LIB_SYMBOL* aFirst, const LIB_SYMBOL* aSecond ) -> bool
332 {
333 return aFirst->GetLibId().Format() < aSecond->GetLibId().Format();
334 };
335
336 std::set<LIB_SYMBOL*, decltype( compareByLibID )> part_list( compareByLibID );
337
338 for( SCH_SHEET_PATH& sheet : hierarchy )
339 {
340 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
341 {
342 SCH_SYMBOL* s = static_cast<SCH_SYMBOL*>( item );
343 LIB_SYMBOL* libSymbol = SchGetLibSymbol( s->GetLibId(), libs, cache );
344
345 if( libSymbol )
346 part_list.insert( libSymbol );
347 }
348 }
349
350 std::vector<PICKED_SYMBOL> alreadyPlaced;
351
352 for( LIB_SYMBOL* libSymbol : part_list )
353 {
354 PICKED_SYMBOL pickedSymbol;
355 pickedSymbol.LibId = libSymbol->GetLibId();
356 alreadyPlaced.push_back( pickedSymbol );
357 }
358
359 // Pick the symbol to be placed
360 bool footprintPreviews = m_frame->eeconfig()->m_Appearance.footprint_preview;
361 PICKED_SYMBOL sel = m_frame->PickSymbolFromLibrary( &filter, *historyList,
362 alreadyPlaced,
363 footprintPreviews );
364
365 LIB_SYMBOL* libSymbol = sel.LibId.IsValid() ? m_frame->GetLibSymbol( sel.LibId )
366 : nullptr;
367
368 if( !libSymbol )
369 continue;
370
371 // If we started with a hotkey which has a position then warp back to that.
372 // Otherwise update to the current mouse position pinned inside the autoscroll
373 // boundaries.
374 if( evt->IsPrime() && !ignorePrimePosition )
375 {
376 cursorPos = grid.Align( evt->Position(), GRID_HELPER_GRIDS::GRID_CONNECTABLE );
377 getViewControls()->WarpMouseCursor( cursorPos, true );
378 }
379 else
380 {
382 cursorPos = grid.Align( getViewControls()->GetMousePosition(),
383 GRID_HELPER_GRIDS::GRID_CONNECTABLE );
384 }
385
386 symbol = new SCH_SYMBOL( *libSymbol, &m_frame->GetCurrentSheet(), sel, cursorPos,
387 &m_frame->Schematic() );
388 addSymbol( symbol );
389 annotate();
390
391 // Update the list of references for the next symbol placement.
392 SCH_REFERENCE placedSymbolReference( symbol, m_frame->GetCurrentSheet() );
393 existingRefs.AddItem( placedSymbolReference );
394 existingRefs.SortByReferenceOnly();
395
397 symbol->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
398
399 // Update cursor now that we have a symbol
400 setCursor();
401 }
402 else
403 {
405 m_frame->AddToScreen( symbol, screen );
406
408 symbol->AutoplaceFields( screen, false /* aManual */ );
409
411
412 SCH_COMMIT commit( m_toolMgr );
413 commit.Added( symbol, screen );
414
416 lwbTool->TrimOverLappingWires( &commit, &m_selectionTool->GetSelection() );
417 lwbTool->AddJunctionsIfNeeded( &commit, &m_selectionTool->GetSelection() );
418
419 commit.Push( _( "Add Symbol" ) );
420
421 SCH_SYMBOL* nextSymbol = nullptr;
422
425 {
426 int new_unit = symbol->GetUnit();
427
429 && symbol->GetUnit() < symbol->GetUnitCount() )
430 {
431 new_unit++;
432 }
433 else
434 {
435 new_unit = 1;
436 }
437
438 // We are either stepping to the next unit or next symbol
439 if( m_frame->eeconfig()->m_SymChooserPanel.keep_symbol || new_unit > 1 )
440 {
441 nextSymbol = static_cast<SCH_SYMBOL*>( symbol->Duplicate() );
442 nextSymbol->SetUnit( new_unit );
443 nextSymbol->SetUnitSelection( new_unit );
444
445 // Start new annotation sequence at first unit
446 if( new_unit == 1 )
447 nextSymbol->ClearAnnotation( nullptr, false );
448
449 addSymbol( nextSymbol );
450 symbol = nextSymbol;
451 annotate();
452
453 // Update the list of references for the next symbol placement.
454 SCH_REFERENCE placedSymbolReference( symbol, m_frame->GetCurrentSheet() );
455 existingRefs.AddItem( placedSymbolReference );
456 existingRefs.SortByReferenceOnly();
457 }
458 }
459
460 symbol = nextSymbol;
461 }
462 }
463 else if( evt->IsClick( BUT_RIGHT ) )
464 {
465 // Warp after context menu only if dragging...
466 if( !symbol )
468
470 }
471 else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
472 {
473 if( *evt->GetCommandId() >= ID_POPUP_SCH_SELECT_UNIT
474 && *evt->GetCommandId() <= ID_POPUP_SCH_SELECT_UNIT_END )
475 {
476 int unit = *evt->GetCommandId() - ID_POPUP_SCH_SELECT_UNIT;
477
478 if( symbol )
479 {
480 m_frame->SelectUnit( symbol, unit );
482 }
483 }
484 }
485 else if( evt->IsAction( &ACTIONS::duplicate )
486 || evt->IsAction( &EE_ACTIONS::repeatDrawItem ) )
487 {
488 if( symbol )
489 {
490 // This doesn't really make sense; we'll just end up dragging a stack of
491 // objects so we ignore the duplicate and just carry on.
492 wxBell();
493 continue;
494 }
495
496 // Exit. The duplicate will run in its own loop.
497 m_frame->PopTool( aEvent );
498 break;
499 }
500 else if( symbol && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
501 {
502 symbol->SetPosition( cursorPos );
504 m_view->AddToPreview( symbol, false ); // Add, but not give ownership
505 m_frame->SetMsgPanel( symbol );
506 }
507 else if( symbol && evt->IsAction( &ACTIONS::doDelete ) )
508 {
509 cleanup();
510 }
511 else if( symbol && evt->IsAction( &ACTIONS::redo ) )
512 {
513 wxBell();
514 }
515 else
516 {
517 evt->SetPassEvent();
518 }
519
520 // Enable autopanning and cursor capture only when there is a symbol to be placed
521 getViewControls()->SetAutoPan( symbol != nullptr );
522 getViewControls()->CaptureCursor( symbol != nullptr );
523 }
524
525 getViewControls()->SetAutoPan( false );
526 getViewControls()->CaptureCursor( false );
527 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
528
529 return 0;
530}
531
532
534{
535 SCH_BITMAP* image = aEvent.Parameter<SCH_BITMAP*>();
536 bool immediateMode = image != nullptr;
537 bool ignorePrimePosition = false;
538 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
539
540 if( m_inDrawingTool )
541 return 0;
542
544
547 VECTOR2I cursorPos;
548
550
551 // Add all the drawable symbols to preview
552 if( image )
553 {
554 image->SetPosition( getViewControls()->GetCursorPosition() );
556 m_view->AddToPreview( image, false ); // Add, but not give ownership
557 }
558
559 m_frame->PushTool( aEvent );
560
561 auto setCursor =
562 [&]()
563 {
564 if( image )
565 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::MOVING );
566 else
567 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
568 };
569
570 auto cleanup =
571 [&] ()
572 {
576 delete image;
577 image = nullptr;
578 };
579
580 Activate();
581
582 // Must be done after Activate() so that it gets set into the correct context
583 getViewControls()->ShowCursor( true );
584
585 // Set initial cursor
586 setCursor();
587
588 // Prime the pump
589 if( image )
590 {
592 }
593 else if( aEvent.HasPosition() )
594 {
595 m_toolMgr->PrimeTool( aEvent.Position() );
596 }
597 else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() )
598 {
599 m_toolMgr->PrimeTool( { 0, 0 } );
600 ignorePrimePosition = true;
601 }
602
603 // Main loop: keep receiving events
604 while( TOOL_EVENT* evt = Wait() )
605 {
606 setCursor();
607 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
608 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
609
610 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
611 controls->ForceCursorPosition( true, cursorPos );
612
613 // The tool hotkey is interpreted as a click when drawing
614 bool isSyntheticClick = image && evt->IsActivate() && evt->HasPosition()
615 && evt->Matches( aEvent );
616
617 if( evt->IsCancelInteractive() || ( image && evt->IsAction( &ACTIONS::undo ) ) )
618 {
620
621 if( image )
622 {
623 cleanup();
624 }
625 else
626 {
627 m_frame->PopTool( aEvent );
628 break;
629 }
630
631 if( immediateMode )
632 {
633 m_frame->PopTool( aEvent );
634 break;
635 }
636 }
637 else if( evt->IsActivate() && !isSyntheticClick )
638 {
639 if( image && evt->IsMoveTool() )
640 {
641 // we're already moving our own item; ignore the move tool
642 evt->SetPassEvent( false );
643 continue;
644 }
645
646 if( image )
647 {
648 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel image creation." ) );
649 evt->SetPassEvent( false );
650 continue;
651 }
652
653 if( evt->IsMoveTool() )
654 {
655 // leave ourselves on the stack so we come back after the move
656 break;
657 }
658 else
659 {
660 m_frame->PopTool( aEvent );
661 break;
662 }
663 }
664 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) || isSyntheticClick )
665 {
666 if( !image )
667 {
669
670 wxFileDialog dlg( m_frame, _( "Choose Image" ), m_mruPath, wxEmptyString,
671 _( "Image Files" ) + wxS( " " ) + wxImage::GetImageExtWildcard(),
672 wxFD_OPEN );
673
674 if( dlg.ShowModal() != wxID_OK )
675 continue;
676
677 // If we started with a hotkey which has a position then warp back to that.
678 // Otherwise update to the current mouse position pinned inside the autoscroll
679 // boundaries.
680 if( evt->IsPrime() && !ignorePrimePosition )
681 {
682 cursorPos = grid.Align( evt->Position() );
683 getViewControls()->WarpMouseCursor( cursorPos, true );
684 }
685 else
686 {
688 cursorPos = getViewControls()->GetMousePosition();
689 }
690
691 wxString fullFilename = dlg.GetPath();
692 m_mruPath = wxPathOnly( fullFilename );
693
694 if( wxFileExists( fullFilename ) )
695 image = new SCH_BITMAP( cursorPos );
696
697 if( !image || !image->ReadImageFile( fullFilename ) )
698 {
699 wxMessageBox( _( "Could not load image from '%s'." ), fullFilename );
700 delete image;
701 image = nullptr;
702 continue;
703 }
704
705 image->SetFlags( IS_NEW | IS_MOVING );
706
708
710 m_view->AddToPreview( image, false ); // Add, but not give ownership
711 m_view->RecacheAllItems(); // Bitmaps are cached in Opengl
712
714
715 getViewControls()->SetCursorPosition( cursorPos, false );
716 setCursor();
717 }
718 else
719 {
720 SCH_COMMIT commit( m_toolMgr );
721 commit.Add( image, m_frame->GetScreen() );
722 commit.Push( _( "Add Image" ) );
723
724 image = nullptr;
726
728
729 if( immediateMode )
730 {
731 m_frame->PopTool( aEvent );
732 break;
733 }
734 }
735 }
736 else if( evt->IsClick( BUT_RIGHT ) )
737 {
738 // Warp after context menu only if dragging...
739 if( !image )
741
743 }
744 else if( evt->IsAction( &ACTIONS::duplicate )
745 || evt->IsAction( &EE_ACTIONS::repeatDrawItem ) )
746 {
747 if( image )
748 {
749 // This doesn't really make sense; we'll just end up dragging a stack of
750 // objects so we ignore the duplicate and just carry on.
751 wxBell();
752 continue;
753 }
754
755 // Exit. The duplicate will run in its own loop.
756 m_frame->PopTool( aEvent );
757 break;
758 }
759 else if( image && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
760 {
761 image->SetPosition( cursorPos );
763 m_view->AddToPreview( image, false ); // Add, but not give ownership
764 m_view->RecacheAllItems(); // Bitmaps are cached in Opengl
766 }
767 else if( image && evt->IsAction( &ACTIONS::doDelete ) )
768 {
769 cleanup();
770 }
771 else if( image && evt->IsAction( &ACTIONS::redo ) )
772 {
773 wxBell();
774 }
775 else
776 {
777 evt->SetPassEvent();
778 }
779
780 // Enable autopanning and cursor capture only when there is an image to be placed
781 getViewControls()->SetAutoPan( image != nullptr );
782 getViewControls()->CaptureCursor( image != nullptr );
783 }
784
785 getViewControls()->SetAutoPan( false );
786 getViewControls()->CaptureCursor( false );
787 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
788
789 return 0;
790}
791
792
794{
795 if( m_inDrawingTool )
796 return 0;
797
799
800 // Note: PlaceImportedGraphics() will convert PCB_SHAPE_T and PCB_TEXT_T to footprint
801 // items if needed
803 int dlgResult = dlg.ShowModal();
804
805 std::list<std::unique_ptr<EDA_ITEM>>& list = dlg.GetImportedItems();
806
807 if( dlgResult != wxID_OK )
808 return 0;
809
810 // Ensure the list is not empty:
811 if( list.empty() )
812 {
813 wxMessageBox( _( "No graphic items found in file." ) );
814 return 0;
815 }
816
818
820 std::vector<SCH_ITEM*> newItems; // all new items, including group
821 std::vector<SCH_ITEM*> selectedItems; // the group, or newItems if no group
822 EE_SELECTION preview;
823 SCH_COMMIT commit( m_toolMgr );
824
825 for( std::unique_ptr<EDA_ITEM>& ptr : list )
826 {
827 SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( ptr.get() );
828 wxCHECK2( item, continue );
829
830 newItems.push_back( item );
831 selectedItems.push_back( item );
832 preview.Add( item );
833
834 ptr.release();
835 }
836
837 if( !dlg.IsPlacementInteractive() )
838 {
839 // Place the imported drawings
840 for( SCH_ITEM* item : newItems )
841 commit.Add(item, m_frame->GetScreen());
842
843 commit.Push( _( "Import Graphic" ) );
844 return 0;
845 }
846
847 m_view->Add( &preview );
848
849 // Clear the current selection then select the drawings so that edit tools work on them
851
852 EDA_ITEMS selItems( selectedItems.begin(), selectedItems.end() );
854
855 m_frame->PushTool( aEvent );
856
857 auto setCursor = [&]()
858 {
859 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::MOVING );
860 };
861
862 Activate();
863 // Must be done after Activate() so that it gets set into the correct context
864 controls->ShowCursor( true );
865 controls->ForceCursorPosition( false );
866 // Set initial cursor
867 setCursor();
868
869 //SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::DXF );
871
872 // Now move the new items to the current cursor position:
873 VECTOR2I cursorPos = controls->GetCursorPosition( !aEvent.DisableGridSnapping() );
874 VECTOR2I delta = cursorPos;
875 VECTOR2I currentOffset;
876
877 for( SCH_ITEM* item : selectedItems )
878 item->Move( delta );
879
880 currentOffset += delta;
881
882 m_view->Update( &preview );
883
884 // Main loop: keep receiving events
885 while( TOOL_EVENT* evt = Wait() )
886 {
887 setCursor();
888
889 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
890 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
891
892 cursorPos = grid.Align( controls->GetMousePosition(), GRID_GRAPHICS );
893 controls->ForceCursorPosition( true, cursorPos );
894
895 if( evt->IsCancelInteractive() || evt->IsActivate() )
896 {
898
899 for( SCH_ITEM* item : newItems )
900 delete item;
901
902 break;
903 }
904 else if( evt->IsMotion() )
905 {
906 delta = cursorPos - currentOffset;
907
908 for( SCH_ITEM* item : selectedItems )
909 item->Move( delta );
910
911 currentOffset += delta;
912
913 m_view->Update( &preview );
914 }
915 else if( evt->IsClick( BUT_RIGHT ) )
916 {
918 }
919 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
920 {
921 // Place the imported drawings
922 for( SCH_ITEM* item : newItems )
923 commit.Add( item, m_frame->GetScreen() );
924
925 commit.Push( _( "Import Graphic" ) );
926 break; // This is a one-shot command, not a tool
927 }
928 else
929 {
930 evt->SetPassEvent();
931 }
932 }
933
934 preview.Clear();
935 m_view->Remove( &preview );
936
937 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
938 controls->ForceCursorPosition( false );
939
940 m_frame->PopTool( aEvent );
941
942 return 0;
943}
944
945
947{
948 VECTOR2I cursorPos;
949 KICAD_T type = aEvent.Parameter<KICAD_T>();
952 SCH_ITEM* previewItem;
953 bool loggedInfoBarError = false;
954 wxString description;
955 SCH_SCREEN* screen = m_frame->GetScreen();
956 bool allowRepeat = false; // Set to true to allow new item repetition
957
958 if( m_inDrawingTool )
959 return 0;
960
962
963 if( type == SCH_JUNCTION_T && aEvent.HasPosition() )
964 {
966 SCH_LINE* wire = dynamic_cast<SCH_LINE*>( selection.Front() );
967
968 if( wire )
969 {
970 SEG seg( wire->GetStartPoint(), wire->GetEndPoint() );
971 VECTOR2I nearest = seg.NearestPoint( getViewControls()->GetCursorPosition() );
972 getViewControls()->SetCrossHairCursorPosition( nearest, false );
973 getViewControls()->WarpMouseCursor( getViewControls()->GetCursorPosition(), true );
974 }
975 }
976
977 switch( type )
978 {
979 case SCH_NO_CONNECT_T:
980 previewItem = new SCH_NO_CONNECT( cursorPos );
981 previewItem->SetParent( screen );
982 description = _( "Add No Connect Flag" );
983 allowRepeat = true;
984 break;
985
986 case SCH_JUNCTION_T:
987 previewItem = new SCH_JUNCTION( cursorPos );
988 previewItem->SetParent( screen );
989 description = _( "Add Junction" );
990 break;
991
993 previewItem = new SCH_BUS_WIRE_ENTRY( cursorPos );
994 previewItem->SetParent( screen );
995 description = _( "Add Wire to Bus Entry" );
996 allowRepeat = true;
997 break;
998
999 default:
1000 wxASSERT_MSG( false, "Unknown item type in SCH_DRAWING_TOOLS::SingleClickPlace" );
1001 return 0;
1002 }
1003
1005
1006 cursorPos = aEvent.HasPosition() ? aEvent.Position() : controls->GetMousePosition();
1007
1008 m_frame->PushTool( aEvent );
1009
1010 auto setCursor =
1011 [&]()
1012 {
1013 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PLACE );
1014 };
1015
1016 Activate();
1017
1018 // Must be done after Activate() so that it gets set into the correct context
1019 getViewControls()->ShowCursor( true );
1020
1021 // Set initial cursor
1022 setCursor();
1023
1025 m_view->AddToPreview( previewItem->Clone() );
1026
1027 // Prime the pump
1028 if( aEvent.HasPosition() && type != SCH_SHEET_PIN_T )
1029 m_toolMgr->PrimeTool( aEvent.Position() );
1030 else
1032
1033 // Main loop: keep receiving events
1034 while( TOOL_EVENT* evt = Wait() )
1035 {
1036 setCursor();
1037 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1038 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1039
1040 cursorPos = evt->IsPrime() ? evt->Position() : controls->GetMousePosition();
1041 cursorPos = grid.BestSnapAnchor( cursorPos, grid.GetItemGrid( previewItem ), nullptr );
1042 controls->ForceCursorPosition( true, cursorPos );
1043
1044 if( evt->IsCancelInteractive() )
1045 {
1046 m_frame->PopTool( aEvent );
1047 break;
1048 }
1049 else if( evt->IsActivate() )
1050 {
1051 if( evt->IsMoveTool() )
1052 {
1053 // leave ourselves on the stack so we come back after the move
1054 break;
1055 }
1056 else
1057 {
1058 m_frame->PopTool( aEvent );
1059 break;
1060 }
1061 }
1062 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
1063 {
1064 if( !screen->GetItem( cursorPos, 0, type ) )
1065 {
1066 if( type == SCH_JUNCTION_T )
1067 {
1068 if( !screen->IsExplicitJunctionAllowed( cursorPos ) )
1069 {
1070 m_frame->ShowInfoBarError( _( "Junction location contains no joinable "
1071 "wires and/or pins." ) );
1072 loggedInfoBarError = true;
1073 continue;
1074 }
1075 else if( loggedInfoBarError )
1076 {
1078 }
1079 }
1080
1081 SCH_ITEM* newItem = static_cast<SCH_ITEM*>( previewItem->Clone() );
1082 const_cast<KIID&>( newItem->m_Uuid ) = KIID();
1083 newItem->SetPosition( cursorPos );
1084 newItem->SetFlags( IS_NEW );
1085 m_frame->AddToScreen( newItem, screen );
1086
1087 if( allowRepeat )
1088 m_frame->SaveCopyForRepeatItem( newItem );
1089
1090 SCH_COMMIT commit( m_toolMgr );
1091 commit.Added( newItem, screen );
1092
1093 m_frame->SchematicCleanUp( &commit );
1094
1095 commit.Push( description );
1096 }
1097
1098 if( evt->IsDblClick( BUT_LEFT ) || type == SCH_SHEET_PIN_T ) // Finish tool.
1099 {
1100 m_frame->PopTool( aEvent );
1101 break;
1102 }
1103 }
1104 else if( evt->IsClick( BUT_RIGHT ) )
1105 {
1107 }
1108 else if( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() )
1109 {
1110 previewItem->SetPosition( cursorPos );
1112 m_view->AddToPreview( previewItem->Clone() );
1113 m_frame->SetMsgPanel( previewItem );
1114 }
1115 else if( evt->Category() == TC_COMMAND )
1116 {
1117 if( ( type == SCH_BUS_WIRE_ENTRY_T ) && ( evt->IsAction( &EE_ACTIONS::rotateCW )
1118 || evt->IsAction( &EE_ACTIONS::rotateCCW )
1119 || evt->IsAction( &EE_ACTIONS::mirrorV )
1120 || evt->IsAction( &EE_ACTIONS::mirrorH ) ) )
1121 {
1122 SCH_BUS_ENTRY_BASE* busItem = static_cast<SCH_BUS_ENTRY_BASE*>( previewItem );
1123
1124 if( evt->IsAction( &EE_ACTIONS::rotateCW ) )
1125 {
1126 busItem->Rotate( busItem->GetPosition(), false );
1127 }
1128 else if( evt->IsAction( &EE_ACTIONS::rotateCCW ) )
1129 {
1130 busItem->Rotate( busItem->GetPosition(), true );
1131 }
1132 else if( evt->IsAction( &EE_ACTIONS::mirrorV ) )
1133 {
1134 busItem->MirrorVertically( busItem->GetPosition().y );
1135 }
1136 else if( evt->IsAction( &EE_ACTIONS::mirrorH ) )
1137 {
1138 busItem->MirrorHorizontally( busItem->GetPosition().x );
1139 }
1140
1142 m_view->AddToPreview( previewItem->Clone() );
1143 }
1144 else if( evt->IsAction( &EE_ACTIONS::properties ) )
1145 {
1146 switch( type )
1147 {
1149 {
1150 std::deque<SCH_ITEM*> strokeItems;
1151 strokeItems.push_back( previewItem );
1152
1153 DIALOG_WIRE_BUS_PROPERTIES dlg( m_frame, strokeItems );
1154 }
1155 break;
1156
1157 case SCH_JUNCTION_T:
1158 {
1159 std::deque<SCH_JUNCTION*> junctions;
1160 junctions.push_back( static_cast<SCH_JUNCTION*>( previewItem ) );
1161
1162 DIALOG_JUNCTION_PROPS dlg( m_frame, junctions );
1163 }
1164 break;
1165 default:
1166 // Do nothing
1167 break;
1168 }
1169
1171 m_view->AddToPreview( previewItem->Clone() );
1172 }
1173 else
1174 {
1175 evt->SetPassEvent();
1176 }
1177 }
1178 else
1179 {
1180 evt->SetPassEvent();
1181 }
1182 }
1183
1184 delete previewItem;
1186
1187 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1188 controls->ForceCursorPosition( false );
1189
1190 return 0;
1191}
1192
1193
1195{
1196 for( SCH_ITEM* item : m_frame->GetScreen()->Items().Overlapping( SCH_LINE_T, aPosition ) )
1197 {
1198 SCH_LINE* line = static_cast<SCH_LINE*>( item );
1199
1200 if( line->GetEditFlags() & STRUCT_DELETED )
1201 continue;
1202
1203 if( line->IsWire() )
1204 return line;
1205 }
1206
1207 return nullptr;
1208}
1209
1210
1212{
1213 wxASSERT( aWire->IsWire() );
1214
1215 SCH_SHEET_PATH sheetPath = m_frame->GetCurrentSheet();
1216
1217 if( SCH_CONNECTION* wireConnection = aWire->Connection( &sheetPath ) )
1218 {
1219 SCH_ITEM* wireDriver = wireConnection->Driver();
1220
1221 if( wireDriver && wireDriver->IsType( { SCH_LABEL_T, SCH_GLOBAL_LABEL_T } ) )
1222 return wireConnection->LocalName();
1223 }
1224
1225 return wxEmptyString;
1226}
1227
1228
1230{
1231 SCHEMATIC* schematic = getModel<SCHEMATIC>();
1232 SCHEMATIC_SETTINGS& settings = schematic->Settings();
1233 SCH_TEXT* textItem = nullptr;
1234 SCH_LABEL_BASE* labelItem = nullptr;
1235 wxString netName;
1236
1237 switch( aType )
1238 {
1239 case LAYER_NOTES:
1240 textItem = new SCH_TEXT( aPosition );
1241 break;
1242
1243 case LAYER_LOCLABEL:
1244 labelItem = new SCH_LABEL( aPosition );
1245 textItem = labelItem;
1246
1247 if( SCH_LINE* wire = findWire( aPosition ) )
1248 netName = findWireLabelDriverName( wire );
1249
1250 break;
1251
1253 labelItem = new SCH_DIRECTIVE_LABEL( aPosition );
1254 labelItem->SetShape( m_lastNetClassFlagShape );
1255 labelItem->GetFields().emplace_back( SCH_FIELD( {0,0}, 0, labelItem, wxT( "Netclass" ) ) );
1256 labelItem->GetFields().back().SetItalic( true );
1257 labelItem->GetFields().back().SetVisible( true );
1258 textItem = labelItem;
1259 break;
1260
1261 case LAYER_HIERLABEL:
1262 labelItem = new SCH_HIERLABEL( aPosition );
1263 labelItem->SetShape( m_lastGlobalLabelShape );
1265 textItem = labelItem;
1266 break;
1267
1268 case LAYER_GLOBLABEL:
1269 labelItem = new SCH_GLOBALLABEL( aPosition );
1270 labelItem->SetShape( m_lastGlobalLabelShape );
1271 labelItem->GetFields()[0].SetVisible( settings.m_IntersheetRefsShow );
1273 textItem = labelItem;
1274
1275 if( SCH_LINE* wire = findWire( aPosition ) )
1276 netName = findWireLabelDriverName( wire );
1277
1278 break;
1279
1280 default:
1281 wxFAIL_MSG( "SCH_EDIT_FRAME::CreateNewText() unknown layer type" );
1282 return nullptr;
1283 }
1284
1285 textItem->SetParent( schematic );
1286
1287 textItem->SetTextSize( VECTOR2I( settings.m_DefaultTextSize, settings.m_DefaultTextSize ) );
1288
1289 if( aType != LAYER_NETCLASS_REFS )
1290 {
1291 // Must be after SetTextSize()
1292 textItem->SetBold( m_lastTextBold );
1293 textItem->SetItalic( m_lastTextItalic );
1294 }
1295
1296 if( labelItem )
1297 {
1298 labelItem->SetSpinStyle( m_lastTextOrientation );
1299 }
1300 else
1301 {
1304 textItem->SetTextAngle( m_lastTextAngle );
1305 }
1306
1307 textItem->SetFlags( IS_NEW | IS_MOVING );
1308
1309 if( !labelItem )
1310 {
1311 DIALOG_TEXT_PROPERTIES dlg( m_frame, textItem );
1312
1313 // QuasiModal required for syntax help and Scintilla auto-complete
1314 if( dlg.ShowQuasiModal() != wxID_OK )
1315 {
1316 delete textItem;
1317 return nullptr;
1318 }
1319 }
1320 else if( !netName.IsEmpty() )
1321 {
1322 // Auto-create from attached wire
1323 textItem->SetText( netName );
1324 }
1325 else
1326 {
1327 DIALOG_LABEL_PROPERTIES dlg( m_frame, static_cast<SCH_LABEL_BASE*>( textItem ) );
1328
1329 // QuasiModal required for syntax help and Scintilla auto-complete
1330 if( dlg.ShowQuasiModal() != wxID_OK )
1331 {
1332 delete labelItem;
1333 return nullptr;
1334 }
1335 }
1336
1337 wxString text = textItem->GetText();
1338
1339 if( textItem->Type() != SCH_DIRECTIVE_LABEL_T && NoPrintableChars( text ) )
1340 {
1341 delete textItem;
1342 return nullptr;
1343 }
1344
1345 if( aType != LAYER_NETCLASS_REFS )
1346 {
1347 m_lastTextBold = textItem->IsBold();
1348 m_lastTextItalic = textItem->IsItalic();
1349 }
1350
1351 if( labelItem )
1352 {
1353 m_lastTextOrientation = labelItem->GetSpinStyle();
1354 }
1355 else
1356 {
1357 m_lastTextHJustify = textItem->GetHorizJustify();
1358 m_lastTextVJustify = textItem->GetVertJustify();
1359 m_lastTextAngle = textItem->GetTextAngle();
1360 }
1361
1362 if( aType == LAYER_GLOBLABEL || aType == LAYER_HIERLABEL )
1363 {
1364 m_lastGlobalLabelShape = labelItem->GetShape();
1366 }
1367 else if( aType == LAYER_NETCLASS_REFS )
1368 {
1369 m_lastNetClassFlagShape = labelItem->GetShape();
1370 }
1371
1372 return textItem;
1373}
1374
1376{
1377 SCHEMATIC_SETTINGS& settings = aSheet->Schematic()->Settings();
1378 SCH_SHEET_PIN* pin = new SCH_SHEET_PIN( aSheet );
1379
1380 pin->SetFlags( IS_NEW | IS_MOVING );
1381 pin->SetText( std::to_string( aSheet->GetPins().size() + 1 ) );
1382 pin->SetTextSize( VECTOR2I( settings.m_DefaultTextSize, settings.m_DefaultTextSize ) );
1383 pin->SetPosition( aPosition );
1384 pin->ClearSelected();
1385
1386 m_lastSheetPinType = pin->GetShape();
1387
1388 return pin;
1389}
1390
1391
1393{
1394 SCH_ITEM* item = nullptr;
1397 bool ignorePrimePosition = false;
1398 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
1399 SCH_SHEET* sheet = nullptr;
1400 wxString description;
1401
1402 if( m_inDrawingTool )
1403 return 0;
1404
1406
1407 bool isText = aEvent.IsAction( &EE_ACTIONS::placeSchematicText );
1408 bool isGlobalLabel = aEvent.IsAction( &EE_ACTIONS::placeGlobalLabel );
1409 bool isHierLabel = aEvent.IsAction( &EE_ACTIONS::placeHierLabel );
1410 bool isClassLabel = aEvent.IsAction( &EE_ACTIONS::placeClassLabel );
1411 bool isNetLabel = aEvent.IsAction( &EE_ACTIONS::placeLabel );
1412 bool isSheetPin = aEvent.IsAction( &EE_ACTIONS::placeSheetPin );
1413
1414 GRID_HELPER_GRIDS snapGrid = isText ? GRID_TEXT : GRID_CONNECTABLE;
1415
1416 // If we have a selected sheet use it, otherwise try to get one under the cursor
1417 if( isSheetPin )
1418 sheet = dynamic_cast<SCH_SHEET*>( m_selectionTool->GetSelection().Front() );
1419
1421
1422 m_frame->PushTool( aEvent );
1423
1424 auto setCursor =
1425 [&]()
1426 {
1427 if( item )
1428 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PLACE );
1429 else if( isText )
1430 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::TEXT );
1431 else if( isGlobalLabel )
1432 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_GLOBAL );
1433 else if( isNetLabel )
1434 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_NET );
1435 else if( isClassLabel )
1436 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_NET ); // JEY TODO: netclass directive cursor
1437 else if( isHierLabel )
1438 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_HIER );
1439 else
1440 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
1441 };
1442
1443 auto updatePreview =
1444 [&]()
1445 {
1447 m_view->AddToPreview( item->Clone() );
1448 item->RunOnChildren( [&]( SCH_ITEM* aChild )
1449 {
1450 m_view->AddToPreview( aChild->Clone() );
1451 } );
1452 m_frame->SetMsgPanel( item );
1453 };
1454
1455 auto cleanup =
1456 [&]()
1457 {
1460 delete item;
1461 item = nullptr;
1462 };
1463
1464 Activate();
1465
1466 // Must be done after Activate() so that it gets set into the correct context
1467 controls->ShowCursor( true );
1468
1469 // Set initial cursor
1470 setCursor();
1471
1472 if( aEvent.HasPosition() )
1473 {
1474 m_toolMgr->PrimeTool( aEvent.Position() );
1475 }
1476 else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate()
1477 && ( isText || isGlobalLabel || isHierLabel || isClassLabel || isNetLabel ) )
1478 {
1479 m_toolMgr->PrimeTool( { 0, 0 } );
1480 ignorePrimePosition = true;
1481 }
1482
1483 // Main loop: keep receiving events
1484 while( TOOL_EVENT* evt = Wait() )
1485 {
1486 setCursor();
1487 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1488 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1489
1490 VECTOR2I cursorPos = controls->GetMousePosition();
1491 cursorPos = grid.BestSnapAnchor( cursorPos, snapGrid, item );
1492 controls->ForceCursorPosition( true, cursorPos );
1493
1494 // The tool hotkey is interpreted as a click when drawing
1495 bool isSyntheticClick = item && evt->IsActivate() && evt->HasPosition()
1496 && evt->Matches( aEvent );
1497
1498 if( evt->IsCancelInteractive() || evt->IsAction( &ACTIONS::undo ) )
1499 {
1501
1502 if( item )
1503 {
1504 cleanup();
1505 }
1506 else
1507 {
1508 m_frame->PopTool( aEvent );
1509 break;
1510 }
1511 }
1512 else if( evt->IsActivate() && !isSyntheticClick )
1513 {
1514 if( item && evt->IsMoveTool() )
1515 {
1516 // we're already moving our own item; ignore the move tool
1517 evt->SetPassEvent( false );
1518 continue;
1519 }
1520
1521 if( item )
1522 {
1523 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel item creation." ) );
1524 evt->SetPassEvent( false );
1525 continue;
1526 }
1527
1528 if( evt->IsPointEditor() )
1529 {
1530 // don't exit (the point editor runs in the background)
1531 }
1532 else if( evt->IsMoveTool() )
1533 {
1534 // leave ourselves on the stack so we come back after the move
1535 break;
1536 }
1537 else
1538 {
1539 m_frame->PopTool( aEvent );
1540 break;
1541 }
1542 }
1543 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) || isSyntheticClick )
1544 {
1545 // First click creates...
1546 if( !item )
1547 {
1549
1550 if( isText )
1551 {
1552 item = createNewText( cursorPos, LAYER_NOTES );
1553 description = _( "Add Text" );
1554 }
1555 else if( isHierLabel )
1556 {
1557 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->GetPlacementTemplate() )
1558 {
1559 auto pin = static_cast<SCH_HIERLABEL*>(
1560 m_dialogSyncSheetPin->GetPlacementTemplate() );
1561 SCH_HIERLABEL* label = new SCH_HIERLABEL( cursorPos );
1562 SCHEMATIC* schematic = getModel<SCHEMATIC>();
1563 label->SetText( pin->GetText() );
1564 label->SetShape( pin->GetShape() );
1566 label->SetParent( schematic );
1567 label->SetBold( m_lastTextBold );
1568 label->SetItalic( m_lastTextItalic );
1570 label->SetTextSize( VECTOR2I( schematic->Settings().m_DefaultTextSize,
1571 schematic->Settings().m_DefaultTextSize ) );
1572 label->SetFlags( IS_NEW | IS_MOVING );
1573 item = label;
1574 }
1575 else
1576 {
1577 item = createNewText( cursorPos, LAYER_HIERLABEL );
1578 }
1579
1580 description = _( "Add Hierarchical Label" );
1581 }
1582 else if( isNetLabel )
1583 {
1584 item = createNewText( cursorPos, LAYER_LOCLABEL );
1585 description = _( "Add Label" );
1586 }
1587 else if( isGlobalLabel )
1588 {
1589 item = createNewText( cursorPos, LAYER_GLOBLABEL );
1590 description = _( "Add Label" );
1591 }
1592 else if( isClassLabel )
1593 {
1594 item = createNewText( cursorPos, LAYER_NETCLASS_REFS );
1595 description = _( "Add Label" );
1596 }
1597 else if( isSheetPin )
1598 {
1599 EDA_ITEM* i = nullptr;
1600
1601 // If we didn't have a sheet selected, try to find one under the cursor
1602 if( !sheet && m_selectionTool->SelectPoint( cursorPos, { SCH_SHEET_T }, &i ) )
1603 sheet = dynamic_cast<SCH_SHEET*>( i );
1604
1605 if( !sheet )
1606 {
1607 m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( m_frame );
1608 m_statusPopup->SetText( _( "Click over a sheet." ) );
1610 + wxPoint( 20, 20 ) );
1611 m_statusPopup->PopupFor( 2000 );
1612 item = nullptr;
1613 }
1614 else
1615 {
1616 item = createNewSheetPin( sheet, cursorPos );
1617
1618 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->GetPlacementTemplate() )
1619 {
1620 auto label = static_cast<SCH_HIERLABEL*>(
1621 m_dialogSyncSheetPin->GetPlacementTemplate() );
1622 auto pin = static_cast<SCH_HIERLABEL*>( item );
1623 pin->SetText( label->GetText() );
1624 pin->SetShape( label->GetShape() );
1625 }
1626 }
1627
1628 description = _( "Add Sheet Pin" );
1629 }
1630
1631 // If we started with a hotkey which has a position then warp back to that.
1632 // Otherwise update to the current mouse position pinned inside the autoscroll
1633 // boundaries.
1634 if( evt->IsPrime() && !ignorePrimePosition )
1635 {
1636 cursorPos = grid.Align( evt->Position() );
1637 getViewControls()->WarpMouseCursor( cursorPos, true );
1638 }
1639 else
1640 {
1642 cursorPos = getViewControls()->GetMousePosition();
1643 cursorPos = grid.BestSnapAnchor( cursorPos, snapGrid, item );
1644 }
1645
1646 if( item )
1647 {
1648 item->SetPosition( cursorPos );
1649
1650 item->SetFlags( IS_NEW | IS_MOVING );
1651 item->AutoplaceFields( nullptr, false /* aManual */ );
1652 updatePreview();
1655
1656 // update the cursor so it looks correct before another event
1657 setCursor();
1658 }
1659
1660 controls->SetCursorPosition( cursorPos, false );
1661 }
1662 else // ... and second click places:
1663 {
1664 SCH_COMMIT commit( m_toolMgr );
1665
1666 item->ClearFlags( IS_MOVING );
1667
1668 if( item->IsConnectable() )
1670
1671 if( isSheetPin )
1672 {
1673 // Sheet pins are owned by their parent sheet.
1674 commit.Modify( sheet, m_frame->GetScreen() );
1675 sheet->AddPin( (SCH_SHEET_PIN*) item );
1676 }
1677 else
1678 {
1680 m_frame->AddToScreen( item, m_frame->GetScreen() );
1681 commit.Added( item, m_frame->GetScreen() );
1682 }
1683
1684 item->AutoplaceFields( m_frame->GetScreen(), false /* aManual */ );
1685
1686 commit.Push( description );
1687
1689
1690 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->GetPlacementTemplate() )
1691 {
1692 m_frame->PopTool( aEvent );
1694 m_dialogSyncSheetPin->EndPlaceItem( item );
1695 m_dialogSyncSheetPin->Show( true );
1696 break;
1697 }
1698 else
1699 {
1700 item = nullptr;
1701 }
1702
1703 if( isSheetPin )
1704 {
1705 item = createNewSheetPin( sheet, cursorPos );
1706 item->SetPosition( cursorPos );
1709 }
1710 }
1711 }
1712 else if( evt->IsClick( BUT_RIGHT ) )
1713 {
1714 // Warp after context menu only if dragging...
1715 if( !item )
1717
1719 }
1720 else if( item && evt->IsSelectionEvent() )
1721 {
1722 // This happens if our text was replaced out from under us by ConvertTextType()
1724
1725 if( selection.GetSize() == 1 )
1726 {
1727 item = (SCH_ITEM*) selection.Front();
1728 updatePreview();
1729 }
1730 else
1731 {
1732 item = nullptr;
1733 }
1734 }
1735 else if( evt->IsAction( &ACTIONS::duplicate )
1736 || evt->IsAction( &EE_ACTIONS::repeatDrawItem ) )
1737 {
1738 if( item )
1739 {
1740 // This doesn't really make sense; we'll just end up dragging a stack of
1741 // objects so we ignore the duplicate and just carry on.
1742 wxBell();
1743 continue;
1744 }
1745
1746 // Exit. The duplicate will run in its own loop.
1747 m_frame->PopTool( aEvent );
1748 break;
1749 }
1750 else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
1751 {
1752 item->SetPosition( cursorPos );
1753 item->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
1754 updatePreview();
1755 }
1756 else if( item && evt->IsAction( &ACTIONS::doDelete ) )
1757 {
1758 cleanup();
1759 }
1760 else if( evt->IsAction( &ACTIONS::redo ) )
1761 {
1762 wxBell();
1763 }
1764 else
1765 {
1766 evt->SetPassEvent();
1767 }
1768
1769 // Enable autopanning and cursor capture only when there is an item to be placed
1770 controls->SetAutoPan( item != nullptr );
1771 controls->CaptureCursor( item != nullptr );
1772 }
1773
1774 controls->SetAutoPan( false );
1775 controls->CaptureCursor( false );
1776 controls->ForceCursorPosition( false );
1777 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1778
1779 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->GetPlacementTemplate() )
1780 {
1781 m_dialogSyncSheetPin->EndPlaceItem( nullptr );
1782 m_dialogSyncSheetPin->Show( true );
1783 }
1784
1785 return 0;
1786}
1787
1788
1790{
1791 SCHEMATIC* schematic = getModel<SCHEMATIC>();
1792 SCHEMATIC_SETTINGS& sch_settings = schematic->Settings();
1793 SCH_SHAPE* item = nullptr;
1794 bool isTextBox = aEvent.IsAction( &EE_ACTIONS::drawTextBox );
1795 SHAPE_T type = aEvent.Parameter<SHAPE_T>();
1796 wxString description;
1797
1798 if( m_inDrawingTool )
1799 return 0;
1800
1802
1805 VECTOR2I cursorPos;
1806
1807 // We might be running as the same shape in another co-routine. Make sure that one
1808 // gets whacked.
1810
1812
1813 m_frame->PushTool( aEvent );
1814
1815 auto setCursor =
1816 [&]()
1817 {
1818 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
1819 };
1820
1821 auto cleanup =
1822 [&] ()
1823 {
1826 delete item;
1827 item = nullptr;
1828 };
1829
1830 Activate();
1831
1832 // Must be done after Activate() so that it gets set into the correct context
1833 getViewControls()->ShowCursor( true );
1834
1835 // Set initial cursor
1836 setCursor();
1837
1838 if( aEvent.HasPosition() )
1839 m_toolMgr->PrimeTool( aEvent.Position() );
1840
1841 // Main loop: keep receiving events
1842 while( TOOL_EVENT* evt = Wait() )
1843 {
1844 setCursor();
1845 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1846 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1847
1848 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
1849 controls->ForceCursorPosition( true, cursorPos );
1850
1851 // The tool hotkey is interpreted as a click when drawing
1852 bool isSyntheticClick = item && evt->IsActivate() && evt->HasPosition()
1853 && evt->Matches( aEvent );
1854
1855 if( evt->IsCancelInteractive() || ( item && evt->IsAction( &ACTIONS::undo ) ) )
1856 {
1857 if( item )
1858 {
1859 cleanup();
1860 }
1861 else
1862 {
1863 m_frame->PopTool( aEvent );
1864 break;
1865 }
1866 }
1867 else if( evt->IsActivate() && !isSyntheticClick )
1868 {
1869 if( item && evt->IsMoveTool() )
1870 {
1871 // we're already drawing our own item; ignore the move tool
1872 evt->SetPassEvent( false );
1873 continue;
1874 }
1875
1876 if( item )
1877 cleanup();
1878
1879 if( evt->IsPointEditor() )
1880 {
1881 // don't exit (the point editor runs in the background)
1882 }
1883 else if( evt->IsMoveTool() )
1884 {
1885 // leave ourselves on the stack so we come back after the move
1886 break;
1887 }
1888 else
1889 {
1890 m_frame->PopTool( aEvent );
1891 break;
1892 }
1893 }
1894 else if( evt->IsClick( BUT_LEFT ) && !item )
1895 {
1897
1898 if( isTextBox )
1899 {
1901
1902 textbox->SetTextSize( VECTOR2I( sch_settings.m_DefaultTextSize,
1903 sch_settings.m_DefaultTextSize ) );
1904
1905 // Must come after SetTextSize()
1906 textbox->SetBold( m_lastTextBold );
1907 textbox->SetItalic( m_lastTextItalic );
1908
1909 textbox->SetTextAngle( m_lastTextboxAngle );
1912 textbox->SetStroke( m_lastTextboxStroke );
1914 textbox->SetParent( schematic );
1915
1916 item = textbox;
1917 description = _( "Add Text Box" );
1918 }
1919 else
1920 {
1921 item = new SCH_SHAPE( type, LAYER_NOTES, 0, m_lastFillStyle );
1922
1923 item->SetStroke( m_lastStroke );
1925 item->SetParent( schematic );
1926 description = wxString::Format( _( "Add %s" ), item->GetFriendlyName() );
1927 }
1928
1929 item->SetFlags( IS_NEW );
1930 item->BeginEdit( cursorPos );
1931
1933 m_view->AddToPreview( item->Clone() );
1934 }
1935 else if( item && ( evt->IsClick( BUT_LEFT )
1936 || evt->IsDblClick( BUT_LEFT )
1937 || isSyntheticClick
1938 || evt->IsAction( &ACTIONS::finishInteractive ) ) )
1939 {
1940 if( evt->IsDblClick( BUT_LEFT )
1941 || evt->IsAction( &ACTIONS::finishInteractive )
1942 || !item->ContinueEdit( cursorPos ) )
1943 {
1944 item->EndEdit();
1945 item->ClearEditFlags();
1946 item->SetFlags( IS_NEW );
1947
1948 if( isTextBox )
1949 {
1950 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( item );
1951 DIALOG_TEXT_PROPERTIES dlg( m_frame, textbox );
1952
1953 getViewControls()->SetAutoPan( false );
1954 getViewControls()->CaptureCursor( false );
1955
1956 // QuasiModal required for syntax help and Scintilla auto-complete
1957 if( dlg.ShowQuasiModal() != wxID_OK )
1958 {
1959 cleanup();
1960 continue;
1961 }
1962
1963 m_lastTextBold = textbox->IsBold();
1964 m_lastTextItalic = textbox->IsItalic();
1965 m_lastTextboxAngle = textbox->GetTextAngle();
1968 m_lastTextboxStroke = textbox->GetStroke();
1971 }
1972 else
1973 {
1974 m_lastStroke = item->GetStroke();
1975 m_lastFillStyle = item->GetFillMode();
1976 m_lastFillColor = item->GetFillColor();
1977 }
1978
1979 SCH_COMMIT commit( m_toolMgr );
1980 commit.Add( item, m_frame->GetScreen() );
1981 commit.Push( wxString::Format( _( "Draw %s" ), item->GetClass() ) );
1982
1984 item = nullptr;
1985
1988 }
1989 }
1990 else if( evt->IsAction( &ACTIONS::duplicate )
1991 || evt->IsAction( &EE_ACTIONS::repeatDrawItem ) )
1992 {
1993 if( item )
1994 {
1995 // This doesn't really make sense; we'll just end up dragging a stack of
1996 // objects so we ignore the duplicate and just carry on.
1997 wxBell();
1998 continue;
1999 }
2000
2001 // Exit. The duplicate will run in its own loop.
2002 m_frame->PopTool( aEvent );
2003 break;
2004 }
2005 else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
2006 {
2007 item->CalcEdit( cursorPos );
2009 m_view->AddToPreview( item->Clone() );
2010 m_frame->SetMsgPanel( item );
2011 }
2012 else if( evt->IsDblClick( BUT_LEFT ) && !item )
2013 {
2015 }
2016 else if( evt->IsClick( BUT_RIGHT ) )
2017 {
2018 // Warp after context menu only if dragging...
2019 if( !item )
2021
2023 }
2024 else if( item && evt->IsAction( &ACTIONS::redo ) )
2025 {
2026 wxBell();
2027 }
2028 else
2029 {
2030 evt->SetPassEvent();
2031 }
2032
2033 // Enable autopanning and cursor capture only when there is a shape being drawn
2034 getViewControls()->SetAutoPan( item != nullptr );
2035 getViewControls()->CaptureCursor( item != nullptr );
2036 }
2037
2038 getViewControls()->SetAutoPan( false );
2039 getViewControls()->CaptureCursor( false );
2040 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2041 return 0;
2042}
2043
2044
2046{
2047 if( m_inDrawingTool )
2048 return 0;
2049
2051 SCOPED_SET_RESET<bool> scopedDrawMode( m_drawingRuleArea, true );
2052
2055 VECTOR2I cursorPos;
2056
2057 RULE_AREA_CREATE_HELPER ruleAreaTool( *getView(), m_frame, m_toolMgr );
2058 POLYGON_GEOM_MANAGER polyGeomMgr( ruleAreaTool );
2059 bool started = false;
2060
2061 // We might be running as the same shape in another co-routine. Make sure that one
2062 // gets whacked.
2064
2066
2067 m_frame->PushTool( aEvent );
2068
2069 auto setCursor =
2070 [&]()
2071 {
2072 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
2073 };
2074
2075 auto cleanup = [&]()
2076 {
2077 polyGeomMgr.Reset();
2078 started = false;
2079 getViewControls()->SetAutoPan( false );
2080 getViewControls()->CaptureCursor( false );
2082 };
2083
2084 Activate();
2085
2086 // Must be done after Activate() so that it gets set into the correct context
2087 getViewControls()->ShowCursor( true );
2088 //m_controls->ForceCursorPosition( false );
2089
2090 // Set initial cursor
2091 setCursor();
2092
2093 if( aEvent.HasPosition() )
2094 m_toolMgr->PrimeTool( aEvent.Position() );
2095
2096 // Main loop: keep receiving events
2097 while( TOOL_EVENT* evt = Wait() )
2098 {
2099 setCursor();
2100
2101 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
2102 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
2103
2104 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_CONNECTABLE );
2105 controls->ForceCursorPosition( true, cursorPos );
2106
2110
2111 if( evt->IsCancelInteractive() )
2112 {
2113 if( started )
2114 {
2115 cleanup();
2116 }
2117 else
2118 {
2119 m_frame->PopTool( aEvent );
2120
2121 // We've handled the cancel event. Don't cancel other tools
2122 evt->SetPassEvent( false );
2123 break;
2124 }
2125 }
2126 else if( evt->IsActivate() )
2127 {
2128 if( started )
2129 cleanup();
2130
2131 if( evt->IsPointEditor() )
2132 {
2133 // don't exit (the point editor runs in the background)
2134 }
2135 else if( evt->IsMoveTool() )
2136 {
2137 // leave ourselves on the stack so we come back after the move
2138 break;
2139 }
2140 else
2141 {
2142 m_frame->PopTool( aEvent );
2143 break;
2144 }
2145 }
2146 else if( evt->IsClick( BUT_RIGHT ) )
2147 {
2148 if( !started )
2150
2152 }
2153 // events that lock in nodes
2154 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT )
2155 || evt->IsAction( &EE_ACTIONS::closeOutline ) )
2156 {
2157 // Check if it is double click / closing line (so we have to finish the zone)
2158 const bool endPolygon = evt->IsDblClick( BUT_LEFT )
2159 || evt->IsAction( &EE_ACTIONS::closeOutline )
2160 || polyGeomMgr.NewPointClosesOutline( cursorPos );
2161
2162 if( endPolygon )
2163 {
2164 polyGeomMgr.SetFinished();
2165 polyGeomMgr.Reset();
2166
2167 started = false;
2168 getViewControls()->SetAutoPan( false );
2169 getViewControls()->CaptureCursor( false );
2170 }
2171 // adding a corner
2172 else if( polyGeomMgr.AddPoint( cursorPos ) )
2173 {
2174 if( !started )
2175 {
2176 started = true;
2177
2178 getViewControls()->SetAutoPan( true );
2179 getViewControls()->CaptureCursor( true );
2180 }
2181 }
2182 }
2183 else if( started
2184 && ( evt->IsAction( &EE_ACTIONS::deleteLastPoint )
2185 || evt->IsAction( &ACTIONS::doDelete ) || evt->IsAction( &ACTIONS::undo ) ) )
2186 {
2187 if( std::optional<VECTOR2I> last = polyGeomMgr.DeleteLastCorner() )
2188 {
2189 cursorPos = last.value();
2190 getViewControls()->WarpMouseCursor( cursorPos, true );
2191 getViewControls()->ForceCursorPosition( true, cursorPos );
2192 polyGeomMgr.SetCursorPosition( cursorPos );
2193 }
2194 else
2195 {
2196 cleanup();
2197 }
2198 }
2199 else if( started && ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) )
2200 {
2201 polyGeomMgr.SetCursorPosition( cursorPos );
2202 }
2203 else
2204 {
2205 evt->SetPassEvent();
2206 }
2207
2208 } // end while
2209
2210 getViewControls()->SetAutoPan( false );
2211 getViewControls()->CaptureCursor( false );
2212 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2213 return 0;
2214}
2215
2216
2218{
2219 SCHEMATIC* schematic = getModel<SCHEMATIC>();
2220 SCH_TABLE* table = nullptr;
2221
2222 if( m_inDrawingTool )
2223 return 0;
2224
2226
2229 VECTOR2I cursorPos;
2230
2231 // We might be running as the same shape in another co-routine. Make sure that one
2232 // gets whacked.
2234
2236
2237 m_frame->PushTool( aEvent );
2238
2239 auto setCursor =
2240 [&]()
2241 {
2242 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
2243 };
2244
2245 auto cleanup =
2246 [&] ()
2247 {
2250 delete table;
2251 table = nullptr;
2252 };
2253
2254 Activate();
2255
2256 // Must be done after Activate() so that it gets set into the correct context
2257 getViewControls()->ShowCursor( true );
2258
2259 // Set initial cursor
2260 setCursor();
2261
2262 if( aEvent.HasPosition() )
2263 m_toolMgr->PrimeTool( aEvent.Position() );
2264
2265 // Main loop: keep receiving events
2266 while( TOOL_EVENT* evt = Wait() )
2267 {
2268 setCursor();
2269 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
2270 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
2271
2272 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
2273 controls->ForceCursorPosition( true, cursorPos );
2274
2275 // The tool hotkey is interpreted as a click when drawing
2276 bool isSyntheticClick = table && evt->IsActivate() && evt->HasPosition()
2277 && evt->Matches( aEvent );
2278
2279 if( evt->IsCancelInteractive() || ( table && evt->IsAction( &ACTIONS::undo ) ) )
2280 {
2281 if( table )
2282 {
2283 cleanup();
2284 }
2285 else
2286 {
2287 m_frame->PopTool( aEvent );
2288 break;
2289 }
2290 }
2291 else if( evt->IsActivate() && !isSyntheticClick )
2292 {
2293 if( table && evt->IsMoveTool() )
2294 {
2295 // we're already drawing our own item; ignore the move tool
2296 evt->SetPassEvent( false );
2297 continue;
2298 }
2299
2300 if( table )
2301 cleanup();
2302
2303 if( evt->IsPointEditor() )
2304 {
2305 // don't exit (the point editor runs in the background)
2306 }
2307 else if( evt->IsMoveTool() )
2308 {
2309 // leave ourselves on the stack so we come back after the move
2310 break;
2311 }
2312 else
2313 {
2314 m_frame->PopTool( aEvent );
2315 break;
2316 }
2317 }
2318 else if( evt->IsClick( BUT_LEFT ) && !table )
2319 {
2321
2322 table = new SCH_TABLE( 0 );
2323 table->SetColCount( 1 );
2324 table->AddCell( new SCH_TABLECELL() );
2325
2326 table->SetParent( schematic );
2327 table->SetFlags( IS_NEW );
2328 table->SetPosition( cursorPos );
2329
2331 m_view->AddToPreview( table->Clone() );
2332 }
2333 else if( table && ( evt->IsClick( BUT_LEFT )
2334 || evt->IsDblClick( BUT_LEFT )
2335 || isSyntheticClick
2336 || evt->IsAction( &EE_ACTIONS::finishInteractive ) ) )
2337 {
2338 table->ClearEditFlags();
2339 table->SetFlags( IS_NEW );
2340 table->Normalize();
2341
2342 DIALOG_TABLE_PROPERTIES dlg( m_frame, table );
2343
2344 // QuasiModal required for Scintilla auto-complete
2345 if( dlg.ShowQuasiModal() == wxID_OK )
2346 {
2347 SCH_COMMIT commit( m_toolMgr );
2348 commit.Add( table, m_frame->GetScreen() );
2349 commit.Push( _( "Draw Table" ) );
2350
2351 m_selectionTool->AddItemToSel( table );
2353 }
2354 else
2355 {
2356 delete table;
2357 }
2358
2359 table = nullptr;
2361 }
2362 else if( table && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
2363 {
2364 VECTOR2I gridSize = grid.GetGridSize( grid.GetItemGrid( table ) );
2365 int fontSize = schematic->Settings().m_DefaultTextSize;
2366 VECTOR2I origin( table->GetPosition() );
2367 VECTOR2I requestedSize( cursorPos - origin );
2368
2369 int colCount = std::max( 1, requestedSize.x / ( fontSize * 15 ) );
2370 int rowCount = std::max( 1, requestedSize.y / ( fontSize * 2 ) );
2371
2372 VECTOR2I cellSize( std::max( gridSize.x * 5, requestedSize.x / colCount ),
2373 std::max( gridSize.y * 2, requestedSize.y / rowCount ) );
2374
2375 cellSize.x = KiROUND( (double) cellSize.x / gridSize.x ) * gridSize.x;
2376 cellSize.y = KiROUND( (double) cellSize.y / gridSize.y ) * gridSize.y;
2377
2378 table->ClearCells();
2379 table->SetColCount( colCount );
2380
2381 for( int col = 0; col < colCount; ++col )
2382 table->SetColWidth( col, cellSize.x );
2383
2384 for( int row = 0; row < rowCount; ++row )
2385 {
2386 table->SetRowHeight( row, cellSize.y );
2387
2388 for( int col = 0; col < colCount; ++col )
2389 {
2390 SCH_TABLECELL* cell = new SCH_TABLECELL();
2391 cell->SetPosition( origin + VECTOR2I( col * cellSize.x, row * cellSize.y ) );
2392 cell->SetEnd( cell->GetPosition() + cellSize );
2393 table->AddCell( cell );
2394 }
2395 }
2396
2398 m_view->AddToPreview( table->Clone() );
2399 m_frame->SetMsgPanel( table );
2400 }
2401 else if( evt->IsDblClick( BUT_LEFT ) && !table )
2402 {
2404 }
2405 else if( evt->IsClick( BUT_RIGHT ) )
2406 {
2407 // Warp after context menu only if dragging...
2408 if( !table )
2410
2412 }
2413 else if( table && evt->IsAction( &ACTIONS::redo ) )
2414 {
2415 wxBell();
2416 }
2417 else
2418 {
2419 evt->SetPassEvent();
2420 }
2421
2422 // Enable autopanning and cursor capture only when there is a shape being drawn
2423 getViewControls()->SetAutoPan( table != nullptr );
2424 getViewControls()->CaptureCursor( table != nullptr );
2425 }
2426
2427 getViewControls()->SetAutoPan( false );
2428 getViewControls()->CaptureCursor( false );
2429 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2430 return 0;
2431}
2432
2433
2435{
2436 SCH_SHEET* sheet = nullptr;
2437
2438 if( m_inDrawingTool )
2439 return 0;
2440
2442
2445 VECTOR2I cursorPos;
2446
2448
2449 m_frame->PushTool( aEvent );
2450
2451 auto setCursor =
2452 [&]()
2453 {
2454 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
2455 };
2456
2457 auto cleanup =
2458 [&] ()
2459 {
2462 delete sheet;
2463 sheet = nullptr;
2464 };
2465
2466 Activate();
2467
2468 // Must be done after Activate() so that it gets set into the correct context
2469 getViewControls()->ShowCursor( true );
2470
2471 // Set initial cursor
2472 setCursor();
2473
2474 if( aEvent.HasPosition() )
2475 m_toolMgr->PrimeTool( aEvent.Position() );
2476
2477 // Main loop: keep receiving events
2478 while( TOOL_EVENT* evt = Wait() )
2479 {
2480 setCursor();
2481 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
2482 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
2483
2484 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
2485 controls->ForceCursorPosition( true, cursorPos );
2486
2487 // The tool hotkey is interpreted as a click when drawing
2488 bool isSyntheticClick = sheet && evt->IsActivate() && evt->HasPosition()
2489 && evt->Matches( aEvent );
2490
2491 if( evt->IsCancelInteractive() || ( sheet && evt->IsAction( &ACTIONS::undo ) ) )
2492 {
2494
2495 if( sheet )
2496 {
2497 cleanup();
2498 }
2499 else
2500 {
2501 m_frame->PopTool( aEvent );
2502 break;
2503 }
2504 }
2505 else if( evt->IsActivate() && !isSyntheticClick )
2506 {
2507 if( sheet && evt->IsMoveTool() )
2508 {
2509 // we're already drawing our own item; ignore the move tool
2510 evt->SetPassEvent( false );
2511 continue;
2512 }
2513
2514 if( sheet )
2515 {
2516 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel sheet creation." ) );
2517 evt->SetPassEvent( false );
2518 continue;
2519 }
2520
2521 if( evt->IsPointEditor() )
2522 {
2523 // don't exit (the point editor runs in the background)
2524 }
2525 else if( evt->IsMoveTool() )
2526 {
2527 // leave ourselves on the stack so we come back after the move
2528 break;
2529 }
2530 else
2531 {
2532 m_frame->PopTool( aEvent );
2533 break;
2534 }
2535 }
2536 else if( !sheet && ( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) ) )
2537 {
2540
2541 if( selection.Size() == 1
2542 && selection.Front()->Type() == SCH_SHEET_T
2543 && selection.Front()->GetBoundingBox().Contains( cursorPos ) )
2544 {
2545 if( evt->IsClick( BUT_LEFT ) )
2546 {
2547 // sheet already selected
2548 continue;
2549 }
2550 else if( evt->IsDblClick( BUT_LEFT ) )
2551 {
2553 break;
2554 }
2555 }
2556
2558
2559 sheet = new SCH_SHEET( m_frame->GetCurrentSheet().Last(), cursorPos );
2560 sheet->SetFlags( IS_NEW | IS_MOVING );
2561 sheet->SetScreen( nullptr );
2565 sheet->GetFields()[ SHEETNAME ].SetText( "Untitled Sheet" );
2566 sheet->GetFields()[ SHEETFILENAME ].SetText( "untitled." + FILEEXT::KiCadSchematicFileExtension );
2567 sizeSheet( sheet, cursorPos );
2568
2570 m_view->AddToPreview( sheet->Clone() );
2571 }
2572 else if( sheet && ( evt->IsClick( BUT_LEFT )
2573 || evt->IsDblClick( BUT_LEFT )
2574 || isSyntheticClick
2575 || evt->IsAction( &ACTIONS::finishInteractive ) ) )
2576 {
2577 getViewControls()->SetAutoPan( false );
2578 getViewControls()->CaptureCursor( false );
2579
2580 if( m_frame->EditSheetProperties( static_cast<SCH_SHEET*>( sheet ),
2581 &m_frame->GetCurrentSheet() ) )
2582 {
2584
2585 sheet->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
2586
2587 SCH_COMMIT commit( m_toolMgr );
2588 commit.Add( sheet, m_frame->GetScreen() );
2589 commit.Push( "Draw Sheet" );
2590
2592 newPath.push_back( sheet );
2593
2595 m_selectionTool->AddItemToSel( sheet );
2596 }
2597 else
2598 {
2600 delete sheet;
2601 }
2602
2603 sheet = nullptr;
2604 }
2605 else if( evt->IsAction( &ACTIONS::duplicate )
2606 || evt->IsAction( &EE_ACTIONS::repeatDrawItem ) )
2607 {
2608 if( sheet )
2609 {
2610 // This doesn't really make sense; we'll just end up dragging a stack of
2611 // objects so we ignore the duplicate and just carry on.
2612 wxBell();
2613 continue;
2614 }
2615
2616 // Exit. The duplicate will run in its own loop.
2617 m_frame->PopTool( aEvent );
2618 break;
2619 }
2620 else if( sheet && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
2621 {
2622 sizeSheet( sheet, cursorPos );
2624 m_view->AddToPreview( sheet->Clone() );
2625 m_frame->SetMsgPanel( sheet );
2626 }
2627 else if( evt->IsClick( BUT_RIGHT ) )
2628 {
2629 // Warp after context menu only if dragging...
2630 if( !sheet )
2632
2634 }
2635 else if( sheet && evt->IsAction( &ACTIONS::redo ) )
2636 {
2637 wxBell();
2638 }
2639 else
2640 {
2641 evt->SetPassEvent();
2642 }
2643
2644 // Enable autopanning and cursor capture only when there is a sheet to be placed
2645 getViewControls()->SetAutoPan( sheet != nullptr );
2646 getViewControls()->CaptureCursor( sheet != nullptr );
2647 }
2648
2649 getViewControls()->SetAutoPan( false );
2650 getViewControls()->CaptureCursor( false );
2651 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2652
2653 return 0;
2654}
2655
2656
2658{
2659 VECTOR2I pos = aSheet->GetPosition();
2660 VECTOR2I size = aPos - pos;
2661
2662 size.x = std::max( size.x, schIUScale.MilsToIU( MIN_SHEET_WIDTH ) );
2663 size.y = std::max( size.y, schIUScale.MilsToIU( MIN_SHEET_HEIGHT ) );
2664
2666 aSheet->Resize( VECTOR2I( grid.x - pos.x, grid.y - pos.y ) );
2667}
2668
2669
2670int SCH_DRAWING_TOOLS::doSyncSheetsPins( std::list<SCH_SHEET_PATH> sheetPaths )
2671{
2672 if( !sheetPaths.size() )
2673 return 0;
2674
2675 m_dialogSyncSheetPin = std::make_unique<DIALOG_SYNC_SHEET_PINS>(
2676 m_frame, std::move( sheetPaths ),
2677 std::make_shared<SHEET_SYNCHRONIZATION_AGENT>(
2678 [&]( EDA_ITEM* aItem, SCH_SHEET_PATH aPath,
2680 {
2681 SCH_COMMIT commit( m_toolMgr );
2682
2683 if( auto pin = dynamic_cast<SCH_SHEET_PIN*>( aItem ) )
2684 {
2685 commit.Modify( pin->GetParent(), aPath.LastScreen() );
2686 aModify();
2687 commit.Push( _( "Modify sheet pin" ) );
2688 }
2689 else
2690 {
2691 commit.Modify( aItem, aPath.LastScreen() );
2692 aModify();
2693 commit.Push( _( "Modify schematic item" ) );
2694 }
2695
2696 updateItem( aItem, true );
2697 m_frame->OnModify();
2698 },
2699 [&]( EDA_ITEM* aItem, SCH_SHEET_PATH aPath )
2700 {
2702 EE_ACTIONS::changeSheet, &aPath );
2704 selectionTool->UnbrightenItem( aItem );
2705 selectionTool->AddItemToSel( aItem, true );
2707 },
2708 [&]( SCH_SHEET* aItem, SCH_SHEET_PATH aPath,
2710 EDA_ITEM* aTemplate )
2711 {
2712 switch( aOp )
2713 {
2715 {
2716 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
2717 m_dialogSyncSheetPin->Hide();
2718 m_dialogSyncSheetPin->BeginPlaceItem(
2720 aTemplate );
2722 EE_ACTIONS::changeSheet, &aPath );
2724 break;
2725 }
2727 {
2728 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
2729 m_dialogSyncSheetPin->Hide();
2730 m_dialogSyncSheetPin->BeginPlaceItem(
2732 aTemplate );
2734 EE_ACTIONS::changeSheet, &aPath );
2735 m_toolMgr->GetTool<EE_SELECTION_TOOL>()->SyncSelection( {}, nullptr,
2736 { sheet } );
2738 break;
2739 }
2740 }
2741 },
2742 m_toolMgr, m_frame ) );
2743 m_dialogSyncSheetPin->Show( true );
2744 return 0;
2745}
2746
2747
2749{
2750 SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( m_selectionTool->GetSelection().Front() );
2751
2752 if( !sheet )
2753 {
2754 VECTOR2I cursorPos = getViewControls()->GetMousePosition();
2755
2756 if( EDA_ITEM* i = nullptr; static_cast<void>(m_selectionTool->SelectPoint( cursorPos, { SCH_SHEET_T }, &i ) ) , i != nullptr )
2757 {
2758 sheet = dynamic_cast<SCH_SHEET*>( i );
2759 }
2760 }
2761
2762 if ( sheet )
2763 {
2765 current.push_back( sheet );
2766 return doSyncSheetsPins( { current } );
2767 }
2768
2769 return 0;
2770}
2771
2772
2774{
2775 static const std::function<void( std::list<SCH_SHEET_PATH>&, SCH_SCREEN*,
2776 std::set<SCH_SCREEN*>&, SCH_SHEET_PATH const& )>
2777 getSheetChildren = []( std::list<SCH_SHEET_PATH>& aPaths, SCH_SCREEN* aScene,
2778 std::set<SCH_SCREEN*>& aVisited, SCH_SHEET_PATH const& aCurPath )
2779 {
2780 if( ! aScene || aVisited.find(aScene) != aVisited.end() )
2781 return ;
2782
2783 std::vector<SCH_ITEM*> sheetChildren;
2784 aScene->GetSheets( &sheetChildren );
2785 aVisited.insert( aScene );
2786
2787 for( SCH_ITEM* child : sheetChildren )
2788 {
2789 SCH_SHEET_PATH cp = aCurPath;
2790 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( child );
2791 cp.push_back( sheet );
2792 aPaths.push_back( cp );
2793 getSheetChildren( aPaths, sheet->GetScreen(), aVisited, cp );
2794 }
2795 };
2796
2797 std::list<SCH_SHEET_PATH> sheetPaths;
2798 std::set<SCH_SCREEN*> visited;
2799 SCH_SHEET_PATH current;
2800 current.push_back( &m_frame->Schematic().Root() );
2801 getSheetChildren( sheetPaths, m_frame->Schematic().Root().GetScreen(), visited, current );
2802 return doSyncSheetsPins( std::move( sheetPaths ) );
2803}
2804
2805
2807{
2830}
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
static TOOL_ACTION cancelInteractive
Definition: actions.h:64
static TOOL_ACTION undo
Definition: actions.h:67
static TOOL_ACTION duplicate
Definition: actions.h:75
static TOOL_ACTION activatePointEditor
Definition: actions.h:209
static TOOL_ACTION doDelete
Definition: actions.h:76
static TOOL_ACTION redo
Definition: actions.h:68
static TOOL_ACTION refreshPreview
Definition: actions.h:138
static TOOL_ACTION finishInteractive
Definition: actions.h:65
bool Contains(const Vec &aPoint) const
Definition: box2.h:158
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Create an undo entry for an item that has been already modified.
Definition: commit.h:105
COMMIT & Added(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
Definition: commit.h:86
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
Definition: commit.h:80
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.
std::list< std::unique_ptr< EDA_ITEM > > & GetImportedItems()
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:88
virtual void ClearEditFlags()
Definition: eda_item.h:140
virtual void SetPosition(const VECTOR2I &aPos)
Definition: eda_item.h:243
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:132
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:126
const KIID m_Uuid
Definition: eda_item.h:485
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:100
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:128
virtual bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const
Compare the item against the search criteria in aSearchData.
Definition: eda_item.h:375
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:103
virtual wxString GetFriendlyName() const
Definition: eda_item.cpp:329
virtual EDA_ITEM * Clone() const
Create a duplicate of this item with linked list members set to NULL.
Definition: eda_item.cpp:82
FILL_T GetFillMode() const
Definition: eda_shape.h:107
void SetFillColor(const COLOR4D &aColor)
Definition: eda_shape.h:112
COLOR4D GetFillColor() const
Definition: eda_shape.h:111
void SetEnd(const VECTOR2I &aEnd)
Definition: eda_shape.h:171
bool IsItalic() const
Definition: eda_text.h:144
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:134
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition: eda_text.cpp:372
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:98
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition: eda_text.cpp:274
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition: eda_text.h:164
void SetBold(bool aBold)
Definition: eda_text.cpp:219
bool IsBold() const
Definition: eda_text.h:148
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition: eda_text.h:167
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:181
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:203
void SetItalic(bool aItalic)
Definition: eda_text.cpp:211
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition: eda_text.cpp:266
PANEL_ANNOTATE m_AnnotatePanel
PANEL_SYM_CHOOSER m_SymChooserPanel
AUTOPLACE_FIELDS m_AutoplaceFields
static TOOL_ACTION mirrorV
Definition: ee_actions.h:126
static TOOL_ACTION properties
Definition: ee_actions.h:129
static TOOL_ACTION addItemsToSel
Selects a list of items (specified as the event parameter)
Definition: ee_actions.h:63
static TOOL_ACTION changeSheet
Definition: ee_actions.h:217
static TOOL_ACTION drawTable
Definition: ee_actions.h:99
static TOOL_ACTION syncAllSheetsPins
Definition: ee_actions.h:96
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 drawRuleArea
Definition: ee_actions.h:107
static TOOL_ACTION placeClassLabel
Definition: ee_actions.h:88
static TOOL_ACTION closeOutline
Definition: ee_actions.h:109
static TOOL_ACTION drawCircle
Definition: ee_actions.h:101
static TOOL_ACTION rotateCCW
Definition: ee_actions.h:125
static TOOL_ACTION placePower
Definition: ee_actions.h:80
static TOOL_ACTION deleteLastPoint
Definition: ee_actions.h:108
static TOOL_ACTION placeSheetPin
Definition: ee_actions.h:92
static TOOL_ACTION mirrorH
Definition: ee_actions.h:127
static TOOL_ACTION syncSheetPins
Definition: ee_actions.h:94
static TOOL_ACTION rotateCW
Definition: ee_actions.h:124
static TOOL_ACTION importGraphics
Definition: ee_actions.h:254
static TOOL_ACTION leaveSheet
Definition: ee_actions.h:219
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:98
static TOOL_ACTION drawRectangle
Definition: ee_actions.h:100
static TOOL_ACTION placeImage
Definition: ee_actions.h:104
static TOOL_ACTION enterSheet
Definition: ee_actions.h:218
static TOOL_ACTION placeSchematicText
Definition: ee_actions.h:97
static TOOL_ACTION drawArc
Definition: ee_actions.h:102
static TOOL_ACTION drawSheet
Definition: ee_actions.h:91
static TOOL_ACTION placeLabel
Definition: ee_actions.h:87
static TOOL_ACTION repeatDrawItem
Definition: ee_actions.h:123
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
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).
int ClearSelection(const TOOL_EVENT &aEvent)
Select all visible items in sheet.
EE_SELECTION & GetSelection()
A foundation class for a tool operating on a schematic or symbol.
Definition: ee_tool_base.h:48
void updateItem(EDA_ITEM *aItem, bool aUpdateRTree) const
Similar to getView()->Update(), but handles items that are redrawn by their parents and updating the ...
Definition: ee_tool_base.h:109
EE_SELECTION_TOOL * m_selectionTool
Definition: ee_tool_base.h:200
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.
VECTOR2D GetCursorPosition() const
Return the current cursor position 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
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:315
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:354
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:1631
void ClearPreview()
Definition: view.cpp:1653
void RecacheAllItems()
Rebuild GAL display lists.
Definition: view.cpp:1410
void AddToPreview(VIEW_ITEM *aItem, bool aTakeOwnership=true)
Definition: view.cpp:1675
Definition: kiid.h:49
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
bool IsValid() const
Check if this LID_ID is valid.
Definition: lib_id.h:172
UTF8 Format() const
Definition: lib_id.cpp:118
Define a library symbol object.
Definition: lib_symbol.h:77
const LIB_ID & GetLibId() const override
Definition: lib_symbol.h:146
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition: pgm_base.cpp:678
Class that handles the drawing of a polygon, including management of last corner deletion and drawing...
bool AddPoint(const VECTOR2I &aPt)
Lock in a polygon point.
@ DIRECT
Unconstrained point-to-point.
void SetCursorPosition(const VECTOR2I &aPos)
Set the current cursor position.
bool NewPointClosesOutline(const VECTOR2I &aPt) const
std::optional< VECTOR2I > DeleteLastCorner()
Remove the last-added point from the polygon.
void SetFinished()
Mark the polygon finished and update the client.
void SetLeaderMode(LEADER_MODE aMode)
Set the leader mode to use when calculating the leader/returner lines.
void Reset()
Clear the manager state and start again.
static SYMBOL_LIB_TABLE * SchSymbolLibTable(PROJECT *aProject)
Accessor for project symbol library table.
static SYMBOL_LIBS * SchLibs(PROJECT *aProject)
Definition: project_sch.cpp:90
An adjunct helper to the DRAWING_TOOL interactive tool, which handles incoming geometry changes from ...
These are loaded from Eeschema settings but then overwritten by the project settings.
Holds all the data relating to one schematic.
Definition: schematic.h:75
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:289
SCH_SHEET & Root() const
Definition: schematic.h:112
SCH_SHEET_LIST BuildSheetListSortedByPageNumbers() const override
Definition: schematic.h:95
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 PickSymbolFromLibrary(const SYMBOL_LIBRARY_FILTER *aFilter, std::vector< PICKED_SYMBOL > &aHistoryList, std::vector< PICKED_SYMBOL > &aAlreadyPlaced, bool aShowFootprints, const LIB_ID *aHighlight=nullptr, bool aAllowFields=true)
Call the library viewer to select symbol to import into schematic.
Definition: picksymbol.cpp:49
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, bool aRotateCCW) 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:406
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
STROKE_PARAMS m_lastTextboxStroke
GR_TEXT_V_ALIGN_T m_lastTextboxVJustify
int DrawSheet(const TOOL_EVENT &aEvent)
SPIN_STYLE m_lastTextOrientation
int SyncSheetsPins(const TOOL_EVENT &aEvent)
STROKE_PARAMS m_lastStroke
SCH_TEXT * createNewText(const VECTOR2I &aPosition, int aType)
GR_TEXT_H_ALIGN_T m_lastTextboxHJustify
std::vector< PICKED_SYMBOL > m_powerHistoryList
int SingleClickPlace(const TOOL_EVENT &aEvent)
SCH_LINE * findWire(const VECTOR2I &aPosition)
Gets the (global) label name driving this wire, if it is driven by a label.
void sizeSheet(SCH_SHEET *aSheet, const VECTOR2I &aPos)
Set up handlers for various events.
LABEL_FLAG_SHAPE m_lastGlobalLabelShape
LABEL_FLAG_SHAPE m_lastNetClassFlagShape
GR_TEXT_H_ALIGN_T m_lastTextHJustify
int ImportGraphics(const TOOL_EVENT &aEvent)
EDA_ANGLE m_lastTextboxAngle
int DrawRuleArea(const TOOL_EVENT &aEvent)
std::unique_ptr< STATUS_TEXT_POPUP > m_statusPopup
int TwoClickPlace(const TOOL_EVENT &aEvent)
SCH_SHEET_PIN * createNewSheetPin(SCH_SHEET *aSheet, const VECTOR2I &aPosition)
int SyncAllSheetsPins(const TOOL_EVENT &aEvent)
wxString findWireLabelDriverName(SCH_LINE *aWire)
int DrawTable(const TOOL_EVENT &aEvent)
GR_TEXT_V_ALIGN_T m_lastTextVJustify
int doSyncSheetsPins(std::list< SCH_SHEET_PATH > aSheets)
LABEL_FLAG_SHAPE m_lastSheetPinType
int DrawShape(const TOOL_EVENT &aEvent)
std::unique_ptr< DIALOG_SYNC_SHEET_PINS > m_dialogSyncSheetPin
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
Schematic editor (Eeschema) main window.
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag and update other data struc...
bool EditSheetProperties(SCH_SHEET *aSheet, SCH_SHEET_PATH *aHierarchy, bool *aIsUndoable=nullptr, bool *aClearAnnotationNewItems=nullptr, bool *aUpdateHierarchyNavigator=nullptr)
Edit an existing sheet or add a new sheet to the schematic.
Definition: sheet.cpp:593
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...
void UpdateHierarchyNavigator(bool aRefreshNetNavigator=true)
Update the hierarchy navigation tree and history.
SCH_SHEET_PATH & GetCurrentSheet() const
SCHEMATIC & Schematic() const
void SelectUnit(SCH_SYMBOL *aSymbol, int aUnit)
Definition: picksymbol.cpp:93
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:51
void SetSpinStyle(SPIN_STYLE aSpinStyle) override
Definition: sch_label.cpp:2084
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:166
virtual bool IsConnectable() const
Definition: sch_item.h:449
SCHEMATIC * Schematic() const
Searches the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:145
int GetUnit() const
Definition: sch_item.h:229
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction)
Definition: sch_item.h:568
virtual void SetUnit(int aUnit)
Definition: sch_item.h:228
virtual void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual)
Definition: sch_item.h:566
SCH_CONNECTION * Connection(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve the connection associated with this object in the given sheet.
Definition: sch_item.cpp:216
SCH_ITEM * Duplicate(bool doClone=false) const
Routine to create a new copy of given item.
Definition: sch_item.cpp:126
bool IsType(const std::vector< KICAD_T > &aScanTypes) const override
Check whether the item is one of the listed types.
Definition: sch_item.h:181
bool AutoRotateOnPlacement() const
autoRotateOnPlacement
Definition: sch_label.cpp:1454
SPIN_STYLE GetSpinStyle() const
Definition: sch_label.cpp:373
void SetShape(LABEL_FLAG_SHAPE aShape)
Definition: sch_label.h:173
LABEL_FLAG_SHAPE GetShape() const
Definition: sch_label.h:172
void SetAutoRotateOnPlacement(bool autoRotate=true)
setAutoRotateOnPlacement
Definition: sch_label.cpp:1460
std::vector< SCH_FIELD > & GetFields()
Definition: sch_label.h:196
virtual void SetSpinStyle(SPIN_STYLE aSpinStyle)
Definition: sch_label.cpp:338
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:41
bool IsWire() const
Return true if the line is a wire.
Definition: sch_line.cpp:976
VECTOR2I GetEndPoint() const
Definition: sch_line.h:141
VECTOR2I GetStartPoint() const
Definition: sch_line.h:136
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:108
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:391
bool IsExplicitJunctionAllowed(const VECTOR2I &aPosition) const
Indicates that a juction dot may be placed at the given location.
Definition: sch_screen.cpp:505
void SetPosition(const VECTOR2I &aPos) override
Definition: sch_shape.h:71
void BeginEdit(const VECTOR2I &aStartPoint) override
Begin drawing a symbol library draw item at aPosition.
Definition: sch_shape.h:75
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: sch_shape.cpp:46
void EndEdit(bool aClosed=false) override
End an object editing action.
Definition: sch_shape.h:78
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: sch_shape.cpp:63
bool ContinueEdit(const VECTOR2I &aPosition) override
Continue an edit in progress at aPosition.
Definition: sch_shape.h:76
void CalcEdit(const VECTOR2I &aPosition) override
Calculate the attributes of an item at aPosition when it is being edited.
Definition: sch_shape.h:77
wxString GetClass() const override
Return the class name.
Definition: sch_shape.h:42
STROKE_PARAMS GetStroke() const override
Definition: sch_shape.h:55
VECTOR2I GetPosition() const override
Definition: sch_shape.h:70
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) 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.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
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:426
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: sch_sheet.cpp:166
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: sch_sheet.cpp:1027
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:400
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:172
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual) override
Definition: sch_sheet.cpp:663
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:1010
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:181
Schematic symbol object.
Definition: sch_symbol.h:105
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:780
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.
const LIB_ID & GetLibId() const override
Definition: sch_symbol.h:179
int GetUnitCount() const override
Return the number of units per package of the symbol.
Definition: sch_symbol.cpp:398
void SetUnitSelection(const SCH_SHEET_PATH *aSheet, int aUnitSelection)
Set the selected unit of this symbol on one sheet.
Definition: sch_symbol.cpp:792
void SetRowHeight(int aRow, int aHeight)
Definition: sch_table.h:121
void SetColCount(int aCount)
Definition: sch_table.h:103
void SetColWidth(int aCol, int aWidth)
Definition: sch_table.h:111
void AddCell(SCH_TABLECELL *aCell)
Definition: sch_table.h:146
VECTOR2I GetPosition() const override
Definition: sch_table.cpp:115
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: sch_table.h:188
void ClearCells()
Definition: sch_table.h:158
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: sch_table.h:210
void SetPosition(const VECTOR2I &aPos) override
Definition: sch_table.cpp:109
void Normalize()
Definition: sch_table.cpp:135
RAII class that sets an value at construction and resets it to the original value at destruction.
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)
void UnbrightenItem(EDA_ITEM *aItem)
virtual void Add(EDA_ITEM *aItem)
Definition: selection.cpp:42
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition: selection.h:100
EDA_ITEM * Front() const
Definition: selection.h:172
virtual void Clear() override
Remove all the stored items from the group.
Definition: selection.h:93
int Size() const
Returns the number of selected parts.
Definition: selection.h:116
Helper object to filter a list of libraries.
SYMBOL_LIB * GetCacheLibrary()
Object used to load, save, search, and otherwise manipulate symbol library files.
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.
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
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:217
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
bool DisableGridSnapping() const
Definition: tool_event.h:363
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:82
T Parameter() const
Return a parameter assigned to the event.
Definition: tool_event.h:460
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:150
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:235
void VetoContextMenuMouseWarp()
Disable mouse warping after the current context menu is closed.
Definition: tool_manager.h:530
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:401
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
Definition: eda_item.h:532
#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:82
@ ID_POPUP_SCH_SELECT_UNIT_END
Definition: eeschema_id.h:86
@ LINE_MODE_FREE
GRID_HELPER_GRIDS
Definition: grid_helper.h:37
@ GRID_TEXT
Definition: grid_helper.h:44
@ GRID_GRAPHICS
Definition: grid_helper.h:45
@ GRID_CONNECTABLE
Definition: grid_helper.h:41
static const std::string KiCadSchematicFileExtension
@ LAYER_HIERLABEL
Definition: layer_ids.h:361
@ LAYER_GLOBLABEL
Definition: layer_ids.h:360
@ LAYER_NOTES
Definition: layer_ids.h:371
@ LAYER_LOCLABEL
Definition: layer_ids.h:359
@ LAYER_NETCLASS_REFS
Definition: layer_ids.h:368
wxPoint GetMousePosition()
Returns the mouse position in screen coordinates.
Definition: wxgtk/ui.cpp:611
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1059
see class PGM_BASE
LIB_SYMBOL * SchGetLibSymbol(const LIB_ID &aLibId, SYMBOL_LIB_TABLE *aLibTable, SYMBOL_LIB *aCacheLib, wxWindow *aParent, bool aShowErrorMsg)
Load symbol from symbol library table.
LABEL_FLAG_SHAPE
Definition: sch_label.h:93
@ F_ROUND
Definition: sch_label.h:102
@ L_INPUT
Definition: sch_label.h:94
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
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
bool NoPrintableChars(const wxString &aString)
Return true if the string is empty or contains only whitespace.
LINE_STYLE
Dashed line types.
Definition: stroke_params.h:48
constexpr int MilsToIU(int mils) const
Definition: base_units.h:93
LIB_ID LibId
Definition: sch_screen.h:79
Definition for symbol library class.
constexpr int delta
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
@ 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:163
@ SCH_NO_CONNECT_T
Definition: typeinfo.h:160
@ SCH_SYMBOL_T
Definition: typeinfo.h:172
@ SCH_DIRECTIVE_LABEL_T
Definition: typeinfo.h:171
@ SCH_SHEET_T
Definition: typeinfo.h:174
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:173
@ SCH_BUS_WIRE_ENTRY_T
Definition: typeinfo.h:161
@ SCH_JUNCTION_T
Definition: typeinfo.h:159
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:118
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:638
Definition of file extensions used in Kicad.