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 {
1695 delete labelItem;
1696 return nullptr;
1697 }
1698 }
1699
1700 wxString text = textItem->GetText();
1701
1702 if( textItem->Type() != SCH_DIRECTIVE_LABEL_T && NoPrintableChars( text ) )
1703 {
1704 delete textItem;
1705 return nullptr;
1706 }
1707
1708 if( aType != LAYER_NETCLASS_REFS )
1709 {
1710 m_lastTextBold = textItem->IsBold();
1711 m_lastTextItalic = textItem->IsItalic();
1712 }
1713
1714 if( labelItem )
1715 {
1716 m_lastTextOrientation = labelItem->GetSpinStyle();
1717 }
1718 else
1719 {
1720 m_lastTextHJustify = textItem->GetHorizJustify();
1721 m_lastTextVJustify = textItem->GetVertJustify();
1722 m_lastTextAngle = textItem->GetTextAngle();
1723 }
1724
1725 if( aType == LAYER_GLOBLABEL || aType == LAYER_HIERLABEL )
1726 {
1727 m_lastGlobalLabelShape = labelItem->GetShape();
1729 }
1730 else if( aType == LAYER_NETCLASS_REFS )
1731 {
1732 m_lastNetClassFlagShape = labelItem->GetShape();
1733 }
1734
1735 return textItem;
1736}
1737
1739{
1740 SCHEMATIC_SETTINGS& settings = aSheet->Schematic()->Settings();
1741 SCH_SHEET_PIN* pin = new SCH_SHEET_PIN( aSheet );
1742
1743 pin->SetFlags( IS_NEW | IS_MOVING );
1744 pin->SetText( std::to_string( aSheet->GetPins().size() + 1 ) );
1745 pin->SetTextSize( VECTOR2I( settings.m_DefaultTextSize, settings.m_DefaultTextSize ) );
1746 pin->SetPosition( aPosition );
1747 pin->ClearSelected();
1748
1749 m_lastSheetPinType = pin->GetShape();
1750
1751 return pin;
1752}
1753
1755 const VECTOR2I& aPosition,
1756 SCH_HIERLABEL* aLabel )
1757{
1758 auto pin = createNewSheetPin( aSheet, aPosition );
1759 pin->SetText( aLabel->GetText() );
1760 pin->SetShape( aLabel->GetShape() );
1761 return pin;
1762}
1763
1764
1766{
1767 SCH_ITEM* item = nullptr;
1770 bool ignorePrimePosition = false;
1771 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
1772 SCH_SHEET* sheet = nullptr;
1773 wxString description;
1774
1775 if( m_inDrawingTool )
1776 return 0;
1777
1779
1780 bool isText = aEvent.IsAction( &EE_ACTIONS::placeSchematicText );
1781 bool isGlobalLabel = aEvent.IsAction( &EE_ACTIONS::placeGlobalLabel );
1782 bool isHierLabel = aEvent.IsAction( &EE_ACTIONS::placeHierLabel );
1783 bool isClassLabel = aEvent.IsAction( &EE_ACTIONS::placeClassLabel );
1784 bool isNetLabel = aEvent.IsAction( &EE_ACTIONS::placeLabel );
1785 bool isSheetPin = aEvent.IsAction( &EE_ACTIONS::placeSheetPin );
1786
1787 GRID_HELPER_GRIDS snapGrid = isText ? GRID_TEXT : GRID_CONNECTABLE;
1788
1789 // If we have a selected sheet use it, otherwise try to get one under the cursor
1790 if( isSheetPin )
1791 sheet = dynamic_cast<SCH_SHEET*>( m_selectionTool->GetSelection().Front() );
1792
1794
1795 m_frame->PushTool( aEvent );
1796
1797 auto setCursor =
1798 [&]()
1799 {
1800 if( item )
1801 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PLACE );
1802 else if( isText )
1803 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::TEXT );
1804 else if( isGlobalLabel )
1805 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_GLOBAL );
1806 else if( isNetLabel )
1807 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_NET );
1808 else if( isClassLabel )
1809 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_NET ); // JEY TODO: netclass directive cursor
1810 else if( isHierLabel )
1811 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_HIER );
1812 else
1813 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
1814 };
1815
1816 auto updatePreview =
1817 [&]()
1818 {
1820 m_view->AddToPreview( item, false );
1821 item->RunOnChildren( [&]( SCH_ITEM* aChild )
1822 {
1823 m_view->AddToPreview( aChild, false );
1824 } );
1825 m_frame->SetMsgPanel( item );
1826 };
1827
1828 auto cleanup =
1829 [&]()
1830 {
1833 delete item;
1834 item = nullptr;
1835 };
1836
1837 Activate();
1838
1839 // Must be done after Activate() so that it gets set into the correct context
1840 controls->ShowCursor( true );
1841
1842 // Set initial cursor
1843 setCursor();
1844
1845 if( aEvent.HasPosition() )
1846 {
1847 m_toolMgr->PrimeTool( aEvent.Position() );
1848 }
1849 else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate()
1850 && ( isText || isGlobalLabel || isHierLabel || isClassLabel || isNetLabel ) )
1851 {
1852 m_toolMgr->PrimeTool( { 0, 0 } );
1853 ignorePrimePosition = true;
1854 }
1855
1856 SCH_COMMIT commit( m_toolMgr );
1857
1858 // Main loop: keep receiving events
1859 while( TOOL_EVENT* evt = Wait() )
1860 {
1861 setCursor();
1862 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1863 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1864
1865 VECTOR2I cursorPos = controls->GetMousePosition();
1866 cursorPos = grid.BestSnapAnchor( cursorPos, snapGrid, item );
1867 controls->ForceCursorPosition( true, cursorPos );
1868
1869 // The tool hotkey is interpreted as a click when drawing
1870 bool isSyntheticClick = item && evt->IsActivate() && evt->HasPosition()
1871 && evt->Matches( aEvent );
1872
1873 if( evt->IsCancelInteractive() || evt->IsAction( &ACTIONS::undo ) )
1874 {
1876
1877 if( item )
1878 {
1879 cleanup();
1880 }
1881 else
1882 {
1883 m_frame->PopTool( aEvent );
1884 break;
1885 }
1886 }
1887 else if( evt->IsActivate() && !isSyntheticClick )
1888 {
1889 if( item && evt->IsMoveTool() )
1890 {
1891 // we're already moving our own item; ignore the move tool
1892 evt->SetPassEvent( false );
1893 continue;
1894 }
1895
1896 if( item )
1897 {
1898 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel item creation." ) );
1899 evt->SetPassEvent( false );
1900 continue;
1901 }
1902
1903 if( evt->IsPointEditor() )
1904 {
1905 // don't exit (the point editor runs in the background)
1906 }
1907 else if( evt->IsMoveTool() )
1908 {
1909 // leave ourselves on the stack so we come back after the move
1910 break;
1911 }
1912 else
1913 {
1914 m_frame->PopTool( aEvent );
1915 break;
1916 }
1917 }
1918 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) || isSyntheticClick )
1919 {
1920 PLACE_NEXT:
1921 // First click creates...
1922 if( !item )
1923 {
1925
1926 if( isText )
1927 {
1928 item = createNewText( cursorPos, LAYER_NOTES );
1929 description = _( "Add Text" );
1930 }
1931 else if( isHierLabel )
1932 {
1933 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->GetPlacementTemplate() )
1934 {
1935 auto pin = static_cast<SCH_HIERLABEL*>(
1936 m_dialogSyncSheetPin->GetPlacementTemplate() );
1937 SCH_HIERLABEL* label = new SCH_HIERLABEL( cursorPos );
1938 SCHEMATIC* schematic = getModel<SCHEMATIC>();
1939 label->SetText( pin->GetText() );
1940 label->SetShape( pin->GetShape() );
1942 label->SetParent( schematic );
1943 label->SetBold( m_lastTextBold );
1944 label->SetItalic( m_lastTextItalic );
1946 label->SetTextSize( VECTOR2I( schematic->Settings().m_DefaultTextSize,
1947 schematic->Settings().m_DefaultTextSize ) );
1948 label->SetFlags( IS_NEW | IS_MOVING );
1949 item = label;
1950 }
1951 else
1952 {
1953 item = createNewText( cursorPos, LAYER_HIERLABEL );
1954 }
1955
1956 description = _( "Add Hierarchical Label" );
1957 }
1958 else if( isNetLabel )
1959 {
1960 item = createNewText( cursorPos, LAYER_LOCLABEL );
1961 description = _( "Add Label" );
1962 }
1963 else if( isGlobalLabel )
1964 {
1965 item = createNewText( cursorPos, LAYER_GLOBLABEL );
1966 description = _( "Add Label" );
1967 }
1968 else if( isClassLabel )
1969 {
1970 item = createNewText( cursorPos, LAYER_NETCLASS_REFS );
1971 description = _( "Add Label" );
1972 }
1973 else if( isSheetPin )
1974 {
1975 EDA_ITEM* i = nullptr;
1976
1977 // If we didn't have a sheet selected, try to find one under the cursor
1978 if( !sheet && m_selectionTool->SelectPoint( cursorPos, { SCH_SHEET_T }, &i ) )
1979 sheet = dynamic_cast<SCH_SHEET*>( i );
1980
1981 if( !sheet )
1982 {
1983 m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( m_frame );
1984 m_statusPopup->SetText( _( "Click over a sheet." ) );
1986 + wxPoint( 20, 20 ) );
1987 m_statusPopup->PopupFor( 2000 );
1988 item = nullptr;
1989 }
1990 else
1991 {
1992 // User is using the 'Sync Sheet Pins' tool
1993 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->GetPlacementTemplate() )
1994 {
1996 sheet, cursorPos,
1997 static_cast<SCH_HIERLABEL*>(
1998 m_dialogSyncSheetPin->GetPlacementTemplate() ) );
1999 }
2000 else
2001 {
2002 // User is using the 'Place Sheet Pins' tool
2003 SCH_HIERLABEL* label = importHierLabel( sheet );
2004
2005 if( !label )
2006 {
2007 m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( m_frame );
2008 m_statusPopup->SetText( _( "No new hierarchical labels found." ) );
2010 + wxPoint( 20, 20 ) );
2011 m_statusPopup->PopupFor( 2000 );
2012 item = nullptr;
2013
2014 m_frame->PopTool( aEvent );
2015 break;
2016 }
2017
2018 item = createNewSheetPinFromLabel( sheet, cursorPos, label );
2019 }
2020 }
2021
2022 description = _( "Add Sheet Pin" );
2023 }
2024
2025 // If we started with a hotkey which has a position then warp back to that.
2026 // Otherwise update to the current mouse position pinned inside the autoscroll
2027 // boundaries.
2028 if( evt->IsPrime() && !ignorePrimePosition )
2029 {
2030 cursorPos = grid.Align( evt->Position() );
2031 getViewControls()->WarpMouseCursor( cursorPos, true );
2032 }
2033 else
2034 {
2036 cursorPos = getViewControls()->GetMousePosition();
2037 cursorPos = grid.BestSnapAnchor( cursorPos, snapGrid, item );
2038 }
2039
2040 if( item )
2041 {
2042 item->SetPosition( cursorPos );
2043
2044 item->SetFlags( IS_NEW | IS_MOVING );
2045
2046 // Not placed yet, so pass a nullptr screen reference
2047 item->AutoplaceFields( nullptr, AUTOPLACE_AUTO );
2048
2049 updatePreview();
2052
2053 // update the cursor so it looks correct before another event
2054 setCursor();
2055 }
2056
2057 controls->SetCursorPosition( cursorPos, false );
2058 }
2059 else // ... and second click places:
2060 {
2061 item->ClearFlags( IS_MOVING );
2062
2063 if( item->IsConnectable() )
2065
2066 if( isSheetPin )
2067 {
2068 // Sheet pins are owned by their parent sheet.
2069 commit.Modify( sheet, m_frame->GetScreen() );
2070 sheet->AddPin( (SCH_SHEET_PIN*) item );
2071 }
2072 else
2073 {
2075 m_frame->AddToScreen( item, m_frame->GetScreen() );
2076 commit.Added( item, m_frame->GetScreen() );
2077 }
2078
2080
2081 commit.Push( description );
2082
2084
2085 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->GetPlacementTemplate() )
2086 {
2087 m_dialogSyncSheetPin->EndPlaceItem( item );
2088
2089 if( m_dialogSyncSheetPin->CanPlaceMore() )
2090 {
2091 item = nullptr;
2092 goto PLACE_NEXT;
2093 }
2094
2095 m_frame->PopTool( aEvent );
2097 m_dialogSyncSheetPin->Show( true );
2098 break;
2099 }
2100
2101 item = nullptr;
2102
2103 if( isSheetPin )
2104 {
2105 SCH_HIERLABEL* label = importHierLabel( sheet );
2106
2107 if( !label )
2108 {
2109 m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( m_frame );
2110 m_statusPopup->SetText( _( "No new hierarchical labels found." ) );
2112 + wxPoint( 20, 20 ) );
2113 m_statusPopup->PopupFor( 2000 );
2114
2115 m_frame->PopTool( aEvent );
2116 break;
2117 }
2118
2119 item = createNewSheetPinFromLabel( sheet, cursorPos, label );
2120 }
2121 }
2122 }
2123 else if( evt->IsClick( BUT_RIGHT ) )
2124 {
2125 // Warp after context menu only if dragging...
2126 if( !item )
2128
2129 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
2130 }
2131 else if( item && evt->IsSelectionEvent() )
2132 {
2133 // This happens if our text was replaced out from under us by ConvertTextType()
2135
2136 if( selection.GetSize() == 1 )
2137 {
2138 item = (SCH_ITEM*) selection.Front();
2139 updatePreview();
2140 }
2141 else
2142 {
2143 item = nullptr;
2144 }
2145 }
2146 else if( evt->IsAction( &ACTIONS::increment ) )
2147 {
2149 evt->Parameter<ACTIONS::INCREMENT>() );
2150 }
2151 else if( evt->IsAction( &ACTIONS::duplicate )
2152 || evt->IsAction( &EE_ACTIONS::repeatDrawItem ) )
2153 {
2154 if( item )
2155 {
2156 // This doesn't really make sense; we'll just end up dragging a stack of
2157 // objects so we ignore the duplicate and just carry on.
2158 wxBell();
2159 continue;
2160 }
2161
2162 // Exit. The duplicate will run in its own loop.
2163 m_frame->PopTool( aEvent );
2164 break;
2165 }
2166 else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
2167 {
2168 item->SetPosition( cursorPos );
2169
2170 // Not placed yet, so pass a nullptr screen reference
2171 item->AutoplaceFields( nullptr, AUTOPLACE_AUTO );
2172
2173 updatePreview();
2174 }
2175 else if( item && evt->IsAction( &ACTIONS::doDelete ) )
2176 {
2177 cleanup();
2178 }
2179 else if( evt->IsAction( &ACTIONS::redo ) )
2180 {
2181 wxBell();
2182 }
2183 else
2184 {
2185 evt->SetPassEvent();
2186 }
2187
2188 // Enable autopanning and cursor capture only when there is an item to be placed
2189 controls->SetAutoPan( item != nullptr );
2190 controls->CaptureCursor( item != nullptr );
2191 }
2192
2193 controls->SetAutoPan( false );
2194 controls->CaptureCursor( false );
2195 controls->ForceCursorPosition( false );
2196 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2197
2198 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->CanPlaceMore() )
2199 {
2200 m_dialogSyncSheetPin->EndPlacement();
2201 m_dialogSyncSheetPin->Show( true );
2202 }
2203
2204 return 0;
2205}
2206
2207
2209{
2210 SCHEMATIC* schematic = getModel<SCHEMATIC>();
2211 SCHEMATIC_SETTINGS& sch_settings = schematic->Settings();
2212 SCH_SHAPE* item = nullptr;
2213 bool isTextBox = aEvent.IsAction( &EE_ACTIONS::drawTextBox );
2214 SHAPE_T type = aEvent.Parameter<SHAPE_T>();
2215 wxString description;
2216
2217 if( m_inDrawingTool )
2218 return 0;
2219
2221
2224 VECTOR2I cursorPos;
2225
2226 // We might be running as the same shape in another co-routine. Make sure that one
2227 // gets whacked.
2229
2231
2232 m_frame->PushTool( aEvent );
2233
2234 auto setCursor =
2235 [&]()
2236 {
2237 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
2238 };
2239
2240 auto cleanup =
2241 [&] ()
2242 {
2245 delete item;
2246 item = nullptr;
2247 };
2248
2249 Activate();
2250
2251 // Must be done after Activate() so that it gets set into the correct context
2252 getViewControls()->ShowCursor( true );
2253
2254 // Set initial cursor
2255 setCursor();
2256
2257 if( aEvent.HasPosition() )
2258 m_toolMgr->PrimeTool( aEvent.Position() );
2259
2260 // Main loop: keep receiving events
2261 while( TOOL_EVENT* evt = Wait() )
2262 {
2263 setCursor();
2264 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
2265 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
2266
2267 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
2268 controls->ForceCursorPosition( true, cursorPos );
2269
2270 // The tool hotkey is interpreted as a click when drawing
2271 bool isSyntheticClick = item && evt->IsActivate() && evt->HasPosition()
2272 && evt->Matches( aEvent );
2273
2274 if( evt->IsCancelInteractive() || ( item && evt->IsAction( &ACTIONS::undo ) ) )
2275 {
2276 if( item )
2277 {
2278 cleanup();
2279 }
2280 else
2281 {
2282 m_frame->PopTool( aEvent );
2283 break;
2284 }
2285 }
2286 else if( evt->IsActivate() && !isSyntheticClick )
2287 {
2288 if( item && evt->IsMoveTool() )
2289 {
2290 // we're already drawing our own item; ignore the move tool
2291 evt->SetPassEvent( false );
2292 continue;
2293 }
2294
2295 if( item )
2296 cleanup();
2297
2298 if( evt->IsPointEditor() )
2299 {
2300 // don't exit (the point editor runs in the background)
2301 }
2302 else if( evt->IsMoveTool() )
2303 {
2304 // leave ourselves on the stack so we come back after the move
2305 break;
2306 }
2307 else
2308 {
2309 m_frame->PopTool( aEvent );
2310 break;
2311 }
2312 }
2313 else if( evt->IsClick( BUT_LEFT ) && !item )
2314 {
2316
2317 if( isTextBox )
2318 {
2320
2321 textbox->SetTextSize( VECTOR2I( sch_settings.m_DefaultTextSize,
2322 sch_settings.m_DefaultTextSize ) );
2323
2324 // Must come after SetTextSize()
2325 textbox->SetBold( m_lastTextBold );
2326 textbox->SetItalic( m_lastTextItalic );
2327
2328 textbox->SetTextAngle( m_lastTextboxAngle );
2331 textbox->SetStroke( m_lastTextboxStroke );
2333 textbox->SetParent( schematic );
2334
2335 item = textbox;
2336 description = _( "Add Text Box" );
2337 }
2338 else
2339 {
2340 item = new SCH_SHAPE( type, LAYER_NOTES, 0, m_lastFillStyle );
2341
2342 item->SetStroke( m_lastStroke );
2344 item->SetParent( schematic );
2345 description = wxString::Format( _( "Add %s" ), item->GetFriendlyName() );
2346 }
2347
2348 item->SetFlags( IS_NEW );
2349 item->BeginEdit( cursorPos );
2350
2352 m_view->AddToPreview( item->Clone() );
2353 }
2354 else if( item && ( evt->IsClick( BUT_LEFT )
2355 || evt->IsDblClick( BUT_LEFT )
2356 || isSyntheticClick
2357 || evt->IsAction( &ACTIONS::finishInteractive ) ) )
2358 {
2359 if( evt->IsDblClick( BUT_LEFT )
2360 || evt->IsAction( &ACTIONS::finishInteractive )
2361 || !item->ContinueEdit( cursorPos ) )
2362 {
2363 item->EndEdit();
2364 item->ClearEditFlags();
2365 item->SetFlags( IS_NEW );
2366
2367 if( isTextBox )
2368 {
2369 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( item );
2370 DIALOG_TEXT_PROPERTIES dlg( m_frame, textbox );
2371
2372 getViewControls()->SetAutoPan( false );
2373 getViewControls()->CaptureCursor( false );
2374
2375 // QuasiModal required for syntax help and Scintilla auto-complete
2376 if( dlg.ShowQuasiModal() != wxID_OK )
2377 {
2378 cleanup();
2379 continue;
2380 }
2381
2382 m_lastTextBold = textbox->IsBold();
2383 m_lastTextItalic = textbox->IsItalic();
2384 m_lastTextboxAngle = textbox->GetTextAngle();
2387 m_lastTextboxStroke = textbox->GetStroke();
2390 }
2391 else
2392 {
2393 m_lastStroke = item->GetStroke();
2394 m_lastFillStyle = item->GetFillMode();
2395 m_lastFillColor = item->GetFillColor();
2396 }
2397
2398 SCH_COMMIT commit( m_toolMgr );
2399 commit.Add( item, m_frame->GetScreen() );
2400 commit.Push( wxString::Format( _( "Draw %s" ), item->GetClass() ) );
2401
2403 item = nullptr;
2404
2407 }
2408 }
2409 else if( evt->IsAction( &ACTIONS::duplicate )
2410 || evt->IsAction( &EE_ACTIONS::repeatDrawItem ) )
2411 {
2412 if( item )
2413 {
2414 // This doesn't really make sense; we'll just end up dragging a stack of
2415 // objects so we ignore the duplicate and just carry on.
2416 wxBell();
2417 continue;
2418 }
2419
2420 // Exit. The duplicate will run in its own loop.
2421 m_frame->PopTool( aEvent );
2422 break;
2423 }
2424 else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
2425 {
2426 item->CalcEdit( cursorPos );
2428 m_view->AddToPreview( item->Clone() );
2429 m_frame->SetMsgPanel( item );
2430 }
2431 else if( evt->IsDblClick( BUT_LEFT ) && !item )
2432 {
2434 }
2435 else if( evt->IsClick( BUT_RIGHT ) )
2436 {
2437 // Warp after context menu only if dragging...
2438 if( !item )
2440
2441 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
2442 }
2443 else if( item && evt->IsAction( &ACTIONS::redo ) )
2444 {
2445 wxBell();
2446 }
2447 else
2448 {
2449 evt->SetPassEvent();
2450 }
2451
2452 // Enable autopanning and cursor capture only when there is a shape being drawn
2453 getViewControls()->SetAutoPan( item != nullptr );
2454 getViewControls()->CaptureCursor( item != nullptr );
2455 }
2456
2457 getViewControls()->SetAutoPan( false );
2458 getViewControls()->CaptureCursor( false );
2459 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2460 return 0;
2461}
2462
2463
2465{
2466 if( m_inDrawingTool )
2467 return 0;
2468
2470 SCOPED_SET_RESET<bool> scopedDrawMode( m_drawingRuleArea, true );
2471
2474 VECTOR2I cursorPos;
2475
2476 RULE_AREA_CREATE_HELPER ruleAreaTool( *getView(), m_frame, m_toolMgr );
2477 POLYGON_GEOM_MANAGER polyGeomMgr( ruleAreaTool );
2478 bool started = false;
2479
2480 // We might be running as the same shape in another co-routine. Make sure that one
2481 // gets whacked.
2483
2485
2486 m_frame->PushTool( aEvent );
2487
2488 auto setCursor =
2489 [&]()
2490 {
2491 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
2492 };
2493
2494 auto cleanup = [&]()
2495 {
2496 polyGeomMgr.Reset();
2497 started = false;
2498 getViewControls()->SetAutoPan( false );
2499 getViewControls()->CaptureCursor( false );
2501 };
2502
2503 Activate();
2504
2505 // Must be done after Activate() so that it gets set into the correct context
2506 getViewControls()->ShowCursor( true );
2507 //m_controls->ForceCursorPosition( false );
2508
2509 // Set initial cursor
2510 setCursor();
2511
2512 if( aEvent.HasPosition() )
2513 m_toolMgr->PrimeTool( aEvent.Position() );
2514
2515 // Main loop: keep receiving events
2516 while( TOOL_EVENT* evt = Wait() )
2517 {
2518 setCursor();
2519
2520 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
2521 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
2522
2523 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_CONNECTABLE );
2524 controls->ForceCursorPosition( true, cursorPos );
2525
2529
2530 if( evt->IsCancelInteractive() )
2531 {
2532 if( started )
2533 {
2534 cleanup();
2535 }
2536 else
2537 {
2538 m_frame->PopTool( aEvent );
2539
2540 // We've handled the cancel event. Don't cancel other tools
2541 evt->SetPassEvent( false );
2542 break;
2543 }
2544 }
2545 else if( evt->IsActivate() )
2546 {
2547 if( started )
2548 cleanup();
2549
2550 if( evt->IsPointEditor() )
2551 {
2552 // don't exit (the point editor runs in the background)
2553 }
2554 else if( evt->IsMoveTool() )
2555 {
2556 // leave ourselves on the stack so we come back after the move
2557 break;
2558 }
2559 else
2560 {
2561 m_frame->PopTool( aEvent );
2562 break;
2563 }
2564 }
2565 else if( evt->IsClick( BUT_RIGHT ) )
2566 {
2567 if( !started )
2569
2570 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
2571 }
2572 // events that lock in nodes
2573 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT )
2574 || evt->IsAction( &EE_ACTIONS::closeOutline ) )
2575 {
2576 // Check if it is double click / closing line (so we have to finish the zone)
2577 const bool endPolygon = evt->IsDblClick( BUT_LEFT )
2578 || evt->IsAction( &EE_ACTIONS::closeOutline )
2579 || polyGeomMgr.NewPointClosesOutline( cursorPos );
2580
2581 if( endPolygon )
2582 {
2583 polyGeomMgr.SetFinished();
2584 polyGeomMgr.Reset();
2585
2586 started = false;
2587 getViewControls()->SetAutoPan( false );
2588 getViewControls()->CaptureCursor( false );
2589 }
2590 // adding a corner
2591 else if( polyGeomMgr.AddPoint( cursorPos ) )
2592 {
2593 if( !started )
2594 {
2595 started = true;
2596
2597 getViewControls()->SetAutoPan( true );
2598 getViewControls()->CaptureCursor( true );
2599 }
2600 }
2601 }
2602 else if( started
2603 && ( evt->IsAction( &EE_ACTIONS::deleteLastPoint )
2604 || evt->IsAction( &ACTIONS::doDelete )
2605 || evt->IsAction( &ACTIONS::undo ) ) )
2606 {
2607 if( std::optional<VECTOR2I> last = polyGeomMgr.DeleteLastCorner() )
2608 {
2609 cursorPos = last.value();
2610 getViewControls()->WarpMouseCursor( cursorPos, true );
2611 getViewControls()->ForceCursorPosition( true, cursorPos );
2612 polyGeomMgr.SetCursorPosition( cursorPos );
2613 }
2614 else
2615 {
2616 cleanup();
2617 }
2618 }
2619 else if( started && ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) )
2620 {
2621 polyGeomMgr.SetCursorPosition( cursorPos );
2622 }
2623 else
2624 {
2625 evt->SetPassEvent();
2626 }
2627
2628 } // end while
2629
2630 getViewControls()->SetAutoPan( false );
2631 getViewControls()->CaptureCursor( false );
2632 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2633 return 0;
2634}
2635
2636
2638{
2639 SCHEMATIC* schematic = getModel<SCHEMATIC>();
2640 SCH_TABLE* table = nullptr;
2641
2642 if( m_inDrawingTool )
2643 return 0;
2644
2646
2649 VECTOR2I cursorPos;
2650
2651 // We might be running as the same shape in another co-routine. Make sure that one
2652 // gets whacked.
2654
2656
2657 m_frame->PushTool( aEvent );
2658
2659 auto setCursor =
2660 [&]()
2661 {
2662 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
2663 };
2664
2665 auto cleanup =
2666 [&] ()
2667 {
2670 delete table;
2671 table = nullptr;
2672 };
2673
2674 Activate();
2675
2676 // Must be done after Activate() so that it gets set into the correct context
2677 getViewControls()->ShowCursor( true );
2678
2679 // Set initial cursor
2680 setCursor();
2681
2682 if( aEvent.HasPosition() )
2683 m_toolMgr->PrimeTool( aEvent.Position() );
2684
2685 // Main loop: keep receiving events
2686 while( TOOL_EVENT* evt = Wait() )
2687 {
2688 setCursor();
2689 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
2690 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
2691
2692 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
2693 controls->ForceCursorPosition( true, cursorPos );
2694
2695 // The tool hotkey is interpreted as a click when drawing
2696 bool isSyntheticClick = table
2697 && evt->IsActivate()
2698 && evt->HasPosition()
2699 && evt->Matches( aEvent );
2700
2701 if( evt->IsCancelInteractive() || ( table && evt->IsAction( &ACTIONS::undo ) ) )
2702 {
2703 if( table )
2704 {
2705 cleanup();
2706 }
2707 else
2708 {
2709 m_frame->PopTool( aEvent );
2710 break;
2711 }
2712 }
2713 else if( evt->IsActivate() && !isSyntheticClick )
2714 {
2715 if( table && evt->IsMoveTool() )
2716 {
2717 // we're already drawing our own item; ignore the move tool
2718 evt->SetPassEvent( false );
2719 continue;
2720 }
2721
2722 if( table )
2723 cleanup();
2724
2725 if( evt->IsPointEditor() )
2726 {
2727 // don't exit (the point editor runs in the background)
2728 }
2729 else if( evt->IsMoveTool() )
2730 {
2731 // leave ourselves on the stack so we come back after the move
2732 break;
2733 }
2734 else
2735 {
2736 m_frame->PopTool( aEvent );
2737 break;
2738 }
2739 }
2740 else if( evt->IsClick( BUT_LEFT ) && !table )
2741 {
2743
2744 table = new SCH_TABLE( 0 );
2745 table->SetColCount( 1 );
2746
2747 SCH_TABLECELL* tableCell = new SCH_TABLECELL();
2748 int defaultTextSize = schematic->Settings().m_DefaultTextSize;
2749
2750 tableCell->SetTextSize( VECTOR2I( defaultTextSize, defaultTextSize ) );
2751 table->AddCell( tableCell );
2752
2753 table->SetParent( schematic );
2754 table->SetFlags( IS_NEW );
2755 table->SetPosition( cursorPos );
2756
2758 m_view->AddToPreview( table->Clone() );
2759 }
2760 else if( table && ( evt->IsClick( BUT_LEFT )
2761 || evt->IsDblClick( BUT_LEFT )
2762 || isSyntheticClick
2763 || evt->IsAction( &EE_ACTIONS::finishInteractive ) ) )
2764 {
2765 table->ClearEditFlags();
2766 table->SetFlags( IS_NEW );
2767 table->Normalize();
2768
2769 DIALOG_TABLE_PROPERTIES dlg( m_frame, table );
2770
2771 // QuasiModal required for Scintilla auto-complete
2772 if( dlg.ShowQuasiModal() == wxID_OK )
2773 {
2774 SCH_COMMIT commit( m_toolMgr );
2775 commit.Add( table, m_frame->GetScreen() );
2776 commit.Push( _( "Draw Table" ) );
2777
2778 m_selectionTool->AddItemToSel( table );
2780 }
2781 else
2782 {
2783 delete table;
2784 }
2785
2786 table = nullptr;
2788 }
2789 else if( table && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
2790 {
2791 VECTOR2I gridSize = grid.GetGridSize( grid.GetItemGrid( table ) );
2792 int fontSize = schematic->Settings().m_DefaultTextSize;
2793 VECTOR2I origin( table->GetPosition() );
2794 VECTOR2I requestedSize( cursorPos - origin );
2795
2796 int colCount = std::max( 1, requestedSize.x / ( fontSize * 15 ) );
2797 int rowCount = std::max( 1, requestedSize.y / ( fontSize * 2 ) );
2798
2799 VECTOR2I cellSize( std::max( gridSize.x * 5, requestedSize.x / colCount ),
2800 std::max( gridSize.y * 2, requestedSize.y / rowCount ) );
2801
2802 cellSize.x = KiROUND( (double) cellSize.x / gridSize.x ) * gridSize.x;
2803 cellSize.y = KiROUND( (double) cellSize.y / gridSize.y ) * gridSize.y;
2804
2805 table->ClearCells();
2806 table->SetColCount( colCount );
2807
2808 for( int col = 0; col < colCount; ++col )
2809 table->SetColWidth( col, cellSize.x );
2810
2811 for( int row = 0; row < rowCount; ++row )
2812 {
2813 table->SetRowHeight( row, cellSize.y );
2814
2815 for( int col = 0; col < colCount; ++col )
2816 {
2817 SCH_TABLECELL* cell = new SCH_TABLECELL();
2818 int defaultTextSize = schematic->Settings().m_DefaultTextSize;
2819
2820 cell->SetTextSize( VECTOR2I( defaultTextSize, defaultTextSize ) );
2821 cell->SetPosition( origin + VECTOR2I( col * cellSize.x, row * cellSize.y ) );
2822 cell->SetEnd( cell->GetPosition() + cellSize );
2823 table->AddCell( cell );
2824 }
2825 }
2826
2828 m_view->AddToPreview( table->Clone() );
2829 m_frame->SetMsgPanel( table );
2830 }
2831 else if( evt->IsDblClick( BUT_LEFT ) && !table )
2832 {
2834 }
2835 else if( evt->IsClick( BUT_RIGHT ) )
2836 {
2837 // Warp after context menu only if dragging...
2838 if( !table )
2840
2841 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
2842 }
2843 else if( table && evt->IsAction( &ACTIONS::redo ) )
2844 {
2845 wxBell();
2846 }
2847 else
2848 {
2849 evt->SetPassEvent();
2850 }
2851
2852 // Enable autopanning and cursor capture only when there is a shape being drawn
2853 getViewControls()->SetAutoPan( table != nullptr );
2854 getViewControls()->CaptureCursor( table != nullptr );
2855 }
2856
2857 getViewControls()->SetAutoPan( false );
2858 getViewControls()->CaptureCursor( false );
2859 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2860 return 0;
2861}
2862
2863
2865{
2866 bool isDrawSheetCopy = aEvent.IsAction( &EE_ACTIONS::drawSheetFromFile );
2867 bool isDrawSheetFromDesignBlock = aEvent.IsAction( &EE_ACTIONS::drawSheetFromDesignBlock );
2868
2869 DESIGN_BLOCK* designBlock = nullptr;
2870 SCH_SHEET* sheet = nullptr;
2871 wxString filename;
2872
2873 if( isDrawSheetCopy )
2874 {
2875 wxString* ptr = aEvent.Parameter<wxString*>();
2876 wxCHECK( ptr, 0 );
2877
2878 // We own the string if we're importing a sheet
2879 filename = *ptr;
2880 delete ptr;
2881 }
2882 else if( isDrawSheetFromDesignBlock )
2883 {
2884 designBlock = aEvent.Parameter<DESIGN_BLOCK*>();
2885 wxCHECK( designBlock, 0 );
2886 filename = designBlock->GetSchematicFile();
2887 }
2888
2889 if( ( isDrawSheetCopy || isDrawSheetFromDesignBlock ) && !wxFileExists( filename ) )
2890 {
2891 wxMessageBox( wxString::Format( _( "File '%s' does not exist." ), filename ) );
2892 return 0;
2893 }
2894
2895 if( m_inDrawingTool )
2896 return 0;
2897
2899
2901 SCHEMATIC_SETTINGS& schSettings = m_frame->Schematic().Settings();
2904 VECTOR2I cursorPos;
2905
2907
2908 m_frame->PushTool( aEvent );
2909
2910 auto setCursor =
2911 [&]()
2912 {
2913 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
2914 };
2915
2916 auto cleanup =
2917 [&] ()
2918 {
2921 delete sheet;
2922 sheet = nullptr;
2923 };
2924
2925 Activate();
2926
2927 // Must be done after Activate() so that it gets set into the correct context
2928 getViewControls()->ShowCursor( true );
2929
2930 // Set initial cursor
2931 setCursor();
2932
2933 if( aEvent.HasPosition() && !( isDrawSheetCopy || isDrawSheetFromDesignBlock ) )
2934 m_toolMgr->PrimeTool( aEvent.Position() );
2935
2936 // Main loop: keep receiving events
2937 while( TOOL_EVENT* evt = Wait() )
2938 {
2939 setCursor();
2940 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
2941 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
2942
2943 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
2944 controls->ForceCursorPosition( true, cursorPos );
2945
2946 // The tool hotkey is interpreted as a click when drawing
2947 bool isSyntheticClick = sheet && evt->IsActivate() && evt->HasPosition()
2948 && evt->Matches( aEvent );
2949
2950 if( evt->IsCancelInteractive() || ( sheet && evt->IsAction( &ACTIONS::undo ) ) )
2951 {
2953
2954 if( sheet )
2955 {
2956 cleanup();
2957 }
2958 else
2959 {
2960 m_frame->PopTool( aEvent );
2961 break;
2962 }
2963 }
2964 else if( evt->IsActivate() && !isSyntheticClick )
2965 {
2966 if( sheet && evt->IsMoveTool() )
2967 {
2968 // we're already drawing our own item; ignore the move tool
2969 evt->SetPassEvent( false );
2970 continue;
2971 }
2972
2973 if( sheet )
2974 {
2975 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel sheet creation." ) );
2976 evt->SetPassEvent( false );
2977 continue;
2978 }
2979
2980 if( evt->IsPointEditor() )
2981 {
2982 // don't exit (the point editor runs in the background)
2983 }
2984 else if( evt->IsMoveTool() )
2985 {
2986 // leave ourselves on the stack so we come back after the move
2987 break;
2988 }
2989 else
2990 {
2991 m_frame->PopTool( aEvent );
2992 break;
2993 }
2994 }
2995 else if( !sheet && ( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) ) )
2996 {
2998
2999 if( selection.Size() == 1
3000 && selection.Front()->Type() == SCH_SHEET_T
3001 && selection.Front()->GetBoundingBox().Contains( cursorPos ) )
3002 {
3003 if( evt->IsClick( BUT_LEFT ) )
3004 {
3005 // sheet already selected
3006 continue;
3007 }
3008 else if( evt->IsDblClick( BUT_LEFT ) )
3009 {
3011 m_frame->PopTool( aEvent );
3012 break;
3013 }
3014 }
3015
3017
3018 sheet = new SCH_SHEET( m_frame->GetCurrentSheet().Last(), cursorPos );
3019 sheet->SetScreen( nullptr );
3020
3021 if( isDrawSheetCopy )
3022 {
3023 wxFileName fn( filename );
3024
3025 sheet->GetFields()[SHEETNAME].SetText( fn.GetName() );
3026 sheet->GetFields()[SHEETFILENAME].SetText( fn.GetName() + wxT( "." )
3028 }
3029 else if( isDrawSheetFromDesignBlock )
3030 {
3031 wxFileName fn( filename );
3032
3033 sheet->GetFields()[SHEETNAME].SetText( designBlock->GetLibId().GetLibItemName() );
3034 sheet->GetFields()[SHEETFILENAME].SetText( fn.GetName() + wxT( "." )
3036
3037 std::vector<SCH_FIELD>& sheetFields = sheet->GetFields();
3038
3039 // Copy default fields into the sheet
3040 for( const auto& field : designBlock->GetFields() )
3041 {
3042 SCH_FIELD newField( sheet, sheetFields.size(), field.first );
3043 newField.SetText( field.second );
3044 newField.SetVisible( false );
3045
3046 sheetFields.emplace_back( newField );
3047 }
3048 }
3049 else
3050 {
3051 sheet->GetFields()[SHEETNAME].SetText( wxT( "Untitled Sheet" ) );
3052 sheet->GetFields()[SHEETFILENAME].SetText(
3053 wxString::Format( wxT( "untitled.%s" ), FILEEXT::KiCadSchematicFileExtension ) );
3054 }
3055
3056 sheet->SetFlags( IS_NEW | IS_MOVING );
3060 sizeSheet( sheet, cursorPos );
3061
3062 SCH_SHEET_LIST hierarchy = m_frame->Schematic().Hierarchy();
3064 instance.push_back( sheet );
3065 wxString pageNumber;
3066
3067 // Don't try to be too clever when assigning the next availabe page number. Just use
3068 // the number of sheets plus one.
3069 pageNumber.Printf( wxT( "%d" ), static_cast<int>( hierarchy.size() ) + 1 );
3070 instance.SetPageNumber( pageNumber );
3071
3073 m_view->AddToPreview( sheet->Clone() );
3074 }
3075 else if( sheet && ( evt->IsClick( BUT_LEFT )
3076 || evt->IsDblClick( BUT_LEFT )
3077 || isSyntheticClick
3078 || evt->IsAction( &ACTIONS::finishInteractive ) ) )
3079 {
3080 getViewControls()->SetAutoPan( false );
3081 getViewControls()->CaptureCursor( false );
3082
3083 if( m_frame->EditSheetProperties( static_cast<SCH_SHEET*>( sheet ),
3084 &m_frame->GetCurrentSheet(), nullptr, nullptr,
3085 nullptr, &filename ) )
3086 {
3088
3090
3091 // Use the commit we were provided or make our own
3092 SCH_COMMIT tempCommit = SCH_COMMIT( m_toolMgr );
3093 SCH_COMMIT& c = evt->Commit() ? *( (SCH_COMMIT*) evt->Commit() ) : tempCommit;
3094
3095 // We need to manually add the sheet to the screen otherwise annotation will not be able to find
3096 // the sheet and its symbols to annotate.
3097 m_frame->AddToScreen( sheet );
3098 c.Added( sheet, m_frame->GetScreen() );
3099
3100 // This convoluted logic means we always annotate unless we are drawing a copy/design block
3101 // and the user has explicitly requested we keep the annotations via checkbox
3103
3104 if( annotate.automatic
3105 && !( ( isDrawSheetCopy || isDrawSheetFromDesignBlock )
3107 {
3108 // Annotation will remove this from selection, but we add it back later
3109 m_selectionTool->AddItemToSel( sheet );
3110
3111 NULL_REPORTER reporter;
3114 (ANNOTATE_ALGO_T) annotate.method, true /* recursive */,
3115 schSettings.m_AnnotateStartNum, true, false, reporter );
3116 }
3117
3118 c.Push( isDrawSheetCopy ? "Import Sheet Copy" : "Draw Sheet" );
3119
3120 m_selectionTool->AddItemToSel( sheet );
3121 }
3122 else
3123 {
3125 delete sheet;
3126 }
3127
3128 sheet = nullptr;
3129 }
3130 else if( evt->IsAction( &ACTIONS::duplicate )
3131 || evt->IsAction( &EE_ACTIONS::repeatDrawItem ) )
3132 {
3133 if( sheet )
3134 {
3135 // This doesn't really make sense; we'll just end up dragging a stack of
3136 // objects so we ignore the duplicate and just carry on.
3137 wxBell();
3138 continue;
3139 }
3140
3141 // Exit. The duplicate will run in its own loop.
3142 m_frame->PopTool( aEvent );
3143 break;
3144 }
3145 else if( sheet && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
3146 {
3147 sizeSheet( sheet, cursorPos );
3149 m_view->AddToPreview( sheet->Clone() );
3150 m_frame->SetMsgPanel( sheet );
3151 }
3152 else if( evt->IsClick( BUT_RIGHT ) )
3153 {
3154 // Warp after context menu only if dragging...
3155 if( !sheet )
3157
3158 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
3159 }
3160 else if( sheet && evt->IsAction( &ACTIONS::redo ) )
3161 {
3162 wxBell();
3163 }
3164 else
3165 {
3166 evt->SetPassEvent();
3167 }
3168
3169 // Enable autopanning and cursor capture only when there is a sheet to be placed
3170 getViewControls()->SetAutoPan( sheet != nullptr );
3171 getViewControls()->CaptureCursor( sheet != nullptr );
3172 }
3173
3174 getViewControls()->SetAutoPan( false );
3175 getViewControls()->CaptureCursor( false );
3176 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
3177
3178 return 0;
3179}
3180
3181
3183{
3184 VECTOR2I pos = aSheet->GetPosition();
3185 VECTOR2I size = aPos - pos;
3186
3187 size.x = std::max( size.x, schIUScale.MilsToIU( MIN_SHEET_WIDTH ) );
3188 size.y = std::max( size.y, schIUScale.MilsToIU( MIN_SHEET_HEIGHT ) );
3189
3191 aSheet->Resize( VECTOR2I( grid.x - pos.x, grid.y - pos.y ) );
3192}
3193
3194
3195int SCH_DRAWING_TOOLS::doSyncSheetsPins( std::list<SCH_SHEET_PATH> sheetPaths )
3196{
3197 if( !sheetPaths.size() )
3198 {
3199 return 0;
3200 }
3201
3202 m_dialogSyncSheetPin = std::make_unique<DIALOG_SYNC_SHEET_PINS>(
3203 m_frame, std::move( sheetPaths ),
3204 std::make_shared<SHEET_SYNCHRONIZATION_AGENT>(
3205 [&]( EDA_ITEM* aItem, SCH_SHEET_PATH aPath,
3207 {
3208 SCH_COMMIT commit( m_toolMgr );
3209
3210 if( auto pin = dynamic_cast<SCH_SHEET_PIN*>( aItem ) )
3211 {
3212 commit.Modify( pin->GetParent(), aPath.LastScreen() );
3213 aModify();
3214 commit.Push( _( "Modify sheet pin" ) );
3215 }
3216 else
3217 {
3218 commit.Modify( aItem, aPath.LastScreen() );
3219 aModify();
3220 commit.Push( _( "Modify schematic item" ) );
3221 }
3222
3223 updateItem( aItem, true );
3224 m_frame->OnModify();
3225 },
3226 [&]( EDA_ITEM* aItem, SCH_SHEET_PATH aPath )
3227 {
3229 EE_ACTIONS::changeSheet, &aPath );
3231 selectionTool->UnbrightenItem( aItem );
3232 selectionTool->AddItemToSel( aItem, true );
3234 },
3235 [&]( SCH_SHEET* aItem, SCH_SHEET_PATH aPath,
3237 std::set<EDA_ITEM*> aTemplates )
3238 {
3239 switch( aOp )
3240 {
3242 {
3243 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
3244 m_dialogSyncSheetPin->Hide();
3245 m_dialogSyncSheetPin->PreparePlacementTemplate(
3247 aTemplates );
3249 EE_ACTIONS::changeSheet, &aPath );
3251 break;
3252 }
3254 {
3255 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
3256 m_dialogSyncSheetPin->Hide();
3257 m_dialogSyncSheetPin->PreparePlacementTemplate(
3259 aTemplates );
3261 EE_ACTIONS::changeSheet, &aPath );
3262 m_toolMgr->GetTool<EE_SELECTION_TOOL>()->SyncSelection( {}, nullptr,
3263 { sheet } );
3265 break;
3266 }
3267 }
3268 },
3269 m_toolMgr, m_frame ) );
3270 m_dialogSyncSheetPin->Show( true );
3271 return 0;
3272}
3273
3274
3276{
3277 SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( m_selectionTool->GetSelection().Front() );
3278
3279 if( !sheet )
3280 {
3281 VECTOR2I cursorPos = getViewControls()->GetMousePosition();
3282
3283 if( EDA_ITEM* i = nullptr; static_cast<void>(m_selectionTool->SelectPoint( cursorPos, { SCH_SHEET_T }, &i ) ) , i != nullptr )
3284 {
3285 sheet = dynamic_cast<SCH_SHEET*>( i );
3286 }
3287 }
3288
3289 if ( sheet )
3290 {
3292 current.push_back( sheet );
3293 return doSyncSheetsPins( { current } );
3294 }
3295
3296 return 0;
3297}
3298
3299
3301{
3302 static const std::function<void( std::list<SCH_SHEET_PATH>&, SCH_SCREEN*,
3303 std::set<SCH_SCREEN*>&, SCH_SHEET_PATH const& )>
3304 getSheetChildren = []( std::list<SCH_SHEET_PATH>& aPaths, SCH_SCREEN* aScene,
3305 std::set<SCH_SCREEN*>& aVisited, SCH_SHEET_PATH const& aCurPath )
3306 {
3307 if( ! aScene || aVisited.find(aScene) != aVisited.end() )
3308 return ;
3309
3310 std::vector<SCH_ITEM*> sheetChildren;
3311 aScene->GetSheets( &sheetChildren );
3312 aVisited.insert( aScene );
3313
3314 for( SCH_ITEM* child : sheetChildren )
3315 {
3316 SCH_SHEET_PATH cp = aCurPath;
3317 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( child );
3318 cp.push_back( sheet );
3319 aPaths.push_back( cp );
3320 getSheetChildren( aPaths, sheet->GetScreen(), aVisited, cp );
3321 }
3322 };
3323
3324 std::list<SCH_SHEET_PATH> sheetPaths;
3325 std::set<SCH_SCREEN*> visited;
3326 SCH_SHEET_PATH current;
3327 current.push_back( &m_frame->Schematic().Root() );
3328 getSheetChildren( sheetPaths, m_frame->Schematic().Root().GetScreen(), visited, current );
3329
3330 if( sheetPaths.size() == 0 )
3331 {
3332 m_frame->ShowInfoBarMsg( _( "No sub schematic found in the current project" ) );
3333 return 0;
3334 }
3335
3336
3337 return doSyncSheetsPins( std::move( sheetPaths ) );
3338}
3339
3341{
3342 if( !aSheet->GetScreen() )
3343 return nullptr;
3344
3345 for( EDA_ITEM* item : aSheet->GetScreen()->Items().OfType( SCH_HIER_LABEL_T ) )
3346 {
3347 SCH_HIERLABEL* label = static_cast<SCH_HIERLABEL*>( item );
3348
3349 /* A global label has been found: check if there a corresponding sheet label. */
3350 if( !aSheet->HasPin( label->GetText() ) )
3351 return label;
3352 }
3353
3354 return nullptr;
3355}
3356
3357
3359{
3360 // clang-format off
3389 // clang-format on
3390}
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()
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:231
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:269
static TOOL_ACTION leaveSheet
Definition: ee_actions.h:233
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:232
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:243
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:238
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)
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:82
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:130
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:432
virtual void Revert() override
Revert the commit by restoring the modified items state.
Definition: sch_commit.cpp:510
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:181
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:1212
void SetSpinStyle(SPIN_STYLE aSpinStyle) override
Definition: sch_label.cpp:2030
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:450
virtual void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo)
Definition: sch_item.h:552
SCHEMATIC * Schematic() const
Searches the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:150
int GetUnit() const
Definition: sch_item.h:230
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction)
Definition: sch_item.h:554
virtual void SetUnit(int aUnit)
Definition: sch_item.h:229
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:1400
SPIN_STYLE GetSpinStyle() const
Definition: sch_label.cpp:331
void SetShape(LABEL_FLAG_SHAPE aShape)
Definition: sch_label.h:178
LABEL_FLAG_SHAPE GetShape() const
Definition: sch_label.h:177
void SetAutoRotateOnPlacement(bool autoRotate=true)
setAutoRotateOnPlacement
Definition: sch_label.cpp:1406
std::vector< SCH_FIELD > & GetFields()
Definition: sch_label.h:201
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:956
VECTOR2I GetEndPoint() const
Definition: sch_line.h:141
VECTOR2I GetStartPoint() const
Definition: sch_line.h:136
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
void SortByReferenceOnly()
Sort the list of references by reference.
void ReannotateByOptions(ANNOTATE_ORDER_T aSortOption, ANNOTATE_ALGO_T aAlgoOption, int aStartNumber, const SCH_REFERENCE_LIST &aAdditionalRefs, bool aStartAtCurrent, SCH_SHEET_LIST *aHierarchy)
Forces reannotation of the provided references.
size_t GetCount() const
void AddItem(const SCH_REFERENCE &aItem)
void UpdateAnnotation()
Update the symbol references for the schematic project (or the current sheet).
A helper to define a symbol's reference designator in a schematic.
bool AlwaysAnnotate() const
Verify the reference should always be automatically annotated.
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:108
SCH_ITEM * GetItem(const VECTOR2I &aPosition, int aAccuracy=0, KICAD_T aType=SCH_LOCATE_ANY_T) const
Check aPosition within a distance of aAccuracy for items of type aFilter.
Definition: sch_screen.cpp:392
bool IsExplicitJunctionAllowed(const VECTOR2I &aPosition) const
Indicates that a juction dot may be placed at the given location.
Definition: sch_screen.cpp:506
void SetPosition(const VECTOR2I &aPos) override
Definition: sch_shape.h:73
void BeginEdit(const VECTOR2I &aStartPoint) override
Begin drawing a symbol library draw item at aPosition.
Definition: sch_shape.h:77
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:80
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:78
void CalcEdit(const VECTOR2I &aPosition) override
Calculate the attributes of an item at aPosition when it is being edited.
Definition: sch_shape.h:79
wxString GetClass() const override
Return the class name.
Definition: sch_shape.h:42
STROKE_PARAMS GetStroke() const override
Definition: sch_shape.h:55
VECTOR2I GetPosition() const override
Definition: sch_shape.h:72
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:57
void SetBorderColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:118
void AddPin(SCH_SHEET_PIN *aSheetPin)
Add aSheetPin to the sheet.
Definition: sch_sheet.cpp:428
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: sch_sheet.cpp:166
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: sch_sheet.cpp:1023
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:92
void SetBackgroundColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:121
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:109
VECTOR2I GetPosition() const override
Definition: sch_sheet.h:399
bool HasPin(const wxString &aName) const
Checks if the sheet already has a sheet pin named aName.
Definition: sch_sheet.cpp:456
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:172
void SetBorderWidth(int aWidth)
Definition: sch_sheet.h:115
void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo) override
Definition: sch_sheet.cpp:665
void Resize(const VECTOR2I &aSize)
Resize this sheet to aSize and adjust all of the labels accordingly.
Definition: sch_sheet.cpp:1006
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:180
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:847
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
Definition: sch_symbol.cpp:703
void SetRowHeight(int aRow, int aHeight)
Definition: sch_table.h:122
void SetColCount(int aCount)
Definition: sch_table.h:104
void SetColWidth(int aCol, int aWidth)
Definition: sch_table.h:112
void AddCell(SCH_TABLECELL *aCell)
Definition: sch_table.h:147
VECTOR2I GetPosition() const override
Definition: sch_table.cpp:115
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: sch_table.h:189
void ClearCells()
Definition: sch_table.h:159
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: sch_table.h:214
void SetPosition(const VECTOR2I &aPos) override
Definition: sch_table.cpp:109
void Normalize()
Definition: sch_table.cpp:149
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:189
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:409
@ LAYER_GLOBLABEL
Definition: layer_ids.h:408
@ LAYER_NOTES
Definition: layer_ids.h:419
@ LAYER_LOCLABEL
Definition: layer_ids.h:407
@ LAYER_NETCLASS_REFS
Definition: layer_ids.h:416
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:98
@ F_ROUND
Definition: sch_label.h:107
@ L_INPUT
Definition: sch_label.h:99
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:320
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.