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