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