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 The 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>
38#include <ee_actions.h>
39#include <ee_tool_utils.h>
40#include <sch_edit_frame.h>
41#include <pgm_base.h>
42#include <design_block.h>
43#include <design_block_pane.h>
44#include <eeschema_id.h>
45#include <confirm.h>
46#include <view/view_controls.h>
47#include <view/view.h>
48#include <sch_symbol.h>
49#include <sch_no_connect.h>
50#include <sch_line.h>
51#include <sch_junction.h>
52#include <sch_bus_entry.h>
53#include <sch_rule_area.h>
54#include <sch_text.h>
55#include <sch_textbox.h>
56#include <sch_table.h>
57#include <sch_tablecell.h>
58#include <sch_sheet.h>
59#include <sch_sheet_pin.h>
60#include <sch_label.h>
61#include <sch_bitmap.h>
62#include <schematic.h>
63#include <sch_commit.h>
64#include <scoped_set_reset.h>
65#include <symbol_library.h>
66#include <eeschema_settings.h>
68#include <dialogs/dialog_text_properties.h>
71#include <dialogs/dialog_table_properties.h>
74#include <string_utils.h>
76#include <wx/filedlg.h>
77#include <wx/msgdlg.h>
78
80 EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.InteractiveDrawing" ),
81 m_lastSheetPinType( LABEL_FLAG_SHAPE::L_INPUT ),
82 m_lastGlobalLabelShape( LABEL_FLAG_SHAPE::L_INPUT ),
83 m_lastNetClassFlagShape( LABEL_FLAG_SHAPE::F_ROUND ),
84 m_lastTextOrientation( SPIN_STYLE::RIGHT ),
85 m_lastTextBold( false ),
86 m_lastTextItalic( false ),
87 m_lastTextAngle( ANGLE_0 ),
88 m_lastTextboxAngle( ANGLE_0 ),
89 m_lastTextHJustify( GR_TEXT_H_ALIGN_CENTER ),
90 m_lastTextVJustify( GR_TEXT_V_ALIGN_CENTER ),
91 m_lastTextboxHJustify( GR_TEXT_H_ALIGN_LEFT ),
92 m_lastTextboxVJustify( GR_TEXT_V_ALIGN_TOP ),
93 m_lastFillStyle( FILL_T::NO_FILL ),
94 m_lastTextboxFillStyle( FILL_T::NO_FILL ),
95 m_lastFillColor( COLOR4D::UNSPECIFIED ),
96 m_lastTextboxFillColor( COLOR4D::UNSPECIFIED ),
97 m_lastStroke( 0, LINE_STYLE::DEFAULT, COLOR4D::UNSPECIFIED ),
98 m_lastTextboxStroke( 0, LINE_STYLE::DEFAULT, COLOR4D::UNSPECIFIED ),
99 m_mruPath( wxEmptyString ),
100 m_lastAutoLabelRotateOnPlacement( false ),
101 m_drawingRuleArea( false ),
102 m_inDrawingTool( false )
103{
104}
105
106
108{
110
111 auto belowRootSheetCondition =
112 [&]( const SELECTION& aSel )
113 {
114 return m_frame->GetCurrentSheet().Last() != &m_frame->Schematic().Root();
115 };
116
117 auto inDrawingRuleArea =
118 [&]( const SELECTION& aSel )
119 {
120 return m_drawingRuleArea;
121 };
122
123 CONDITIONAL_MENU& ctxMenu = m_menu->GetMenu();
124 ctxMenu.AddItem( EE_ACTIONS::leaveSheet, belowRootSheetCondition, 150 );
125 ctxMenu.AddItem( EE_ACTIONS::closeOutline, inDrawingRuleArea, 200 );
126 ctxMenu.AddItem( EE_ACTIONS::deleteLastPoint, inDrawingRuleArea, 200 );
127
128 return true;
129}
130
131
133{
134 const EE_ACTIONS::PLACE_SYMBOL_PARAMS& toolParams =
136
137 SCH_SYMBOL* symbol = toolParams.m_Symbol;
138 // If we get an parameterised symbol, we probably just want to place
139 // that and get out of the placmeent tool, rather than popping the
140 // chooser afterwards
141 bool placeOneOnly = symbol != nullptr;
142
144 std::vector<PICKED_SYMBOL>* historyList = nullptr;
145 bool ignorePrimePosition = false;
146 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
147 SCH_SCREEN* screen = m_frame->GetScreen();
148
149 if( m_inDrawingTool )
150 return 0;
151
153
156 VECTOR2I cursorPos;
157
158 // First we need to get all instances of this sheet so we can annotate
159 // whatever symbols we place on all copies
160 SCH_SHEET_LIST hierarchy = m_frame->Schematic().Hierarchy();
161 SCH_SHEET_LIST newInstances =
163 newInstances.SortByPageNumbers();
164
165 // Get a list of all references in the schematic to avoid duplicates wherever
166 // they're placed
167 SCH_REFERENCE_LIST existingRefs;
168 hierarchy.GetSymbols( existingRefs );
169 existingRefs.SortByReferenceOnly();
170
171 if( aEvent.IsAction( &EE_ACTIONS::placeSymbol ) )
172 {
173 historyList = &m_symbolHistoryList;
174 }
175 else if (aEvent.IsAction( &EE_ACTIONS::placePower ) )
176 {
177 historyList = &m_powerHistoryList;
178 filter.FilterPowerSymbols( true );
179 }
180 else
181 {
182 wxFAIL_MSG( "PlaceSymbol(): unexpected request" );
183 }
184
185 m_frame->PushTool( aEvent );
186
187 auto addSymbol =
188 [this]( SCH_SYMBOL* aSymbol )
189 {
191 m_selectionTool->AddItemToSel( aSymbol );
192
193 aSymbol->SetFlags( IS_NEW | IS_MOVING );
194
196 m_view->AddToPreview( aSymbol, false ); // Add, but not give ownership
197
198 // Set IS_MOVING again, as AddItemToCommitAndScreen() will have cleared it.
199 aSymbol->SetFlags( IS_MOVING );
201 };
202
203 auto setCursor =
204 [&]()
205 {
206 m_frame->GetCanvas()->SetCurrentCursor( symbol ? KICURSOR::MOVING
207 : KICURSOR::COMPONENT );
208 };
209
210 auto cleanup =
211 [&]()
212 {
215 delete symbol;
216 symbol = nullptr;
217
218 existingRefs.Clear();
219 hierarchy.GetSymbols( existingRefs );
220 existingRefs.SortByReferenceOnly();
221 };
222
223 auto annotate =
224 [&]()
225 {
227
228 // Then we need to annotate all instances by sheet
229 for( SCH_SHEET_PATH& instance : newInstances )
230 {
231 SCH_REFERENCE newReference( symbol, instance );
233 refs.AddItem( newReference );
234
235 if( cfg->m_AnnotatePanel.automatic || newReference.AlwaysAnnotate() )
236 {
240 existingRefs, false, &hierarchy );
241
242 refs.UpdateAnnotation();
243
244 // Update existing refs for next iteration
245 for( size_t i = 0; i < refs.GetCount(); i++ )
246 existingRefs.AddItem( refs[i] );
247 }
248 }
249
251 };
252
253 Activate();
254
255 // Must be done after Activate() so that it gets set into the correct context
256 getViewControls()->ShowCursor( true );
257
258 // Set initial cursor
259 setCursor();
260
261 // Prime the pump
262 if( symbol )
263 {
264 addSymbol( symbol );
265
266 if( toolParams.m_Reannotate )
267 annotate();
268
269 getViewControls()->WarpMouseCursor( getViewControls()->GetMousePosition( false ) );
270 }
271 else if( aEvent.HasPosition() )
272 {
273 m_toolMgr->PrimeTool( aEvent.Position() );
274 }
275 else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() )
276 {
277 m_toolMgr->PrimeTool( { 0, 0 } );
278 ignorePrimePosition = true;
279 }
280
281 // Main loop: keep receiving events
282 while( TOOL_EVENT* evt = Wait() )
283 {
284 setCursor();
285 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
286 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
287
288 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_CONNECTABLE );
289 controls->ForceCursorPosition( true, cursorPos );
290
291 // The tool hotkey is interpreted as a click when drawing
292 bool isSyntheticClick = symbol && evt->IsActivate() && evt->HasPosition()
293 && evt->Matches( aEvent );
294
295 if( evt->IsCancelInteractive() || ( symbol && evt->IsAction( &ACTIONS::undo ) ) )
296 {
298
299 if( symbol )
300 {
301 cleanup();
302 }
303 else
304 {
305 m_frame->PopTool( aEvent );
306 break;
307 }
308 }
309 else if( evt->IsActivate() && !isSyntheticClick )
310 {
311 if( symbol && evt->IsMoveTool() )
312 {
313 // we're already moving our own item; ignore the move tool
314 evt->SetPassEvent( false );
315 continue;
316 }
317
318 if( symbol )
319 {
320 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel symbol creation." ) );
321 evt->SetPassEvent( false );
322 continue;
323 }
324
325 if( evt->IsMoveTool() )
326 {
327 // leave ourselves on the stack so we come back after the move
328 break;
329 }
330 else
331 {
332 m_frame->PopTool( aEvent );
333 break;
334 }
335 }
336 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) || isSyntheticClick )
337 {
338 if( !symbol )
339 {
341
344
345 std::set<UTF8> unique_libid;
346 std::vector<PICKED_SYMBOL> alreadyPlaced;
347
348 for( SCH_SHEET_PATH& sheet : hierarchy )
349 {
350 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
351 {
352 SCH_SYMBOL* s = static_cast<SCH_SYMBOL*>( item );
353
354 if( !unique_libid.insert( s->GetLibId().Format() ).second )
355 continue;
356
357 LIB_SYMBOL* libSymbol = SchGetLibSymbol( s->GetLibId(), libs, cache );
358
359 if( libSymbol )
360 {
361 PICKED_SYMBOL pickedSymbol;
362 pickedSymbol.LibId = libSymbol->GetLibId();
363 alreadyPlaced.push_back( pickedSymbol );
364 }
365 }
366 }
367
368 // Pick the symbol to be placed
369 bool footprintPreviews = m_frame->eeconfig()->m_Appearance.footprint_preview;
370 PICKED_SYMBOL sel = m_frame->PickSymbolFromLibrary( &filter, *historyList,
371 alreadyPlaced,
372 footprintPreviews );
373
374 LIB_SYMBOL* libSymbol = sel.LibId.IsValid() ? m_frame->GetLibSymbol( sel.LibId )
375 : nullptr;
376
377 if( !libSymbol )
378 continue;
379
380 // If we started with a hotkey which has a position then warp back to that.
381 // Otherwise update to the current mouse position pinned inside the autoscroll
382 // boundaries.
383 if( evt->IsPrime() && !ignorePrimePosition )
384 {
385 cursorPos = grid.Align( evt->Position(), GRID_HELPER_GRIDS::GRID_CONNECTABLE );
386 getViewControls()->WarpMouseCursor( cursorPos, true );
387 }
388 else
389 {
391 cursorPos = grid.Align( getViewControls()->GetMousePosition(),
392 GRID_HELPER_GRIDS::GRID_CONNECTABLE );
393 }
394
395 symbol = new SCH_SYMBOL( *libSymbol, &m_frame->GetCurrentSheet(), sel, cursorPos,
396 &m_frame->Schematic() );
397 addSymbol( symbol );
398 annotate();
399
400 // Update the list of references for the next symbol placement.
401 SCH_REFERENCE placedSymbolReference( symbol, m_frame->GetCurrentSheet() );
402 existingRefs.AddItem( placedSymbolReference );
403 existingRefs.SortByReferenceOnly();
404
406 {
407 // Not placed yet, so pass a nullptr screen reference
408 symbol->AutoplaceFields( nullptr, AUTOPLACE_AUTO );
409 }
410
411 // Update cursor now that we have a symbol
412 setCursor();
413 }
414 else
415 {
417 m_frame->AddToScreen( symbol, screen );
418
420 symbol->AutoplaceFields( screen, AUTOPLACE_AUTO );
421
423
424 SCH_COMMIT commit( m_toolMgr );
425 commit.Added( symbol, screen );
426
428 lwbTool->TrimOverLappingWires( &commit, &m_selectionTool->GetSelection() );
429 lwbTool->AddJunctionsIfNeeded( &commit, &m_selectionTool->GetSelection() );
430
431 commit.Push( _( "Place Symbol" ) );
432
433 if( placeOneOnly )
434 {
435 m_frame->PopTool( aEvent );
436 break;
437 }
438
439 SCH_SYMBOL* nextSymbol = nullptr;
440
443 {
444 int new_unit = symbol->GetUnit();
445
447 && symbol->GetUnit() < symbol->GetUnitCount() )
448 {
449 new_unit++;
450 }
451 else
452 {
453 new_unit = 1;
454 }
455
456 // We are either stepping to the next unit or next symbol
457 if( m_frame->eeconfig()->m_SymChooserPanel.keep_symbol || new_unit > 1 )
458 {
459 nextSymbol = static_cast<SCH_SYMBOL*>( symbol->Duplicate() );
460 nextSymbol->SetUnit( new_unit );
461 nextSymbol->SetUnitSelection( new_unit );
462
463 // Start new annotation sequence at first unit
464 if( new_unit == 1 )
465 nextSymbol->ClearAnnotation( nullptr, false );
466
467 addSymbol( nextSymbol );
468 symbol = nextSymbol;
469 annotate();
470
471 // Update the list of references for the next symbol placement.
472 SCH_REFERENCE placedSymbolReference( symbol, m_frame->GetCurrentSheet() );
473 existingRefs.AddItem( placedSymbolReference );
474 existingRefs.SortByReferenceOnly();
475 }
476 }
477
478 symbol = nextSymbol;
479 }
480 }
481 else if( evt->IsClick( BUT_RIGHT ) )
482 {
483 // Warp after context menu only if dragging...
484 if( !symbol )
486
487 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
488 }
489 else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
490 {
491 if( *evt->GetCommandId() >= ID_POPUP_SCH_SELECT_UNIT
492 && *evt->GetCommandId() <= ID_POPUP_SCH_SELECT_UNIT_END )
493 {
494 int unit = *evt->GetCommandId() - ID_POPUP_SCH_SELECT_UNIT;
495
496 if( symbol )
497 {
498 m_frame->SelectUnit( symbol, unit );
500 }
501 }
502 else if( *evt->GetCommandId() >= ID_POPUP_SCH_SELECT_BASE
503 && *evt->GetCommandId() <= ID_POPUP_SCH_SELECT_ALT )
504 {
505 int bodyStyle = ( *evt->GetCommandId() - ID_POPUP_SCH_SELECT_BASE ) + 1;
506
507 if( symbol && symbol->GetBodyStyle() != bodyStyle )
508 {
509 m_frame->FlipBodyStyle( symbol );
511 }
512 }
513 }
514 else if( evt->IsAction( &ACTIONS::duplicate )
515 || evt->IsAction( &EE_ACTIONS::repeatDrawItem ) )
516 {
517 if( symbol )
518 {
519 // This doesn't really make sense; we'll just end up dragging a stack of
520 // objects so we ignore the duplicate and just carry on.
521 wxBell();
522 continue;
523 }
524
525 // Exit. The duplicate will run in its own loop.
526 m_frame->PopTool( aEvent );
527 break;
528 }
529 else if( symbol && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
530 {
531 symbol->SetPosition( cursorPos );
533 m_view->AddToPreview( symbol, false ); // Add, but not give ownership
534 m_frame->SetMsgPanel( symbol );
535 }
536 else if( symbol && evt->IsAction( &ACTIONS::doDelete ) )
537 {
538 cleanup();
539 }
540 else if( symbol && evt->IsAction( &ACTIONS::redo ) )
541 {
542 wxBell();
543 }
544 else
545 {
546 evt->SetPassEvent();
547 }
548
549 // Enable autopanning and cursor capture only when there is a symbol to be placed
550 getViewControls()->SetAutoPan( symbol != nullptr );
551 getViewControls()->CaptureCursor( symbol != nullptr );
552 }
553
554 getViewControls()->SetAutoPan( false );
555 getViewControls()->CaptureCursor( false );
556 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
557
558 return 0;
559}
560
561
563{
564 SCH_SYMBOL* symbol = aEvent.Parameter<SCH_SYMBOL*>();
565
566 // TODO: get from selection
567 if( !symbol )
568 {
569 static const std::vector<KICAD_T> symbolTypes = { SCH_SYMBOL_T };
570 EE_SELECTION& selection = m_selectionTool->RequestSelection( symbolTypes );
571
572 if( selection.Size() != 1 )
573 {
574 m_frame->ShowInfoBarMsg( _( "Select a single symbol to place the next unit." ) );
575 return 0;
576 }
577
578 wxCHECK( selection.Front()->Type() == SCH_SYMBOL_T, 0 );
579 symbol = static_cast<SCH_SYMBOL*>( selection.Front() );
580 }
581
582 if( !symbol )
583 return 0;
584
585 if( !symbol->IsMulti() )
586 {
587 m_frame->ShowInfoBarMsg( _( "This symbol has only one unit." ) );
588 return 0;
589 }
590
591 const std::set<int> missingUnits = GetUnplacedUnitsForSymbol( *symbol );
592
593 if( missingUnits.empty() )
594 {
595 m_frame->ShowInfoBarMsg( _( "All units of this symbol are already placed." ) );
596 return 0;
597 }
598
599 // Find the lowest unit number that is missing
600 const int nextMissing = *std::min_element( missingUnits.begin(), missingUnits.end() );
601
602 std::unique_ptr<SCH_SYMBOL> newSymbol = std::make_unique<SCH_SYMBOL>( *symbol );
603 const SCH_SHEET_PATH& sheetPath = m_frame->GetCurrentSheet();
604
605 newSymbol->SetUnitProp( nextMissing );
606 newSymbol->SetRefProp( symbol->GetRef( &sheetPath, false ) );
607
608 // Post the new symbol - don't reannotate it - we set the reference ourselves
610 EE_ACTIONS::PLACE_SYMBOL_PARAMS{ newSymbol.release(), false } );
611 return 0;
612}
613
614
616{
617 bool placingDesignBlock = aEvent.IsAction( &EE_ACTIONS::placeDesignBlock );
618
619 DESIGN_BLOCK* designBlock = nullptr;
620 wxString sheetFileName = wxEmptyString;
621
622 if( placingDesignBlock )
623 {
625 {
626 designBlock =
628
629 if( !designBlock )
630 return 0;
631
632 sheetFileName = designBlock->GetSchematicFile();
633 }
634 }
635 else
636 {
637 wxString* importSourceFile = aEvent.Parameter<wxString*>();
638
639 if( importSourceFile != nullptr )
640 sheetFileName = *importSourceFile;
641 }
642
643 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
645 SCHEMATIC_SETTINGS& schSettings = m_frame->Schematic().Settings();
646 SCH_SCREEN* screen = m_frame->GetScreen();
647 SCH_SHEET_PATH& sheetPath = m_frame->GetCurrentSheet();
648
651 VECTOR2I cursorPos;
652
653 if( !cfg || !common_settings )
654 return 0;
655
656 if( m_inDrawingTool )
657 return 0;
658
659 auto setCursor =
660 [&]()
661 {
662 m_frame->GetCanvas()->SetCurrentCursor( designBlock ? KICURSOR::MOVING
663 : KICURSOR::COMPONENT );
664 };
665
666 auto placeSheetContents =
667 [&]()
668 {
669 SCH_COMMIT commit( m_toolMgr );
671 EDA_ITEMS newItems;
672 bool keepAnnotations = cfg->m_DesignBlockChooserPanel.keep_annotations;
673
674 selectionTool->ClearSelection();
675
676 // Mark all existing items on the screen so we don't select them after appending
677 for( EDA_ITEM* item : screen->Items() )
678 item->SetFlags( SKIP_STRUCT );
679
680 if( !m_frame->LoadSheetFromFile( sheetPath.Last(), &sheetPath, sheetFileName, true,
681 placingDesignBlock ) )
682 return false;
683
685
686 m_frame->SyncView();
687 m_frame->OnModify();
688 m_frame->HardRedraw(); // Full reinit of the current screen and the display.
689
690 // Select all new items
691 for( EDA_ITEM* item : screen->Items() )
692 {
693 if( !item->HasFlag( SKIP_STRUCT ) )
694 {
695 if( item->Type() == SCH_SYMBOL_T && !keepAnnotations )
696 static_cast<SCH_SYMBOL*>( item )->ClearAnnotation( &sheetPath, false );
697
698 if( item->Type() == SCH_LINE_T )
699 item->SetFlags( STARTPOINT | ENDPOINT );
700
701 commit.Added( item, screen );
702 newItems.emplace_back( item );
703 }
704 else
705 item->ClearFlags( SKIP_STRUCT );
706 }
707
708 selectionTool->AddItemsToSel( &newItems, true );
709
710 cursorPos = grid.Align( controls->GetMousePosition(),
711 grid.GetSelectionGrid( selectionTool->GetSelection() ) );
712 controls->ForceCursorPosition( true, cursorPos );
713
714 // Move everything to our current mouse position now
715 // that we have a selection to get a reference point
716 VECTOR2I anchorPos = selectionTool->GetSelection().GetReferencePoint();
717 VECTOR2I delta = cursorPos - anchorPos;
718
719 // Will all be SCH_ITEMs as these were pulled from the screen->Items()
720 for( EDA_ITEM* item : newItems )
721 static_cast<SCH_ITEM*>( item )->Move( delta );
722
723 if( !keepAnnotations )
724 {
726
727 if( annotate.automatic )
728 {
729 NULL_REPORTER reporter;
731 (ANNOTATE_ORDER_T) annotate.sort_order,
732 (ANNOTATE_ALGO_T) annotate.method, true /* recursive */,
733 schSettings.m_AnnotateStartNum, false, false, reporter );
734 }
735
736 // Annotation will clear selection, so we need to restore it
737 for( EDA_ITEM* item : newItems )
738 {
739 if( item->Type() == SCH_LINE_T )
740 item->SetFlags( STARTPOINT | ENDPOINT );
741 }
742
743 selectionTool->AddItemsToSel( &newItems, true );
744 }
745
746 // Start moving selection, cancel undoes the insertion
747 bool placed = m_toolMgr->RunSynchronousAction( EE_ACTIONS::move, &commit );
748
749 // Update our cursor position to the new location in case we're placing repeated copies
750 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_CONNECTABLE );
751
752 if( placed )
753 commit.Push( placingDesignBlock ? _( "Add design block" )
754 : _( "Import Schematic Sheet Content..." ) );
755 else
756 commit.Revert();
757
759
760 return placed;
761 };
762
763 // Whether we are placing the sheet as a sheet, or as its contents, we need to get a filename
764 // if we weren't provided one
765 if( sheetFileName.IsEmpty() )
766 {
767 wxString path;
768 wxString file;
769
770 if (!placingDesignBlock) {
771
772 if( sheetFileName.IsEmpty() )
773 {
774 path = wxPathOnly( m_frame->Prj().GetProjectFullName() );
775 file = wxEmptyString;
776 }
777 else
778 {
779 path = wxPathOnly( sheetFileName );
780 file = wxFileName( sheetFileName ).GetFullName();
781 }
782
783 // Open file chooser dialog even if we have been provided a file so the user
784 // can select the options they want
785 wxFileDialog dlg( m_frame, _( "Choose Schematic" ), path, file,
787 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
788
789 FILEDLG_IMPORT_SHEET_CONTENTS dlgHook( cfg );
790 dlg.SetCustomizeHook( dlgHook );
791
792 if( dlg.ShowModal() == wxID_CANCEL )
793 return 0;
794
795 sheetFileName = dlg.GetPath();
796
798 }
799
800 if( sheetFileName.IsEmpty() )
801 return 0;
802 }
803
804 // If we're placing sheet contents, we don't even want to run our tool loop, just add the items
805 // to the canvas and run the move tool
807 {
808 while( placeSheetContents() && cfg->m_DesignBlockChooserPanel.repeated_placement )
809 ;
810
813 delete designBlock;
814 designBlock = nullptr;
815
816 return 0;
817 }
818
819 // We're placing a sheet as a sheet, we need to run a small tool loop to get the starting
820 // coordinate of the sheet drawing
821 m_frame->PushTool( aEvent );
822
823 Activate();
824
825 // Must be done after Activate() so that it gets set into the correct context
826 getViewControls()->ShowCursor( true );
827
828 // Set initial cursor
829 setCursor();
830
831 if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() )
832 {
833 m_toolMgr->PrimeTool( { 0, 0 } );
834 }
835
836 // Main loop: keep receiving events
837 while( TOOL_EVENT* evt = Wait() )
838 {
839 setCursor();
840 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
841 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
842
843 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_CONNECTABLE );
844 controls->ForceCursorPosition( true, cursorPos );
845
846 // The tool hotkey is interpreted as a click when drawing
847 bool isSyntheticClick = designBlock && evt->IsActivate() && evt->HasPosition()
848 && evt->Matches( aEvent );
849
850 if( evt->IsCancelInteractive() || ( designBlock && evt->IsAction( &ACTIONS::undo ) ) )
851 {
853 break;
854 }
855 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) || isSyntheticClick )
856 {
857 if( placingDesignBlock )
859 else
860 {
861 // drawSheet must delete
863 new wxString( sheetFileName ) );
864 }
865
866 break;
867 }
868 else if( evt->IsClick( BUT_RIGHT ) )
869 {
870 // Warp after context menu only if dragging...
871 if( !designBlock )
873
874 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
875 }
876 else if( evt->IsAction( &ACTIONS::duplicate )
877 || evt->IsAction( &EE_ACTIONS::repeatDrawItem ) )
878 {
879 wxBell();
880 }
881 else
882 {
883 evt->SetPassEvent();
884 }
885 }
886
887 m_frame->PopTool( aEvent );
888 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
889
890 return 0;
891}
892
893
895{
896 SCH_BITMAP* image = aEvent.Parameter<SCH_BITMAP*>();
897 bool immediateMode = image != nullptr;
898 bool ignorePrimePosition = false;
899 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
900
901 if( m_inDrawingTool )
902 return 0;
903
905
908 VECTOR2I cursorPos;
909
911
912 // Add all the drawable symbols to preview
913 if( image )
914 {
915 image->SetPosition( getViewControls()->GetCursorPosition() );
917 m_view->AddToPreview( image, false ); // Add, but not give ownership
918 }
919
920 m_frame->PushTool( aEvent );
921
922 auto setCursor =
923 [&]()
924 {
925 if( image )
926 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::MOVING );
927 else
928 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
929 };
930
931 auto cleanup =
932 [&] ()
933 {
937 delete image;
938 image = nullptr;
939 };
940
941 Activate();
942
943 // Must be done after Activate() so that it gets set into the correct context
944 getViewControls()->ShowCursor( true );
945
946 // Set initial cursor
947 setCursor();
948
949 // Prime the pump
950 if( image )
951 {
953 }
954 else if( aEvent.HasPosition() )
955 {
956 m_toolMgr->PrimeTool( aEvent.Position() );
957 }
958 else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() )
959 {
960 m_toolMgr->PrimeTool( { 0, 0 } );
961 ignorePrimePosition = true;
962 }
963
964 // Main loop: keep receiving events
965 while( TOOL_EVENT* evt = Wait() )
966 {
967 setCursor();
968 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
969 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
970
971 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
972 controls->ForceCursorPosition( true, cursorPos );
973
974 // The tool hotkey is interpreted as a click when drawing
975 bool isSyntheticClick = image && evt->IsActivate() && evt->HasPosition()
976 && evt->Matches( aEvent );
977
978 if( evt->IsCancelInteractive() || ( image && evt->IsAction( &ACTIONS::undo ) ) )
979 {
981
982 if( image )
983 {
984 cleanup();
985 }
986 else
987 {
988 m_frame->PopTool( aEvent );
989 break;
990 }
991
992 if( immediateMode )
993 {
994 m_frame->PopTool( aEvent );
995 break;
996 }
997 }
998 else if( evt->IsActivate() && !isSyntheticClick )
999 {
1000 if( image && evt->IsMoveTool() )
1001 {
1002 // we're already moving our own item; ignore the move tool
1003 evt->SetPassEvent( false );
1004 continue;
1005 }
1006
1007 if( image )
1008 {
1009 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel image creation." ) );
1010 evt->SetPassEvent( false );
1011 continue;
1012 }
1013
1014 if( evt->IsMoveTool() )
1015 {
1016 // leave ourselves on the stack so we come back after the move
1017 break;
1018 }
1019 else
1020 {
1021 m_frame->PopTool( aEvent );
1022 break;
1023 }
1024 }
1025 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) || isSyntheticClick )
1026 {
1027 if( !image )
1028 {
1030
1031 wxFileDialog dlg( m_frame, _( "Choose Image" ), m_mruPath, wxEmptyString,
1032 _( "Image Files" ) + wxS( " " ) + wxImage::GetImageExtWildcard(),
1033 wxFD_OPEN );
1034
1035 if( dlg.ShowModal() != wxID_OK )
1036 continue;
1037
1038 // If we started with a hotkey which has a position then warp back to that.
1039 // Otherwise update to the current mouse position pinned inside the autoscroll
1040 // boundaries.
1041 if( evt->IsPrime() && !ignorePrimePosition )
1042 {
1043 cursorPos = grid.Align( evt->Position() );
1044 getViewControls()->WarpMouseCursor( cursorPos, true );
1045 }
1046 else
1047 {
1049 cursorPos = getViewControls()->GetMousePosition();
1050 }
1051
1052 wxString fullFilename = dlg.GetPath();
1053 m_mruPath = wxPathOnly( fullFilename );
1054
1055 if( wxFileExists( fullFilename ) )
1056 image = new SCH_BITMAP( cursorPos );
1057
1058 if( !image || !image->GetReferenceImage().ReadImageFile( fullFilename ) )
1059 {
1060 wxMessageBox( wxString::Format( _( "Could not load image from '%s'." ), fullFilename ) );
1061 delete image;
1062 image = nullptr;
1063 continue;
1064 }
1065
1066 image->SetFlags( IS_NEW | IS_MOVING );
1067
1069
1071 m_view->AddToPreview( image, false ); // Add, but not give ownership
1072 m_view->RecacheAllItems(); // Bitmaps are cached in Opengl
1073
1075
1076 getViewControls()->SetCursorPosition( cursorPos, false );
1077 setCursor();
1078 }
1079 else
1080 {
1081 SCH_COMMIT commit( m_toolMgr );
1082 commit.Add( image, m_frame->GetScreen() );
1083 commit.Push( _( "Place Image" ) );
1084
1085 image = nullptr;
1087
1089
1090 if( immediateMode )
1091 {
1092 m_frame->PopTool( aEvent );
1093 break;
1094 }
1095 }
1096 }
1097 else if( evt->IsClick( BUT_RIGHT ) )
1098 {
1099 // Warp after context menu only if dragging...
1100 if( !image )
1102
1103 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
1104 }
1105 else if( evt->IsAction( &ACTIONS::duplicate )
1106 || evt->IsAction( &EE_ACTIONS::repeatDrawItem ) )
1107 {
1108 if( image )
1109 {
1110 // This doesn't really make sense; we'll just end up dragging a stack of
1111 // objects so we ignore the duplicate and just carry on.
1112 wxBell();
1113 continue;
1114 }
1115
1116 // Exit. The duplicate will run in its own loop.
1117 m_frame->PopTool( aEvent );
1118 break;
1119 }
1120 else if( image && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
1121 {
1122 image->SetPosition( cursorPos );
1124 m_view->AddToPreview( image, false ); // Add, but not give ownership
1125 m_view->RecacheAllItems(); // Bitmaps are cached in Opengl
1127 }
1128 else if( image && evt->IsAction( &ACTIONS::doDelete ) )
1129 {
1130 cleanup();
1131 }
1132 else if( image && evt->IsAction( &ACTIONS::redo ) )
1133 {
1134 wxBell();
1135 }
1136 else
1137 {
1138 evt->SetPassEvent();
1139 }
1140
1141 // Enable autopanning and cursor capture only when there is an image to be placed
1142 getViewControls()->SetAutoPan( image != nullptr );
1143 getViewControls()->CaptureCursor( image != nullptr );
1144 }
1145
1146 getViewControls()->SetAutoPan( false );
1147 getViewControls()->CaptureCursor( false );
1148 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1149
1150 return 0;
1151}
1152
1153
1155{
1156 if( m_inDrawingTool )
1157 return 0;
1158
1160
1161 // Note: PlaceImportedGraphics() will convert PCB_SHAPE_T and PCB_TEXT_T to footprint
1162 // items if needed
1164 int dlgResult = dlg.ShowModal();
1165
1166 std::list<std::unique_ptr<EDA_ITEM>>& list = dlg.GetImportedItems();
1167
1168 if( dlgResult != wxID_OK )
1169 return 0;
1170
1171 // Ensure the list is not empty:
1172 if( list.empty() )
1173 {
1174 wxMessageBox( _( "No graphic items found in file." ) );
1175 return 0;
1176 }
1177
1179
1181 std::vector<SCH_ITEM*> newItems; // all new items, including group
1182 std::vector<SCH_ITEM*> selectedItems; // the group, or newItems if no group
1183 EE_SELECTION preview;
1184 SCH_COMMIT commit( m_toolMgr );
1185
1186 for( std::unique_ptr<EDA_ITEM>& ptr : list )
1187 {
1188 SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( ptr.get() );
1189 wxCHECK2_MSG( item, continue, wxString::Format( "Bad item type: ", ptr->Type() ) );
1190
1191 newItems.push_back( item );
1192 selectedItems.push_back( item );
1193 preview.Add( item );
1194
1195 ptr.release();
1196 }
1197
1198 if( !dlg.IsPlacementInteractive() )
1199 {
1200 // Place the imported drawings
1201 for( SCH_ITEM* item : newItems )
1202 commit.Add(item, m_frame->GetScreen());
1203
1204 commit.Push( _( "Import Graphic" ) );
1205 return 0;
1206 }
1207
1208 m_view->Add( &preview );
1209
1210 // Clear the current selection then select the drawings so that edit tools work on them
1212
1213 EDA_ITEMS selItems( selectedItems.begin(), selectedItems.end() );
1215
1216 m_frame->PushTool( aEvent );
1217
1218 auto setCursor = [&]()
1219 {
1220 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::MOVING );
1221 };
1222
1223 Activate();
1224 // Must be done after Activate() so that it gets set into the correct context
1225 controls->ShowCursor( true );
1226 controls->ForceCursorPosition( false );
1227 // Set initial cursor
1228 setCursor();
1229
1230 //SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::DXF );
1232
1233 // Now move the new items to the current cursor position:
1234 VECTOR2I cursorPos = controls->GetCursorPosition( !aEvent.DisableGridSnapping() );
1235 VECTOR2I delta = cursorPos;
1236 VECTOR2I currentOffset;
1237
1238 for( SCH_ITEM* item : selectedItems )
1239 item->Move( delta );
1240
1241 currentOffset += delta;
1242
1243 m_view->Update( &preview );
1244
1245 // Main loop: keep receiving events
1246 while( TOOL_EVENT* evt = Wait() )
1247 {
1248 setCursor();
1249
1250 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1251 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1252
1253 cursorPos = grid.Align( controls->GetMousePosition(), GRID_GRAPHICS );
1254 controls->ForceCursorPosition( true, cursorPos );
1255
1256 if( evt->IsCancelInteractive() || evt->IsActivate() )
1257 {
1259
1260 for( SCH_ITEM* item : newItems )
1261 delete item;
1262
1263 break;
1264 }
1265 else if( evt->IsMotion() )
1266 {
1267 delta = cursorPos - currentOffset;
1268
1269 for( SCH_ITEM* item : selectedItems )
1270 item->Move( delta );
1271
1272 currentOffset += delta;
1273
1274 m_view->Update( &preview );
1275 }
1276 else if( evt->IsClick( BUT_RIGHT ) )
1277 {
1278 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
1279 }
1280 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
1281 {
1282 // Place the imported drawings
1283 for( SCH_ITEM* item : newItems )
1284 commit.Add( item, m_frame->GetScreen() );
1285
1286 commit.Push( _( "Import Graphic" ) );
1287 break; // This is a one-shot command, not a tool
1288 }
1289 else
1290 {
1291 evt->SetPassEvent();
1292 }
1293 }
1294
1295 preview.Clear();
1296 m_view->Remove( &preview );
1297
1298 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1299 controls->ForceCursorPosition( false );
1300
1301 m_frame->PopTool( aEvent );
1302
1303 return 0;
1304}
1305
1306
1308{
1309 VECTOR2I cursorPos;
1310 KICAD_T type = aEvent.Parameter<KICAD_T>();
1313 SCH_ITEM* previewItem;
1314 bool loggedInfoBarError = false;
1315 wxString description;
1316 SCH_SCREEN* screen = m_frame->GetScreen();
1317 bool allowRepeat = false; // Set to true to allow new item repetition
1318
1319 if( m_inDrawingTool )
1320 return 0;
1321
1323
1324 if( type == SCH_JUNCTION_T && aEvent.HasPosition() )
1325 {
1327 SCH_LINE* wire = dynamic_cast<SCH_LINE*>( selection.Front() );
1328
1329 if( wire )
1330 {
1331 SEG seg( wire->GetStartPoint(), wire->GetEndPoint() );
1332 VECTOR2I nearest = seg.NearestPoint( getViewControls()->GetCursorPosition() );
1333 getViewControls()->SetCrossHairCursorPosition( nearest, false );
1334 getViewControls()->WarpMouseCursor( getViewControls()->GetCursorPosition(), true );
1335 }
1336 }
1337
1338 switch( type )
1339 {
1340 case SCH_NO_CONNECT_T:
1341 previewItem = new SCH_NO_CONNECT( cursorPos );
1342 previewItem->SetParent( screen );
1343 description = _( "Add No Connect Flag" );
1344 allowRepeat = true;
1345 break;
1346
1347 case SCH_JUNCTION_T:
1348 previewItem = new SCH_JUNCTION( cursorPos );
1349 previewItem->SetParent( screen );
1350 description = _( "Add Junction" );
1351 break;
1352
1354 previewItem = new SCH_BUS_WIRE_ENTRY( cursorPos );
1355 previewItem->SetParent( screen );
1356 description = _( "Add Wire to Bus Entry" );
1357 allowRepeat = true;
1358 break;
1359
1360 default:
1361 wxASSERT_MSG( false, "Unknown item type in SCH_DRAWING_TOOLS::SingleClickPlace" );
1362 return 0;
1363 }
1364
1366
1367 cursorPos = aEvent.HasPosition() ? aEvent.Position() : controls->GetMousePosition();
1368
1369 m_frame->PushTool( aEvent );
1370
1371 auto setCursor =
1372 [&]()
1373 {
1374 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PLACE );
1375 };
1376
1377 Activate();
1378
1379 // Must be done after Activate() so that it gets set into the correct context
1380 getViewControls()->ShowCursor( true );
1381
1382 // Set initial cursor
1383 setCursor();
1384
1386 m_view->AddToPreview( previewItem->Clone() );
1387
1388 // Prime the pump
1389 if( aEvent.HasPosition() && type != SCH_SHEET_PIN_T )
1390 m_toolMgr->PrimeTool( aEvent.Position() );
1391 else
1393
1394 // Main loop: keep receiving events
1395 while( TOOL_EVENT* evt = Wait() )
1396 {
1397 setCursor();
1398 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1399 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1400
1401 cursorPos = evt->IsPrime() ? evt->Position() : controls->GetMousePosition();
1402 cursorPos = grid.BestSnapAnchor( cursorPos, grid.GetItemGrid( previewItem ), nullptr );
1403 controls->ForceCursorPosition( true, cursorPos );
1404
1405 if( evt->IsCancelInteractive() )
1406 {
1407 m_frame->PopTool( aEvent );
1408 break;
1409 }
1410 else if( evt->IsActivate() )
1411 {
1412 if( evt->IsMoveTool() )
1413 {
1414 // leave ourselves on the stack so we come back after the move
1415 break;
1416 }
1417 else
1418 {
1419 m_frame->PopTool( aEvent );
1420 break;
1421 }
1422 }
1423 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
1424 {
1425 if( !screen->GetItem( cursorPos, 0, type ) )
1426 {
1427 if( type == SCH_JUNCTION_T )
1428 {
1429 if( !screen->IsExplicitJunctionAllowed( cursorPos ) )
1430 {
1431 m_frame->ShowInfoBarError( _( "Junction location contains no joinable "
1432 "wires and/or pins." ) );
1433 loggedInfoBarError = true;
1434 continue;
1435 }
1436 else if( loggedInfoBarError )
1437 {
1439 }
1440 }
1441
1442 SCH_ITEM* newItem = static_cast<SCH_ITEM*>( previewItem->Clone() );
1443 const_cast<KIID&>( newItem->m_Uuid ) = KIID();
1444 newItem->SetPosition( cursorPos );
1445 newItem->SetFlags( IS_NEW );
1446 m_frame->AddToScreen( newItem, screen );
1447
1448 if( allowRepeat )
1449 m_frame->SaveCopyForRepeatItem( newItem );
1450
1451 SCH_COMMIT commit( m_toolMgr );
1452 commit.Added( newItem, screen );
1453
1454 m_frame->SchematicCleanUp( &commit );
1455
1456 commit.Push( description );
1457 }
1458
1459 if( evt->IsDblClick( BUT_LEFT ) || type == SCH_SHEET_PIN_T ) // Finish tool.
1460 {
1461 m_frame->PopTool( aEvent );
1462 break;
1463 }
1464 }
1465 else if( evt->IsClick( BUT_RIGHT ) )
1466 {
1467 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
1468 }
1469 else if( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() )
1470 {
1471 previewItem->SetPosition( cursorPos );
1473 m_view->AddToPreview( previewItem->Clone() );
1474 m_frame->SetMsgPanel( previewItem );
1475 }
1476 else if( evt->Category() == TC_COMMAND )
1477 {
1478 if( ( type == SCH_BUS_WIRE_ENTRY_T ) && ( evt->IsAction( &EE_ACTIONS::rotateCW )
1479 || evt->IsAction( &EE_ACTIONS::rotateCCW )
1480 || evt->IsAction( &EE_ACTIONS::mirrorV )
1481 || evt->IsAction( &EE_ACTIONS::mirrorH ) ) )
1482 {
1483 SCH_BUS_ENTRY_BASE* busItem = static_cast<SCH_BUS_ENTRY_BASE*>( previewItem );
1484
1485 if( evt->IsAction( &EE_ACTIONS::rotateCW ) )
1486 {
1487 busItem->Rotate( busItem->GetPosition(), false );
1488 }
1489 else if( evt->IsAction( &EE_ACTIONS::rotateCCW ) )
1490 {
1491 busItem->Rotate( busItem->GetPosition(), true );
1492 }
1493 else if( evt->IsAction( &EE_ACTIONS::mirrorV ) )
1494 {
1495 busItem->MirrorVertically( busItem->GetPosition().y );
1496 }
1497 else if( evt->IsAction( &EE_ACTIONS::mirrorH ) )
1498 {
1499 busItem->MirrorHorizontally( busItem->GetPosition().x );
1500 }
1501
1503 m_view->AddToPreview( previewItem->Clone() );
1504 }
1505 else if( evt->IsAction( &EE_ACTIONS::properties ) )
1506 {
1507 switch( type )
1508 {
1510 {
1511 std::deque<SCH_ITEM*> strokeItems;
1512 strokeItems.push_back( previewItem );
1513
1514 DIALOG_WIRE_BUS_PROPERTIES dlg( m_frame, strokeItems );
1515 }
1516 break;
1517
1518 case SCH_JUNCTION_T:
1519 {
1520 std::deque<SCH_JUNCTION*> junctions;
1521 junctions.push_back( static_cast<SCH_JUNCTION*>( previewItem ) );
1522
1523 DIALOG_JUNCTION_PROPS dlg( m_frame, junctions );
1524 }
1525 break;
1526 default:
1527 // Do nothing
1528 break;
1529 }
1530
1532 m_view->AddToPreview( previewItem->Clone() );
1533 }
1534 else
1535 {
1536 evt->SetPassEvent();
1537 }
1538 }
1539 else
1540 {
1541 evt->SetPassEvent();
1542 }
1543 }
1544
1545 delete previewItem;
1547
1548 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1549 controls->ForceCursorPosition( false );
1550
1551 return 0;
1552}
1553
1554
1556{
1557 for( SCH_ITEM* item : m_frame->GetScreen()->Items().Overlapping( SCH_LINE_T, aPosition ) )
1558 {
1559 SCH_LINE* line = static_cast<SCH_LINE*>( item );
1560
1561 if( line->GetEditFlags() & STRUCT_DELETED )
1562 continue;
1563
1564 if( line->IsWire() )
1565 return line;
1566 }
1567
1568 return nullptr;
1569}
1570
1571
1573{
1574 wxASSERT( aWire->IsWire() );
1575
1576 SCH_SHEET_PATH sheetPath = m_frame->GetCurrentSheet();
1577
1578 if( SCH_CONNECTION* wireConnection = aWire->Connection( &sheetPath ) )
1579 {
1580 SCH_ITEM* wireDriver = wireConnection->Driver();
1581
1582 if( wireDriver && wireDriver->IsType( { SCH_LABEL_T, SCH_GLOBAL_LABEL_T } ) )
1583 return wireConnection->LocalName();
1584 }
1585
1586 return wxEmptyString;
1587}
1588
1589
1591{
1592 SCHEMATIC* schematic = getModel<SCHEMATIC>();
1593 SCHEMATIC_SETTINGS& settings = schematic->Settings();
1594 SCH_TEXT* textItem = nullptr;
1595 SCH_LABEL_BASE* labelItem = nullptr;
1596 wxString netName;
1597
1598 switch( aType )
1599 {
1600 case LAYER_NOTES:
1601 textItem = new SCH_TEXT( aPosition );
1602 break;
1603
1604 case LAYER_LOCLABEL:
1605 labelItem = new SCH_LABEL( aPosition );
1606 textItem = labelItem;
1607
1608 if( SCH_LINE* wire = findWire( aPosition ) )
1609 netName = findWireLabelDriverName( wire );
1610
1611 break;
1612
1614 labelItem = new SCH_DIRECTIVE_LABEL( aPosition );
1615 labelItem->SetShape( m_lastNetClassFlagShape );
1616 labelItem->GetFields().emplace_back( SCH_FIELD( {0,0}, 0, labelItem, wxT( "Netclass" ) ) );
1617 labelItem->GetFields().emplace_back(
1618 SCH_FIELD( { 0, 0 }, 0, labelItem, wxT( "Component Class" ) ) );
1619 labelItem->GetFields().back().SetItalic( true );
1620 labelItem->GetFields().back().SetVisible( true );
1621 textItem = labelItem;
1622 break;
1623
1624 case LAYER_HIERLABEL:
1625 labelItem = new SCH_HIERLABEL( aPosition );
1626 labelItem->SetShape( m_lastGlobalLabelShape );
1628 textItem = labelItem;
1629 break;
1630
1631 case LAYER_GLOBLABEL:
1632 labelItem = new SCH_GLOBALLABEL( aPosition );
1633 labelItem->SetShape( m_lastGlobalLabelShape );
1634 labelItem->GetFields()[0].SetVisible( settings.m_IntersheetRefsShow );
1636 textItem = labelItem;
1637
1638 if( SCH_LINE* wire = findWire( aPosition ) )
1639 netName = findWireLabelDriverName( wire );
1640
1641 break;
1642
1643 default:
1644 wxFAIL_MSG( "SCH_EDIT_FRAME::CreateNewText() unknown layer type" );
1645 return nullptr;
1646 }
1647
1648 textItem->SetParent( schematic );
1649
1650 textItem->SetTextSize( VECTOR2I( settings.m_DefaultTextSize, settings.m_DefaultTextSize ) );
1651
1652 if( aType != LAYER_NETCLASS_REFS )
1653 {
1654 // Must be after SetTextSize()
1655 textItem->SetBold( m_lastTextBold );
1656 textItem->SetItalic( m_lastTextItalic );
1657 }
1658
1659 if( labelItem )
1660 {
1661 labelItem->SetSpinStyle( m_lastTextOrientation );
1662 }
1663 else
1664 {
1667 textItem->SetTextAngle( m_lastTextAngle );
1668 }
1669
1670 textItem->SetFlags( IS_NEW | IS_MOVING );
1671
1672 if( !labelItem )
1673 {
1674 DIALOG_TEXT_PROPERTIES dlg( m_frame, textItem );
1675
1676 // QuasiModal required for syntax help and Scintilla auto-complete
1677 if( dlg.ShowQuasiModal() != wxID_OK )
1678 {
1679 delete textItem;
1680 return nullptr;
1681 }
1682 }
1683 else if( !netName.IsEmpty() )
1684 {
1685 // Auto-create from attached wire
1686 textItem->SetText( netName );
1687 }
1688 else
1689 {
1690 DIALOG_LABEL_PROPERTIES dlg( m_frame, static_cast<SCH_LABEL_BASE*>( textItem ) );
1691
1692 // QuasiModal required for syntax help and Scintilla auto-complete
1693 if( dlg.ShowQuasiModal() != wxID_OK )
1694 {
1696 delete labelItem;
1697 return nullptr;
1698 }
1699 }
1700
1701 wxString text = textItem->GetText();
1702
1703 if( textItem->Type() != SCH_DIRECTIVE_LABEL_T && NoPrintableChars( text ) )
1704 {
1705 delete textItem;
1706 return nullptr;
1707 }
1708
1709 if( aType != LAYER_NETCLASS_REFS )
1710 {
1711 m_lastTextBold = textItem->IsBold();
1712 m_lastTextItalic = textItem->IsItalic();
1713 }
1714
1715 if( labelItem )
1716 {
1717 m_lastTextOrientation = labelItem->GetSpinStyle();
1718 }
1719 else
1720 {
1721 m_lastTextHJustify = textItem->GetHorizJustify();
1722 m_lastTextVJustify = textItem->GetVertJustify();
1723 m_lastTextAngle = textItem->GetTextAngle();
1724 }
1725
1726 if( aType == LAYER_GLOBLABEL || aType == LAYER_HIERLABEL )
1727 {
1728 m_lastGlobalLabelShape = labelItem->GetShape();
1730 }
1731 else if( aType == LAYER_NETCLASS_REFS )
1732 {
1733 m_lastNetClassFlagShape = labelItem->GetShape();
1734 }
1735
1736 return textItem;
1737}
1738
1739
1741{
1742 SCHEMATIC_SETTINGS& settings = aSheet->Schematic()->Settings();
1743 SCH_SHEET_PIN* pin = new SCH_SHEET_PIN( aSheet );
1744
1745 pin->SetFlags( IS_NEW | IS_MOVING );
1746 pin->SetText( std::to_string( aSheet->GetPins().size() + 1 ) );
1747 pin->SetTextSize( VECTOR2I( settings.m_DefaultTextSize, settings.m_DefaultTextSize ) );
1748 pin->SetPosition( aPosition );
1749 pin->ClearSelected();
1750
1751 m_lastSheetPinType = pin->GetShape();
1752
1753 return pin;
1754}
1755
1756
1758 const VECTOR2I& aPosition,
1759 SCH_HIERLABEL* aLabel )
1760{
1761 auto pin = createNewSheetPin( aSheet, aPosition );
1762 pin->SetText( aLabel->GetText() );
1763 pin->SetShape( aLabel->GetShape() );
1764 return pin;
1765}
1766
1767
1769{
1770 SCH_ITEM* item = nullptr;
1773 bool ignorePrimePosition = false;
1774 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
1775 SCH_SHEET* sheet = nullptr;
1776 wxString description;
1777
1778 if( m_inDrawingTool )
1779 return 0;
1780
1782
1783 bool isText = aEvent.IsAction( &EE_ACTIONS::placeSchematicText );
1784 bool isGlobalLabel = aEvent.IsAction( &EE_ACTIONS::placeGlobalLabel );
1785 bool isHierLabel = aEvent.IsAction( &EE_ACTIONS::placeHierLabel );
1786 bool isClassLabel = aEvent.IsAction( &EE_ACTIONS::placeClassLabel );
1787 bool isNetLabel = aEvent.IsAction( &EE_ACTIONS::placeLabel );
1788 bool isSheetPin = aEvent.IsAction( &EE_ACTIONS::placeSheetPin );
1789
1790 GRID_HELPER_GRIDS snapGrid = isText ? GRID_TEXT : GRID_CONNECTABLE;
1791
1792 // If we have a selected sheet use it, otherwise try to get one under the cursor
1793 if( isSheetPin )
1794 sheet = dynamic_cast<SCH_SHEET*>( m_selectionTool->GetSelection().Front() );
1795
1797
1798 m_frame->PushTool( aEvent );
1799
1800 auto setCursor =
1801 [&]()
1802 {
1803 if( item )
1804 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PLACE );
1805 else if( isText )
1806 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::TEXT );
1807 else if( isGlobalLabel )
1808 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_GLOBAL );
1809 else if( isNetLabel )
1810 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_NET );
1811 else if( isClassLabel )
1812 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_NET ); // JEY TODO: netclass directive cursor
1813 else if( isHierLabel )
1814 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_HIER );
1815 else
1816 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
1817 };
1818
1819 auto updatePreview =
1820 [&]()
1821 {
1823 m_view->AddToPreview( item, false );
1824 item->RunOnChildren( [&]( SCH_ITEM* aChild )
1825 {
1826 m_view->AddToPreview( aChild, false );
1827 } );
1828 m_frame->SetMsgPanel( item );
1829 };
1830
1831 auto cleanup =
1832 [&]()
1833 {
1836 delete item;
1837 item = nullptr;
1838 };
1839
1840 Activate();
1841
1842 // Must be done after Activate() so that it gets set into the correct context
1843 controls->ShowCursor( true );
1844
1845 // Set initial cursor
1846 setCursor();
1847
1848 if( aEvent.HasPosition() )
1849 {
1850 m_toolMgr->PrimeTool( aEvent.Position() );
1851 }
1852 else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate()
1853 && ( isText || isGlobalLabel || isHierLabel || isClassLabel || isNetLabel ) )
1854 {
1855 m_toolMgr->PrimeTool( { 0, 0 } );
1856 ignorePrimePosition = true;
1857 }
1858
1859 SCH_COMMIT commit( m_toolMgr );
1860
1861 // Main loop: keep receiving events
1862 while( TOOL_EVENT* evt = Wait() )
1863 {
1864 setCursor();
1865 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1866 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1867
1868 VECTOR2I cursorPos = controls->GetMousePosition();
1869 cursorPos = grid.BestSnapAnchor( cursorPos, snapGrid, item );
1870 controls->ForceCursorPosition( true, cursorPos );
1871
1872 // The tool hotkey is interpreted as a click when drawing
1873 bool isSyntheticClick = item && evt->IsActivate() && evt->HasPosition()
1874 && evt->Matches( aEvent );
1875
1876 if( evt->IsCancelInteractive() || evt->IsAction( &ACTIONS::undo ) )
1877 {
1879
1880 if( item )
1881 {
1882 cleanup();
1883 }
1884 else
1885 {
1886 m_frame->PopTool( aEvent );
1887 break;
1888 }
1889 }
1890 else if( evt->IsActivate() && !isSyntheticClick )
1891 {
1892 if( item && evt->IsMoveTool() )
1893 {
1894 // we're already moving our own item; ignore the move tool
1895 evt->SetPassEvent( false );
1896 continue;
1897 }
1898
1899 if( item )
1900 {
1901 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel item creation." ) );
1902 evt->SetPassEvent( false );
1903 continue;
1904 }
1905
1906 if( evt->IsPointEditor() )
1907 {
1908 // don't exit (the point editor runs in the background)
1909 }
1910 else if( evt->IsMoveTool() )
1911 {
1912 // leave ourselves on the stack so we come back after the move
1913 break;
1914 }
1915 else
1916 {
1917 m_frame->PopTool( aEvent );
1918 break;
1919 }
1920 }
1921 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) || isSyntheticClick )
1922 {
1923 PLACE_NEXT:
1924 // First click creates...
1925 if( !item )
1926 {
1928
1929 if( isText )
1930 {
1931 item = createNewText( cursorPos, LAYER_NOTES );
1932 description = _( "Add Text" );
1933 }
1934 else if( isHierLabel )
1935 {
1936 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->GetPlacementTemplate() )
1937 {
1938 auto pin = static_cast<SCH_HIERLABEL*>(
1939 m_dialogSyncSheetPin->GetPlacementTemplate() );
1940 SCH_HIERLABEL* label = new SCH_HIERLABEL( cursorPos );
1941 SCHEMATIC* schematic = getModel<SCHEMATIC>();
1942 label->SetText( pin->GetText() );
1943 label->SetShape( pin->GetShape() );
1945 label->SetParent( schematic );
1946 label->SetBold( m_lastTextBold );
1947 label->SetItalic( m_lastTextItalic );
1949 label->SetTextSize( VECTOR2I( schematic->Settings().m_DefaultTextSize,
1950 schematic->Settings().m_DefaultTextSize ) );
1951 label->SetFlags( IS_NEW | IS_MOVING );
1952 item = label;
1953 }
1954 else
1955 {
1956 item = createNewText( cursorPos, LAYER_HIERLABEL );
1957 }
1958
1959 description = _( "Add Hierarchical Label" );
1960 }
1961 else if( isNetLabel )
1962 {
1963 item = createNewText( cursorPos, LAYER_LOCLABEL );
1964 description = _( "Add Label" );
1965 }
1966 else if( isGlobalLabel )
1967 {
1968 item = createNewText( cursorPos, LAYER_GLOBLABEL );
1969 description = _( "Add Label" );
1970 }
1971 else if( isClassLabel )
1972 {
1973 item = createNewText( cursorPos, LAYER_NETCLASS_REFS );
1974 description = _( "Add Label" );
1975 }
1976 else if( isSheetPin )
1977 {
1978 EDA_ITEM* i = nullptr;
1979
1980 // If we didn't have a sheet selected, try to find one under the cursor
1981 if( !sheet && m_selectionTool->SelectPoint( cursorPos, { SCH_SHEET_T }, &i ) )
1982 sheet = dynamic_cast<SCH_SHEET*>( i );
1983
1984 if( !sheet )
1985 {
1986 m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( m_frame );
1987 m_statusPopup->SetText( _( "Click over a sheet." ) );
1989 + wxPoint( 20, 20 ) );
1990 m_statusPopup->PopupFor( 2000 );
1991 item = nullptr;
1992 }
1993 else
1994 {
1995 // User is using the 'Sync Sheet Pins' tool
1996 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->GetPlacementTemplate() )
1997 {
1999 sheet, cursorPos,
2000 static_cast<SCH_HIERLABEL*>(
2001 m_dialogSyncSheetPin->GetPlacementTemplate() ) );
2002 }
2003 else
2004 {
2005 // User is using the 'Place Sheet Pins' tool
2006 SCH_HIERLABEL* label = importHierLabel( sheet );
2007
2008 if( !label )
2009 {
2010 m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( m_frame );
2011 m_statusPopup->SetText( _( "No new hierarchical labels found." ) );
2013 + wxPoint( 20, 20 ) );
2014 m_statusPopup->PopupFor( 2000 );
2015 item = nullptr;
2016
2017 m_frame->PopTool( aEvent );
2018 break;
2019 }
2020
2021 item = createNewSheetPinFromLabel( sheet, cursorPos, label );
2022 }
2023 }
2024
2025 description = _( "Add Sheet Pin" );
2026 }
2027
2028 // If we started with a hotkey which has a position then warp back to that.
2029 // Otherwise update to the current mouse position pinned inside the autoscroll
2030 // boundaries.
2031 if( evt->IsPrime() && !ignorePrimePosition )
2032 {
2033 cursorPos = grid.Align( evt->Position() );
2034 getViewControls()->WarpMouseCursor( cursorPos, true );
2035 }
2036 else
2037 {
2039 cursorPos = getViewControls()->GetMousePosition();
2040 cursorPos = grid.BestSnapAnchor( cursorPos, snapGrid, item );
2041 }
2042
2043 if( item )
2044 {
2045 item->SetPosition( cursorPos );
2046
2047 item->SetFlags( IS_NEW | IS_MOVING );
2048
2049 // Not placed yet, so pass a nullptr screen reference
2050 item->AutoplaceFields( nullptr, AUTOPLACE_AUTO );
2051
2052 updatePreview();
2055
2056 // update the cursor so it looks correct before another event
2057 setCursor();
2058 }
2059
2060 controls->SetCursorPosition( cursorPos, false );
2061 }
2062 else // ... and second click places:
2063 {
2064 item->ClearFlags( IS_MOVING );
2065
2066 if( item->IsConnectable() )
2068
2069 if( isSheetPin )
2070 {
2071 // Sheet pins are owned by their parent sheet.
2072 commit.Modify( sheet, m_frame->GetScreen() );
2073 sheet->AddPin( (SCH_SHEET_PIN*) item );
2074 }
2075 else
2076 {
2078 m_frame->AddToScreen( item, m_frame->GetScreen() );
2079 commit.Added( item, m_frame->GetScreen() );
2080 }
2081
2083
2084 commit.Push( description );
2085
2087
2088 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->GetPlacementTemplate() )
2089 {
2090 m_dialogSyncSheetPin->EndPlaceItem( item );
2091
2092 if( m_dialogSyncSheetPin->CanPlaceMore() )
2093 {
2094 item = nullptr;
2095 goto PLACE_NEXT;
2096 }
2097
2098 m_frame->PopTool( aEvent );
2100 m_dialogSyncSheetPin->Show( true );
2101 break;
2102 }
2103
2104 item = nullptr;
2105
2106 if( isSheetPin )
2107 {
2108 SCH_HIERLABEL* label = importHierLabel( sheet );
2109
2110 if( !label )
2111 {
2112 m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( m_frame );
2113 m_statusPopup->SetText( _( "No new hierarchical labels found." ) );
2115 + wxPoint( 20, 20 ) );
2116 m_statusPopup->PopupFor( 2000 );
2117
2118 m_frame->PopTool( aEvent );
2119 break;
2120 }
2121
2122 item = createNewSheetPinFromLabel( sheet, cursorPos, label );
2123 }
2124 }
2125 }
2126 else if( evt->IsClick( BUT_RIGHT ) )
2127 {
2128 // Warp after context menu only if dragging...
2129 if( !item )
2131
2132 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
2133 }
2134 else if( item && evt->IsSelectionEvent() )
2135 {
2136 // This happens if our text was replaced out from under us by ConvertTextType()
2138
2139 if( selection.GetSize() == 1 )
2140 {
2141 item = (SCH_ITEM*) selection.Front();
2142 updatePreview();
2143 }
2144 else
2145 {
2146 item = nullptr;
2147 }
2148 }
2149 else if( evt->IsAction( &ACTIONS::increment ) )
2150 {
2152 evt->Parameter<ACTIONS::INCREMENT>() );
2153 }
2154 else if( evt->IsAction( &ACTIONS::duplicate )
2155 || evt->IsAction( &EE_ACTIONS::repeatDrawItem ) )
2156 {
2157 if( item )
2158 {
2159 // This doesn't really make sense; we'll just end up dragging a stack of
2160 // objects so we ignore the duplicate and just carry on.
2161 wxBell();
2162 continue;
2163 }
2164
2165 // Exit. The duplicate will run in its own loop.
2166 m_frame->PopTool( aEvent );
2167 break;
2168 }
2169 else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
2170 {
2171 item->SetPosition( cursorPos );
2172
2173 // Not placed yet, so pass a nullptr screen reference
2174 item->AutoplaceFields( nullptr, AUTOPLACE_AUTO );
2175
2176 updatePreview();
2177 }
2178 else if( item && evt->IsAction( &ACTIONS::doDelete ) )
2179 {
2180 cleanup();
2181 }
2182 else if( evt->IsAction( &ACTIONS::redo ) )
2183 {
2184 wxBell();
2185 }
2186 else
2187 {
2188 evt->SetPassEvent();
2189 }
2190
2191 // Enable autopanning and cursor capture only when there is an item to be placed
2192 controls->SetAutoPan( item != nullptr );
2193 controls->CaptureCursor( item != nullptr );
2194 }
2195
2196 controls->SetAutoPan( false );
2197 controls->CaptureCursor( false );
2198 controls->ForceCursorPosition( false );
2199 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2200
2201 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->CanPlaceMore() )
2202 {
2203 m_dialogSyncSheetPin->EndPlacement();
2204 m_dialogSyncSheetPin->Show( true );
2205 }
2206
2207 return 0;
2208}
2209
2210
2212{
2213 SCHEMATIC* schematic = getModel<SCHEMATIC>();
2214 SCHEMATIC_SETTINGS& sch_settings = schematic->Settings();
2215 SCH_SHAPE* item = nullptr;
2216 bool isTextBox = aEvent.IsAction( &EE_ACTIONS::drawTextBox );
2217 SHAPE_T type = aEvent.Parameter<SHAPE_T>();
2218 wxString description;
2219
2220 if( m_inDrawingTool )
2221 return 0;
2222
2224
2227 VECTOR2I cursorPos;
2228
2229 // We might be running as the same shape in another co-routine. Make sure that one
2230 // gets whacked.
2232
2234
2235 m_frame->PushTool( aEvent );
2236
2237 auto setCursor =
2238 [&]()
2239 {
2240 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
2241 };
2242
2243 auto cleanup =
2244 [&] ()
2245 {
2248 delete item;
2249 item = nullptr;
2250 };
2251
2252 Activate();
2253
2254 // Must be done after Activate() so that it gets set into the correct context
2255 getViewControls()->ShowCursor( true );
2256
2257 // Set initial cursor
2258 setCursor();
2259
2260 if( aEvent.HasPosition() )
2261 m_toolMgr->PrimeTool( aEvent.Position() );
2262
2263 // Main loop: keep receiving events
2264 while( TOOL_EVENT* evt = Wait() )
2265 {
2266 setCursor();
2267 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
2268 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
2269
2270 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
2271 controls->ForceCursorPosition( true, cursorPos );
2272
2273 // The tool hotkey is interpreted as a click when drawing
2274 bool isSyntheticClick = item && evt->IsActivate() && evt->HasPosition()
2275 && evt->Matches( aEvent );
2276
2277 if( evt->IsCancelInteractive() || ( item && evt->IsAction( &ACTIONS::undo ) ) )
2278 {
2279 if( item )
2280 {
2281 cleanup();
2282 }
2283 else
2284 {
2285 m_frame->PopTool( aEvent );
2286 break;
2287 }
2288 }
2289 else if( evt->IsActivate() && !isSyntheticClick )
2290 {
2291 if( item && evt->IsMoveTool() )
2292 {
2293 // we're already drawing our own item; ignore the move tool
2294 evt->SetPassEvent( false );
2295 continue;
2296 }
2297
2298 if( item )
2299 cleanup();
2300
2301 if( evt->IsPointEditor() )
2302 {
2303 // don't exit (the point editor runs in the background)
2304 }
2305 else if( evt->IsMoveTool() )
2306 {
2307 // leave ourselves on the stack so we come back after the move
2308 break;
2309 }
2310 else
2311 {
2312 m_frame->PopTool( aEvent );
2313 break;
2314 }
2315 }
2316 else if( evt->IsClick( BUT_LEFT ) && !item )
2317 {
2319
2320 if( isTextBox )
2321 {
2323
2324 textbox->SetTextSize( VECTOR2I( sch_settings.m_DefaultTextSize,
2325 sch_settings.m_DefaultTextSize ) );
2326
2327 // Must come after SetTextSize()
2328 textbox->SetBold( m_lastTextBold );
2329 textbox->SetItalic( m_lastTextItalic );
2330
2331 textbox->SetTextAngle( m_lastTextboxAngle );
2334 textbox->SetStroke( m_lastTextboxStroke );
2336 textbox->SetParent( schematic );
2337
2338 item = textbox;
2339 description = _( "Add Text Box" );
2340 }
2341 else
2342 {
2343 item = new SCH_SHAPE( type, LAYER_NOTES, 0, m_lastFillStyle );
2344
2345 item->SetStroke( m_lastStroke );
2347 item->SetParent( schematic );
2348 description = wxString::Format( _( "Add %s" ), item->GetFriendlyName() );
2349 }
2350
2351 item->SetFlags( IS_NEW );
2352 item->BeginEdit( cursorPos );
2353
2355 m_view->AddToPreview( item->Clone() );
2356 }
2357 else if( item && ( evt->IsClick( BUT_LEFT )
2358 || evt->IsDblClick( BUT_LEFT )
2359 || isSyntheticClick
2360 || evt->IsAction( &ACTIONS::finishInteractive ) ) )
2361 {
2362 if( evt->IsDblClick( BUT_LEFT )
2363 || evt->IsAction( &ACTIONS::finishInteractive )
2364 || !item->ContinueEdit( cursorPos ) )
2365 {
2366 item->EndEdit();
2367 item->ClearEditFlags();
2368 item->SetFlags( IS_NEW );
2369
2370 if( isTextBox )
2371 {
2372 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( item );
2373 DIALOG_TEXT_PROPERTIES dlg( m_frame, textbox );
2374
2375 getViewControls()->SetAutoPan( false );
2376 getViewControls()->CaptureCursor( false );
2377
2378 // QuasiModal required for syntax help and Scintilla auto-complete
2379 if( dlg.ShowQuasiModal() != wxID_OK )
2380 {
2381 cleanup();
2382 continue;
2383 }
2384
2385 m_lastTextBold = textbox->IsBold();
2386 m_lastTextItalic = textbox->IsItalic();
2387 m_lastTextboxAngle = textbox->GetTextAngle();
2390 m_lastTextboxStroke = textbox->GetStroke();
2393 }
2394 else
2395 {
2396 m_lastStroke = item->GetStroke();
2397 m_lastFillStyle = item->GetFillMode();
2398 m_lastFillColor = item->GetFillColor();
2399 }
2400
2401 SCH_COMMIT commit( m_toolMgr );
2402 commit.Add( item, m_frame->GetScreen() );
2403 commit.Push( wxString::Format( _( "Draw %s" ), item->GetClass() ) );
2404
2406 item = nullptr;
2407
2410 }
2411 }
2412 else if( evt->IsAction( &ACTIONS::duplicate )
2413 || evt->IsAction( &EE_ACTIONS::repeatDrawItem ) )
2414 {
2415 if( item )
2416 {
2417 // This doesn't really make sense; we'll just end up dragging a stack of
2418 // objects so we ignore the duplicate and just carry on.
2419 wxBell();
2420 continue;
2421 }
2422
2423 // Exit. The duplicate will run in its own loop.
2424 m_frame->PopTool( aEvent );
2425 break;
2426 }
2427 else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
2428 {
2429 item->CalcEdit( cursorPos );
2431 m_view->AddToPreview( item->Clone() );
2432 m_frame->SetMsgPanel( item );
2433 }
2434 else if( evt->IsDblClick( BUT_LEFT ) && !item )
2435 {
2437 }
2438 else if( evt->IsClick( BUT_RIGHT ) )
2439 {
2440 // Warp after context menu only if dragging...
2441 if( !item )
2443
2444 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
2445 }
2446 else if( item && evt->IsAction( &ACTIONS::redo ) )
2447 {
2448 wxBell();
2449 }
2450 else
2451 {
2452 evt->SetPassEvent();
2453 }
2454
2455 // Enable autopanning and cursor capture only when there is a shape being drawn
2456 getViewControls()->SetAutoPan( item != nullptr );
2457 getViewControls()->CaptureCursor( item != nullptr );
2458 }
2459
2460 getViewControls()->SetAutoPan( false );
2461 getViewControls()->CaptureCursor( false );
2462 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2463 return 0;
2464}
2465
2466
2468{
2469 if( m_inDrawingTool )
2470 return 0;
2471
2473 SCOPED_SET_RESET<bool> scopedDrawMode( m_drawingRuleArea, true );
2474
2477 VECTOR2I cursorPos;
2478
2479 RULE_AREA_CREATE_HELPER ruleAreaTool( *getView(), m_frame, m_toolMgr );
2480 POLYGON_GEOM_MANAGER polyGeomMgr( ruleAreaTool );
2481 bool started = false;
2482
2483 // We might be running as the same shape in another co-routine. Make sure that one
2484 // gets whacked.
2486
2488
2489 m_frame->PushTool( aEvent );
2490
2491 auto setCursor =
2492 [&]()
2493 {
2494 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
2495 };
2496
2497 auto cleanup = [&]()
2498 {
2499 polyGeomMgr.Reset();
2500 started = false;
2501 getViewControls()->SetAutoPan( false );
2502 getViewControls()->CaptureCursor( false );
2504 };
2505
2506 Activate();
2507
2508 // Must be done after Activate() so that it gets set into the correct context
2509 getViewControls()->ShowCursor( true );
2510 //m_controls->ForceCursorPosition( false );
2511
2512 // Set initial cursor
2513 setCursor();
2514
2515 if( aEvent.HasPosition() )
2516 m_toolMgr->PrimeTool( aEvent.Position() );
2517
2518 // Main loop: keep receiving events
2519 while( TOOL_EVENT* evt = Wait() )
2520 {
2521 setCursor();
2522
2523 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
2524 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
2525
2526 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_CONNECTABLE );
2527 controls->ForceCursorPosition( true, cursorPos );
2528
2532
2533 if( evt->IsCancelInteractive() )
2534 {
2535 if( started )
2536 {
2537 cleanup();
2538 }
2539 else
2540 {
2541 m_frame->PopTool( aEvent );
2542
2543 // We've handled the cancel event. Don't cancel other tools
2544 evt->SetPassEvent( false );
2545 break;
2546 }
2547 }
2548 else if( evt->IsActivate() )
2549 {
2550 if( started )
2551 cleanup();
2552
2553 if( evt->IsPointEditor() )
2554 {
2555 // don't exit (the point editor runs in the background)
2556 }
2557 else if( evt->IsMoveTool() )
2558 {
2559 // leave ourselves on the stack so we come back after the move
2560 break;
2561 }
2562 else
2563 {
2564 m_frame->PopTool( aEvent );
2565 break;
2566 }
2567 }
2568 else if( evt->IsClick( BUT_RIGHT ) )
2569 {
2570 if( !started )
2572
2573 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
2574 }
2575 // events that lock in nodes
2576 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT )
2577 || evt->IsAction( &EE_ACTIONS::closeOutline ) )
2578 {
2579 // Check if it is double click / closing line (so we have to finish the zone)
2580 const bool endPolygon = evt->IsDblClick( BUT_LEFT )
2581 || evt->IsAction( &EE_ACTIONS::closeOutline )
2582 || polyGeomMgr.NewPointClosesOutline( cursorPos );
2583
2584 if( endPolygon )
2585 {
2586 polyGeomMgr.SetFinished();
2587 polyGeomMgr.Reset();
2588
2589 started = false;
2590 getViewControls()->SetAutoPan( false );
2591 getViewControls()->CaptureCursor( false );
2592 }
2593 // adding a corner
2594 else if( polyGeomMgr.AddPoint( cursorPos ) )
2595 {
2596 if( !started )
2597 {
2598 started = true;
2599
2600 getViewControls()->SetAutoPan( true );
2601 getViewControls()->CaptureCursor( true );
2602 }
2603 }
2604 }
2605 else if( started
2606 && ( evt->IsAction( &EE_ACTIONS::deleteLastPoint )
2607 || evt->IsAction( &ACTIONS::doDelete )
2608 || evt->IsAction( &ACTIONS::undo ) ) )
2609 {
2610 if( std::optional<VECTOR2I> last = polyGeomMgr.DeleteLastCorner() )
2611 {
2612 cursorPos = last.value();
2613 getViewControls()->WarpMouseCursor( cursorPos, true );
2614 getViewControls()->ForceCursorPosition( true, cursorPos );
2615 polyGeomMgr.SetCursorPosition( cursorPos );
2616 }
2617 else
2618 {
2619 cleanup();
2620 }
2621 }
2622 else if( started && ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) )
2623 {
2624 polyGeomMgr.SetCursorPosition( cursorPos );
2625 }
2626 else
2627 {
2628 evt->SetPassEvent();
2629 }
2630
2631 } // end while
2632
2633 getViewControls()->SetAutoPan( false );
2634 getViewControls()->CaptureCursor( false );
2635 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2636 return 0;
2637}
2638
2639
2641{
2642 SCHEMATIC* schematic = getModel<SCHEMATIC>();
2643 SCH_TABLE* table = nullptr;
2644
2645 if( m_inDrawingTool )
2646 return 0;
2647
2649
2652 VECTOR2I cursorPos;
2653
2654 // We might be running as the same shape in another co-routine. Make sure that one
2655 // gets whacked.
2657
2659
2660 m_frame->PushTool( aEvent );
2661
2662 auto setCursor =
2663 [&]()
2664 {
2665 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
2666 };
2667
2668 auto cleanup =
2669 [&] ()
2670 {
2673 delete table;
2674 table = nullptr;
2675 };
2676
2677 Activate();
2678
2679 // Must be done after Activate() so that it gets set into the correct context
2680 getViewControls()->ShowCursor( true );
2681
2682 // Set initial cursor
2683 setCursor();
2684
2685 if( aEvent.HasPosition() )
2686 m_toolMgr->PrimeTool( aEvent.Position() );
2687
2688 // Main loop: keep receiving events
2689 while( TOOL_EVENT* evt = Wait() )
2690 {
2691 setCursor();
2692 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
2693 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
2694
2695 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
2696 controls->ForceCursorPosition( true, cursorPos );
2697
2698 // The tool hotkey is interpreted as a click when drawing
2699 bool isSyntheticClick = table
2700 && evt->IsActivate()
2701 && evt->HasPosition()
2702 && evt->Matches( aEvent );
2703
2704 if( evt->IsCancelInteractive() || ( table && evt->IsAction( &ACTIONS::undo ) ) )
2705 {
2706 if( table )
2707 {
2708 cleanup();
2709 }
2710 else
2711 {
2712 m_frame->PopTool( aEvent );
2713 break;
2714 }
2715 }
2716 else if( evt->IsActivate() && !isSyntheticClick )
2717 {
2718 if( table && evt->IsMoveTool() )
2719 {
2720 // we're already drawing our own item; ignore the move tool
2721 evt->SetPassEvent( false );
2722 continue;
2723 }
2724
2725 if( table )
2726 cleanup();
2727
2728 if( evt->IsPointEditor() )
2729 {
2730 // don't exit (the point editor runs in the background)
2731 }
2732 else if( evt->IsMoveTool() )
2733 {
2734 // leave ourselves on the stack so we come back after the move
2735 break;
2736 }
2737 else
2738 {
2739 m_frame->PopTool( aEvent );
2740 break;
2741 }
2742 }
2743 else if( evt->IsClick( BUT_LEFT ) && !table )
2744 {
2746
2747 table = new SCH_TABLE( 0 );
2748 table->SetColCount( 1 );
2749
2750 SCH_TABLECELL* tableCell = new SCH_TABLECELL();
2751 int defaultTextSize = schematic->Settings().m_DefaultTextSize;
2752
2753 tableCell->SetTextSize( VECTOR2I( defaultTextSize, defaultTextSize ) );
2754 table->AddCell( tableCell );
2755
2756 table->SetParent( schematic );
2757 table->SetFlags( IS_NEW );
2758 table->SetPosition( cursorPos );
2759
2761 m_view->AddToPreview( table->Clone() );
2762 }
2763 else if( table && ( evt->IsClick( BUT_LEFT )
2764 || evt->IsDblClick( BUT_LEFT )
2765 || isSyntheticClick
2766 || evt->IsAction( &EE_ACTIONS::finishInteractive ) ) )
2767 {
2768 table->ClearEditFlags();
2769 table->SetFlags( IS_NEW );
2770 table->Normalize();
2771
2773
2774 // QuasiModal required for Scintilla auto-complete
2775 if( dlg.ShowQuasiModal() == wxID_OK )
2776 {
2777 SCH_COMMIT commit( m_toolMgr );
2778 commit.Add( table, m_frame->GetScreen() );
2779 commit.Push( _( "Draw Table" ) );
2780
2783 }
2784 else
2785 {
2786 delete table;
2787 }
2788
2789 table = nullptr;
2791 }
2792 else if( table && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
2793 {
2794 VECTOR2I gridSize = grid.GetGridSize( grid.GetItemGrid( table ) );
2795 int fontSize = schematic->Settings().m_DefaultTextSize;
2796 VECTOR2I origin( table->GetPosition() );
2797 VECTOR2I requestedSize( cursorPos - origin );
2798
2799 int colCount = std::max( 1, requestedSize.x / ( fontSize * 15 ) );
2800 int rowCount = std::max( 1, requestedSize.y / ( fontSize * 2 ) );
2801
2802 VECTOR2I cellSize( std::max( gridSize.x * 5, requestedSize.x / colCount ),
2803 std::max( gridSize.y * 2, requestedSize.y / rowCount ) );
2804
2805 cellSize.x = KiROUND( (double) cellSize.x / gridSize.x ) * gridSize.x;
2806 cellSize.y = KiROUND( (double) cellSize.y / gridSize.y ) * gridSize.y;
2807
2808 table->ClearCells();
2809 table->SetColCount( colCount );
2810
2811 for( int col = 0; col < colCount; ++col )
2812 table->SetColWidth( col, cellSize.x );
2813
2814 for( int row = 0; row < rowCount; ++row )
2815 {
2816 table->SetRowHeight( row, cellSize.y );
2817
2818 for( int col = 0; col < colCount; ++col )
2819 {
2820 SCH_TABLECELL* cell = new SCH_TABLECELL();
2821 int defaultTextSize = schematic->Settings().m_DefaultTextSize;
2822
2823 cell->SetTextSize( VECTOR2I( defaultTextSize, defaultTextSize ) );
2824 cell->SetPosition( origin + VECTOR2I( col * cellSize.x, row * cellSize.y ) );
2825 cell->SetEnd( cell->GetPosition() + cellSize );
2826 table->AddCell( cell );
2827 }
2828 }
2829
2831 m_view->AddToPreview( table->Clone() );
2833 }
2834 else if( evt->IsDblClick( BUT_LEFT ) && !table )
2835 {
2837 }
2838 else if( evt->IsClick( BUT_RIGHT ) )
2839 {
2840 // Warp after context menu only if dragging...
2841 if( !table )
2843
2844 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
2845 }
2846 else if( table && evt->IsAction( &ACTIONS::redo ) )
2847 {
2848 wxBell();
2849 }
2850 else
2851 {
2852 evt->SetPassEvent();
2853 }
2854
2855 // Enable autopanning and cursor capture only when there is a shape being drawn
2856 getViewControls()->SetAutoPan( table != nullptr );
2857 getViewControls()->CaptureCursor( table != nullptr );
2858 }
2859
2860 getViewControls()->SetAutoPan( false );
2861 getViewControls()->CaptureCursor( false );
2862 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2863 return 0;
2864}
2865
2866
2868{
2869 bool isDrawSheetCopy = aEvent.IsAction( &EE_ACTIONS::drawSheetFromFile );
2870 bool isDrawSheetFromDesignBlock = aEvent.IsAction( &EE_ACTIONS::drawSheetFromDesignBlock );
2871
2872 DESIGN_BLOCK* designBlock = nullptr;
2873 SCH_SHEET* sheet = nullptr;
2874 wxString filename;
2875
2876 if( isDrawSheetCopy )
2877 {
2878 wxString* ptr = aEvent.Parameter<wxString*>();
2879 wxCHECK( ptr, 0 );
2880
2881 // We own the string if we're importing a sheet
2882 filename = *ptr;
2883 delete ptr;
2884 }
2885 else if( isDrawSheetFromDesignBlock )
2886 {
2887 designBlock = aEvent.Parameter<DESIGN_BLOCK*>();
2888 wxCHECK( designBlock, 0 );
2889 filename = designBlock->GetSchematicFile();
2890 }
2891
2892 if( ( isDrawSheetCopy || isDrawSheetFromDesignBlock ) && !wxFileExists( filename ) )
2893 {
2894 wxMessageBox( wxString::Format( _( "File '%s' does not exist." ), filename ) );
2895 return 0;
2896 }
2897
2898 if( m_inDrawingTool )
2899 return 0;
2900
2902
2904 SCHEMATIC_SETTINGS& schSettings = m_frame->Schematic().Settings();
2907 VECTOR2I cursorPos;
2908
2910
2911 m_frame->PushTool( aEvent );
2912
2913 auto setCursor =
2914 [&]()
2915 {
2916 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
2917 };
2918
2919 auto cleanup =
2920 [&] ()
2921 {
2924 delete sheet;
2925 sheet = nullptr;
2926 };
2927
2928 Activate();
2929
2930 // Must be done after Activate() so that it gets set into the correct context
2931 getViewControls()->ShowCursor( true );
2932
2933 // Set initial cursor
2934 setCursor();
2935
2936 if( aEvent.HasPosition() && !( isDrawSheetCopy || isDrawSheetFromDesignBlock ) )
2937 m_toolMgr->PrimeTool( aEvent.Position() );
2938
2939 // Main loop: keep receiving events
2940 while( TOOL_EVENT* evt = Wait() )
2941 {
2942 setCursor();
2943 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
2944 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
2945
2946 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
2947 controls->ForceCursorPosition( true, cursorPos );
2948
2949 // The tool hotkey is interpreted as a click when drawing
2950 bool isSyntheticClick = sheet && evt->IsActivate() && evt->HasPosition()
2951 && evt->Matches( aEvent );
2952
2953 if( evt->IsCancelInteractive() || ( sheet && evt->IsAction( &ACTIONS::undo ) ) )
2954 {
2956
2957 if( sheet )
2958 {
2959 cleanup();
2960 }
2961 else
2962 {
2963 m_frame->PopTool( aEvent );
2964 break;
2965 }
2966 }
2967 else if( evt->IsActivate() && !isSyntheticClick )
2968 {
2969 if( sheet && evt->IsMoveTool() )
2970 {
2971 // we're already drawing our own item; ignore the move tool
2972 evt->SetPassEvent( false );
2973 continue;
2974 }
2975
2976 if( sheet )
2977 {
2978 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel sheet creation." ) );
2979 evt->SetPassEvent( false );
2980 continue;
2981 }
2982
2983 if( evt->IsPointEditor() )
2984 {
2985 // don't exit (the point editor runs in the background)
2986 }
2987 else if( evt->IsMoveTool() )
2988 {
2989 // leave ourselves on the stack so we come back after the move
2990 break;
2991 }
2992 else
2993 {
2994 m_frame->PopTool( aEvent );
2995 break;
2996 }
2997 }
2998 else if( !sheet && ( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) ) )
2999 {
3001
3002 if( selection.Size() == 1
3003 && selection.Front()->Type() == SCH_SHEET_T
3004 && selection.Front()->GetBoundingBox().Contains( cursorPos ) )
3005 {
3006 if( evt->IsClick( BUT_LEFT ) )
3007 {
3008 // sheet already selected
3009 continue;
3010 }
3011 else if( evt->IsDblClick( BUT_LEFT ) )
3012 {
3014 m_frame->PopTool( aEvent );
3015 break;
3016 }
3017 }
3018
3020
3021 sheet = new SCH_SHEET( m_frame->GetCurrentSheet().Last(), cursorPos );
3022 sheet->SetScreen( nullptr );
3023
3024 if( isDrawSheetCopy )
3025 {
3026 wxFileName fn( filename );
3027
3028 sheet->GetFields()[SHEETNAME].SetText( fn.GetName() );
3029 sheet->GetFields()[SHEETFILENAME].SetText( fn.GetName() + wxT( "." )
3031 }
3032 else if( isDrawSheetFromDesignBlock )
3033 {
3034 wxFileName fn( filename );
3035
3036 sheet->GetFields()[SHEETNAME].SetText( designBlock->GetLibId().GetLibItemName() );
3037 sheet->GetFields()[SHEETFILENAME].SetText( fn.GetName() + wxT( "." )
3039
3040 std::vector<SCH_FIELD>& sheetFields = sheet->GetFields();
3041
3042 // Copy default fields into the sheet
3043 for( const auto& field : designBlock->GetFields() )
3044 {
3045 SCH_FIELD newField( sheet, sheetFields.size(), field.first );
3046 newField.SetText( field.second );
3047 newField.SetVisible( false );
3048
3049 sheetFields.emplace_back( newField );
3050 }
3051 }
3052 else
3053 {
3054 sheet->GetFields()[SHEETNAME].SetText( wxT( "Untitled Sheet" ) );
3055 sheet->GetFields()[SHEETFILENAME].SetText(
3056 wxString::Format( wxT( "untitled.%s" ), FILEEXT::KiCadSchematicFileExtension ) );
3057 }
3058
3059 sheet->SetFlags( IS_NEW | IS_MOVING );
3063 sizeSheet( sheet, cursorPos );
3064
3065 SCH_SHEET_LIST hierarchy = m_frame->Schematic().Hierarchy();
3067 instance.push_back( sheet );
3068 wxString pageNumber;
3069
3070 // Don't try to be too clever when assigning the next availabe page number. Just use
3071 // the number of sheets plus one.
3072 pageNumber.Printf( wxT( "%d" ), static_cast<int>( hierarchy.size() ) + 1 );
3073 instance.SetPageNumber( pageNumber );
3074
3076 m_view->AddToPreview( sheet->Clone() );
3077 }
3078 else if( sheet && ( evt->IsClick( BUT_LEFT )
3079 || evt->IsDblClick( BUT_LEFT )
3080 || isSyntheticClick
3081 || evt->IsAction( &ACTIONS::finishInteractive ) ) )
3082 {
3083 getViewControls()->SetAutoPan( false );
3084 getViewControls()->CaptureCursor( false );
3085
3086 if( m_frame->EditSheetProperties( static_cast<SCH_SHEET*>( sheet ),
3087 &m_frame->GetCurrentSheet(), nullptr, nullptr,
3088 nullptr, &filename ) )
3089 {
3091
3093
3094 // Use the commit we were provided or make our own
3095 SCH_COMMIT tempCommit = SCH_COMMIT( m_toolMgr );
3096 SCH_COMMIT& c = evt->Commit() ? *( (SCH_COMMIT*) evt->Commit() ) : tempCommit;
3097
3098 // We need to manually add the sheet to the screen otherwise annotation will not be able to find
3099 // the sheet and its symbols to annotate.
3100 m_frame->AddToScreen( sheet );
3101 c.Added( sheet, m_frame->GetScreen() );
3102
3103 // This convoluted logic means we always annotate unless we are drawing a copy/design block
3104 // and the user has explicitly requested we keep the annotations via checkbox
3106
3107 if( annotate.automatic
3108 && !( ( isDrawSheetCopy || isDrawSheetFromDesignBlock )
3110 {
3111 // Annotation will remove this from selection, but we add it back later
3112 m_selectionTool->AddItemToSel( sheet );
3113
3114 NULL_REPORTER reporter;
3117 (ANNOTATE_ALGO_T) annotate.method, true /* recursive */,
3118 schSettings.m_AnnotateStartNum, true, false, reporter );
3119 }
3120
3121 c.Push( isDrawSheetCopy ? "Import Sheet Copy" : "Draw Sheet" );
3122
3123 m_selectionTool->AddItemToSel( sheet );
3124 }
3125 else
3126 {
3128 delete sheet;
3129 }
3130
3131 sheet = nullptr;
3132 }
3133 else if( evt->IsAction( &ACTIONS::duplicate )
3134 || evt->IsAction( &EE_ACTIONS::repeatDrawItem ) )
3135 {
3136 if( sheet )
3137 {
3138 // This doesn't really make sense; we'll just end up dragging a stack of
3139 // objects so we ignore the duplicate and just carry on.
3140 wxBell();
3141 continue;
3142 }
3143
3144 // Exit. The duplicate will run in its own loop.
3145 m_frame->PopTool( aEvent );
3146 break;
3147 }
3148 else if( sheet && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
3149 {
3150 sizeSheet( sheet, cursorPos );
3152 m_view->AddToPreview( sheet->Clone() );
3153 m_frame->SetMsgPanel( sheet );
3154 }
3155 else if( evt->IsClick( BUT_RIGHT ) )
3156 {
3157 // Warp after context menu only if dragging...
3158 if( !sheet )
3160
3161 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
3162 }
3163 else if( sheet && evt->IsAction( &ACTIONS::redo ) )
3164 {
3165 wxBell();
3166 }
3167 else
3168 {
3169 evt->SetPassEvent();
3170 }
3171
3172 // Enable autopanning and cursor capture only when there is a sheet to be placed
3173 getViewControls()->SetAutoPan( sheet != nullptr );
3174 getViewControls()->CaptureCursor( sheet != nullptr );
3175 }
3176
3177 getViewControls()->SetAutoPan( false );
3178 getViewControls()->CaptureCursor( false );
3179 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
3180
3181 return 0;
3182}
3183
3184
3186{
3187 VECTOR2I pos = aSheet->GetPosition();
3188 VECTOR2I size = aPos - pos;
3189
3190 size.x = std::max( size.x, schIUScale.MilsToIU( MIN_SHEET_WIDTH ) );
3191 size.y = std::max( size.y, schIUScale.MilsToIU( MIN_SHEET_HEIGHT ) );
3192
3194 aSheet->Resize( VECTOR2I( grid.x - pos.x, grid.y - pos.y ) );
3195}
3196
3197
3198int SCH_DRAWING_TOOLS::doSyncSheetsPins( std::list<SCH_SHEET_PATH> sheetPaths )
3199{
3200 if( !sheetPaths.size() )
3201 {
3202 return 0;
3203 }
3204
3205 m_dialogSyncSheetPin = std::make_unique<DIALOG_SYNC_SHEET_PINS>(
3206 m_frame, std::move( sheetPaths ),
3207 std::make_shared<SHEET_SYNCHRONIZATION_AGENT>(
3208 [&]( EDA_ITEM* aItem, SCH_SHEET_PATH aPath,
3210 {
3211 SCH_COMMIT commit( m_toolMgr );
3212
3213 if( auto pin = dynamic_cast<SCH_SHEET_PIN*>( aItem ) )
3214 {
3215 commit.Modify( pin->GetParent(), aPath.LastScreen() );
3216 aModify();
3217 commit.Push( _( "Modify sheet pin" ) );
3218 }
3219 else
3220 {
3221 commit.Modify( aItem, aPath.LastScreen() );
3222 aModify();
3223 commit.Push( _( "Modify schematic item" ) );
3224 }
3225
3226 updateItem( aItem, true );
3227 m_frame->OnModify();
3228 },
3229 [&]( EDA_ITEM* aItem, SCH_SHEET_PATH aPath )
3230 {
3232 EE_ACTIONS::changeSheet, &aPath );
3234 selectionTool->UnbrightenItem( aItem );
3235 selectionTool->AddItemToSel( aItem, true );
3237 },
3238 [&]( SCH_SHEET* aItem, SCH_SHEET_PATH aPath,
3240 std::set<EDA_ITEM*> aTemplates )
3241 {
3242 switch( aOp )
3243 {
3245 {
3246 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
3247 m_dialogSyncSheetPin->Hide();
3248 m_dialogSyncSheetPin->PreparePlacementTemplate(
3250 aTemplates );
3252 EE_ACTIONS::changeSheet, &aPath );
3254 break;
3255 }
3257 {
3258 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
3259 m_dialogSyncSheetPin->Hide();
3260 m_dialogSyncSheetPin->PreparePlacementTemplate(
3262 aTemplates );
3264 EE_ACTIONS::changeSheet, &aPath );
3265 m_toolMgr->GetTool<EE_SELECTION_TOOL>()->SyncSelection( {}, nullptr,
3266 { sheet } );
3268 break;
3269 }
3270 }
3271 },
3272 m_toolMgr, m_frame ) );
3273 m_dialogSyncSheetPin->Show( true );
3274 return 0;
3275}
3276
3277
3279{
3280 SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( m_selectionTool->GetSelection().Front() );
3281
3282 if( !sheet )
3283 {
3284 VECTOR2I cursorPos = getViewControls()->GetMousePosition();
3285
3286 if( EDA_ITEM* i = nullptr; static_cast<void>(m_selectionTool->SelectPoint( cursorPos, { SCH_SHEET_T }, &i ) ) , i != nullptr )
3287 {
3288 sheet = dynamic_cast<SCH_SHEET*>( i );
3289 }
3290 }
3291
3292 if ( sheet )
3293 {
3295 current.push_back( sheet );
3296 return doSyncSheetsPins( { current } );
3297 }
3298
3299 return 0;
3300}
3301
3302
3304{
3305 static const std::function<void( std::list<SCH_SHEET_PATH>&, SCH_SCREEN*,
3306 std::set<SCH_SCREEN*>&, SCH_SHEET_PATH const& )>
3307 getSheetChildren = []( std::list<SCH_SHEET_PATH>& aPaths, SCH_SCREEN* aScene,
3308 std::set<SCH_SCREEN*>& aVisited, SCH_SHEET_PATH const& aCurPath )
3309 {
3310 if( ! aScene || aVisited.find(aScene) != aVisited.end() )
3311 return ;
3312
3313 std::vector<SCH_ITEM*> sheetChildren;
3314 aScene->GetSheets( &sheetChildren );
3315 aVisited.insert( aScene );
3316
3317 for( SCH_ITEM* child : sheetChildren )
3318 {
3319 SCH_SHEET_PATH cp = aCurPath;
3320 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( child );
3321 cp.push_back( sheet );
3322 aPaths.push_back( cp );
3323 getSheetChildren( aPaths, sheet->GetScreen(), aVisited, cp );
3324 }
3325 };
3326
3327 std::list<SCH_SHEET_PATH> sheetPaths;
3328 std::set<SCH_SCREEN*> visited;
3329 SCH_SHEET_PATH current;
3330 current.push_back( &m_frame->Schematic().Root() );
3331 getSheetChildren( sheetPaths, m_frame->Schematic().Root().GetScreen(), visited, current );
3332
3333 if( sheetPaths.size() == 0 )
3334 {
3335 m_frame->ShowInfoBarMsg( _( "No sub schematic found in the current project" ) );
3336 return 0;
3337 }
3338
3339
3340 return doSyncSheetsPins( std::move( sheetPaths ) );
3341}
3342
3344{
3345 if( !aSheet->GetScreen() )
3346 return nullptr;
3347
3348 std::vector<SCH_HIERLABEL*> labels;
3349 for( EDA_ITEM* item : aSheet->GetScreen()->Items().OfType( SCH_HIER_LABEL_T ) )
3350 {
3351 SCH_HIERLABEL* label = static_cast<SCH_HIERLABEL*>( item );
3352 labels.push_back( label );
3353 }
3354
3355 std::sort( labels.begin(), labels.end(),
3356 []( const SCH_HIERLABEL* label1, const SCH_HIERLABEL* label2 )
3357 {
3358 return StrNumCmp( label1->GetText(), label2->GetText(), true ) < 0;
3359 } );
3360
3361 for( SCH_HIERLABEL* label : labels )
3362 {
3363 if( !aSheet->HasPin( label->GetText() ) )
3364 return label;
3365 }
3366
3367 return nullptr;
3368}
3369
3370
3372{
3373 // clang-format off
3402 // clang-format on
3403}
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
static TOOL_ACTION cancelInteractive
Definition: actions.h:65
static TOOL_ACTION undo
Definition: actions.h:68
static TOOL_ACTION duplicate
Definition: actions.h:77
static TOOL_ACTION activatePointEditor
Definition: actions.h:221
static TOOL_ACTION doDelete
Definition: actions.h:78
static TOOL_ACTION redo
Definition: actions.h:69
static TOOL_ACTION increment
Definition: actions.h:87
static TOOL_ACTION refreshPreview
Definition: actions.h:149
static TOOL_ACTION finishInteractive
Definition: actions.h:66
constexpr bool Contains(const Vec &aPoint) const
Definition: box2.h:168
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Modify a given item in the model.
Definition: commit.h:108
COMMIT & Added(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
Definition: commit.h:86
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
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.
LIB_ID GetSelectedLibId(int *aUnit=nullptr) const
To be called after this dialog returns from ShowModal().
const wxString & GetSchematicFile() const
Definition: design_block.h:41
const LIB_ID & GetLibId() const
Definition: design_block.h:33
const nlohmann::ordered_map< wxString, wxString > & GetFields() const
Definition: design_block.h:49
std::list< std::unique_ptr< EDA_ITEM > > & GetImportedItems()
FIELDS_GRID_TABLE * GetFieldsGridTable()
int ShowQuasiModal()
int ShowModal() override
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:89
virtual void ClearEditFlags()
Definition: eda_item.h:141
virtual void SetPosition(const VECTOR2I &aPos)
Definition: eda_item.h:245
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:77
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:133
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:127
const KIID m_Uuid
Definition: eda_item.h:490
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:129
virtual bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const
Compare the item against the search criteria in aSearchData.
Definition: eda_item.h:378
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:104
virtual wxString GetFriendlyName() const
Definition: eda_item.cpp:332
virtual EDA_ITEM * Clone() const
Create a duplicate of this item with linked list members set to NULL.
Definition: eda_item.cpp:85
FILL_T GetFillMode() const
Definition: eda_shape.h:114
void SetFillColor(const COLOR4D &aColor)
Definition: eda_shape.h:119
COLOR4D GetFillColor() const
Definition: eda_shape.h:118
void SetEnd(const VECTOR2I &aEnd)
Definition: eda_shape.h:178
bool IsItalic() const
Definition: eda_text.h:156
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:134
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition: eda_text.cpp:524
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:408
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition: eda_text.h:187
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:377
void SetBold(bool aBold)
Set the text to be bold - this will also update the font if needed.
Definition: eda_text.cpp:326
bool IsBold() const
Definition: eda_text.h:171
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition: eda_text.h:190
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:268
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:290
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
Definition: eda_text.cpp:298
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition: eda_text.cpp:400
PANEL_DESIGN_BLOCK_CHOOSER m_DesignBlockChooserPanel
PANEL_ANNOTATE m_AnnotatePanel
PANEL_SYM_CHOOSER m_SymChooserPanel
AUTOPLACE_FIELDS m_AutoplaceFields
static TOOL_ACTION drawSheetFromFile
Definition: ee_actions.h:94
static TOOL_ACTION mirrorV
Definition: ee_actions.h:132
static TOOL_ACTION drawSheetFromDesignBlock
Definition: ee_actions.h:95
static TOOL_ACTION placeDesignBlock
Definition: ee_actions.h:82
static TOOL_ACTION properties
Definition: ee_actions.h:135
static TOOL_ACTION addItemsToSel
Selects a list of items (specified as the event parameter)
Definition: ee_actions.h:63
static TOOL_ACTION move
Definition: ee_actions.h:127
static TOOL_ACTION changeSheet
Definition: ee_actions.h:223
static TOOL_ACTION drawTable
Definition: ee_actions.h:104
static TOOL_ACTION syncAllSheetsPins
Definition: ee_actions.h:101
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:113
static TOOL_ACTION placeClassLabel
Definition: ee_actions.h:90
static TOOL_ACTION placeNextSymbolUnit
Definition: ee_actions.h:80
static TOOL_ACTION closeOutline
Definition: ee_actions.h:115
static TOOL_ACTION drawCircle
Definition: ee_actions.h:106
static TOOL_ACTION rotateCCW
Definition: ee_actions.h:131
static TOOL_ACTION placePower
Definition: ee_actions.h:81
static TOOL_ACTION deleteLastPoint
Definition: ee_actions.h:114
static TOOL_ACTION placeSheetPin
Definition: ee_actions.h:96
static TOOL_ACTION mirrorH
Definition: ee_actions.h:133
static TOOL_ACTION syncSheetPins
Definition: ee_actions.h:99
static TOOL_ACTION rotateCW
Definition: ee_actions.h:130
static TOOL_ACTION importGraphics
Definition: ee_actions.h:261
static TOOL_ACTION leaveSheet
Definition: ee_actions.h:225
static TOOL_ACTION placeGlobalLabel
Definition: ee_actions.h:91
static TOOL_ACTION placeHierLabel
Definition: ee_actions.h:92
static TOOL_ACTION drawTextBox
Definition: ee_actions.h:103
static TOOL_ACTION drawRectangle
Definition: ee_actions.h:105
static TOOL_ACTION placeImage
Definition: ee_actions.h:110
static TOOL_ACTION enterSheet
Definition: ee_actions.h:224
static TOOL_ACTION placeSchematicText
Definition: ee_actions.h:102
static TOOL_ACTION drawArc
Definition: ee_actions.h:107
static TOOL_ACTION drawSheet
Definition: ee_actions.h:93
static TOOL_ACTION drawBezier
Definition: ee_actions.h:108
static TOOL_ACTION placeLabel
Definition: ee_actions.h:89
static TOOL_ACTION repeatDrawItem
Definition: ee_actions.h:129
static TOOL_ACTION placeBusWireEntry
Definition: ee_actions.h:88
static TOOL_ACTION placeJunction
Definition: ee_actions.h:87
static TOOL_ACTION importSheet
Definition: ee_actions.h:97
static TOOL_ACTION placeNoConnect
Definition: ee_actions.h:86
EE_TYPE Overlapping(const BOX2I &aRect) const
Definition: sch_rtree.h:246
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:241
EE_SELECTION & RequestSelection(const std::vector< KICAD_T > &aScanTypes={ SCH_LOCATE_ANY_T }, bool aPromoteCellSelections=false)
Return either an existing selection (filtered), or the selection at the current cursor position if th...
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:297
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:332
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:1673
void ClearPreview()
Definition: view.cpp:1695
void RecacheAllItems()
Rebuild GAL display lists.
Definition: view.cpp:1439
void AddToPreview(VIEW_ITEM *aItem, bool aTakeOwnership=true)
Definition: view.cpp:1717
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
const UTF8 & GetLibItemName() const
Definition: lib_id.h:102
Define a library symbol object.
Definition: lib_symbol.h:84
const LIB_ID & GetLibId() const override
Definition: lib_symbol.h:154
A singleton reporter that reports to nowhere.
Definition: reporter.h:203
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition: pgm_base.cpp:689
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)
These are all prefaced with "Sch".
Definition: project_sch.cpp:90
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition: project.cpp:140
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:83
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:312
SCH_SHEET_LIST Hierarchy() const override
Return the full schematic flattened hierarchical sheet list.
Definition: schematic.cpp:214
SCH_SHEET & Root() const
Definition: schematic.h:131
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:51
void SyncView()
Mark all items for refresh.
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:40
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
Execute the changes.
Definition: sch_commit.cpp:433
virtual void Revert() override
Revert the commit by restoring the modified items state.
Definition: sch_commit.cpp:511
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
int ImportSheet(const TOOL_EVENT &aEvent)
STROKE_PARAMS m_lastTextboxStroke
GR_TEXT_V_ALIGN_T m_lastTextboxVJustify
int PlaceNextSymbolUnit(const TOOL_EVENT &aEvent)
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)
SCH_SHEET_PIN * createNewSheetPinFromLabel(SCH_SHEET *aSheet, const VECTOR2I &aPosition, SCH_HIERLABEL *aLabel)
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)
Try finding any hierlabel that does not have a sheet pin associated with it.
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
SCH_HIERLABEL * importHierLabel(SCH_SHEET *aSheet)
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.
bool LoadSheetFromFile(SCH_SHEET *aSheet, SCH_SHEET_PATH *aCurrentSheet, const wxString &aFileName, bool aSkipRecursionCheck=false, bool aSkipLibCheck=false)
Load a the KiCad schematic file aFileName into the sheet aSheet.
Definition: sheet.cpp:169
void AnnotateSymbols(SCH_COMMIT *aCommit, ANNOTATE_SCOPE_T aAnnotateScope, ANNOTATE_ORDER_T aSortOption, ANNOTATE_ALGO_T aAlgoOption, bool aRecursive, int aStartNumber, bool aResetAnnotation, bool aRepairTimestamps, REPORTER &aReporter)
Annotate the symbols in the schematic that are not currently annotated.
Definition: annotate.cpp:212
void HardRedraw() override
Rebuild the GAL and redraw the screen.
SCH_SHEET_PATH & GetCurrentSheet() const
SCHEMATIC & Schematic() const
DESIGN_BLOCK * GetDesignBlock(const LIB_ID &aLibId, bool aUseCacheLib=false, bool aShowErrorMsg=false)
Load design block from design block library table.
bool EditSheetProperties(SCH_SHEET *aSheet, SCH_SHEET_PATH *aHierarchy, bool *aIsUndoable=nullptr, bool *aClearAnnotationNewItems=nullptr, bool *aUpdateHierarchyNavigator=nullptr, wxString *aSourceSheetFilename=nullptr)
Edit an existing sheet or add a new sheet to the schematic.
Definition: sheet.cpp:603
void FlipBodyStyle(SCH_SYMBOL *aSymbol)
Definition: picksymbol.cpp:182
void SetSheetNumberAndCount()
Set the m_ScreenNumber and m_NumberOfScreens members for screens.
void SelectUnit(SCH_SYMBOL *aSymbol, int aUnit)
Definition: picksymbol.cpp:95
void UpdateDesignBlockOptions()
Design block panel options have changed and the panel needs to be refreshed.
DESIGN_BLOCK_PANE * GetDesignBlockPane() const
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 SetText(const wxString &aText) override
Definition: sch_field.cpp:1218
void SetSpinStyle(SPIN_STYLE aSpinStyle) override
Definition: sch_label.cpp:2041
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:167
virtual bool IsConnectable() const
Definition: sch_item.h:459
virtual void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo)
Definition: sch_item.h:561
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:150
int GetUnit() const
Definition: sch_item.h:233
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction)
Definition: sch_item.h:563
virtual void SetUnit(int aUnit)
Definition: sch_item.h:232
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:218
bool IsType(const std::vector< KICAD_T > &aScanTypes) const override
Check whether the item is one of the listed types.
Definition: sch_item.h:182
bool AutoRotateOnPlacement() const
autoRotateOnPlacement
Definition: sch_label.cpp:1410
SPIN_STYLE GetSpinStyle() const
Definition: sch_label.cpp:331
void SetShape(LABEL_FLAG_SHAPE aShape)
Definition: sch_label.h:190
LABEL_FLAG_SHAPE GetShape() const
Definition: sch_label.h:189
void SetAutoRotateOnPlacement(bool autoRotate=true)
Definition: sch_label.cpp:1416
std::vector< SCH_FIELD > & GetFields()
Definition: sch_label.h:213
virtual void SetSpinStyle(SPIN_STYLE aSpinStyle)
Definition: sch_label.cpp:296
Tool responsible for drawing/placing items (symbols, wires, buses, labels, etc.)
int AddJunctionsIfNeeded(SCH_COMMIT *aCommit, EE_SELECTION *aSelection)
Handle the addition of junctions to a selection of objects.
int TrimOverLappingWires(SCH_COMMIT *aCommit, EE_SELECTION *aSelection)
Logic to remove wires when overlapping correct items.
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:41
bool IsWire() const
Return true if the line is a wire.
Definition: sch_line.cpp:964
VECTOR2I GetEndPoint() const
Definition: sch_line.h:143
VECTOR2I GetStartPoint() const
Definition: sch_line.h:138
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()
Get the full RTree, usually for iterating.
Definition: sch_screen.h:109
SCH_ITEM * GetItem(const VECTOR2I &aPosition, int aAccuracy=0, KICAD_T aType=SCH_LOCATE_ANY_T) const
Check aPosition within a distance of aAccuracy for items of type aFilter.
Definition: sch_screen.cpp:394
bool IsExplicitJunctionAllowed(const VECTOR2I &aPosition) const
Indicate that a junction dot may be placed at the given location.
Definition: sch_screen.cpp:508
void SetPosition(const VECTOR2I &aPos) override
Definition: sch_shape.h:74
void BeginEdit(const VECTOR2I &aStartPoint) override
Begin drawing a symbol library draw item at aPosition.
Definition: sch_shape.h:78
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:81
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:79
void CalcEdit(const VECTOR2I &aPosition) override
Calculate the attributes of an item at aPosition when it is being edited.
Definition: sch_shape.h:80
wxString GetClass() const override
Return the class name.
Definition: sch_shape.h:43
STROKE_PARAMS GetStroke() const override
Definition: sch_shape.h:56
VECTOR2I GetPosition() const override
Definition: sch_shape.h:73
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()
void SetPageNumber(const wxString &aPageNumber)
Set the sheet instance user definable page number.
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:59
void SetBorderColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:122
void AddPin(SCH_SHEET_PIN *aSheetPin)
Add aSheetPin to the sheet.
Definition: sch_sheet.cpp:426
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: sch_sheet.cpp:165
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: sch_sheet.cpp:1021
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:96
void SetBackgroundColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:125
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:113
VECTOR2I GetPosition() const override
Definition: sch_sheet.h:404
bool HasPin(const wxString &aName) const
Check if the sheet already has a sheet pin named aName.
Definition: sch_sheet.cpp:454
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:171
void SetBorderWidth(int aWidth)
Definition: sch_sheet.h:119
void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo) override
Definition: sch_sheet.cpp:663
void Resize(const VECTOR2I &aSize)
Resize this sheet to aSize and adjust all of the labels accordingly.
Definition: sch_sheet.cpp:1004
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:184
Schematic symbol object.
Definition: sch_symbol.h:77
void ClearAnnotation(const SCH_SHEET_PATH *aSheetPath, bool aResetPrefix)
Clear exiting symbol annotation.
const LIB_ID & GetLibId() const override
Definition: sch_symbol.h:166
bool IsMulti() const override
Definition: sch_symbol.h:268
void SetUnitSelection(const SCH_SHEET_PATH *aSheet, int aUnitSelection)
Set the selected unit of this symbol on one sheet.
Definition: sch_symbol.cpp:849
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
Definition: sch_symbol.cpp:705
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:327
int AddItemsToSel(const TOOL_EVENT &aEvent)
int AddItemToSel(const TOOL_EVENT &aEvent)
void UnbrightenItem(EDA_ITEM *aItem)
virtual void Add(EDA_ITEM *aItem)
Definition: selection.cpp:42
VECTOR2I GetReferencePoint() const
Definition: selection.cpp:169
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:44
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:220
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:38
Generic, UI-independent tool event.
Definition: tool_event.h:168
bool HasPosition() const
Returns if it this event has a valid position (true for mouse events and context-menu or hotkey-based...
Definition: tool_event.h:257
bool DisableGridSnapping() const
Definition: tool_event.h:368
const VECTOR2D Position() const
Return mouse cursor position in world coordinates.
Definition: tool_event.h:290
bool IsReactivate() const
Control whether the tool is first being pushed to the stack or being reactivated after a pause.
Definition: tool_event.h:270
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:465
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).
std::unique_ptr< 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
bool RunSynchronousAction(const TOOL_ACTION &aAction, COMMIT *aCommit, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:197
void VetoContextMenuMouseWarp()
Disable mouse warping after the current context menu is closed.
Definition: tool_manager.h:511
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: wx_infobar.cpp:190
This file is part of the common library.
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition: eda_angle.h:401
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
Definition: eda_item.h:538
#define IS_NEW
New item, just created.
#define STRUCT_DELETED
flag indication structures to be erased
#define ENDPOINT
ends. (Used to support dragging.)
#define SKIP_STRUCT
flag indicating that the structure should be ignored
#define IS_MOVING
Item being moved.
#define STARTPOINT
When a line is selected, these flags indicate which.
SHAPE_T
Definition: eda_shape.h:43
FILL_T
Definition: eda_shape.h:56
std::set< int > GetUnplacedUnitsForSymbol(const SCH_SYMBOL &aSym)
Get a list of unplaced (i.e.
@ ID_POPUP_SCH_SELECT_UNIT
Definition: eeschema_id.h:82
@ ID_POPUP_SCH_SELECT_BASE
Definition: eeschema_id.h:88
@ ID_POPUP_SCH_SELECT_ALT
Definition: eeschema_id.h:89
@ ID_POPUP_SCH_SELECT_UNIT_END
Definition: eeschema_id.h:86
@ LINE_MODE_FREE
GRID_HELPER_GRIDS
Definition: grid_helper.h:42
@ GRID_TEXT
Definition: grid_helper.h:49
@ GRID_GRAPHICS
Definition: grid_helper.h:50
@ GRID_CONNECTABLE
Definition: grid_helper.h:46
static const std::string KiCadSchematicFileExtension
static wxString KiCadSchematicFileWildcard()
@ LAYER_HIERLABEL
Definition: layer_ids.h:446
@ LAYER_GLOBLABEL
Definition: layer_ids.h:445
@ LAYER_NOTES
Definition: layer_ids.h:456
@ LAYER_LOCLABEL
Definition: layer_ids.h:444
@ LAYER_NETCLASS_REFS
Definition: layer_ids.h:453
wxPoint GetMousePosition()
Returns the mouse position in screen coordinates.
Definition: wxgtk/ui.cpp:677
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:1073
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.
@ AUTOPLACE_AUTO
Definition: sch_item.h:70
LABEL_FLAG_SHAPE
Definition: sch_label.h:99
@ F_ROUND
Definition: sch_label.h:108
@ L_INPUT
Definition: sch_label.h:100
ANNOTATE_ORDER_T
Schematic annotation order options.
@ ANNOTATE_SELECTION
Annotate the selection.
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:46
constexpr int MilsToIU(int mils) const
Definition: base_units.h:93
SCH_SYMBOL * m_Symbol
< Provide a symbol to place
Definition: ee_actions.h:312
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
Context menu choice.
Definition: tool_event.h:98
@ TC_COMMAND
Definition: tool_event.h:57
@ MD_SHIFT
Definition: tool_event.h:143
@ BUT_LEFT
Definition: tool_event.h:132
@ BUT_RIGHT
Definition: tool_event.h:133
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_HIER_LABEL_T
Definition: typeinfo.h:169
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:173
@ SCH_BUS_WIRE_ENTRY_T
Definition: typeinfo.h:161
@ SCH_JUNCTION_T
Definition: typeinfo.h:159
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695
Definition of file extensions used in Kicad.