KiCad PCB EDA Suite
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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 <sch_actions.h>
39#include <sch_tool_utils.h>
40#include <sch_edit_frame.h>
41#include <pgm_base.h>
42#include <design_block.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 SCH_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( SCH_ACTIONS::leaveSheet, belowRootSheetCondition, 150 );
125 ctxMenu.AddItem( SCH_ACTIONS::closeOutline, inDrawingRuleArea, 200 );
126 ctxMenu.AddItem( SCH_ACTIONS::deleteLastPoint, inDrawingRuleArea, 200 );
127
128 return true;
129}
130
131
133{
134 const SCH_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( &SCH_ACTIONS::placeSymbol ) )
172 {
173 historyList = &m_symbolHistoryList;
174 }
175 else if (aEvent.IsAction( &SCH_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
396
397 if( !libSymbol->IsLocalPower() && cfg->m_Drawing.new_power_symbols == POWER_SYMBOLS::LOCAL )
398 {
399 libSymbol->SetLocalPower();
400 wxString keywords = libSymbol->GetKeyWords();
401
402 // Adjust the KiCad library default fields to match the new power symbol type
403 if( keywords.Contains( wxT( "global power" ) ) )
404 {
405 keywords.Replace( wxT( "global power" ), wxT( "local power" ) );
406 libSymbol->SetKeyWords( keywords );
407 }
408
409 wxString desc = libSymbol->GetDescription();
410
411 if( desc.Contains( wxT( "global label" ) ) )
412 {
413 desc.Replace( wxT( "global label" ), wxT( "local label" ) );
414 libSymbol->SetDescription( desc );
415 }
416 }
417 else if( !libSymbol->IsGlobalPower()
418 && cfg->m_Drawing.new_power_symbols == POWER_SYMBOLS::GLOBAL )
419 {
420 // We do not currently have local power symbols in the KiCad library, so
421 // don't update any fields
422 libSymbol->SetGlobalPower();
423 }
424
425 symbol = new SCH_SYMBOL( *libSymbol, &m_frame->GetCurrentSheet(), sel, cursorPos,
426 &m_frame->Schematic() );
427 addSymbol( symbol );
428 annotate();
429
430 // Update the list of references for the next symbol placement.
431 SCH_REFERENCE placedSymbolReference( symbol, m_frame->GetCurrentSheet() );
432 existingRefs.AddItem( placedSymbolReference );
433 existingRefs.SortByReferenceOnly();
434
436 {
437 // Not placed yet, so pass a nullptr screen reference
438 symbol->AutoplaceFields( nullptr, AUTOPLACE_AUTO );
439 }
440
441 // Update cursor now that we have a symbol
442 setCursor();
443 }
444 else
445 {
447 m_frame->AddToScreen( symbol, screen );
448
450 symbol->AutoplaceFields( screen, AUTOPLACE_AUTO );
451
453
454 SCH_COMMIT commit( m_toolMgr );
455 commit.Added( symbol, screen );
456
458 lwbTool->TrimOverLappingWires( &commit, &m_selectionTool->GetSelection() );
459 lwbTool->AddJunctionsIfNeeded( &commit, &m_selectionTool->GetSelection() );
460
461 commit.Push( _( "Place Symbol" ) );
462
463 if( placeOneOnly )
464 {
465 m_frame->PopTool( aEvent );
466 break;
467 }
468
469 SCH_SYMBOL* nextSymbol = nullptr;
470
473 {
474 int new_unit = symbol->GetUnit();
475
477 && symbol->GetUnit() < symbol->GetUnitCount() )
478 {
479 new_unit++;
480 }
481 else
482 {
483 new_unit = 1;
484 }
485
486 // We are either stepping to the next unit or next symbol
487 if( m_frame->eeconfig()->m_SymChooserPanel.keep_symbol || new_unit > 1 )
488 {
489 nextSymbol = static_cast<SCH_SYMBOL*>( symbol->Duplicate() );
490 nextSymbol->SetUnit( new_unit );
491 nextSymbol->SetUnitSelection( new_unit );
492
493 // Start new annotation sequence at first unit
494 if( new_unit == 1 )
495 nextSymbol->ClearAnnotation( nullptr, false );
496
497 addSymbol( nextSymbol );
498 symbol = nextSymbol;
499 annotate();
500
501 // Update the list of references for the next symbol placement.
502 SCH_REFERENCE placedSymbolReference( symbol, m_frame->GetCurrentSheet() );
503 existingRefs.AddItem( placedSymbolReference );
504 existingRefs.SortByReferenceOnly();
505 }
506 }
507
508 symbol = nextSymbol;
509 }
510 }
511 else if( evt->IsClick( BUT_RIGHT ) )
512 {
513 // Warp after context menu only if dragging...
514 if( !symbol )
516
517 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
518 }
519 else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
520 {
521 if( *evt->GetCommandId() >= ID_POPUP_SCH_SELECT_UNIT
522 && *evt->GetCommandId() <= ID_POPUP_SCH_SELECT_UNIT_END )
523 {
524 int unit = *evt->GetCommandId() - ID_POPUP_SCH_SELECT_UNIT;
525
526 if( symbol )
527 {
528 m_frame->SelectUnit( symbol, unit );
530 }
531 }
532 else if( *evt->GetCommandId() >= ID_POPUP_SCH_SELECT_BASE
533 && *evt->GetCommandId() <= ID_POPUP_SCH_SELECT_ALT )
534 {
535 int bodyStyle = ( *evt->GetCommandId() - ID_POPUP_SCH_SELECT_BASE ) + 1;
536
537 if( symbol && symbol->GetBodyStyle() != bodyStyle )
538 {
539 m_frame->FlipBodyStyle( symbol );
541 }
542 }
543 }
544 else if( evt->IsAction( &ACTIONS::duplicate )
545 || evt->IsAction( &SCH_ACTIONS::repeatDrawItem ) )
546 {
547 if( symbol )
548 {
549 // This doesn't really make sense; we'll just end up dragging a stack of
550 // objects so we ignore the duplicate and just carry on.
551 wxBell();
552 continue;
553 }
554
555 // Exit. The duplicate will run in its own loop.
556 m_frame->PopTool( aEvent );
557 break;
558 }
559 else if( symbol && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
560 {
561 symbol->SetPosition( cursorPos );
563 m_view->AddToPreview( symbol, false ); // Add, but not give ownership
564 m_frame->SetMsgPanel( symbol );
565 }
566 else if( symbol && evt->IsAction( &ACTIONS::doDelete ) )
567 {
568 cleanup();
569 }
570 else if( symbol && evt->IsAction( &ACTIONS::redo ) )
571 {
572 wxBell();
573 }
574 else
575 {
576 evt->SetPassEvent();
577 }
578
579 // Enable autopanning and cursor capture only when there is a symbol to be placed
580 getViewControls()->SetAutoPan( symbol != nullptr );
581 getViewControls()->CaptureCursor( symbol != nullptr );
582 }
583
584 getViewControls()->SetAutoPan( false );
585 getViewControls()->CaptureCursor( false );
586 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
587
588 return 0;
589}
590
591
593{
594 SCH_SYMBOL* symbol = aEvent.Parameter<SCH_SYMBOL*>();
595
596 // TODO: get from selection
597 if( !symbol )
598 {
599 static const std::vector<KICAD_T> symbolTypes = { SCH_SYMBOL_T };
600 SCH_SELECTION& selection = m_selectionTool->RequestSelection( symbolTypes );
601
602 if( selection.Size() != 1 )
603 {
604 m_frame->ShowInfoBarMsg( _( "Select a single symbol to place the next unit." ) );
605 return 0;
606 }
607
608 wxCHECK( selection.Front()->Type() == SCH_SYMBOL_T, 0 );
609 symbol = static_cast<SCH_SYMBOL*>( selection.Front() );
610 }
611
612 if( !symbol )
613 return 0;
614
615 if( !symbol->IsMulti() )
616 {
617 m_frame->ShowInfoBarMsg( _( "This symbol has only one unit." ) );
618 return 0;
619 }
620
621 const std::set<int> missingUnits = GetUnplacedUnitsForSymbol( *symbol );
622
623 if( missingUnits.empty() )
624 {
625 m_frame->ShowInfoBarMsg( _( "All units of this symbol are already placed." ) );
626 return 0;
627 }
628
629 // Find the lowest unit number that is missing
630 const int nextMissing = *std::min_element( missingUnits.begin(), missingUnits.end() );
631
632 std::unique_ptr<SCH_SYMBOL> newSymbol = std::make_unique<SCH_SYMBOL>( *symbol );
633 const SCH_SHEET_PATH& sheetPath = m_frame->GetCurrentSheet();
634
635 newSymbol->SetUnitSelection( &sheetPath, nextMissing );
636 newSymbol->SetUnit( nextMissing );
637 newSymbol->SetRefProp( symbol->GetRef( &sheetPath, false ) );
638
639 // Post the new symbol - don't reannotate it - we set the reference ourselves
641 SCH_ACTIONS::PLACE_SYMBOL_PARAMS{ newSymbol.release(), false } );
642 return 0;
643}
644
645
647{
648 bool placingDesignBlock = aEvent.IsAction( &SCH_ACTIONS::placeDesignBlock );
649
650 DESIGN_BLOCK* designBlock = nullptr;
651 wxString sheetFileName = wxEmptyString;
652
653 if( placingDesignBlock )
654 {
656 {
657 designBlock = m_frame->GetDesignBlockPane()->GetDesignBlock(
658 m_frame->GetDesignBlockPane()->GetSelectedLibId(), true, true );
659
660 if( !designBlock )
661 return 0;
662
663 sheetFileName = designBlock->GetSchematicFile();
664 }
665 }
666 else
667 {
668 wxString* importSourceFile = aEvent.Parameter<wxString*>();
669
670 if( importSourceFile != nullptr )
671 sheetFileName = *importSourceFile;
672 }
673
674 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
676 SCHEMATIC_SETTINGS& schSettings = m_frame->Schematic().Settings();
677 SCH_SCREEN* screen = m_frame->GetScreen();
678 SCH_SHEET_PATH& sheetPath = m_frame->GetCurrentSheet();
679
682 VECTOR2I cursorPos;
683
684 if( !cfg || !common_settings )
685 return 0;
686
687 if( m_inDrawingTool )
688 return 0;
689
690 auto setCursor =
691 [&]()
692 {
693 m_frame->GetCanvas()->SetCurrentCursor( designBlock ? KICURSOR::MOVING
694 : KICURSOR::COMPONENT );
695 };
696
697 auto placeSheetContents =
698 [&]()
699 {
700 SCH_COMMIT commit( m_toolMgr );
702
703 EDA_ITEMS newItems;
704 bool keepAnnotations = cfg->m_DesignBlockChooserPanel.keep_annotations;
705
706 selectionTool->ClearSelection();
707
708 // Mark all existing items on the screen so we don't select them after appending
709 for( EDA_ITEM* item : screen->Items() )
710 item->SetFlags( SKIP_STRUCT );
711
712 if( !m_frame->LoadSheetFromFile( sheetPath.Last(), &sheetPath, sheetFileName, true,
713 placingDesignBlock ) )
714 return false;
715
717
718 m_frame->SyncView();
719 m_frame->OnModify();
720 m_frame->HardRedraw(); // Full reinit of the current screen and the display.
721
722 // Select all new items
723 for( EDA_ITEM* item : screen->Items() )
724 {
725 if( !item->HasFlag( SKIP_STRUCT ) )
726 {
727 if( item->Type() == SCH_SYMBOL_T && !keepAnnotations )
728 static_cast<SCH_SYMBOL*>( item )->ClearAnnotation( &sheetPath, false );
729
730 if( item->Type() == SCH_LINE_T )
731 item->SetFlags( STARTPOINT | ENDPOINT );
732
733 commit.Added( item, screen );
734 newItems.emplace_back( item );
735 }
736 else
737 item->ClearFlags( SKIP_STRUCT );
738 }
739
740 selectionTool->AddItemsToSel( &newItems, true );
741
742 cursorPos = grid.Align( controls->GetMousePosition(),
743 grid.GetSelectionGrid( selectionTool->GetSelection() ) );
744 controls->ForceCursorPosition( true, cursorPos );
745
746 // Move everything to our current mouse position now
747 // that we have a selection to get a reference point
748 VECTOR2I anchorPos = selectionTool->GetSelection().GetReferencePoint();
749 VECTOR2I delta = cursorPos - anchorPos;
750
751 // Will all be SCH_ITEMs as these were pulled from the screen->Items()
752 for( EDA_ITEM* item : newItems )
753 static_cast<SCH_ITEM*>( item )->Move( delta );
754
755 if( !keepAnnotations )
756 {
758
759 if( annotate.automatic )
760 {
761 NULL_REPORTER reporter;
763 (ANNOTATE_ORDER_T) annotate.sort_order,
764 (ANNOTATE_ALGO_T) annotate.method, true /* recursive */,
765 schSettings.m_AnnotateStartNum, false, false, reporter );
766 }
767
768 // Annotation will clear selection, so we need to restore it
769 for( EDA_ITEM* item : newItems )
770 {
771 if( item->Type() == SCH_LINE_T )
772 item->SetFlags( STARTPOINT | ENDPOINT );
773 }
774
775 selectionTool->AddItemsToSel( &newItems, true );
776 }
777
778 // Start moving selection, cancel undoes the insertion
779 bool placed = m_toolMgr->RunSynchronousAction( SCH_ACTIONS::move, &commit );
780
781 // Update our cursor position to the new location in case we're placing repeated copies
782 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_CONNECTABLE );
783
784 if( placed )
785 commit.Push( placingDesignBlock ? _( "Add design block" )
786 : _( "Import Schematic Sheet Content..." ) );
787 else
788 commit.Revert();
789
791
792 return placed;
793 };
794
795 // Whether we are placing the sheet as a sheet, or as its contents, we need to get a filename
796 // if we weren't provided one
797 if( sheetFileName.IsEmpty() )
798 {
799 wxString path;
800 wxString file;
801
802 if (!placingDesignBlock) {
803
804 if( sheetFileName.IsEmpty() )
805 {
806 path = wxPathOnly( m_frame->Prj().GetProjectFullName() );
807 file = wxEmptyString;
808 }
809 else
810 {
811 path = wxPathOnly( sheetFileName );
812 file = wxFileName( sheetFileName ).GetFullName();
813 }
814
815 // Open file chooser dialog even if we have been provided a file so the user
816 // can select the options they want
817 wxFileDialog dlg( m_frame, _( "Choose Schematic" ), path, file,
819 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
820
821 FILEDLG_IMPORT_SHEET_CONTENTS dlgHook( cfg );
822 dlg.SetCustomizeHook( dlgHook );
823
824 if( dlg.ShowModal() == wxID_CANCEL )
825 return 0;
826
827 sheetFileName = dlg.GetPath();
828
830 }
831
832 if( sheetFileName.IsEmpty() )
833 return 0;
834 }
835
836 // If we're placing sheet contents, we don't even want to run our tool loop, just add the items
837 // to the canvas and run the move tool
839 {
840 while( placeSheetContents() && cfg->m_DesignBlockChooserPanel.repeated_placement )
841 ;
842
845 delete designBlock;
846 designBlock = nullptr;
847
848 return 0;
849 }
850
851 // We're placing a sheet as a sheet, we need to run a small tool loop to get the starting
852 // coordinate of the sheet drawing
853 m_frame->PushTool( aEvent );
854
855 Activate();
856
857 // Must be done after Activate() so that it gets set into the correct context
858 getViewControls()->ShowCursor( true );
859
860 // Set initial cursor
861 setCursor();
862
863 if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() )
864 {
865 m_toolMgr->PrimeTool( { 0, 0 } );
866 }
867
868 // Main loop: keep receiving events
869 while( TOOL_EVENT* evt = Wait() )
870 {
871 setCursor();
872 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
873 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
874
875 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_CONNECTABLE );
876 controls->ForceCursorPosition( true, cursorPos );
877
878 // The tool hotkey is interpreted as a click when drawing
879 bool isSyntheticClick = designBlock && evt->IsActivate() && evt->HasPosition()
880 && evt->Matches( aEvent );
881
882 if( evt->IsCancelInteractive() || ( designBlock && evt->IsAction( &ACTIONS::undo ) ) )
883 {
885 break;
886 }
887 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) || isSyntheticClick )
888 {
889 if( placingDesignBlock )
890 {
892 }
893 else
894 {
895 // drawSheet must delete
897 new wxString( sheetFileName ) );
898 }
899
900 break;
901 }
902 else if( evt->IsClick( BUT_RIGHT ) )
903 {
904 // Warp after context menu only if dragging...
905 if( !designBlock )
907
908 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
909 }
910 else if( evt->IsAction( &ACTIONS::duplicate )
911 || evt->IsAction( &SCH_ACTIONS::repeatDrawItem ) )
912 {
913 wxBell();
914 }
915 else
916 {
917 evt->SetPassEvent();
918 }
919 }
920
921 m_frame->PopTool( aEvent );
922 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
923
924 return 0;
925}
926
927
929{
930 SCH_BITMAP* image = aEvent.Parameter<SCH_BITMAP*>();
931 bool immediateMode = image != nullptr;
932 bool ignorePrimePosition = false;
933 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
934
935 if( m_inDrawingTool )
936 return 0;
937
939
942 VECTOR2I cursorPos;
943
945
946 // Add all the drawable symbols to preview
947 if( image )
948 {
949 image->SetPosition( getViewControls()->GetCursorPosition() );
951 m_view->AddToPreview( image, false ); // Add, but not give ownership
952 }
953
954 m_frame->PushTool( aEvent );
955
956 auto setCursor =
957 [&]()
958 {
959 if( image )
960 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::MOVING );
961 else
962 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
963 };
964
965 auto cleanup =
966 [&] ()
967 {
971 delete image;
972 image = nullptr;
973 };
974
975 Activate();
976
977 // Must be done after Activate() so that it gets set into the correct context
978 getViewControls()->ShowCursor( true );
979
980 // Set initial cursor
981 setCursor();
982
983 // Prime the pump
984 if( image )
985 {
987 }
988 else if( aEvent.HasPosition() )
989 {
990 m_toolMgr->PrimeTool( aEvent.Position() );
991 }
992 else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() )
993 {
994 m_toolMgr->PrimeTool( { 0, 0 } );
995 ignorePrimePosition = true;
996 }
997
998 // Main loop: keep receiving events
999 while( TOOL_EVENT* evt = Wait() )
1000 {
1001 setCursor();
1002 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1003 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1004
1005 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
1006 controls->ForceCursorPosition( true, cursorPos );
1007
1008 // The tool hotkey is interpreted as a click when drawing
1009 bool isSyntheticClick = image && evt->IsActivate() && evt->HasPosition()
1010 && evt->Matches( aEvent );
1011
1012 if( evt->IsCancelInteractive() || ( image && evt->IsAction( &ACTIONS::undo ) ) )
1013 {
1015
1016 if( image )
1017 {
1018 cleanup();
1019 }
1020 else
1021 {
1022 m_frame->PopTool( aEvent );
1023 break;
1024 }
1025
1026 if( immediateMode )
1027 {
1028 m_frame->PopTool( aEvent );
1029 break;
1030 }
1031 }
1032 else if( evt->IsActivate() && !isSyntheticClick )
1033 {
1034 if( image && evt->IsMoveTool() )
1035 {
1036 // we're already moving our own item; ignore the move tool
1037 evt->SetPassEvent( false );
1038 continue;
1039 }
1040
1041 if( image )
1042 {
1043 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel image creation." ) );
1044 evt->SetPassEvent( false );
1045 continue;
1046 }
1047
1048 if( evt->IsMoveTool() )
1049 {
1050 // leave ourselves on the stack so we come back after the move
1051 break;
1052 }
1053 else
1054 {
1055 m_frame->PopTool( aEvent );
1056 break;
1057 }
1058 }
1059 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) || isSyntheticClick )
1060 {
1061 if( !image )
1062 {
1064
1065 wxFileDialog dlg( m_frame, _( "Choose Image" ), m_mruPath, wxEmptyString,
1066 _( "Image Files" ) + wxS( " " ) + wxImage::GetImageExtWildcard(),
1067 wxFD_OPEN );
1068
1069 if( dlg.ShowModal() != wxID_OK )
1070 continue;
1071
1072 // If we started with a hotkey which has a position then warp back to that.
1073 // Otherwise update to the current mouse position pinned inside the autoscroll
1074 // boundaries.
1075 if( evt->IsPrime() && !ignorePrimePosition )
1076 {
1077 cursorPos = grid.Align( evt->Position() );
1078 getViewControls()->WarpMouseCursor( cursorPos, true );
1079 }
1080 else
1081 {
1083 cursorPos = getViewControls()->GetMousePosition();
1084 }
1085
1086 wxString fullFilename = dlg.GetPath();
1087 m_mruPath = wxPathOnly( fullFilename );
1088
1089 if( wxFileExists( fullFilename ) )
1090 image = new SCH_BITMAP( cursorPos );
1091
1092 if( !image || !image->GetReferenceImage().ReadImageFile( fullFilename ) )
1093 {
1094 wxMessageBox( wxString::Format( _( "Could not load image from '%s'." ), fullFilename ) );
1095 delete image;
1096 image = nullptr;
1097 continue;
1098 }
1099
1100 image->SetFlags( IS_NEW | IS_MOVING );
1101
1103
1105 m_view->AddToPreview( image, false ); // Add, but not give ownership
1106 m_view->RecacheAllItems(); // Bitmaps are cached in Opengl
1107
1109
1110 getViewControls()->SetCursorPosition( cursorPos, false );
1111 setCursor();
1112 }
1113 else
1114 {
1115 SCH_COMMIT commit( m_toolMgr );
1116 commit.Add( image, m_frame->GetScreen() );
1117 commit.Push( _( "Place Image" ) );
1118
1119 image = nullptr;
1121
1123
1124 if( immediateMode )
1125 {
1126 m_frame->PopTool( aEvent );
1127 break;
1128 }
1129 }
1130 }
1131 else if( evt->IsClick( BUT_RIGHT ) )
1132 {
1133 // Warp after context menu only if dragging...
1134 if( !image )
1136
1137 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
1138 }
1139 else if( evt->IsAction( &ACTIONS::duplicate )
1140 || evt->IsAction( &SCH_ACTIONS::repeatDrawItem ) )
1141 {
1142 if( image )
1143 {
1144 // This doesn't really make sense; we'll just end up dragging a stack of
1145 // objects so we ignore the duplicate and just carry on.
1146 wxBell();
1147 continue;
1148 }
1149
1150 // Exit. The duplicate will run in its own loop.
1151 m_frame->PopTool( aEvent );
1152 break;
1153 }
1154 else if( image && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
1155 {
1156 image->SetPosition( cursorPos );
1158 m_view->AddToPreview( image, false ); // Add, but not give ownership
1159 m_view->RecacheAllItems(); // Bitmaps are cached in Opengl
1161 }
1162 else if( image && evt->IsAction( &ACTIONS::doDelete ) )
1163 {
1164 cleanup();
1165 }
1166 else if( image && evt->IsAction( &ACTIONS::redo ) )
1167 {
1168 wxBell();
1169 }
1170 else
1171 {
1172 evt->SetPassEvent();
1173 }
1174
1175 // Enable autopanning and cursor capture only when there is an image to be placed
1176 getViewControls()->SetAutoPan( image != nullptr );
1177 getViewControls()->CaptureCursor( image != nullptr );
1178 }
1179
1180 getViewControls()->SetAutoPan( false );
1181 getViewControls()->CaptureCursor( false );
1182 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1183
1184 return 0;
1185}
1186
1187
1189{
1190 if( m_inDrawingTool )
1191 return 0;
1192
1194
1195 // Note: PlaceImportedGraphics() will convert PCB_SHAPE_T and PCB_TEXT_T to footprint
1196 // items if needed
1198 int dlgResult = dlg.ShowModal();
1199
1200 std::list<std::unique_ptr<EDA_ITEM>>& list = dlg.GetImportedItems();
1201
1202 if( dlgResult != wxID_OK )
1203 return 0;
1204
1205 // Ensure the list is not empty:
1206 if( list.empty() )
1207 {
1208 wxMessageBox( _( "No graphic items found in file." ) );
1209 return 0;
1210 }
1211
1213
1215 std::vector<SCH_ITEM*> newItems; // all new items, including group
1216 std::vector<SCH_ITEM*> selectedItems; // the group, or newItems if no group
1217 SCH_SELECTION preview;
1218 SCH_COMMIT commit( m_toolMgr );
1219
1220 for( std::unique_ptr<EDA_ITEM>& ptr : list )
1221 {
1222 SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( ptr.get() );
1223 wxCHECK2_MSG( item, continue, wxString::Format( "Bad item type: ", ptr->Type() ) );
1224
1225 newItems.push_back( item );
1226 selectedItems.push_back( item );
1227 preview.Add( item );
1228
1229 ptr.release();
1230 }
1231
1232 if( !dlg.IsPlacementInteractive() )
1233 {
1234 // Place the imported drawings
1235 for( SCH_ITEM* item : newItems )
1236 commit.Add(item, m_frame->GetScreen());
1237
1238 commit.Push( _( "Import Graphic" ) );
1239 return 0;
1240 }
1241
1242 m_view->Add( &preview );
1243
1244 // Clear the current selection then select the drawings so that edit tools work on them
1246
1247 EDA_ITEMS selItems( selectedItems.begin(), selectedItems.end() );
1249
1250 m_frame->PushTool( aEvent );
1251
1252 auto setCursor = [&]()
1253 {
1254 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::MOVING );
1255 };
1256
1257 Activate();
1258 // Must be done after Activate() so that it gets set into the correct context
1259 controls->ShowCursor( true );
1260 controls->ForceCursorPosition( false );
1261 // Set initial cursor
1262 setCursor();
1263
1264 //SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::DXF );
1266
1267 // Now move the new items to the current cursor position:
1268 VECTOR2I cursorPos = controls->GetCursorPosition( !aEvent.DisableGridSnapping() );
1269 VECTOR2I delta = cursorPos;
1270 VECTOR2I currentOffset;
1271
1272 for( SCH_ITEM* item : selectedItems )
1273 item->Move( delta );
1274
1275 currentOffset += delta;
1276
1277 m_view->Update( &preview );
1278
1279 // Main loop: keep receiving events
1280 while( TOOL_EVENT* evt = Wait() )
1281 {
1282 setCursor();
1283
1284 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1285 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1286
1287 cursorPos = grid.Align( controls->GetMousePosition(), GRID_GRAPHICS );
1288 controls->ForceCursorPosition( true, cursorPos );
1289
1290 if( evt->IsCancelInteractive() || evt->IsActivate() )
1291 {
1293
1294 for( SCH_ITEM* item : newItems )
1295 delete item;
1296
1297 break;
1298 }
1299 else if( evt->IsMotion() )
1300 {
1301 delta = cursorPos - currentOffset;
1302
1303 for( SCH_ITEM* item : selectedItems )
1304 item->Move( delta );
1305
1306 currentOffset += delta;
1307
1308 m_view->Update( &preview );
1309 }
1310 else if( evt->IsClick( BUT_RIGHT ) )
1311 {
1312 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
1313 }
1314 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
1315 {
1316 // Place the imported drawings
1317 for( SCH_ITEM* item : newItems )
1318 commit.Add( item, m_frame->GetScreen() );
1319
1320 commit.Push( _( "Import Graphic" ) );
1321 break; // This is a one-shot command, not a tool
1322 }
1323 else
1324 {
1325 evt->SetPassEvent();
1326 }
1327 }
1328
1329 preview.Clear();
1330 m_view->Remove( &preview );
1331
1332 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1333 controls->ForceCursorPosition( false );
1334
1335 m_frame->PopTool( aEvent );
1336
1337 return 0;
1338}
1339
1340
1342{
1343 VECTOR2I cursorPos;
1344 KICAD_T type = aEvent.Parameter<KICAD_T>();
1347 SCH_ITEM* previewItem;
1348 bool loggedInfoBarError = false;
1349 wxString description;
1350 SCH_SCREEN* screen = m_frame->GetScreen();
1351 bool allowRepeat = false; // Set to true to allow new item repetition
1352
1353 if( m_inDrawingTool )
1354 return 0;
1355
1357
1358 if( type == SCH_JUNCTION_T && aEvent.HasPosition() )
1359 {
1361 SCH_LINE* wire = dynamic_cast<SCH_LINE*>( selection.Front() );
1362
1363 if( wire )
1364 {
1365 SEG seg( wire->GetStartPoint(), wire->GetEndPoint() );
1366 VECTOR2I nearest = seg.NearestPoint( getViewControls()->GetCursorPosition() );
1367 getViewControls()->SetCrossHairCursorPosition( nearest, false );
1368 getViewControls()->WarpMouseCursor( getViewControls()->GetCursorPosition(), true );
1369 }
1370 }
1371
1372 switch( type )
1373 {
1374 case SCH_NO_CONNECT_T:
1375 previewItem = new SCH_NO_CONNECT( cursorPos );
1376 previewItem->SetParent( screen );
1377 description = _( "Add No Connect Flag" );
1378 allowRepeat = true;
1379 break;
1380
1381 case SCH_JUNCTION_T:
1382 previewItem = new SCH_JUNCTION( cursorPos );
1383 previewItem->SetParent( screen );
1384 description = _( "Add Junction" );
1385 break;
1386
1388 previewItem = new SCH_BUS_WIRE_ENTRY( cursorPos );
1389 previewItem->SetParent( screen );
1390 description = _( "Add Wire to Bus Entry" );
1391 allowRepeat = true;
1392 break;
1393
1394 default:
1395 wxASSERT_MSG( false, "Unknown item type in SCH_DRAWING_TOOLS::SingleClickPlace" );
1396 return 0;
1397 }
1398
1400
1401 cursorPos = aEvent.HasPosition() ? aEvent.Position() : controls->GetMousePosition();
1402
1403 m_frame->PushTool( aEvent );
1404
1405 auto setCursor =
1406 [&]()
1407 {
1408 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PLACE );
1409 };
1410
1411 Activate();
1412
1413 // Must be done after Activate() so that it gets set into the correct context
1414 getViewControls()->ShowCursor( true );
1415
1416 // Set initial cursor
1417 setCursor();
1418
1420 m_view->AddToPreview( previewItem->Clone() );
1421
1422 // Prime the pump
1423 if( aEvent.HasPosition() && type != SCH_SHEET_PIN_T )
1424 m_toolMgr->PrimeTool( aEvent.Position() );
1425 else
1427
1428 // Main loop: keep receiving events
1429 while( TOOL_EVENT* evt = Wait() )
1430 {
1431 setCursor();
1432 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1433 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1434
1435 cursorPos = evt->IsPrime() ? evt->Position() : controls->GetMousePosition();
1436 cursorPos = grid.BestSnapAnchor( cursorPos, grid.GetItemGrid( previewItem ), nullptr );
1437 controls->ForceCursorPosition( true, cursorPos );
1438
1439 if( evt->IsCancelInteractive() )
1440 {
1441 m_frame->PopTool( aEvent );
1442 break;
1443 }
1444 else if( evt->IsActivate() )
1445 {
1446 if( evt->IsMoveTool() )
1447 {
1448 // leave ourselves on the stack so we come back after the move
1449 break;
1450 }
1451 else
1452 {
1453 m_frame->PopTool( aEvent );
1454 break;
1455 }
1456 }
1457 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
1458 {
1459 if( !screen->GetItem( cursorPos, 0, type ) )
1460 {
1461 if( type == SCH_JUNCTION_T )
1462 {
1463 if( !screen->IsExplicitJunctionAllowed( cursorPos ) )
1464 {
1465 m_frame->ShowInfoBarError( _( "Junction location contains no joinable "
1466 "wires and/or pins." ) );
1467 loggedInfoBarError = true;
1468 continue;
1469 }
1470 else if( loggedInfoBarError )
1471 {
1473 }
1474 }
1475
1476 SCH_ITEM* newItem = static_cast<SCH_ITEM*>( previewItem->Clone() );
1477 const_cast<KIID&>( newItem->m_Uuid ) = KIID();
1478 newItem->SetPosition( cursorPos );
1479 newItem->SetFlags( IS_NEW );
1480 m_frame->AddToScreen( newItem, screen );
1481
1482 if( allowRepeat )
1483 m_frame->SaveCopyForRepeatItem( newItem );
1484
1485 SCH_COMMIT commit( m_toolMgr );
1486 commit.Added( newItem, screen );
1487
1488 m_frame->SchematicCleanUp( &commit );
1489
1490 commit.Push( description );
1491 }
1492
1493 if( evt->IsDblClick( BUT_LEFT ) || type == SCH_SHEET_PIN_T ) // Finish tool.
1494 {
1495 m_frame->PopTool( aEvent );
1496 break;
1497 }
1498 }
1499 else if( evt->IsClick( BUT_RIGHT ) )
1500 {
1501 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
1502 }
1503 else if( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() )
1504 {
1505 previewItem->SetPosition( cursorPos );
1507 m_view->AddToPreview( previewItem->Clone() );
1508 m_frame->SetMsgPanel( previewItem );
1509 }
1510 else if( evt->Category() == TC_COMMAND )
1511 {
1512 if( ( type == SCH_BUS_WIRE_ENTRY_T ) && ( evt->IsAction( &SCH_ACTIONS::rotateCW )
1513 || evt->IsAction( &SCH_ACTIONS::rotateCCW )
1514 || evt->IsAction( &SCH_ACTIONS::mirrorV )
1515 || evt->IsAction( &SCH_ACTIONS::mirrorH ) ) )
1516 {
1517 SCH_BUS_ENTRY_BASE* busItem = static_cast<SCH_BUS_ENTRY_BASE*>( previewItem );
1518
1519 if( evt->IsAction( &SCH_ACTIONS::rotateCW ) )
1520 {
1521 busItem->Rotate( busItem->GetPosition(), false );
1522 }
1523 else if( evt->IsAction( &SCH_ACTIONS::rotateCCW ) )
1524 {
1525 busItem->Rotate( busItem->GetPosition(), true );
1526 }
1527 else if( evt->IsAction( &SCH_ACTIONS::mirrorV ) )
1528 {
1529 busItem->MirrorVertically( busItem->GetPosition().y );
1530 }
1531 else if( evt->IsAction( &SCH_ACTIONS::mirrorH ) )
1532 {
1533 busItem->MirrorHorizontally( busItem->GetPosition().x );
1534 }
1535
1537 m_view->AddToPreview( previewItem->Clone() );
1538 }
1539 else if( evt->IsAction( &SCH_ACTIONS::properties ) )
1540 {
1541 switch( type )
1542 {
1544 {
1545 std::deque<SCH_ITEM*> strokeItems;
1546 strokeItems.push_back( previewItem );
1547
1548 DIALOG_WIRE_BUS_PROPERTIES dlg( m_frame, strokeItems );
1549 }
1550 break;
1551
1552 case SCH_JUNCTION_T:
1553 {
1554 std::deque<SCH_JUNCTION*> junctions;
1555 junctions.push_back( static_cast<SCH_JUNCTION*>( previewItem ) );
1556
1557 DIALOG_JUNCTION_PROPS dlg( m_frame, junctions );
1558 }
1559 break;
1560 default:
1561 // Do nothing
1562 break;
1563 }
1564
1566 m_view->AddToPreview( previewItem->Clone() );
1567 }
1568 else
1569 {
1570 evt->SetPassEvent();
1571 }
1572 }
1573 else
1574 {
1575 evt->SetPassEvent();
1576 }
1577 }
1578
1579 delete previewItem;
1581
1582 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1583 controls->ForceCursorPosition( false );
1584
1585 return 0;
1586}
1587
1588
1590{
1591 for( SCH_ITEM* item : m_frame->GetScreen()->Items().Overlapping( SCH_LINE_T, aPosition ) )
1592 {
1593 SCH_LINE* line = static_cast<SCH_LINE*>( item );
1594
1595 if( line->GetEditFlags() & STRUCT_DELETED )
1596 continue;
1597
1598 if( line->IsWire() )
1599 return line;
1600 }
1601
1602 return nullptr;
1603}
1604
1605
1607{
1608 wxASSERT( aWire->IsWire() );
1609
1610 SCH_SHEET_PATH sheetPath = m_frame->GetCurrentSheet();
1611
1612 if( SCH_CONNECTION* wireConnection = aWire->Connection( &sheetPath ) )
1613 {
1614 SCH_ITEM* wireDriver = wireConnection->Driver();
1615
1616 if( wireDriver && wireDriver->IsType( { SCH_LABEL_T, SCH_GLOBAL_LABEL_T } ) )
1617 return wireConnection->LocalName();
1618 }
1619
1620 return wxEmptyString;
1621}
1622
1623
1624bool SCH_DRAWING_TOOLS::createNewLabel( const VECTOR2I& aPosition, int aType,
1625 std::list<std::unique_ptr<SCH_LABEL_BASE>>& aLabelList )
1626{
1627 SCHEMATIC* schematic = getModel<SCHEMATIC>();
1628 SCHEMATIC_SETTINGS& settings = schematic->Settings();
1629 SCH_LABEL_BASE* labelItem = nullptr;
1630 SCH_GLOBALLABEL* globalLabel = nullptr;
1631 wxString netName;
1632
1633 switch( aType )
1634 {
1635 case LAYER_LOCLABEL:
1636 labelItem = new SCH_LABEL( aPosition );
1637
1638 if( SCH_LINE* wire = findWire( aPosition ) )
1639 netName = findWireLabelDriverName( wire );
1640
1641 break;
1642
1644 labelItem = new SCH_DIRECTIVE_LABEL( aPosition );
1645 labelItem->SetShape( m_lastNetClassFlagShape );
1646 labelItem->GetFields().emplace_back( VECTOR2I(), FIELD_T::USER, labelItem, wxT( "Netclass" ) );
1647 labelItem->GetFields().emplace_back( VECTOR2I(), FIELD_T::USER, labelItem, wxT( "Component Class" ) );
1648 labelItem->GetFields().back().SetItalic( true );
1649 labelItem->GetFields().back().SetVisible( true );
1650 break;
1651
1652 case LAYER_HIERLABEL:
1653 labelItem = new SCH_HIERLABEL( aPosition );
1654 labelItem->SetShape( m_lastGlobalLabelShape );
1656 break;
1657
1658 case LAYER_GLOBLABEL:
1659 globalLabel = new SCH_GLOBALLABEL( aPosition );
1660 globalLabel->SetShape( m_lastGlobalLabelShape );
1661 globalLabel->GetField( FIELD_T::INTERSHEET_REFS )->SetVisible( settings.m_IntersheetRefsShow );
1663 labelItem = globalLabel;
1664
1665 if( SCH_LINE* wire = findWire( aPosition ) )
1666 netName = findWireLabelDriverName( wire );
1667
1668 break;
1669
1670 default:
1671 wxFAIL_MSG( "SCH_EDIT_FRAME::CreateNewText() unknown layer type" );
1672 return false;
1673 }
1674
1675 labelItem->SetParent( schematic );
1676
1677 labelItem->SetTextSize( VECTOR2I( settings.m_DefaultTextSize, settings.m_DefaultTextSize ) );
1678
1679 if( aType != LAYER_NETCLASS_REFS )
1680 {
1681 // Must be after SetTextSize()
1682 labelItem->SetBold( m_lastTextBold );
1683 labelItem->SetItalic( m_lastTextItalic );
1684 }
1685
1686 labelItem->SetSpinStyle( m_lastTextOrientation );
1687 labelItem->SetFlags( IS_NEW | IS_MOVING );
1688
1689 if( !netName.IsEmpty() )
1690 {
1691 // Auto-create from attached wire
1692 labelItem->SetText( netName );
1693 }
1694 else
1695 {
1696 DIALOG_LABEL_PROPERTIES dlg( m_frame, labelItem, true );
1697
1698 dlg.SetLabelList( &aLabelList );
1699
1700 // QuasiModal required for syntax help and Scintilla auto-complete
1701 if( dlg.ShowQuasiModal() != wxID_OK )
1702 {
1704 delete labelItem;
1705 return false;
1706 }
1707 }
1708
1709 if( aType != LAYER_NETCLASS_REFS )
1710 {
1711 m_lastTextBold = labelItem->IsBold();
1712 m_lastTextItalic = labelItem->IsItalic();
1713 }
1714
1715 m_lastTextOrientation = labelItem->GetSpinStyle();
1716
1717 if( aType == LAYER_GLOBLABEL || aType == LAYER_HIERLABEL )
1718 {
1719 m_lastGlobalLabelShape = labelItem->GetShape();
1721 }
1722 else if( aType == LAYER_NETCLASS_REFS )
1723 {
1724 m_lastNetClassFlagShape = labelItem->GetShape();
1725 }
1726
1727 // Return elements are kept in aLabelList
1728 delete labelItem;
1729 return true;
1730}
1731
1732
1734{
1735 SCHEMATIC* schematic = getModel<SCHEMATIC>();
1736 SCHEMATIC_SETTINGS& settings = schematic->Settings();
1737 SCH_TEXT* textItem = nullptr;
1738
1739 textItem = new SCH_TEXT( aPosition );
1740 textItem->SetParent( schematic );
1741 textItem->SetTextSize( VECTOR2I( settings.m_DefaultTextSize, settings.m_DefaultTextSize ) );
1742 // Must be after SetTextSize()
1743 textItem->SetBold( m_lastTextBold );
1744 textItem->SetItalic( m_lastTextItalic );
1747 textItem->SetTextAngle( m_lastTextAngle );
1748 textItem->SetFlags( IS_NEW | IS_MOVING );
1749
1750 DIALOG_TEXT_PROPERTIES dlg( m_frame, textItem );
1751
1752 // QuasiModal required for syntax help and Scintilla auto-complete
1753 if( dlg.ShowQuasiModal() != wxID_OK )
1754 {
1755 delete textItem;
1756 return nullptr;
1757 }
1758
1759 m_lastTextBold = textItem->IsBold();
1760 m_lastTextItalic = textItem->IsItalic();
1761 m_lastTextHJustify = textItem->GetHorizJustify();
1762 m_lastTextVJustify = textItem->GetVertJustify();
1763 m_lastTextAngle = textItem->GetTextAngle();
1764 return textItem;
1765}
1766
1767
1769{
1770 SCHEMATIC_SETTINGS& settings = aSheet->Schematic()->Settings();
1771 SCH_SHEET_PIN* pin = new SCH_SHEET_PIN( aSheet );
1772
1773 pin->SetFlags( IS_NEW | IS_MOVING );
1774 pin->SetText( std::to_string( aSheet->GetPins().size() + 1 ) );
1775 pin->SetTextSize( VECTOR2I( settings.m_DefaultTextSize, settings.m_DefaultTextSize ) );
1776 pin->SetPosition( aPosition );
1777 pin->ClearSelected();
1778
1779 m_lastSheetPinType = pin->GetShape();
1780
1781 return pin;
1782}
1783
1784
1786 const VECTOR2I& aPosition,
1787 SCH_HIERLABEL* aLabel )
1788{
1789 auto pin = createNewSheetPin( aSheet, aPosition );
1790 pin->SetText( aLabel->GetText() );
1791 pin->SetShape( aLabel->GetShape() );
1792 return pin;
1793}
1794
1795
1797{
1798 SCH_ITEM* item = nullptr;
1801 bool ignorePrimePosition = false;
1802 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
1803 SCH_SHEET* sheet = nullptr;
1804 wxString description;
1805
1806 if( m_inDrawingTool )
1807 return 0;
1808
1810
1811 bool isText = aEvent.IsAction( &SCH_ACTIONS::placeSchematicText );
1812 bool isGlobalLabel = aEvent.IsAction( &SCH_ACTIONS::placeGlobalLabel );
1813 bool isHierLabel = aEvent.IsAction( &SCH_ACTIONS::placeHierLabel );
1814 bool isClassLabel = aEvent.IsAction( &SCH_ACTIONS::placeClassLabel );
1815 bool isNetLabel = aEvent.IsAction( &SCH_ACTIONS::placeLabel );
1816 bool isSheetPin = aEvent.IsAction( &SCH_ACTIONS::placeSheetPin );
1817
1818 GRID_HELPER_GRIDS snapGrid = isText ? GRID_TEXT : GRID_CONNECTABLE;
1819
1820 // If we have a selected sheet use it, otherwise try to get one under the cursor
1821 if( isSheetPin )
1822 sheet = dynamic_cast<SCH_SHEET*>( m_selectionTool->GetSelection().Front() );
1823
1825
1826 m_frame->PushTool( aEvent );
1827
1828 auto setCursor =
1829 [&]()
1830 {
1831 if( item )
1832 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PLACE );
1833 else if( isText )
1834 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::TEXT );
1835 else if( isGlobalLabel )
1836 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_GLOBAL );
1837 else if( isNetLabel )
1838 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_NET );
1839 else if( isClassLabel )
1840 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_NET ); // JEY TODO: netclass directive cursor
1841 else if( isHierLabel )
1842 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_HIER );
1843 else
1844 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
1845 };
1846
1847 auto updatePreview =
1848 [&]()
1849 {
1851 m_view->AddToPreview( item, false );
1852 item->RunOnChildren( [&]( SCH_ITEM* aChild )
1853 {
1854 m_view->AddToPreview( aChild, false );
1855 },
1856 RECURSE_MODE::NO_RECURSE );
1857 m_frame->SetMsgPanel( item );
1858 };
1859
1860 auto cleanup =
1861 [&]()
1862 {
1865 delete item;
1866 item = nullptr;
1867 };
1868
1869 auto prepItemForPlacement =
1870 [&]( SCH_ITEM* aItem, const VECTOR2I& cursorPos )
1871 {
1872 item->SetPosition( cursorPos );
1873
1874 item->SetFlags( IS_NEW | IS_MOVING );
1875
1876 // Not placed yet, so pass a nullptr screen reference
1877 item->AutoplaceFields( nullptr, AUTOPLACE_AUTO );
1878
1879 updatePreview();
1882
1883 // update the cursor so it looks correct before another event
1884 setCursor();
1885 };
1886
1887
1888 Activate();
1889
1890 // Must be done after Activate() so that it gets set into the correct context
1891 controls->ShowCursor( true );
1892
1893 // Set initial cursor
1894 setCursor();
1895
1896 if( aEvent.HasPosition() )
1897 {
1898 m_toolMgr->PrimeTool( aEvent.Position() );
1899 }
1900 else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate()
1901 && ( isText || isGlobalLabel || isHierLabel || isClassLabel || isNetLabel ) )
1902 {
1903 m_toolMgr->PrimeTool( { 0, 0 } );
1904 ignorePrimePosition = true;
1905 }
1906
1907 SCH_COMMIT commit( m_toolMgr );
1908 std::list<std::unique_ptr<SCH_LABEL_BASE>> itemsToPlace;
1909
1910 // Main loop: keep receiving events
1911 while( TOOL_EVENT* evt = Wait() )
1912 {
1913 setCursor();
1914 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1915 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1916
1917 VECTOR2I cursorPos = controls->GetMousePosition();
1918 cursorPos = grid.BestSnapAnchor( cursorPos, snapGrid, item );
1919 controls->ForceCursorPosition( true, cursorPos );
1920
1921 // The tool hotkey is interpreted as a click when drawing
1922 bool isSyntheticClick = item && evt->IsActivate() && evt->HasPosition()
1923 && evt->Matches( aEvent );
1924
1925 if( evt->IsCancelInteractive() || evt->IsAction( &ACTIONS::undo ) )
1926 {
1928
1929 if( item )
1930 {
1931 cleanup();
1932 }
1933 else
1934 {
1935 m_frame->PopTool( aEvent );
1936 break;
1937 }
1938 }
1939 else if( evt->IsActivate() && !isSyntheticClick )
1940 {
1941 if( item && evt->IsMoveTool() )
1942 {
1943 // we're already moving our own item; ignore the move tool
1944 evt->SetPassEvent( false );
1945 continue;
1946 }
1947
1948 if( item )
1949 {
1950 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel item creation." ) );
1951 evt->SetPassEvent( false );
1952 continue;
1953 }
1954
1955 if( evt->IsPointEditor() )
1956 {
1957 // don't exit (the point editor runs in the background)
1958 }
1959 else if( evt->IsMoveTool() )
1960 {
1961 // leave ourselves on the stack so we come back after the move
1962 break;
1963 }
1964 else
1965 {
1966 m_frame->PopTool( aEvent );
1967 break;
1968 }
1969 }
1970 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) || isSyntheticClick )
1971 {
1972 PLACE_NEXT:
1973 // First click creates...
1974 if( !item )
1975 {
1977
1978 if( isText )
1979 {
1980 item = createNewText( cursorPos );
1981 description = _( "Add Text" );
1982 }
1983 else if( isHierLabel )
1984 {
1985 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->GetPlacementTemplate() )
1986 {
1987 auto pin = static_cast<SCH_HIERLABEL*>(
1988 m_dialogSyncSheetPin->GetPlacementTemplate() );
1989 SCH_HIERLABEL* label = new SCH_HIERLABEL( cursorPos );
1990 SCHEMATIC* schematic = getModel<SCHEMATIC>();
1991 label->SetText( pin->GetText() );
1992 label->SetShape( pin->GetShape() );
1994 label->SetParent( schematic );
1995 label->SetBold( m_lastTextBold );
1996 label->SetItalic( m_lastTextItalic );
1998 label->SetTextSize( VECTOR2I( schematic->Settings().m_DefaultTextSize,
1999 schematic->Settings().m_DefaultTextSize ) );
2000 label->SetFlags( IS_NEW | IS_MOVING );
2001 itemsToPlace.push_back( std::unique_ptr<SCH_LABEL_BASE>( label ) );
2002 }
2003 else
2004 {
2005 createNewLabel( cursorPos, LAYER_HIERLABEL, itemsToPlace );
2006 }
2007
2008 description = _( "Add Hierarchical Label" );
2009 }
2010 else if( isNetLabel )
2011 {
2012 createNewLabel( cursorPos, LAYER_LOCLABEL, itemsToPlace );
2013 description = _( "Add Label" );
2014 }
2015 else if( isGlobalLabel )
2016 {
2017 createNewLabel( cursorPos, LAYER_GLOBLABEL, itemsToPlace );
2018 description = _( "Add Label" );
2019 }
2020 else if( isClassLabel )
2021 {
2022 createNewLabel( cursorPos, LAYER_NETCLASS_REFS, itemsToPlace );
2023 description = _( "Add Label" );
2024 }
2025 else if( isSheetPin )
2026 {
2027 EDA_ITEM* i = nullptr;
2028
2029 // If we didn't have a sheet selected, try to find one under the cursor
2030 if( !sheet && m_selectionTool->SelectPoint( cursorPos, { SCH_SHEET_T }, &i ) )
2031 sheet = dynamic_cast<SCH_SHEET*>( i );
2032
2033 if( !sheet )
2034 {
2035 m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( m_frame );
2036 m_statusPopup->SetText( _( "Click over a sheet." ) );
2038 + wxPoint( 20, 20 ) );
2039 m_statusPopup->PopupFor( 2000 );
2040 item = nullptr;
2041 }
2042 else
2043 {
2044 // User is using the 'Sync Sheet Pins' tool
2045 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->GetPlacementTemplate() )
2046 {
2048 sheet, cursorPos,
2049 static_cast<SCH_HIERLABEL*>(
2050 m_dialogSyncSheetPin->GetPlacementTemplate() ) );
2051 }
2052 else
2053 {
2054 // User is using the 'Place Sheet Pins' tool
2055 SCH_HIERLABEL* label = importHierLabel( sheet );
2056
2057 if( !label )
2058 {
2059 m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( m_frame );
2060 m_statusPopup->SetText( _( "No new hierarchical labels found." ) );
2062 + wxPoint( 20, 20 ) );
2063 m_statusPopup->PopupFor( 2000 );
2064 item = nullptr;
2065
2066 m_frame->PopTool( aEvent );
2067 break;
2068 }
2069
2070 item = createNewSheetPinFromLabel( sheet, cursorPos, label );
2071 }
2072 }
2073
2074 description = _( "Add Sheet Pin" );
2075 }
2076
2077 // If we started with a hotkey which has a position then warp back to that.
2078 // Otherwise update to the current mouse position pinned inside the autoscroll
2079 // boundaries.
2080 if( evt->IsPrime() && !ignorePrimePosition )
2081 {
2082 cursorPos = grid.Align( evt->Position() );
2083 getViewControls()->WarpMouseCursor( cursorPos, true );
2084 }
2085 else
2086 {
2088 cursorPos = getViewControls()->GetMousePosition();
2089 cursorPos = grid.BestSnapAnchor( cursorPos, snapGrid, item );
2090 }
2091
2092 if( !itemsToPlace.empty() )
2093 {
2094 item = itemsToPlace.front().release();
2095 itemsToPlace.pop_front();
2096 }
2097
2098 if( item )
2099 prepItemForPlacement( item, cursorPos );
2100
2101 controls->SetCursorPosition( cursorPos, false );
2102 }
2103 else // ... and second click places:
2104 {
2105 item->ClearFlags( IS_MOVING );
2106
2107 if( item->IsConnectable() )
2109
2110 if( isSheetPin )
2111 {
2112 // Sheet pins are owned by their parent sheet.
2113 commit.Modify( sheet, m_frame->GetScreen() );
2114 sheet->AddPin( (SCH_SHEET_PIN*) item );
2115 }
2116 else
2117 {
2119 m_frame->AddToScreen( item, m_frame->GetScreen() );
2120 commit.Added( item, m_frame->GetScreen() );
2121 }
2122
2124
2125 commit.Push( description );
2126
2128
2129 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->GetPlacementTemplate() )
2130 {
2131 m_dialogSyncSheetPin->EndPlaceItem( item );
2132
2133 if( m_dialogSyncSheetPin->CanPlaceMore() )
2134 {
2135 item = nullptr;
2136 goto PLACE_NEXT;
2137 }
2138
2139 m_frame->PopTool( aEvent );
2141 m_dialogSyncSheetPin->Show( true );
2142 break;
2143 }
2144
2145 item = nullptr;
2146
2147 if( isSheetPin )
2148 {
2149 SCH_HIERLABEL* label = importHierLabel( sheet );
2150
2151 if( !label )
2152 {
2153 m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( m_frame );
2154 m_statusPopup->SetText( _( "No new hierarchical labels found." ) );
2156 + wxPoint( 20, 20 ) );
2157 m_statusPopup->PopupFor( 2000 );
2158
2159 m_frame->PopTool( aEvent );
2160 break;
2161 }
2162
2163 item = createNewSheetPinFromLabel( sheet, cursorPos, label );
2164 }
2165 else if( !itemsToPlace.empty() )
2166 {
2167
2168 item = itemsToPlace.front().release();
2169 itemsToPlace.pop_front();
2170 prepItemForPlacement( item, cursorPos );
2171 }
2172 }
2173 }
2174 else if( evt->IsClick( BUT_RIGHT ) )
2175 {
2176 // Warp after context menu only if dragging...
2177 if( !item )
2179
2180 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
2181 }
2182 else if( item && evt->IsSelectionEvent() )
2183 {
2184 // This happens if our text was replaced out from under us by ConvertTextType()
2186
2187 if( selection.GetSize() == 1 )
2188 {
2189 item = (SCH_ITEM*) selection.Front();
2190 updatePreview();
2191 }
2192 else
2193 {
2194 item = nullptr;
2195 }
2196 }
2197 else if( evt->IsAction( &ACTIONS::increment ) )
2198 {
2200 evt->Parameter<ACTIONS::INCREMENT>() );
2201 }
2202 else if( evt->IsAction( &ACTIONS::duplicate )
2203 || evt->IsAction( &SCH_ACTIONS::repeatDrawItem ) )
2204 {
2205 if( item )
2206 {
2207 // This doesn't really make sense; we'll just end up dragging a stack of
2208 // objects so we ignore the duplicate and just carry on.
2209 wxBell();
2210 continue;
2211 }
2212
2213 // Exit. The duplicate will run in its own loop.
2214 m_frame->PopTool( aEvent );
2215 break;
2216 }
2217 else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
2218 {
2219 item->SetPosition( cursorPos );
2220
2221 // Not placed yet, so pass a nullptr screen reference
2222 item->AutoplaceFields( nullptr, AUTOPLACE_AUTO );
2223
2224 updatePreview();
2225 }
2226 else if( item && evt->IsAction( &ACTIONS::doDelete ) )
2227 {
2228 cleanup();
2229 }
2230 else if( evt->IsAction( &ACTIONS::redo ) )
2231 {
2232 wxBell();
2233 }
2234 else
2235 {
2236 evt->SetPassEvent();
2237 }
2238
2239 // Enable autopanning and cursor capture only when there is an item to be placed
2240 controls->SetAutoPan( item != nullptr );
2241 controls->CaptureCursor( item != nullptr );
2242 }
2243
2244 controls->SetAutoPan( false );
2245 controls->CaptureCursor( false );
2246 controls->ForceCursorPosition( false );
2247 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2248
2249 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->CanPlaceMore() )
2250 {
2251 m_dialogSyncSheetPin->EndPlacement();
2252 m_dialogSyncSheetPin->Show( true );
2253 }
2254
2255 return 0;
2256}
2257
2258
2260{
2261 SCHEMATIC* schematic = getModel<SCHEMATIC>();
2262 SCHEMATIC_SETTINGS& sch_settings = schematic->Settings();
2263 SCH_SHAPE* item = nullptr;
2264 bool isTextBox = aEvent.IsAction( &SCH_ACTIONS::drawTextBox );
2265 SHAPE_T type = aEvent.Parameter<SHAPE_T>();
2266 wxString description;
2267
2268 if( m_inDrawingTool )
2269 return 0;
2270
2272
2275 VECTOR2I cursorPos;
2276
2277 // We might be running as the same shape in another co-routine. Make sure that one
2278 // gets whacked.
2280
2282
2283 m_frame->PushTool( aEvent );
2284
2285 auto setCursor =
2286 [&]()
2287 {
2288 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
2289 };
2290
2291 auto cleanup =
2292 [&] ()
2293 {
2296 delete item;
2297 item = nullptr;
2298 };
2299
2300 Activate();
2301
2302 // Must be done after Activate() so that it gets set into the correct context
2303 getViewControls()->ShowCursor( true );
2304
2305 // Set initial cursor
2306 setCursor();
2307
2308 if( aEvent.HasPosition() )
2309 m_toolMgr->PrimeTool( aEvent.Position() );
2310
2311 // Main loop: keep receiving events
2312 while( TOOL_EVENT* evt = Wait() )
2313 {
2314 setCursor();
2315 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
2316 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
2317
2318 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
2319 controls->ForceCursorPosition( true, cursorPos );
2320
2321 // The tool hotkey is interpreted as a click when drawing
2322 bool isSyntheticClick = item && evt->IsActivate() && evt->HasPosition()
2323 && evt->Matches( aEvent );
2324
2325 if( evt->IsCancelInteractive() || ( item && evt->IsAction( &ACTIONS::undo ) ) )
2326 {
2327 if( item )
2328 {
2329 cleanup();
2330 }
2331 else
2332 {
2333 m_frame->PopTool( aEvent );
2334 break;
2335 }
2336 }
2337 else if( evt->IsActivate() && !isSyntheticClick )
2338 {
2339 if( item && evt->IsMoveTool() )
2340 {
2341 // we're already drawing our own item; ignore the move tool
2342 evt->SetPassEvent( false );
2343 continue;
2344 }
2345
2346 if( item )
2347 cleanup();
2348
2349 if( evt->IsPointEditor() )
2350 {
2351 // don't exit (the point editor runs in the background)
2352 }
2353 else if( evt->IsMoveTool() )
2354 {
2355 // leave ourselves on the stack so we come back after the move
2356 break;
2357 }
2358 else
2359 {
2360 m_frame->PopTool( aEvent );
2361 break;
2362 }
2363 }
2364 else if( evt->IsClick( BUT_LEFT ) && !item )
2365 {
2367
2368 if( isTextBox )
2369 {
2371
2372 textbox->SetTextSize( VECTOR2I( sch_settings.m_DefaultTextSize,
2373 sch_settings.m_DefaultTextSize ) );
2374
2375 // Must come after SetTextSize()
2376 textbox->SetBold( m_lastTextBold );
2377 textbox->SetItalic( m_lastTextItalic );
2378
2379 textbox->SetTextAngle( m_lastTextboxAngle );
2382 textbox->SetStroke( m_lastTextboxStroke );
2384 textbox->SetParent( schematic );
2385
2386 item = textbox;
2387 description = _( "Add Text Box" );
2388 }
2389 else
2390 {
2391 item = new SCH_SHAPE( type, LAYER_NOTES, 0, m_lastFillStyle );
2392
2393 item->SetStroke( m_lastStroke );
2395 item->SetParent( schematic );
2396 description = wxString::Format( _( "Add %s" ), item->GetFriendlyName() );
2397 }
2398
2399 item->SetFlags( IS_NEW );
2400 item->BeginEdit( cursorPos );
2401
2403 m_view->AddToPreview( item->Clone() );
2404 }
2405 else if( item && ( evt->IsClick( BUT_LEFT )
2406 || evt->IsDblClick( BUT_LEFT )
2407 || isSyntheticClick
2408 || evt->IsAction( &ACTIONS::finishInteractive ) ) )
2409 {
2410 if( evt->IsDblClick( BUT_LEFT )
2411 || evt->IsAction( &ACTIONS::finishInteractive )
2412 || !item->ContinueEdit( cursorPos ) )
2413 {
2414 item->EndEdit();
2415 item->ClearEditFlags();
2416 item->SetFlags( IS_NEW );
2417
2418 if( isTextBox )
2419 {
2420 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( item );
2421 DIALOG_TEXT_PROPERTIES dlg( m_frame, textbox );
2422
2423 getViewControls()->SetAutoPan( false );
2424 getViewControls()->CaptureCursor( false );
2425
2426 // QuasiModal required for syntax help and Scintilla auto-complete
2427 if( dlg.ShowQuasiModal() != wxID_OK )
2428 {
2429 cleanup();
2430 continue;
2431 }
2432
2433 m_lastTextBold = textbox->IsBold();
2434 m_lastTextItalic = textbox->IsItalic();
2435 m_lastTextboxAngle = textbox->GetTextAngle();
2438 m_lastTextboxStroke = textbox->GetStroke();
2441 }
2442 else
2443 {
2444 m_lastStroke = item->GetStroke();
2445 m_lastFillStyle = item->GetFillMode();
2446 m_lastFillColor = item->GetFillColor();
2447 }
2448
2449 SCH_COMMIT commit( m_toolMgr );
2450 commit.Add( item, m_frame->GetScreen() );
2451 commit.Push( wxString::Format( _( "Draw %s" ), item->GetClass() ) );
2452
2454 item = nullptr;
2455
2458 }
2459 }
2460 else if( evt->IsAction( &ACTIONS::duplicate )
2461 || evt->IsAction( &SCH_ACTIONS::repeatDrawItem ) )
2462 {
2463 if( item )
2464 {
2465 // This doesn't really make sense; we'll just end up dragging a stack of
2466 // objects so we ignore the duplicate and just carry on.
2467 wxBell();
2468 continue;
2469 }
2470
2471 // Exit. The duplicate will run in its own loop.
2472 m_frame->PopTool( aEvent );
2473 break;
2474 }
2475 else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
2476 {
2477 item->CalcEdit( cursorPos );
2479 m_view->AddToPreview( item->Clone() );
2480 m_frame->SetMsgPanel( item );
2481 }
2482 else if( evt->IsDblClick( BUT_LEFT ) && !item )
2483 {
2485 }
2486 else if( evt->IsClick( BUT_RIGHT ) )
2487 {
2488 // Warp after context menu only if dragging...
2489 if( !item )
2491
2492 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
2493 }
2494 else if( item && evt->IsAction( &ACTIONS::redo ) )
2495 {
2496 wxBell();
2497 }
2498 else
2499 {
2500 evt->SetPassEvent();
2501 }
2502
2503 // Enable autopanning and cursor capture only when there is a shape being drawn
2504 getViewControls()->SetAutoPan( item != nullptr );
2505 getViewControls()->CaptureCursor( item != nullptr );
2506 }
2507
2508 getViewControls()->SetAutoPan( false );
2509 getViewControls()->CaptureCursor( false );
2510 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2511 return 0;
2512}
2513
2514
2516{
2517 if( m_inDrawingTool )
2518 return 0;
2519
2521 SCOPED_SET_RESET<bool> scopedDrawMode( m_drawingRuleArea, true );
2522
2525 VECTOR2I cursorPos;
2526
2527 RULE_AREA_CREATE_HELPER ruleAreaTool( *getView(), m_frame, m_toolMgr );
2528 POLYGON_GEOM_MANAGER polyGeomMgr( ruleAreaTool );
2529 bool started = false;
2530
2531 // We might be running as the same shape in another co-routine. Make sure that one
2532 // gets whacked.
2534
2536
2537 m_frame->PushTool( aEvent );
2538
2539 auto setCursor =
2540 [&]()
2541 {
2542 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
2543 };
2544
2545 auto cleanup = [&]()
2546 {
2547 polyGeomMgr.Reset();
2548 started = false;
2549 getViewControls()->SetAutoPan( false );
2550 getViewControls()->CaptureCursor( false );
2552 };
2553
2554 Activate();
2555
2556 // Must be done after Activate() so that it gets set into the correct context
2557 getViewControls()->ShowCursor( true );
2558 //m_controls->ForceCursorPosition( false );
2559
2560 // Set initial cursor
2561 setCursor();
2562
2563 if( aEvent.HasPosition() )
2564 m_toolMgr->PrimeTool( aEvent.Position() );
2565
2566 // Main loop: keep receiving events
2567 while( TOOL_EVENT* evt = Wait() )
2568 {
2569 setCursor();
2570
2571 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
2572 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
2573
2574 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_CONNECTABLE );
2575 controls->ForceCursorPosition( true, cursorPos );
2576
2580
2581 if( evt->IsCancelInteractive() )
2582 {
2583 if( started )
2584 {
2585 cleanup();
2586 }
2587 else
2588 {
2589 m_frame->PopTool( aEvent );
2590
2591 // We've handled the cancel event. Don't cancel other tools
2592 evt->SetPassEvent( false );
2593 break;
2594 }
2595 }
2596 else if( evt->IsActivate() )
2597 {
2598 if( started )
2599 cleanup();
2600
2601 if( evt->IsPointEditor() )
2602 {
2603 // don't exit (the point editor runs in the background)
2604 }
2605 else if( evt->IsMoveTool() )
2606 {
2607 // leave ourselves on the stack so we come back after the move
2608 break;
2609 }
2610 else
2611 {
2612 m_frame->PopTool( aEvent );
2613 break;
2614 }
2615 }
2616 else if( evt->IsClick( BUT_RIGHT ) )
2617 {
2618 if( !started )
2620
2621 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
2622 }
2623 // events that lock in nodes
2624 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT )
2625 || evt->IsAction( &SCH_ACTIONS::closeOutline ) )
2626 {
2627 // Check if it is double click / closing line (so we have to finish the zone)
2628 const bool endPolygon = evt->IsDblClick( BUT_LEFT )
2629 || evt->IsAction( &SCH_ACTIONS::closeOutline )
2630 || polyGeomMgr.NewPointClosesOutline( cursorPos );
2631
2632 if( endPolygon )
2633 {
2634 polyGeomMgr.SetFinished();
2635 polyGeomMgr.Reset();
2636
2637 started = false;
2638 getViewControls()->SetAutoPan( false );
2639 getViewControls()->CaptureCursor( false );
2640 }
2641 // adding a corner
2642 else if( polyGeomMgr.AddPoint( cursorPos ) )
2643 {
2644 if( !started )
2645 {
2646 started = true;
2647
2648 getViewControls()->SetAutoPan( true );
2649 getViewControls()->CaptureCursor( true );
2650 }
2651 }
2652 }
2653 else if( started
2654 && ( evt->IsAction( &SCH_ACTIONS::deleteLastPoint )
2655 || evt->IsAction( &ACTIONS::doDelete )
2656 || evt->IsAction( &ACTIONS::undo ) ) )
2657 {
2658 if( std::optional<VECTOR2I> last = polyGeomMgr.DeleteLastCorner() )
2659 {
2660 cursorPos = last.value();
2661 getViewControls()->WarpMouseCursor( cursorPos, true );
2662 getViewControls()->ForceCursorPosition( true, cursorPos );
2663 polyGeomMgr.SetCursorPosition( cursorPos );
2664 }
2665 else
2666 {
2667 cleanup();
2668 }
2669 }
2670 else if( started && ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) )
2671 {
2672 polyGeomMgr.SetCursorPosition( cursorPos );
2673 }
2674 else
2675 {
2676 evt->SetPassEvent();
2677 }
2678
2679 } // end while
2680
2681 getViewControls()->SetAutoPan( false );
2682 getViewControls()->CaptureCursor( false );
2683 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2684 return 0;
2685}
2686
2687
2689{
2690 SCHEMATIC* schematic = getModel<SCHEMATIC>();
2691 SCH_TABLE* table = nullptr;
2692
2693 if( m_inDrawingTool )
2694 return 0;
2695
2697
2700 VECTOR2I cursorPos;
2701
2702 // We might be running as the same shape in another co-routine. Make sure that one
2703 // gets whacked.
2705
2707
2708 m_frame->PushTool( aEvent );
2709
2710 auto setCursor =
2711 [&]()
2712 {
2713 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
2714 };
2715
2716 auto cleanup =
2717 [&] ()
2718 {
2721 delete table;
2722 table = nullptr;
2723 };
2724
2725 Activate();
2726
2727 // Must be done after Activate() so that it gets set into the correct context
2728 getViewControls()->ShowCursor( true );
2729
2730 // Set initial cursor
2731 setCursor();
2732
2733 if( aEvent.HasPosition() )
2734 m_toolMgr->PrimeTool( aEvent.Position() );
2735
2736 // Main loop: keep receiving events
2737 while( TOOL_EVENT* evt = Wait() )
2738 {
2739 setCursor();
2740 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
2741 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
2742
2743 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
2744 controls->ForceCursorPosition( true, cursorPos );
2745
2746 // The tool hotkey is interpreted as a click when drawing
2747 bool isSyntheticClick = table
2748 && evt->IsActivate()
2749 && evt->HasPosition()
2750 && evt->Matches( aEvent );
2751
2752 if( evt->IsCancelInteractive() || ( table && evt->IsAction( &ACTIONS::undo ) ) )
2753 {
2754 if( table )
2755 {
2756 cleanup();
2757 }
2758 else
2759 {
2760 m_frame->PopTool( aEvent );
2761 break;
2762 }
2763 }
2764 else if( evt->IsActivate() && !isSyntheticClick )
2765 {
2766 if( table && evt->IsMoveTool() )
2767 {
2768 // we're already drawing our own item; ignore the move tool
2769 evt->SetPassEvent( false );
2770 continue;
2771 }
2772
2773 if( table )
2774 cleanup();
2775
2776 if( evt->IsPointEditor() )
2777 {
2778 // don't exit (the point editor runs in the background)
2779 }
2780 else if( evt->IsMoveTool() )
2781 {
2782 // leave ourselves on the stack so we come back after the move
2783 break;
2784 }
2785 else
2786 {
2787 m_frame->PopTool( aEvent );
2788 break;
2789 }
2790 }
2791 else if( evt->IsClick( BUT_LEFT ) && !table )
2792 {
2794
2795 table = new SCH_TABLE( 0 );
2796 table->SetColCount( 1 );
2797
2798 SCH_TABLECELL* tableCell = new SCH_TABLECELL();
2799 int defaultTextSize = schematic->Settings().m_DefaultTextSize;
2800
2801 tableCell->SetTextSize( VECTOR2I( defaultTextSize, defaultTextSize ) );
2802 table->AddCell( tableCell );
2803
2804 table->SetParent( schematic );
2805 table->SetFlags( IS_NEW );
2806 table->SetPosition( cursorPos );
2807
2809 m_view->AddToPreview( table->Clone() );
2810 }
2811 else if( table && ( evt->IsClick( BUT_LEFT )
2812 || evt->IsDblClick( BUT_LEFT )
2813 || isSyntheticClick
2814 || evt->IsAction( &SCH_ACTIONS::finishInteractive ) ) )
2815 {
2816 table->ClearEditFlags();
2817 table->SetFlags( IS_NEW );
2818 table->Normalize();
2819
2821
2822 // QuasiModal required for Scintilla auto-complete
2823 if( dlg.ShowQuasiModal() == wxID_OK )
2824 {
2825 SCH_COMMIT commit( m_toolMgr );
2826 commit.Add( table, m_frame->GetScreen() );
2827 commit.Push( _( "Draw Table" ) );
2828
2831 }
2832 else
2833 {
2834 delete table;
2835 }
2836
2837 table = nullptr;
2839 }
2840 else if( table && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
2841 {
2842 VECTOR2I gridSize = grid.GetGridSize( grid.GetItemGrid( table ) );
2843 int fontSize = schematic->Settings().m_DefaultTextSize;
2844 VECTOR2I origin( table->GetPosition() );
2845 VECTOR2I requestedSize( cursorPos - origin );
2846
2847 int colCount = std::max( 1, requestedSize.x / ( fontSize * 15 ) );
2848 int rowCount = std::max( 1, requestedSize.y / ( fontSize * 2 ) );
2849
2850 VECTOR2I cellSize( std::max( gridSize.x * 5, requestedSize.x / colCount ),
2851 std::max( gridSize.y * 2, requestedSize.y / rowCount ) );
2852
2853 cellSize.x = KiROUND( (double) cellSize.x / gridSize.x ) * gridSize.x;
2854 cellSize.y = KiROUND( (double) cellSize.y / gridSize.y ) * gridSize.y;
2855
2856 table->ClearCells();
2857 table->SetColCount( colCount );
2858
2859 for( int col = 0; col < colCount; ++col )
2860 table->SetColWidth( col, cellSize.x );
2861
2862 for( int row = 0; row < rowCount; ++row )
2863 {
2864 table->SetRowHeight( row, cellSize.y );
2865
2866 for( int col = 0; col < colCount; ++col )
2867 {
2868 SCH_TABLECELL* cell = new SCH_TABLECELL();
2869 int defaultTextSize = schematic->Settings().m_DefaultTextSize;
2870
2871 cell->SetTextSize( VECTOR2I( defaultTextSize, defaultTextSize ) );
2872 cell->SetPosition( origin + VECTOR2I( col * cellSize.x, row * cellSize.y ) );
2873 cell->SetEnd( cell->GetPosition() + cellSize );
2874 table->AddCell( cell );
2875 }
2876 }
2877
2879 m_view->AddToPreview( table->Clone() );
2881 }
2882 else if( evt->IsDblClick( BUT_LEFT ) && !table )
2883 {
2885 }
2886 else if( evt->IsClick( BUT_RIGHT ) )
2887 {
2888 // Warp after context menu only if dragging...
2889 if( !table )
2891
2892 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
2893 }
2894 else if( table && evt->IsAction( &ACTIONS::redo ) )
2895 {
2896 wxBell();
2897 }
2898 else
2899 {
2900 evt->SetPassEvent();
2901 }
2902
2903 // Enable autopanning and cursor capture only when there is a shape being drawn
2904 getViewControls()->SetAutoPan( table != nullptr );
2905 getViewControls()->CaptureCursor( table != nullptr );
2906 }
2907
2908 getViewControls()->SetAutoPan( false );
2909 getViewControls()->CaptureCursor( false );
2910 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2911 return 0;
2912}
2913
2914
2916{
2917 bool isDrawSheetCopy = aEvent.IsAction( &SCH_ACTIONS::drawSheetFromFile );
2918 bool isDrawSheetFromDesignBlock = aEvent.IsAction( &SCH_ACTIONS::drawSheetFromDesignBlock );
2919
2920 DESIGN_BLOCK* designBlock = nullptr;
2921 SCH_SHEET* sheet = nullptr;
2922 wxString filename;
2923
2924 if( isDrawSheetCopy )
2925 {
2926 wxString* ptr = aEvent.Parameter<wxString*>();
2927 wxCHECK( ptr, 0 );
2928
2929 // We own the string if we're importing a sheet
2930 filename = *ptr;
2931 delete ptr;
2932 }
2933 else if( isDrawSheetFromDesignBlock )
2934 {
2935 designBlock = aEvent.Parameter<DESIGN_BLOCK*>();
2936 wxCHECK( designBlock, 0 );
2937 filename = designBlock->GetSchematicFile();
2938 }
2939
2940 if( ( isDrawSheetCopy || isDrawSheetFromDesignBlock ) && !wxFileExists( filename ) )
2941 {
2942 wxMessageBox( wxString::Format( _( "File '%s' does not exist." ), filename ) );
2943 return 0;
2944 }
2945
2946 if( m_inDrawingTool )
2947 return 0;
2948
2950
2952 SCHEMATIC_SETTINGS& schSettings = m_frame->Schematic().Settings();
2955 VECTOR2I cursorPos;
2956
2958
2959 m_frame->PushTool( aEvent );
2960
2961 auto setCursor =
2962 [&]()
2963 {
2964 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
2965 };
2966
2967 auto cleanup =
2968 [&] ()
2969 {
2972 delete sheet;
2973 sheet = nullptr;
2974 };
2975
2976 Activate();
2977
2978 // Must be done after Activate() so that it gets set into the correct context
2979 getViewControls()->ShowCursor( true );
2980
2981 // Set initial cursor
2982 setCursor();
2983
2984 if( aEvent.HasPosition() && !( isDrawSheetCopy || isDrawSheetFromDesignBlock ) )
2985 m_toolMgr->PrimeTool( aEvent.Position() );
2986
2987 // Main loop: keep receiving events
2988 while( TOOL_EVENT* evt = Wait() )
2989 {
2990 setCursor();
2991 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
2992 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
2993
2994 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
2995 controls->ForceCursorPosition( true, cursorPos );
2996
2997 // The tool hotkey is interpreted as a click when drawing
2998 bool isSyntheticClick = sheet && evt->IsActivate() && evt->HasPosition()
2999 && evt->Matches( aEvent );
3000
3001 if( evt->IsCancelInteractive() || ( sheet && evt->IsAction( &ACTIONS::undo ) ) )
3002 {
3004
3005 if( sheet )
3006 {
3007 cleanup();
3008 }
3009 else
3010 {
3011 m_frame->PopTool( aEvent );
3012 break;
3013 }
3014 }
3015 else if( evt->IsActivate() && !isSyntheticClick )
3016 {
3017 if( sheet && evt->IsMoveTool() )
3018 {
3019 // we're already drawing our own item; ignore the move tool
3020 evt->SetPassEvent( false );
3021 continue;
3022 }
3023
3024 if( sheet )
3025 {
3026 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel sheet creation." ) );
3027 evt->SetPassEvent( false );
3028 continue;
3029 }
3030
3031 if( evt->IsPointEditor() )
3032 {
3033 // don't exit (the point editor runs in the background)
3034 }
3035 else if( evt->IsMoveTool() )
3036 {
3037 // leave ourselves on the stack so we come back after the move
3038 break;
3039 }
3040 else
3041 {
3042 m_frame->PopTool( aEvent );
3043 break;
3044 }
3045 }
3046 else if( !sheet && ( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) ) )
3047 {
3049
3050 if( selection.Size() == 1
3051 && selection.Front()->Type() == SCH_SHEET_T
3052 && selection.Front()->GetBoundingBox().Contains( cursorPos ) )
3053 {
3054 if( evt->IsClick( BUT_LEFT ) )
3055 {
3056 // sheet already selected
3057 continue;
3058 }
3059 else if( evt->IsDblClick( BUT_LEFT ) )
3060 {
3062 m_frame->PopTool( aEvent );
3063 break;
3064 }
3065 }
3066
3068
3069 sheet = new SCH_SHEET( m_frame->GetCurrentSheet().Last(), cursorPos );
3070 sheet->SetScreen( nullptr );
3071
3072 if( isDrawSheetCopy )
3073 {
3074 wxFileName fn( filename );
3075
3076 sheet->GetField( FIELD_T::SHEET_NAME )->SetText( fn.GetName() );
3077 sheet->GetField( FIELD_T::SHEET_FILENAME )->SetText( fn.GetName() + wxT( "." ) + FILEEXT::KiCadSchematicFileExtension );
3078 }
3079 else if( isDrawSheetFromDesignBlock )
3080 {
3081 wxFileName fn( filename );
3082
3083 sheet->GetField( FIELD_T::SHEET_NAME )->SetText( designBlock->GetLibId().GetLibItemName() );
3084 sheet->GetField( FIELD_T::SHEET_FILENAME )->SetText( fn.GetName() + wxT( "." ) + FILEEXT::KiCadSchematicFileExtension );
3085
3086 std::vector<SCH_FIELD>& sheetFields = sheet->GetFields();
3087
3088 // Copy default fields into the sheet
3089 for( const auto& [fieldName, fieldValue] : designBlock->GetFields() )
3090 {
3091 sheetFields.emplace_back( sheet, FIELD_T::USER, fieldName );
3092 sheetFields.back().SetText( fieldValue );
3093 sheetFields.back().SetVisible( false );
3094 }
3095 }
3096 else
3097 {
3098 sheet->GetField( FIELD_T::SHEET_NAME )->SetText( wxT( "Untitled Sheet" ) );
3099 sheet->GetField( FIELD_T::SHEET_FILENAME )->SetText( wxString::Format( wxT( "untitled.%s" ), FILEEXT::KiCadSchematicFileExtension ) );
3100 }
3101
3102 sheet->SetFlags( IS_NEW | IS_MOVING );
3106 sizeSheet( sheet, cursorPos );
3107
3108 SCH_SHEET_LIST hierarchy = m_frame->Schematic().Hierarchy();
3110 instance.push_back( sheet );
3111 wxString pageNumber;
3112
3113 // Don't try to be too clever when assigning the next availabe page number. Just use
3114 // the number of sheets plus one.
3115 pageNumber.Printf( wxT( "%d" ), static_cast<int>( hierarchy.size() ) + 1 );
3116 instance.SetPageNumber( pageNumber );
3117
3119 m_view->AddToPreview( sheet->Clone() );
3120 }
3121 else if( sheet && ( evt->IsClick( BUT_LEFT )
3122 || evt->IsDblClick( BUT_LEFT )
3123 || isSyntheticClick
3124 || evt->IsAction( &ACTIONS::finishInteractive ) ) )
3125 {
3126 getViewControls()->SetAutoPan( false );
3127 getViewControls()->CaptureCursor( false );
3128
3129 if( m_frame->EditSheetProperties( static_cast<SCH_SHEET*>( sheet ),
3130 &m_frame->GetCurrentSheet(), nullptr, nullptr,
3131 nullptr, &filename ) )
3132 {
3134
3136
3137 // Use the commit we were provided or make our own
3138 SCH_COMMIT tempCommit = SCH_COMMIT( m_toolMgr );
3139 SCH_COMMIT& c = evt->Commit() ? *( (SCH_COMMIT*) evt->Commit() ) : tempCommit;
3140
3141 // We need to manually add the sheet to the screen otherwise annotation will not be able to find
3142 // the sheet and its symbols to annotate.
3143 m_frame->AddToScreen( sheet );
3144 c.Added( sheet, m_frame->GetScreen() );
3145
3146 // This convoluted logic means we always annotate unless we are drawing a copy/design block
3147 // and the user has explicitly requested we keep the annotations via checkbox
3149
3150 if( annotate.automatic
3151 && !( ( isDrawSheetCopy || isDrawSheetFromDesignBlock )
3153 {
3154 // Annotation will remove this from selection, but we add it back later
3155 m_selectionTool->AddItemToSel( sheet );
3156
3157 NULL_REPORTER reporter;
3160 (ANNOTATE_ALGO_T) annotate.method, true /* recursive */,
3161 schSettings.m_AnnotateStartNum, true, false, reporter );
3162 }
3163
3164 c.Push( isDrawSheetCopy ? "Import Sheet Copy" : "Draw Sheet" );
3165
3166 m_selectionTool->AddItemToSel( sheet );
3167 }
3168 else
3169 {
3171 delete sheet;
3172 }
3173
3174 sheet = nullptr;
3175 }
3176 else if( evt->IsAction( &ACTIONS::duplicate )
3177 || evt->IsAction( &SCH_ACTIONS::repeatDrawItem ) )
3178 {
3179 if( sheet )
3180 {
3181 // This doesn't really make sense; we'll just end up dragging a stack of
3182 // objects so we ignore the duplicate and just carry on.
3183 wxBell();
3184 continue;
3185 }
3186
3187 // Exit. The duplicate will run in its own loop.
3188 m_frame->PopTool( aEvent );
3189 break;
3190 }
3191 else if( sheet && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
3192 {
3193 sizeSheet( sheet, cursorPos );
3195 m_view->AddToPreview( sheet->Clone() );
3196 m_frame->SetMsgPanel( sheet );
3197 }
3198 else if( evt->IsClick( BUT_RIGHT ) )
3199 {
3200 // Warp after context menu only if dragging...
3201 if( !sheet )
3203
3204 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
3205 }
3206 else if( sheet && evt->IsAction( &ACTIONS::redo ) )
3207 {
3208 wxBell();
3209 }
3210 else
3211 {
3212 evt->SetPassEvent();
3213 }
3214
3215 // Enable autopanning and cursor capture only when there is a sheet to be placed
3216 getViewControls()->SetAutoPan( sheet != nullptr );
3217 getViewControls()->CaptureCursor( sheet != nullptr );
3218 }
3219
3220 getViewControls()->SetAutoPan( false );
3221 getViewControls()->CaptureCursor( false );
3222 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
3223
3224 return 0;
3225}
3226
3227
3229{
3230 VECTOR2I pos = aSheet->GetPosition();
3231 VECTOR2I size = aPos - pos;
3232
3233 size.x = std::max( size.x, schIUScale.MilsToIU( MIN_SHEET_WIDTH ) );
3234 size.y = std::max( size.y, schIUScale.MilsToIU( MIN_SHEET_HEIGHT ) );
3235
3237 aSheet->Resize( VECTOR2I( grid.x - pos.x, grid.y - pos.y ) );
3238}
3239
3240
3241int SCH_DRAWING_TOOLS::doSyncSheetsPins( std::list<SCH_SHEET_PATH> sheetPaths )
3242{
3243 if( !sheetPaths.size() )
3244 {
3245 return 0;
3246 }
3247
3248 m_dialogSyncSheetPin = std::make_unique<DIALOG_SYNC_SHEET_PINS>(
3249 m_frame, std::move( sheetPaths ),
3250 std::make_shared<SHEET_SYNCHRONIZATION_AGENT>(
3251 [&]( EDA_ITEM* aItem, SCH_SHEET_PATH aPath,
3253 {
3254 SCH_COMMIT commit( m_toolMgr );
3255
3256 if( auto pin = dynamic_cast<SCH_SHEET_PIN*>( aItem ) )
3257 {
3258 commit.Modify( pin->GetParent(), aPath.LastScreen() );
3259 aModify();
3260 commit.Push( _( "Modify sheet pin" ) );
3261 }
3262 else
3263 {
3264 commit.Modify( aItem, aPath.LastScreen() );
3265 aModify();
3266 commit.Push( _( "Modify schematic item" ) );
3267 }
3268
3269 updateItem( aItem, true );
3270 m_frame->OnModify();
3271 },
3272 [&]( EDA_ITEM* aItem, SCH_SHEET_PATH aPath )
3273 {
3275 SCH_ACTIONS::changeSheet, &aPath );
3277 selectionTool->UnbrightenItem( aItem );
3278 selectionTool->AddItemToSel( aItem, true );
3280 },
3281 [&]( SCH_SHEET* aItem, SCH_SHEET_PATH aPath,
3283 std::set<EDA_ITEM*> aTemplates )
3284 {
3285 switch( aOp )
3286 {
3288 {
3289 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
3290 m_dialogSyncSheetPin->Hide();
3291 m_dialogSyncSheetPin->PreparePlacementTemplate(
3293 aTemplates );
3295 SCH_ACTIONS::changeSheet, &aPath );
3297 break;
3298 }
3300 {
3301 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
3302 m_dialogSyncSheetPin->Hide();
3303 m_dialogSyncSheetPin->PreparePlacementTemplate(
3305 aTemplates );
3307 SCH_ACTIONS::changeSheet, &aPath );
3308 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->SyncSelection( {}, nullptr,
3309 { sheet } );
3311 break;
3312 }
3313 }
3314 },
3315 m_toolMgr, m_frame ) );
3316 m_dialogSyncSheetPin->Show( true );
3317 return 0;
3318}
3319
3320
3322{
3323 SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( m_selectionTool->GetSelection().Front() );
3324
3325 if( !sheet )
3326 {
3327 VECTOR2I cursorPos = getViewControls()->GetMousePosition();
3328
3329 if( EDA_ITEM* i = nullptr; static_cast<void>(m_selectionTool->SelectPoint( cursorPos, { SCH_SHEET_T }, &i ) ) , i != nullptr )
3330 {
3331 sheet = dynamic_cast<SCH_SHEET*>( i );
3332 }
3333 }
3334
3335 if ( sheet )
3336 {
3338 current.push_back( sheet );
3339 return doSyncSheetsPins( { current } );
3340 }
3341
3342 return 0;
3343}
3344
3345
3347{
3348 if( m_inDrawingTool )
3349 return 0;
3350
3352
3353 SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( m_selectionTool->GetSelection().Front() );
3354 std::vector<SCH_HIERLABEL*> labels = importHierLabels( sheet );
3355
3356 if( labels.empty() )
3357 {
3358 m_frame->PushTool( aEvent );
3359 m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( m_frame );
3360 m_statusPopup->SetText( _( "No new hierarchical labels found." ) );
3361 m_statusPopup->Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, 20 ) );
3362 m_statusPopup->PopupFor( 2000 );
3363 m_frame->PopTool( aEvent );
3366 return 0;
3367 }
3368
3370
3371 SCH_COMMIT commit( m_toolMgr );
3372 BOX2I boundingBox = sheet->GetBoundingBox();
3373 VECTOR2I cursorPos = boundingBox.GetPosition();
3374 SCH_ITEM* lastPlacedLabel = nullptr;
3375
3376 auto calculatePositionForLabel = [&]( const SCH_ITEM* lastLabel,
3377 const SCH_HIERLABEL* currentLabel ) -> VECTOR2I
3378 {
3379 if( !lastLabel )
3380 return cursorPos;
3381
3382 int lastX = lastLabel->GetPosition().x;
3383 int lastY = lastLabel->GetPosition().y;
3384 int lastWidth = lastLabel->GetBoundingBox().GetWidth();
3385 int lastHeight = lastLabel->GetBoundingBox().GetHeight();
3386
3387 int currentWidth = currentLabel->GetBoundingBox().GetWidth();
3388 int currentHeight = currentLabel->GetBoundingBox().GetHeight();
3389
3390 // If there is enough space, place the label to the right of the last placed label
3391 if( ( lastX + lastWidth + currentWidth )
3393 return { lastX + lastWidth, lastY };
3394
3395 // If not enough space to the right, move to the next row if vertical space allows
3396 if( ( lastY + lastHeight + currentHeight )
3398 return { boundingBox.GetPosition().x, lastY + lastHeight };
3399
3400 return cursorPos;
3401 };
3402
3403 for( SCH_HIERLABEL* label : labels )
3404 {
3405 if( !lastPlacedLabel )
3406 {
3407 std::vector<SCH_SHEET_PIN*> existingPins = sheet->GetPins();
3408
3409 if( !existingPins.empty() )
3410 {
3411 std::sort( existingPins.begin(), existingPins.end(),
3412 []( const SCH_ITEM* a, const SCH_ITEM* b )
3413 {
3414 return ( a->GetPosition().x < b->GetPosition().x )
3415 || ( a->GetPosition().x == b->GetPosition().x
3416 && a->GetPosition().y < b->GetPosition().y );
3417 } );
3418
3419 lastPlacedLabel = existingPins.back();
3420 }
3421 }
3422
3423 cursorPos = calculatePositionForLabel( lastPlacedLabel, label );
3424 SCH_ITEM* item = createNewSheetPinFromLabel( sheet, cursorPos, label );
3425
3426 if( item )
3427 {
3428 item->SetFlags( IS_NEW | IS_MOVING );
3429 item->AutoplaceFields( nullptr, AUTOPLACE_AUTO );
3430 item->ClearFlags( IS_MOVING );
3431
3432 if( item->IsConnectable() )
3434
3435 commit.Modify( sheet, m_frame->GetScreen() );
3436
3437 sheet->AddPin( static_cast<SCH_SHEET_PIN*>( item ) );
3439
3440 commit.Push( _( "Add Sheet Pin" ) );
3441
3442 lastPlacedLabel = item;
3443 }
3444 }
3445
3446 return 0;
3447}
3448
3449
3451{
3452 static const std::function<void( std::list<SCH_SHEET_PATH>&, SCH_SCREEN*,
3453 std::set<SCH_SCREEN*>&, SCH_SHEET_PATH const& )>
3454 getSheetChildren = []( std::list<SCH_SHEET_PATH>& aPaths, SCH_SCREEN* aScene,
3455 std::set<SCH_SCREEN*>& aVisited, SCH_SHEET_PATH const& aCurPath )
3456 {
3457 if( ! aScene || aVisited.find(aScene) != aVisited.end() )
3458 return ;
3459
3460 std::vector<SCH_ITEM*> sheetChildren;
3461 aScene->GetSheets( &sheetChildren );
3462 aVisited.insert( aScene );
3463
3464 for( SCH_ITEM* child : sheetChildren )
3465 {
3466 SCH_SHEET_PATH cp = aCurPath;
3467 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( child );
3468 cp.push_back( sheet );
3469 aPaths.push_back( cp );
3470 getSheetChildren( aPaths, sheet->GetScreen(), aVisited, cp );
3471 }
3472 };
3473
3474 std::list<SCH_SHEET_PATH> sheetPaths;
3475 std::set<SCH_SCREEN*> visited;
3476 SCH_SHEET_PATH current;
3477 current.push_back( &m_frame->Schematic().Root() );
3478 getSheetChildren( sheetPaths, m_frame->Schematic().Root().GetScreen(), visited, current );
3479
3480 if( sheetPaths.size() == 0 )
3481 {
3482 m_frame->ShowInfoBarMsg( _( "No sub schematic found in the current project" ) );
3483 return 0;
3484 }
3485
3486
3487 return doSyncSheetsPins( std::move( sheetPaths ) );
3488}
3489
3491{
3492 if( !aSheet->GetScreen() )
3493 return nullptr;
3494
3495 std::vector<SCH_HIERLABEL*> labels;
3496 for( EDA_ITEM* item : aSheet->GetScreen()->Items().OfType( SCH_HIER_LABEL_T ) )
3497 {
3498 SCH_HIERLABEL* label = static_cast<SCH_HIERLABEL*>( item );
3499 labels.push_back( label );
3500 }
3501
3502 std::sort( labels.begin(), labels.end(),
3503 []( const SCH_HIERLABEL* label1, const SCH_HIERLABEL* label2 )
3504 {
3505 return StrNumCmp( label1->GetText(), label2->GetText(), true ) < 0;
3506 } );
3507
3508 for( SCH_HIERLABEL* label : labels )
3509 {
3510 if( !aSheet->HasPin( label->GetText() ) )
3511 return label;
3512 }
3513
3514 return nullptr;
3515}
3516
3517
3518std::vector<SCH_HIERLABEL*> SCH_DRAWING_TOOLS::importHierLabels( SCH_SHEET* aSheet )
3519{
3520 if( !aSheet->GetScreen() )
3521 return {};
3522
3523 std::vector<SCH_HIERLABEL*> labels;
3524
3525 for( EDA_ITEM* item : aSheet->GetScreen()->Items().OfType( SCH_HIER_LABEL_T ) )
3526 {
3527 SCH_HIERLABEL* label = static_cast<SCH_HIERLABEL*>( item );
3528
3529 if( !aSheet->HasPin( label->GetText() ) )
3530 {
3531 labels.push_back( label );
3532 }
3533 }
3534
3535 return labels;
3536}
3537
3538
3540{
3541 // clang-format off
3571 // clang-format on
3572}
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:225
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
PANEL_DESIGN_BLOCK_CHOOSER m_DesignBlockChooserPanel
Definition: app_settings.h:197
constexpr const Vec & GetPosition() const
Definition: box2.h:211
constexpr size_type GetWidth() const
Definition: box2.h:214
constexpr size_type GetHeight() const
Definition: box2.h:215
constexpr bool Contains(const Vec &aPoint) const
Definition: box2.h:168
constexpr const SizeVec & GetSize() const
Definition: box2.h:206
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
DESIGN_BLOCK * GetDesignBlock(const LIB_ID &aLibId, bool aUseCacheLib, bool aShowErrorMsg)
Load design block from design block library table.
const wxString & GetSchematicFile() const
Definition: design_block.h:45
const LIB_ID & GetLibId() const
Definition: design_block.h:37
const nlohmann::ordered_map< wxString, wxString > & GetFields() const
Definition: design_block.h:56
std::list< std::unique_ptr< EDA_ITEM > > & GetImportedItems()
void SetLabelList(std::list< std::unique_ptr< SCH_LABEL_BASE > > *aLabelList)
FIELDS_GRID_TABLE * GetFieldsGridTable()
int ShowQuasiModal()
int ShowModal() override
void ShowInfoBarMsg(const wxString &aMsg, bool aShowCloseButton=false)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an info icon on the left of...
void ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false, WX_INFOBAR::MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an error icon on the left o...
WX_INFOBAR * GetInfoBar()
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
VECTOR2I GetNearestGridPosition(const VECTOR2I &aPosition) const
Return the nearest aGridSize location to aPosition.
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:95
virtual VECTOR2I GetPosition() const
Definition: eda_item.h:248
virtual void ClearEditFlags()
Definition: eda_item.h:145
virtual void SetPosition(const VECTOR2I &aPos)
Definition: eda_item.h:249
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:81
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:137
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:131
const KIID m_Uuid
Definition: eda_item.h:494
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:107
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:133
virtual bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const
Compare the item against the search criteria in aSearchData.
Definition: eda_item.h:382
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:110
virtual wxString GetFriendlyName() const
Definition: eda_item.cpp:371
virtual EDA_ITEM * Clone() const
Create a duplicate of this item with linked list members set to NULL.
Definition: eda_item.cpp:89
FILL_T GetFillMode() const
Definition: eda_shape.h:142
void SetFillColor(const COLOR4D &aColor)
Definition: eda_shape.h:153
COLOR4D GetFillColor() const
Definition: eda_shape.h:152
void SetEnd(const VECTOR2I &aEnd)
Definition: eda_shape.h:219
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:526
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:410
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition: eda_text.h:187
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:379
void SetBold(bool aBold)
Set the text to be bold - this will also update the font if needed.
Definition: eda_text.cpp:328
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:270
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:292
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
Definition: eda_text.cpp:300
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition: eda_text.cpp:402
PANEL_ANNOTATE m_AnnotatePanel
PANEL_SYM_CHOOSER m_SymChooserPanel
AUTOPLACE_FIELDS m_AutoplaceFields
EE_TYPE Overlapping(const BOX2I &aRect) const
Definition: sch_rtree.h:246
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:241
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:119
const UTF8 & GetLibItemName() const
Definition: lib_id.h:102
Define a library symbol object.
Definition: lib_symbol.h:85
wxString GetDescription() const override
Definition: lib_symbol.h:170
const LIB_ID & GetLibId() const override
Definition: lib_symbol.h:155
wxString GetKeyWords() const override
Definition: lib_symbol.h:183
void SetGlobalPower()
Definition: lib_symbol.cpp:473
void SetDescription(const wxString &aDescription)
Gets the Description field text value *‍/.
Definition: lib_symbol.h:164
void SetKeyWords(const wxString &aKeyWords)
Definition: lib_symbol.h:181
bool IsLocalPower() const override
Definition: lib_symbol.cpp:421
void SetLocalPower()
Definition: lib_symbol.cpp:437
bool IsGlobalPower() const override
Definition: lib_symbol.cpp:451
A singleton reporter that reports to nowhere.
Definition: reporter.h:204
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition: pgm_base.cpp:687
Class that handles the drawing of a polygon, including management of last corner deletion and drawing...
bool AddPoint(const VECTOR2I &aPt)
Lock in a polygon point.
@ DIRECT
Unconstrained point-to-point.
void SetCursorPosition(const VECTOR2I &aPos)
Set the current cursor position.
bool NewPointClosesOutline(const VECTOR2I &aPt) const
std::optional< VECTOR2I > DeleteLastCorner()
Remove the last-added point from the polygon.
void SetFinished()
Mark the polygon finished and update the client.
void SetLeaderMode(LEADER_MODE aMode)
Set the leader mode to use when calculating the leader/returner lines.
void Reset()
Clear the manager state and start again.
static SYMBOL_LIB_TABLE * SchSymbolLibTable(PROJECT *aProject)
Accessor for project symbol library table.
static SYMBOL_LIBS * SchLibs(PROJECT *aProject)
These are all prefaced with "Sch".
Definition: project_sch.cpp:90
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition: project.cpp:140
An adjunct helper to the DRAWING_TOOL interactive tool, which handles incoming geometry changes from ...
These are loaded from Eeschema settings but then overwritten by the project settings.
Holds all the data relating to one schematic.
Definition: schematic.h:69
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:306
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
Definition: schematic.cpp:208
SCH_SHEET & Root() const
Definition: schematic.h:117
static TOOL_ACTION rotateCCW
Definition: sch_actions.h:133
static TOOL_ACTION placeClassLabel
Definition: sch_actions.h:91
static TOOL_ACTION placeSheetPin
Definition: sch_actions.h:97
static TOOL_ACTION placeNextSymbolUnit
Definition: sch_actions.h:81
static TOOL_ACTION mirrorV
Definition: sch_actions.h:134
static TOOL_ACTION drawSheetFromFile
Definition: sch_actions.h:95
static TOOL_ACTION clearSelection
Clears the current selection.
Definition: sch_actions.h:57
static TOOL_ACTION placeGlobalLabel
Definition: sch_actions.h:92
static TOOL_ACTION drawTextBox
Definition: sch_actions.h:105
static TOOL_ACTION syncAllSheetsPins
Definition: sch_actions.h:103
static TOOL_ACTION closeOutline
Definition: sch_actions.h:117
static TOOL_ACTION drawArc
Definition: sch_actions.h:109
static TOOL_ACTION drawSheet
Definition: sch_actions.h:94
static TOOL_ACTION properties
Definition: sch_actions.h:137
static TOOL_ACTION leaveSheet
Definition: sch_actions.h:232
static TOOL_ACTION autoplaceAllSheetPins
Definition: sch_actions.h:98
static TOOL_ACTION drawRectangle
Definition: sch_actions.h:107
static TOOL_ACTION placeHierLabel
Definition: sch_actions.h:93
static TOOL_ACTION placeLabel
Definition: sch_actions.h:90
static TOOL_ACTION drawCircle
Definition: sch_actions.h:108
static TOOL_ACTION importGraphics
Definition: sch_actions.h:268
static TOOL_ACTION placeBusWireEntry
Definition: sch_actions.h:89
static TOOL_ACTION drawBezier
Definition: sch_actions.h:110
static TOOL_ACTION rotateCW
Definition: sch_actions.h:132
static TOOL_ACTION importSheet
Definition: sch_actions.h:99
static TOOL_ACTION placeJunction
Definition: sch_actions.h:88
static TOOL_ACTION drawRuleArea
Definition: sch_actions.h:115
static TOOL_ACTION placeSymbol
Definition: sch_actions.h:80
static TOOL_ACTION placeImage
Definition: sch_actions.h:112
static TOOL_ACTION deleteLastPoint
Definition: sch_actions.h:116
static TOOL_ACTION drawSheetFromDesignBlock
Definition: sch_actions.h:96
static TOOL_ACTION mirrorH
Definition: sch_actions.h:135
static TOOL_ACTION placeDesignBlock
Definition: sch_actions.h:83
static TOOL_ACTION drawTable
Definition: sch_actions.h:106
static TOOL_ACTION placeSchematicText
Definition: sch_actions.h:104
static TOOL_ACTION changeSheet
Definition: sch_actions.h:230
static TOOL_ACTION enterSheet
Definition: sch_actions.h:231
static TOOL_ACTION repeatDrawItem
Definition: sch_actions.h:131
static TOOL_ACTION addItemsToSel
Selects a list of items (specified as the event parameter)
Definition: sch_actions.h:64
static TOOL_ACTION placeNoConnect
Definition: sch_actions.h:87
static TOOL_ACTION move
Definition: sch_actions.h:129
static TOOL_ACTION syncSheetPins
Definition: sch_actions.h:101
static TOOL_ACTION placePower
Definition: sch_actions.h:82
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:435
virtual void Revert() override
Revert the commit by restoring the modified items state.
Definition: sch_commit.cpp:513
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
SCH_TEXT * createNewText(const VECTOR2I &aPosition)
int PlaceNextSymbolUnit(const TOOL_EVENT &aEvent)
int DrawSheet(const TOOL_EVENT &aEvent)
bool createNewLabel(const VECTOR2I &aPosition, int aType, std::list< std::unique_ptr< SCH_LABEL_BASE > > &aLabelList)
SPIN_STYLE m_lastTextOrientation
int SyncSheetsPins(const TOOL_EVENT &aEvent)
STROKE_PARAMS m_lastStroke
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 AutoPlaceAllSheetPins(const TOOL_EVENT &aEvent)
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
std::vector< SCH_HIERLABEL * > importHierLabels(SCH_SHEET *aSheet)
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.
SCH_DESIGN_BLOCK_PANE * GetDesignBlockPane() const
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...
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
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:601
void UpdateHierarchyNavigator(bool aRefreshNetNavigator=true, bool aClear=false)
Update the hierarchy navigation tree and history.
void FlipBodyStyle(SCH_SYMBOL *aSymbol)
Definition: picksymbol.cpp:182
void SetSheetNumberAndCount()
Set the m_ScreenNumber and m_NumberOfScreens members for screens.
void SelectUnit(SCH_SYMBOL *aSymbol, int aUnit)
Definition: picksymbol.cpp:95
void 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.
void SetText(const wxString &aText) override
Definition: sch_field.cpp:1069
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this label.
Definition: sch_label.cpp:1838
void SetSpinStyle(SPIN_STYLE aSpinStyle) override
Definition: sch_label.cpp:2067
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:168
virtual bool IsConnectable() const
Definition: sch_item.h:466
virtual void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo)
Definition: sch_item.h:568
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode)
Definition: sch_item.h:570
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:156
int GetUnit() const
Definition: sch_item.h:240
virtual void SetUnit(int aUnit)
Definition: sch_item.h:239
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:224
bool IsType(const std::vector< KICAD_T > &aScanTypes) const override
Check whether the item is one of the listed types.
Definition: sch_item.h:186
bool AutoRotateOnPlacement() const
autoRotateOnPlacement
Definition: sch_label.cpp:1414
SPIN_STYLE GetSpinStyle() const
Definition: sch_label.cpp:337
void SetShape(LABEL_FLAG_SHAPE aShape)
Definition: sch_label.h:177
LABEL_FLAG_SHAPE GetShape() const
Definition: sch_label.h:176
void SetAutoRotateOnPlacement(bool autoRotate=true)
Definition: sch_label.cpp:1420
std::vector< SCH_FIELD > & GetFields()
Definition: sch_label.h:205
virtual void SetSpinStyle(SPIN_STYLE aSpinStyle)
Definition: sch_label.cpp:302
Tool responsible for drawing/placing items (symbols, wires, buses, labels, etc.)
int AddJunctionsIfNeeded(SCH_COMMIT *aCommit, SCH_SELECTION *aSelection)
Handle the addition of junctions to a selection of objects.
int TrimOverLappingWires(SCH_COMMIT *aCommit, SCH_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:933
VECTOR2I GetEndPoint() const
Definition: sch_line.h:143
VECTOR2I GetStartPoint() const
Definition: sch_line.h:138
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
void SortByReferenceOnly()
Sort the list of references by reference.
void ReannotateByOptions(ANNOTATE_ORDER_T aSortOption, ANNOTATE_ALGO_T aAlgoOption, int aStartNumber, const SCH_REFERENCE_LIST &aAdditionalRefs, bool aStartAtCurrent, SCH_SHEET_LIST *aHierarchy)
Forces reannotation of the provided references.
size_t GetCount() const
void AddItem(const SCH_REFERENCE &aItem)
void UpdateAnnotation()
Update the symbol references for the schematic project (or the current sheet).
A helper to define a symbol's reference designator in a schematic.
bool AlwaysAnnotate() const
Verify the reference should always be automatically annotated.
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition: sch_screen.h:112
SCH_ITEM * GetItem(const VECTOR2I &aPosition, int aAccuracy=0, KICAD_T aType=SCH_LOCATE_ANY_T) const
Check aPosition within a distance of aAccuracy for items of type aFilter.
Definition: sch_screen.cpp:394
bool IsExplicitJunctionAllowed(const VECTOR2I &aPosition) const
Indicate that a junction dot may be placed at the given location.
Definition: sch_screen.cpp:508
SCH_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.
SCH_SELECTION & GetSelection()
void SetPosition(const VECTOR2I &aPos) override
Definition: sch_shape.h:82
void BeginEdit(const VECTOR2I &aStartPoint) override
Begin drawing a symbol library draw item at aPosition.
Definition: sch_shape.h:86
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:89
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:87
void CalcEdit(const VECTOR2I &aPosition) override
Calculate the attributes of an item at aPosition when it is being edited.
Definition: sch_shape.h:88
wxString GetClass() const override
Return the class name.
Definition: sch_shape.h:43
STROKE_PARAMS GetStroke() const override
Definition: sch_shape.h:54
VECTOR2I GetPosition() const override
Definition: sch_shape.h:81
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:47
void SetBorderColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:125
void AddPin(SCH_SHEET_PIN *aSheetPin)
Add aSheetPin to the sheet.
Definition: sch_sheet.cpp:400
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: sch_sheet.cpp:131
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: sch_sheet.cpp:1013
std::vector< SCH_FIELD > & GetFields()
Return a reference to the vector holding the sheet's fields.
Definition: sch_sheet.h:87
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this sheet.
Definition: sch_sheet.cpp:369
void SetBackgroundColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:128
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:116
VECTOR2I GetPosition() const override
Definition: sch_sheet.h:415
bool HasPin(const wxString &aName) const
Check if the sheet already has a sheet pin named aName.
Definition: sch_sheet.cpp:428
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:137
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_sheet.cpp:713
void SetBorderWidth(int aWidth)
Definition: sch_sheet.h:122
void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo) override
Definition: sch_sheet.cpp:637
void Resize(const VECTOR2I &aSize)
Resize this sheet to aSize and adjust all of the labels accordingly.
Definition: sch_sheet.cpp:996
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:187
Schematic symbol object.
Definition: sch_symbol.h:75
void ClearAnnotation(const SCH_SHEET_PATH *aSheetPath, bool aResetPrefix)
Clear exiting symbol annotation.
const LIB_ID & GetLibId() const override
Definition: sch_symbol.h:164
bool IsMulti() const override
Definition: sch_symbol.h:266
void SetUnitSelection(const SCH_SHEET_PATH *aSheet, int aUnitSelection)
Set the selected unit of this symbol on one sheet.
Definition: sch_symbol.cpp:755
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
Definition: sch_symbol.cpp:611
A foundation class for a tool operating on a schematic or symbol.
Definition: sch_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 ...
bool Init() override
Init() is called once upon a registration of the tool.
Definition: sch_tool_base.h:64
SCH_SELECTION_TOOL * m_selectionTool
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:515
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: wx_infobar.cpp:190
This file is part of the common library.
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition: eda_angle.h:401
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
Definition: eda_item.h:543
#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
@ ID_POPUP_SCH_SELECT_UNIT
Definition: eeschema_id.h:82
@ ID_POPUP_SCH_SELECT_BASE
Definition: eeschema_id.h:88
@ ID_POPUP_SCH_SELECT_ALT
Definition: eeschema_id.h:89
@ ID_POPUP_SCH_SELECT_UNIT_END
Definition: eeschema_id.h:86
@ LINE_MODE_FREE
GRID_HELPER_GRIDS
Definition: grid_helper.h:42
@ GRID_TEXT
Definition: grid_helper.h:49
@ GRID_GRAPHICS
Definition: grid_helper.h:50
@ GRID_CONNECTABLE
Definition: grid_helper.h:46
static const std::string KiCadSchematicFileExtension
static wxString KiCadSchematicFileWildcard()
@ LAYER_HIERLABEL
Definition: layer_ids.h:446
@ LAYER_GLOBLABEL
Definition: layer_ids.h:445
@ LAYER_NOTES
Definition: layer_ids.h:456
@ LAYER_LOCLABEL
Definition: layer_ids.h:444
@ LAYER_NETCLASS_REFS
Definition: layer_ids.h:453
wxPoint GetMousePosition()
Returns the mouse position in screen coordinates.
Definition: wxgtk/ui.cpp:677
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:1071
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:71
LABEL_FLAG_SHAPE
Definition: sch_label.h:99
@ F_ROUND
Definition: sch_label.h:108
@ L_INPUT
Definition: sch_label.h:100
ANNOTATE_ORDER_T
Schematic annotation order options.
@ ANNOTATE_SELECTION
Annotate the selection.
ANNOTATE_ALGO_T
Schematic annotation type options.
#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.
std::set< int > GetUnplacedUnitsForSymbol(const SCH_SYMBOL &aSym)
Get a list of unplaced (i.e.
BOX2I boundingBox(T aObject, int aLayer)
Used by SHAPE_INDEX to get the bounding box of a generic T object.
Definition: shape_index.h:62
LINE_STYLE
Dashed line types.
Definition: stroke_params.h:46
constexpr int MilsToIU(int mils) const
Definition: base_units.h:93
LIB_ID LibId
Definition: sch_screen.h:80
SCH_SYMBOL * m_Symbol
< Provide a symbol to place
Definition: sch_actions.h:319
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_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.