KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_drawing_tools.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2019-2023 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include "sch_sheet_path.h"
26#include <memory>
27
28#include <kiplatform/ui.h>
29#include <optional>
30#include <project_sch.h>
38#include <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_group.h>
51#include <sch_line.h>
52#include <sch_junction.h>
53#include <sch_bus_entry.h>
54#include <sch_rule_area.h>
55#include <sch_text.h>
56#include <sch_textbox.h>
57#include <sch_table.h>
58#include <sch_tablecell.h>
59#include <sch_sheet.h>
60#include <sch_sheet_pin.h>
61#include <sch_label.h>
62#include <sch_bitmap.h>
63#include <schematic.h>
64#include <sch_commit.h>
65#include <scoped_set_reset.h>
66#include <symbol_library.h>
67#include <eeschema_settings.h>
69#include <dialogs/dialog_text_properties.h>
72#include <dialogs/dialog_table_properties.h>
75#include <string_utils.h>
77#include <wx/filedlg.h>
78#include <wx/msgdlg.h>
79
81 SCH_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.InteractiveDrawing" ),
82 m_lastSheetPinType( LABEL_FLAG_SHAPE::L_INPUT ),
83 m_lastGlobalLabelShape( LABEL_FLAG_SHAPE::L_INPUT ),
84 m_lastNetClassFlagShape( LABEL_FLAG_SHAPE::F_ROUND ),
85 m_lastTextOrientation( SPIN_STYLE::RIGHT ),
86 m_lastTextBold( false ),
87 m_lastTextItalic( false ),
88 m_lastTextAngle( ANGLE_0 ),
89 m_lastTextboxAngle( ANGLE_0 ),
90 m_lastTextHJustify( GR_TEXT_H_ALIGN_CENTER ),
91 m_lastTextVJustify( GR_TEXT_V_ALIGN_CENTER ),
92 m_lastTextboxHJustify( GR_TEXT_H_ALIGN_LEFT ),
93 m_lastTextboxVJustify( GR_TEXT_V_ALIGN_TOP ),
94 m_lastFillStyle( FILL_T::NO_FILL ),
95 m_lastTextboxFillStyle( FILL_T::NO_FILL ),
96 m_lastFillColor( COLOR4D::UNSPECIFIED ),
97 m_lastTextboxFillColor( COLOR4D::UNSPECIFIED ),
98 m_lastStroke( 0, LINE_STYLE::DEFAULT, COLOR4D::UNSPECIFIED ),
99 m_lastTextboxStroke( 0, LINE_STYLE::DEFAULT, COLOR4D::UNSPECIFIED ),
100 m_mruPath( wxEmptyString ),
101 m_lastAutoLabelRotateOnPlacement( false ),
102 m_drawingRuleArea( false ),
103 m_inDrawingTool( false )
104{
105}
106
107
109{
111
112 auto belowRootSheetCondition =
113 [&]( const SELECTION& aSel )
114 {
115 return m_frame->GetCurrentSheet().Last() != &m_frame->Schematic().Root();
116 };
117
118 auto inDrawingRuleArea =
119 [&]( const SELECTION& aSel )
120 {
121 return m_drawingRuleArea;
122 };
123
124 CONDITIONAL_MENU& ctxMenu = m_menu->GetMenu();
125 ctxMenu.AddItem( SCH_ACTIONS::leaveSheet, belowRootSheetCondition, 150 );
126 ctxMenu.AddItem( SCH_ACTIONS::closeOutline, inDrawingRuleArea, 200 );
127 ctxMenu.AddItem( SCH_ACTIONS::deleteLastPoint, inDrawingRuleArea, 200 );
128
129 return true;
130}
131
132
134{
135 const SCH_ACTIONS::PLACE_SYMBOL_PARAMS& toolParams =
137
138 SCH_SYMBOL* symbol = toolParams.m_Symbol;
139 // If we get an parameterised symbol, we probably just want to place
140 // that and get out of the placmeent tool, rather than popping the
141 // chooser afterwards
142 bool placeOneOnly = symbol != nullptr;
143
145 std::vector<PICKED_SYMBOL>* historyList = nullptr;
146 bool ignorePrimePosition = false;
147 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
148 SCH_SCREEN* screen = m_frame->GetScreen();
149
150 if( m_inDrawingTool )
151 return 0;
152
154
157 VECTOR2I cursorPos;
158
159 // First we need to get all instances of this sheet so we can annotate
160 // whatever symbols we place on all copies
161 SCH_SHEET_LIST hierarchy = m_frame->Schematic().Hierarchy();
162 SCH_SHEET_LIST newInstances =
164 newInstances.SortByPageNumbers();
165
166 // Get a list of all references in the schematic to avoid duplicates wherever
167 // they're placed
168 SCH_REFERENCE_LIST existingRefs;
169 hierarchy.GetSymbols( existingRefs );
170 existingRefs.SortByReferenceOnly();
171
172 if( aEvent.IsAction( &SCH_ACTIONS::placeSymbol ) )
173 {
174 historyList = &m_symbolHistoryList;
175 }
176 else if (aEvent.IsAction( &SCH_ACTIONS::placePower ) )
177 {
178 historyList = &m_powerHistoryList;
179 filter.FilterPowerSymbols( true );
180 }
181 else
182 {
183 wxFAIL_MSG( "PlaceSymbol(): unexpected request" );
184 }
185
186 m_frame->PushTool( aEvent );
187
188 auto addSymbol =
189 [this]( SCH_SYMBOL* aSymbol )
190 {
192 m_selectionTool->AddItemToSel( aSymbol );
193
194 aSymbol->SetFlags( IS_NEW | IS_MOVING );
195
197 m_view->AddToPreview( aSymbol, false ); // Add, but not give ownership
198
199 // Set IS_MOVING again, as AddItemToCommitAndScreen() will have cleared it.
200 aSymbol->SetFlags( IS_MOVING );
202 };
203
204 auto setCursor =
205 [&]()
206 {
207 m_frame->GetCanvas()->SetCurrentCursor( symbol ? KICURSOR::MOVING
208 : KICURSOR::COMPONENT );
209 };
210
211 auto cleanup =
212 [&]()
213 {
216 delete symbol;
217 symbol = nullptr;
218
219 existingRefs.Clear();
220 hierarchy.GetSymbols( existingRefs );
221 existingRefs.SortByReferenceOnly();
222 };
223
224 auto annotate =
225 [&]()
226 {
228
229 // Then we need to annotate all instances by sheet
230 for( SCH_SHEET_PATH& instance : newInstances )
231 {
232 SCH_REFERENCE newReference( symbol, instance );
234 refs.AddItem( newReference );
235
236 if( cfg->m_AnnotatePanel.automatic || newReference.AlwaysAnnotate() )
237 {
241 existingRefs, false, &hierarchy );
242
243 refs.UpdateAnnotation();
244
245 // Update existing refs for next iteration
246 for( size_t i = 0; i < refs.GetCount(); i++ )
247 existingRefs.AddItem( refs[i] );
248 }
249 }
250
252 };
253
254 Activate();
255
256 // Must be done after Activate() so that it gets set into the correct context
257 getViewControls()->ShowCursor( true );
258
259 // Set initial cursor
260 setCursor();
261
262 // Prime the pump
263 if( symbol )
264 {
265 addSymbol( symbol );
266
267 if( toolParams.m_Reannotate )
268 annotate();
269
270 getViewControls()->WarpMouseCursor( getViewControls()->GetMousePosition( false ) );
271 }
272 else if( aEvent.HasPosition() )
273 {
274 m_toolMgr->PrimeTool( aEvent.Position() );
275 }
276 else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() )
277 {
278 m_toolMgr->PrimeTool( { 0, 0 } );
279 ignorePrimePosition = true;
280 }
281
282 // Main loop: keep receiving events
283 while( TOOL_EVENT* evt = Wait() )
284 {
285 setCursor();
286 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
287 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
288
289 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_CONNECTABLE );
290 controls->ForceCursorPosition( true, cursorPos );
291
292 // The tool hotkey is interpreted as a click when drawing
293 bool isSyntheticClick = symbol && evt->IsActivate() && evt->HasPosition()
294 && evt->Matches( aEvent );
295
296 if( evt->IsCancelInteractive() || ( symbol && evt->IsAction( &ACTIONS::undo ) ) )
297 {
299
300 if( symbol )
301 {
302 cleanup();
303 }
304 else
305 {
306 m_frame->PopTool( aEvent );
307 break;
308 }
309 }
310 else if( evt->IsActivate() && !isSyntheticClick )
311 {
312 if( symbol && evt->IsMoveTool() )
313 {
314 // we're already moving our own item; ignore the move tool
315 evt->SetPassEvent( false );
316 continue;
317 }
318
319 if( symbol )
320 {
321 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel symbol creation." ) );
322 evt->SetPassEvent( false );
323 continue;
324 }
325
326 if( evt->IsMoveTool() )
327 {
328 // leave ourselves on the stack so we come back after the move
329 break;
330 }
331 else
332 {
333 m_frame->PopTool( aEvent );
334 break;
335 }
336 }
337 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) || isSyntheticClick )
338 {
339 if( !symbol )
340 {
342
345
346 std::set<UTF8> unique_libid;
347 std::vector<PICKED_SYMBOL> alreadyPlaced;
348
349 for( SCH_SHEET_PATH& sheet : hierarchy )
350 {
351 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
352 {
353 SCH_SYMBOL* s = static_cast<SCH_SYMBOL*>( item );
354
355 if( !unique_libid.insert( s->GetLibId().Format() ).second )
356 continue;
357
358 LIB_SYMBOL* libSymbol = SchGetLibSymbol( s->GetLibId(), libs, cache );
359
360 if( libSymbol )
361 {
362 PICKED_SYMBOL pickedSymbol;
363 pickedSymbol.LibId = libSymbol->GetLibId();
364 alreadyPlaced.push_back( pickedSymbol );
365 }
366 }
367 }
368
369 // Pick the symbol to be placed
370 bool footprintPreviews = m_frame->eeconfig()->m_Appearance.footprint_preview;
371 PICKED_SYMBOL sel = m_frame->PickSymbolFromLibrary( &filter, *historyList,
372 alreadyPlaced,
373 footprintPreviews );
374
375 LIB_SYMBOL* libSymbol = sel.LibId.IsValid() ? m_frame->GetLibSymbol( sel.LibId )
376 : nullptr;
377
378 if( !libSymbol )
379 continue;
380
381 // If we started with a hotkey which has a position then warp back to that.
382 // Otherwise update to the current mouse position pinned inside the autoscroll
383 // boundaries.
384 if( evt->IsPrime() && !ignorePrimePosition )
385 {
386 cursorPos = grid.Align( evt->Position(), GRID_HELPER_GRIDS::GRID_CONNECTABLE );
387 getViewControls()->WarpMouseCursor( cursorPos, true );
388 }
389 else
390 {
392 cursorPos = grid.Align( getViewControls()->GetMousePosition(),
393 GRID_HELPER_GRIDS::GRID_CONNECTABLE );
394 }
395
397
398 if( !libSymbol->IsLocalPower() && cfg->m_Drawing.new_power_symbols == POWER_SYMBOLS::LOCAL )
399 {
400 libSymbol->SetLocalPower();
401 wxString keywords = libSymbol->GetKeyWords();
402
403 // Adjust the KiCad library default fields to match the new power symbol type
404 if( keywords.Contains( wxT( "global power" ) ) )
405 {
406 keywords.Replace( wxT( "global power" ), wxT( "local power" ) );
407 libSymbol->SetKeyWords( keywords );
408 }
409
410 wxString desc = libSymbol->GetDescription();
411
412 if( desc.Contains( wxT( "global label" ) ) )
413 {
414 desc.Replace( wxT( "global label" ), wxT( "local label" ) );
415 libSymbol->SetDescription( desc );
416 }
417 }
418 else if( !libSymbol->IsGlobalPower()
419 && cfg->m_Drawing.new_power_symbols == POWER_SYMBOLS::GLOBAL )
420 {
421 // We do not currently have local power symbols in the KiCad library, so
422 // don't update any fields
423 libSymbol->SetGlobalPower();
424 }
425
426 symbol = new SCH_SYMBOL( *libSymbol, &m_frame->GetCurrentSheet(), sel, cursorPos,
427 &m_frame->Schematic() );
428 addSymbol( symbol );
429 annotate();
430
431 // Update the list of references for the next symbol placement.
432 SCH_REFERENCE placedSymbolReference( symbol, m_frame->GetCurrentSheet() );
433 existingRefs.AddItem( placedSymbolReference );
434 existingRefs.SortByReferenceOnly();
435
437 {
438 // Not placed yet, so pass a nullptr screen reference
439 symbol->AutoplaceFields( nullptr, AUTOPLACE_AUTO );
440 }
441
442 // Update cursor now that we have a symbol
443 setCursor();
444 }
445 else
446 {
448 m_frame->AddToScreen( symbol, screen );
449
451 symbol->AutoplaceFields( screen, AUTOPLACE_AUTO );
452
454
455 SCH_COMMIT commit( m_toolMgr );
456 commit.Added( symbol, screen );
457
459 lwbTool->TrimOverLappingWires( &commit, &m_selectionTool->GetSelection() );
460 lwbTool->AddJunctionsIfNeeded( &commit, &m_selectionTool->GetSelection() );
461
462 commit.Push( _( "Place Symbol" ) );
463
464 if( placeOneOnly )
465 {
466 m_frame->PopTool( aEvent );
467 break;
468 }
469
470 SCH_SYMBOL* nextSymbol = nullptr;
471
474 {
475 int new_unit = symbol->GetUnit();
476
478 && symbol->GetUnit() < symbol->GetUnitCount() )
479 {
480 new_unit++;
481 }
482 else
483 {
484 new_unit = 1;
485 }
486
487 // We are either stepping to the next unit or next symbol
488 if( m_frame->eeconfig()->m_SymChooserPanel.keep_symbol || new_unit > 1 )
489 {
490 nextSymbol = static_cast<SCH_SYMBOL*>( symbol->Duplicate() );
491 nextSymbol->SetUnit( new_unit );
492 nextSymbol->SetUnitSelection( new_unit );
493
494 // Start new annotation sequence at first unit
495 if( new_unit == 1 )
496 nextSymbol->ClearAnnotation( nullptr, false );
497
498 addSymbol( nextSymbol );
499 symbol = nextSymbol;
500 annotate();
501
502 // Update the list of references for the next symbol placement.
503 SCH_REFERENCE placedSymbolReference( symbol, m_frame->GetCurrentSheet() );
504 existingRefs.AddItem( placedSymbolReference );
505 existingRefs.SortByReferenceOnly();
506 }
507 }
508
509 symbol = nextSymbol;
510 }
511 }
512 else if( evt->IsClick( BUT_RIGHT ) )
513 {
514 // Warp after context menu only if dragging...
515 if( !symbol )
517
518 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
519 }
520 else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
521 {
522 if( *evt->GetCommandId() >= ID_POPUP_SCH_SELECT_UNIT
523 && *evt->GetCommandId() <= ID_POPUP_SCH_SELECT_UNIT_END )
524 {
525 int unit = *evt->GetCommandId() - ID_POPUP_SCH_SELECT_UNIT;
526
527 if( symbol )
528 {
529 m_frame->SelectUnit( symbol, unit );
531 }
532 }
533 else if( *evt->GetCommandId() >= ID_POPUP_SCH_SELECT_BASE
534 && *evt->GetCommandId() <= ID_POPUP_SCH_SELECT_ALT )
535 {
536 int bodyStyle = ( *evt->GetCommandId() - ID_POPUP_SCH_SELECT_BASE ) + 1;
537
538 if( symbol && symbol->GetBodyStyle() != bodyStyle )
539 {
540 m_frame->FlipBodyStyle( symbol );
542 }
543 }
544 }
545 else if( evt->IsAction( &ACTIONS::duplicate )
546 || evt->IsAction( &SCH_ACTIONS::repeatDrawItem ) )
547 {
548 if( symbol )
549 {
550 // This doesn't really make sense; we'll just end up dragging a stack of
551 // objects so we ignore the duplicate and just carry on.
552 wxBell();
553 continue;
554 }
555
556 // Exit. The duplicate will run in its own loop.
557 m_frame->PopTool( aEvent );
558 break;
559 }
560 else if( symbol && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
561 {
562 symbol->SetPosition( cursorPos );
564 m_view->AddToPreview( symbol, false ); // Add, but not give ownership
565 m_frame->SetMsgPanel( symbol );
566 }
567 else if( symbol && evt->IsAction( &ACTIONS::doDelete ) )
568 {
569 cleanup();
570 }
571 else if( symbol && evt->IsAction( &ACTIONS::redo ) )
572 {
573 wxBell();
574 }
575 else
576 {
577 evt->SetPassEvent();
578 }
579
580 // Enable autopanning and cursor capture only when there is a symbol to be placed
581 getViewControls()->SetAutoPan( symbol != nullptr );
582 getViewControls()->CaptureCursor( symbol != nullptr );
583 }
584
585 getViewControls()->SetAutoPan( false );
586 getViewControls()->CaptureCursor( false );
587 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
588
589 return 0;
590}
591
592
594{
595 SCH_SYMBOL* symbol = aEvent.Parameter<SCH_SYMBOL*>();
596
597 // TODO: get from selection
598 if( !symbol )
599 {
600 static const std::vector<KICAD_T> symbolTypes = { SCH_SYMBOL_T };
601 SCH_SELECTION& selection = m_selectionTool->RequestSelection( symbolTypes );
602
603 if( selection.Size() != 1 )
604 {
605 m_frame->ShowInfoBarMsg( _( "Select a single symbol to place the next unit." ) );
606 return 0;
607 }
608
609 wxCHECK( selection.Front()->Type() == SCH_SYMBOL_T, 0 );
610 symbol = static_cast<SCH_SYMBOL*>( selection.Front() );
611 }
612
613 if( !symbol )
614 return 0;
615
616 if( !symbol->IsMulti() )
617 {
618 m_frame->ShowInfoBarMsg( _( "This symbol has only one unit." ) );
619 return 0;
620 }
621
622 const std::set<int> missingUnits = GetUnplacedUnitsForSymbol( *symbol );
623
624 if( missingUnits.empty() )
625 {
626 m_frame->ShowInfoBarMsg( _( "All units of this symbol are already placed." ) );
627 return 0;
628 }
629
630 // Find the lowest unit number that is missing
631 const int nextMissing = *std::min_element( missingUnits.begin(), missingUnits.end() );
632
633 std::unique_ptr<SCH_SYMBOL> newSymbol = std::make_unique<SCH_SYMBOL>( *symbol );
634 const SCH_SHEET_PATH& sheetPath = m_frame->GetCurrentSheet();
635
636 newSymbol->SetUnitSelection( &sheetPath, nextMissing );
637 newSymbol->SetUnit( nextMissing );
638 newSymbol->SetRefProp( symbol->GetRef( &sheetPath, false ) );
639
640 // Post the new symbol - don't reannotate it - we set the reference ourselves
642 SCH_ACTIONS::PLACE_SYMBOL_PARAMS{ newSymbol.release(), false } );
643 return 0;
644}
645
646
648{
649 bool placingDesignBlock = aEvent.IsAction( &SCH_ACTIONS::placeDesignBlock );
650
651 DESIGN_BLOCK* designBlock = nullptr;
652 wxString sheetFileName = wxEmptyString;
653
654 if( placingDesignBlock )
655 {
657 {
658 designBlock = m_frame->GetDesignBlockPane()->GetDesignBlock(
659 m_frame->GetDesignBlockPane()->GetSelectedLibId(), true, true );
660
661 if( !designBlock )
662 return 0;
663
664 sheetFileName = designBlock->GetSchematicFile();
665 }
666 }
667 else
668 {
669 wxString* importSourceFile = aEvent.Parameter<wxString*>();
670
671 if( importSourceFile != nullptr )
672 sheetFileName = *importSourceFile;
673 }
674
675 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
677 SCHEMATIC_SETTINGS& schSettings = m_frame->Schematic().Settings();
678 SCH_SCREEN* screen = m_frame->GetScreen();
679 SCH_SHEET_PATH& sheetPath = m_frame->GetCurrentSheet();
680
683 VECTOR2I cursorPos;
684
685 if( !cfg || !common_settings )
686 return 0;
687
688 if( m_inDrawingTool )
689 return 0;
690
691 auto setCursor =
692 [&]()
693 {
694 m_frame->GetCanvas()->SetCurrentCursor( designBlock ? KICURSOR::MOVING
695 : KICURSOR::COMPONENT );
696 };
697
698 auto placeSheetContents =
699 [&]()
700 {
701 SCH_COMMIT commit( m_toolMgr );
703
704 EDA_ITEMS newItems;
705 bool keepAnnotations = cfg->m_DesignBlockChooserPanel.keep_annotations;
706 bool placeAsGroup = cfg->m_DesignBlockChooserPanel.place_as_group;
707
708 selectionTool->ClearSelection();
709
710 // Mark all existing items on the screen so we don't select them after appending
711 for( EDA_ITEM* item : screen->Items() )
712 item->SetFlags( SKIP_STRUCT );
713
714 if( !m_frame->LoadSheetFromFile( sheetPath.Last(), &sheetPath, sheetFileName, true,
715 placingDesignBlock ) )
716 return false;
717
719
720 m_frame->SyncView();
721 m_frame->OnModify();
722 m_frame->HardRedraw(); // Full reinit of the current screen and the display.
723
724
725 SCH_GROUP* group = nullptr;
726
727 if( placeAsGroup )
728 {
729 group = new SCH_GROUP( screen );
730
731 if( designBlock )
732 {
733 group->SetName( designBlock->GetLibId().GetLibItemName() );
734 group->SetDesignBlockLibId( designBlock->GetLibId() );
735 }
736 else
737 {
738 group->SetName( wxFileName( sheetFileName ).GetName() );
739 }
740 }
741
742 // Select all new items
743 for( EDA_ITEM* item : screen->Items() )
744 {
745 if( !item->HasFlag( SKIP_STRUCT ) )
746 {
747 if( item->Type() == SCH_SYMBOL_T && !keepAnnotations )
748 static_cast<SCH_SYMBOL*>( item )->ClearAnnotation( &sheetPath, false );
749
750 if( item->Type() == SCH_LINE_T )
751 item->SetFlags( STARTPOINT | ENDPOINT );
752
753 if( placeAsGroup )
754 group->AddItem( item );
755
756 commit.Added( item, screen );
757 newItems.emplace_back( item );
758 }
759 else
760 item->ClearFlags( SKIP_STRUCT );
761 }
762
763 if( placeAsGroup )
764 {
765 commit.Add( group, screen );
766 selectionTool->AddItemToSel( group );
767 }
768 else
769 selectionTool->AddItemsToSel( &newItems, true );
770
771 cursorPos = grid.Align( controls->GetMousePosition(),
772 grid.GetSelectionGrid( selectionTool->GetSelection() ) );
773 controls->ForceCursorPosition( true, cursorPos );
774
775 // Move everything to our current mouse position now
776 // that we have a selection to get a reference point
777 VECTOR2I anchorPos = selectionTool->GetSelection().GetReferencePoint();
778 VECTOR2I delta = cursorPos - anchorPos;
779
780 // Will all be SCH_ITEMs as these were pulled from the screen->Items()
781 for( EDA_ITEM* item : newItems )
782 static_cast<SCH_ITEM*>( item )->Move( delta );
783
784 if( !keepAnnotations )
785 {
787
788 if( annotate.automatic )
789 {
790 NULL_REPORTER reporter;
792 (ANNOTATE_ORDER_T) annotate.sort_order,
793 (ANNOTATE_ALGO_T) annotate.method, true /* recursive */,
794 schSettings.m_AnnotateStartNum, false, false, reporter );
795 }
796
797 // Annotation will clear selection, so we need to restore it
798 for( EDA_ITEM* item : newItems )
799 {
800 if( item->Type() == SCH_LINE_T )
801 item->SetFlags( STARTPOINT | ENDPOINT );
802 }
803
804 selectionTool->AddItemsToSel( &newItems, true );
805 }
806
807 // Start moving selection, cancel undoes the insertion
808 bool placed = m_toolMgr->RunSynchronousAction( SCH_ACTIONS::move, &commit );
809
810 // Update our cursor position to the new location in case we're placing repeated copies
811 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_CONNECTABLE );
812
813 if( placed )
814 commit.Push( placingDesignBlock ? _( "Add design block" )
815 : _( "Import Schematic Sheet Content..." ) );
816 else
817 commit.Revert();
818
820
821 return placed;
822 };
823
824 // Whether we are placing the sheet as a sheet, or as its contents, we need to get a filename
825 // if we weren't provided one
826 if( sheetFileName.IsEmpty() )
827 {
828 wxString path;
829 wxString file;
830
831 if (!placingDesignBlock) {
832
833 if( sheetFileName.IsEmpty() )
834 {
835 path = wxPathOnly( m_frame->Prj().GetProjectFullName() );
836 file = wxEmptyString;
837 }
838 else
839 {
840 path = wxPathOnly( sheetFileName );
841 file = wxFileName( sheetFileName ).GetFullName();
842 }
843
844 // Open file chooser dialog even if we have been provided a file so the user
845 // can select the options they want
846 wxFileDialog dlg( m_frame, _( "Choose Schematic" ), path, file,
848 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
849
850 FILEDLG_IMPORT_SHEET_CONTENTS dlgHook( cfg );
851 dlg.SetCustomizeHook( dlgHook );
852
853 if( dlg.ShowModal() == wxID_CANCEL )
854 return 0;
855
856 sheetFileName = dlg.GetPath();
857
859 }
860
861 if( sheetFileName.IsEmpty() )
862 return 0;
863 }
864
865 // If we're placing sheet contents, we don't even want to run our tool loop, just add the items
866 // to the canvas and run the move tool
868 {
869 while( placeSheetContents() && cfg->m_DesignBlockChooserPanel.repeated_placement )
870 ;
871
874 delete designBlock;
875 designBlock = nullptr;
876
877 return 0;
878 }
879
880 // We're placing a sheet as a sheet, we need to run a small tool loop to get the starting
881 // coordinate of the sheet drawing
882 m_frame->PushTool( aEvent );
883
884 Activate();
885
886 // Must be done after Activate() so that it gets set into the correct context
887 getViewControls()->ShowCursor( true );
888
889 // Set initial cursor
890 setCursor();
891
892 if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() )
893 {
894 m_toolMgr->PrimeTool( { 0, 0 } );
895 }
896
897 // Main loop: keep receiving events
898 while( TOOL_EVENT* evt = Wait() )
899 {
900 setCursor();
901 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
902 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
903
904 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_CONNECTABLE );
905 controls->ForceCursorPosition( true, cursorPos );
906
907 // The tool hotkey is interpreted as a click when drawing
908 bool isSyntheticClick = designBlock && evt->IsActivate() && evt->HasPosition()
909 && evt->Matches( aEvent );
910
911 if( evt->IsCancelInteractive() || ( designBlock && evt->IsAction( &ACTIONS::undo ) ) )
912 {
914 break;
915 }
916 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) || isSyntheticClick )
917 {
918 if( placingDesignBlock )
919 {
921 }
922 else
923 {
924 // drawSheet must delete
926 new wxString( sheetFileName ) );
927 }
928
929 break;
930 }
931 else if( evt->IsClick( BUT_RIGHT ) )
932 {
933 // Warp after context menu only if dragging...
934 if( !designBlock )
936
937 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
938 }
939 else if( evt->IsAction( &ACTIONS::duplicate )
940 || evt->IsAction( &SCH_ACTIONS::repeatDrawItem ) )
941 {
942 wxBell();
943 }
944 else
945 {
946 evt->SetPassEvent();
947 }
948 }
949
950 m_frame->PopTool( aEvent );
951 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
952
953 return 0;
954}
955
956
958{
959 SCH_BITMAP* image = aEvent.Parameter<SCH_BITMAP*>();
960 bool immediateMode = image != nullptr;
961 bool ignorePrimePosition = false;
962 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
963
964 if( m_inDrawingTool )
965 return 0;
966
968
971 VECTOR2I cursorPos;
972
974
975 // Add all the drawable symbols to preview
976 if( image )
977 {
978 image->SetPosition( getViewControls()->GetCursorPosition() );
980 m_view->AddToPreview( image, false ); // Add, but not give ownership
981 }
982
983 m_frame->PushTool( aEvent );
984
985 auto setCursor =
986 [&]()
987 {
988 if( image )
989 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::MOVING );
990 else
991 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
992 };
993
994 auto cleanup =
995 [&] ()
996 {
1000 delete image;
1001 image = nullptr;
1002 };
1003
1004 Activate();
1005
1006 // Must be done after Activate() so that it gets set into the correct context
1007 getViewControls()->ShowCursor( true );
1008
1009 // Set initial cursor
1010 setCursor();
1011
1012 // Prime the pump
1013 if( image )
1014 {
1016 }
1017 else if( aEvent.HasPosition() )
1018 {
1019 m_toolMgr->PrimeTool( aEvent.Position() );
1020 }
1021 else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() )
1022 {
1023 m_toolMgr->PrimeTool( { 0, 0 } );
1024 ignorePrimePosition = true;
1025 }
1026
1027 // Main loop: keep receiving events
1028 while( TOOL_EVENT* evt = Wait() )
1029 {
1030 setCursor();
1031 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1032 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1033
1034 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
1035 controls->ForceCursorPosition( true, cursorPos );
1036
1037 // The tool hotkey is interpreted as a click when drawing
1038 bool isSyntheticClick = image && evt->IsActivate() && evt->HasPosition()
1039 && evt->Matches( aEvent );
1040
1041 if( evt->IsCancelInteractive() || ( image && evt->IsAction( &ACTIONS::undo ) ) )
1042 {
1044
1045 if( image )
1046 {
1047 cleanup();
1048 }
1049 else
1050 {
1051 m_frame->PopTool( aEvent );
1052 break;
1053 }
1054
1055 if( immediateMode )
1056 {
1057 m_frame->PopTool( aEvent );
1058 break;
1059 }
1060 }
1061 else if( evt->IsActivate() && !isSyntheticClick )
1062 {
1063 if( image && evt->IsMoveTool() )
1064 {
1065 // we're already moving our own item; ignore the move tool
1066 evt->SetPassEvent( false );
1067 continue;
1068 }
1069
1070 if( image )
1071 {
1072 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel image creation." ) );
1073 evt->SetPassEvent( false );
1074 continue;
1075 }
1076
1077 if( evt->IsMoveTool() )
1078 {
1079 // leave ourselves on the stack so we come back after the move
1080 break;
1081 }
1082 else
1083 {
1084 m_frame->PopTool( aEvent );
1085 break;
1086 }
1087 }
1088 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) || isSyntheticClick )
1089 {
1090 if( !image )
1091 {
1093
1094 wxFileDialog dlg( m_frame, _( "Choose Image" ), m_mruPath, wxEmptyString,
1095 _( "Image Files" ) + wxS( " " ) + wxImage::GetImageExtWildcard(),
1096 wxFD_OPEN );
1097
1098 if( dlg.ShowModal() != wxID_OK )
1099 continue;
1100
1101 // If we started with a hotkey which has a position then warp back to that.
1102 // Otherwise update to the current mouse position pinned inside the autoscroll
1103 // boundaries.
1104 if( evt->IsPrime() && !ignorePrimePosition )
1105 {
1106 cursorPos = grid.Align( evt->Position() );
1107 getViewControls()->WarpMouseCursor( cursorPos, true );
1108 }
1109 else
1110 {
1112 cursorPos = getViewControls()->GetMousePosition();
1113 }
1114
1115 wxString fullFilename = dlg.GetPath();
1116 m_mruPath = wxPathOnly( fullFilename );
1117
1118 if( wxFileExists( fullFilename ) )
1119 image = new SCH_BITMAP( cursorPos );
1120
1121 if( !image || !image->GetReferenceImage().ReadImageFile( fullFilename ) )
1122 {
1123 wxMessageBox( wxString::Format( _( "Could not load image from '%s'." ), fullFilename ) );
1124 delete image;
1125 image = nullptr;
1126 continue;
1127 }
1128
1129 image->SetFlags( IS_NEW | IS_MOVING );
1130
1132
1134 m_view->AddToPreview( image, false ); // Add, but not give ownership
1135 m_view->RecacheAllItems(); // Bitmaps are cached in Opengl
1136
1138
1139 getViewControls()->SetCursorPosition( cursorPos, false );
1140 setCursor();
1141 }
1142 else
1143 {
1144 SCH_COMMIT commit( m_toolMgr );
1145 commit.Add( image, m_frame->GetScreen() );
1146 commit.Push( _( "Place Image" ) );
1147
1148 image = nullptr;
1150
1152
1153 if( immediateMode )
1154 {
1155 m_frame->PopTool( aEvent );
1156 break;
1157 }
1158 }
1159 }
1160 else if( evt->IsClick( BUT_RIGHT ) )
1161 {
1162 // Warp after context menu only if dragging...
1163 if( !image )
1165
1166 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
1167 }
1168 else if( evt->IsAction( &ACTIONS::duplicate )
1169 || evt->IsAction( &SCH_ACTIONS::repeatDrawItem ) )
1170 {
1171 if( image )
1172 {
1173 // This doesn't really make sense; we'll just end up dragging a stack of
1174 // objects so we ignore the duplicate and just carry on.
1175 wxBell();
1176 continue;
1177 }
1178
1179 // Exit. The duplicate will run in its own loop.
1180 m_frame->PopTool( aEvent );
1181 break;
1182 }
1183 else if( image && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
1184 {
1185 image->SetPosition( cursorPos );
1187 m_view->AddToPreview( image, false ); // Add, but not give ownership
1188 m_view->RecacheAllItems(); // Bitmaps are cached in Opengl
1190 }
1191 else if( image && evt->IsAction( &ACTIONS::doDelete ) )
1192 {
1193 cleanup();
1194 }
1195 else if( image && evt->IsAction( &ACTIONS::redo ) )
1196 {
1197 wxBell();
1198 }
1199 else
1200 {
1201 evt->SetPassEvent();
1202 }
1203
1204 // Enable autopanning and cursor capture only when there is an image to be placed
1205 getViewControls()->SetAutoPan( image != nullptr );
1206 getViewControls()->CaptureCursor( image != nullptr );
1207 }
1208
1209 getViewControls()->SetAutoPan( false );
1210 getViewControls()->CaptureCursor( false );
1211 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1212
1213 return 0;
1214}
1215
1216
1218{
1219 if( m_inDrawingTool )
1220 return 0;
1221
1223
1224 // Note: PlaceImportedGraphics() will convert PCB_SHAPE_T and PCB_TEXT_T to footprint
1225 // items if needed
1227 int dlgResult = dlg.ShowModal();
1228
1229 std::list<std::unique_ptr<EDA_ITEM>>& list = dlg.GetImportedItems();
1230
1231 if( dlgResult != wxID_OK )
1232 return 0;
1233
1234 // Ensure the list is not empty:
1235 if( list.empty() )
1236 {
1237 wxMessageBox( _( "No graphic items found in file." ) );
1238 return 0;
1239 }
1240
1242
1244 std::vector<SCH_ITEM*> newItems; // all new items, including group
1245 std::vector<SCH_ITEM*> selectedItems; // the group, or newItems if no group
1246 SCH_SELECTION preview;
1247 SCH_COMMIT commit( m_toolMgr );
1248
1249 for( std::unique_ptr<EDA_ITEM>& ptr : list )
1250 {
1251 SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( ptr.get() );
1252 wxCHECK2_MSG( item, continue, wxString::Format( "Bad item type: ", ptr->Type() ) );
1253
1254 newItems.push_back( item );
1255 selectedItems.push_back( item );
1256 preview.Add( item );
1257
1258 ptr.release();
1259 }
1260
1261 if( !dlg.IsPlacementInteractive() )
1262 {
1263 // Place the imported drawings
1264 for( SCH_ITEM* item : newItems )
1265 commit.Add(item, m_frame->GetScreen());
1266
1267 commit.Push( _( "Import Graphic" ) );
1268 return 0;
1269 }
1270
1271 m_view->Add( &preview );
1272
1273 // Clear the current selection then select the drawings so that edit tools work on them
1275
1276 EDA_ITEMS selItems( selectedItems.begin(), selectedItems.end() );
1278
1279 m_frame->PushTool( aEvent );
1280
1281 auto setCursor = [&]()
1282 {
1283 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::MOVING );
1284 };
1285
1286 Activate();
1287 // Must be done after Activate() so that it gets set into the correct context
1288 controls->ShowCursor( true );
1289 controls->ForceCursorPosition( false );
1290 // Set initial cursor
1291 setCursor();
1292
1293 //SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::DXF );
1295
1296 // Now move the new items to the current cursor position:
1297 VECTOR2I cursorPos = controls->GetCursorPosition( !aEvent.DisableGridSnapping() );
1298 VECTOR2I delta = cursorPos;
1299 VECTOR2I currentOffset;
1300
1301 for( SCH_ITEM* item : selectedItems )
1302 item->Move( delta );
1303
1304 currentOffset += delta;
1305
1306 m_view->Update( &preview );
1307
1308 // Main loop: keep receiving events
1309 while( TOOL_EVENT* evt = Wait() )
1310 {
1311 setCursor();
1312
1313 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1314 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1315
1316 cursorPos = grid.Align( controls->GetMousePosition(), GRID_GRAPHICS );
1317 controls->ForceCursorPosition( true, cursorPos );
1318
1319 if( evt->IsCancelInteractive() || evt->IsActivate() )
1320 {
1322
1323 for( SCH_ITEM* item : newItems )
1324 delete item;
1325
1326 break;
1327 }
1328 else if( evt->IsMotion() )
1329 {
1330 delta = cursorPos - currentOffset;
1331
1332 for( SCH_ITEM* item : selectedItems )
1333 item->Move( delta );
1334
1335 currentOffset += delta;
1336
1337 m_view->Update( &preview );
1338 }
1339 else if( evt->IsClick( BUT_RIGHT ) )
1340 {
1341 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
1342 }
1343 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
1344 {
1345 // Place the imported drawings
1346 for( SCH_ITEM* item : newItems )
1347 commit.Add( item, m_frame->GetScreen() );
1348
1349 commit.Push( _( "Import Graphic" ) );
1350 break; // This is a one-shot command, not a tool
1351 }
1352 else
1353 {
1354 evt->SetPassEvent();
1355 }
1356 }
1357
1358 preview.Clear();
1359 m_view->Remove( &preview );
1360
1361 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1362 controls->ForceCursorPosition( false );
1363
1364 m_frame->PopTool( aEvent );
1365
1366 return 0;
1367}
1368
1369
1371{
1372 VECTOR2I cursorPos;
1373 KICAD_T type = aEvent.Parameter<KICAD_T>();
1376 SCH_ITEM* previewItem;
1377 bool loggedInfoBarError = false;
1378 wxString description;
1379 SCH_SCREEN* screen = m_frame->GetScreen();
1380 bool allowRepeat = false; // Set to true to allow new item repetition
1381
1382 if( m_inDrawingTool )
1383 return 0;
1384
1386
1387 if( type == SCH_JUNCTION_T && aEvent.HasPosition() )
1388 {
1390 SCH_LINE* wire = dynamic_cast<SCH_LINE*>( selection.Front() );
1391
1392 if( wire )
1393 {
1394 SEG seg( wire->GetStartPoint(), wire->GetEndPoint() );
1395 VECTOR2I nearest = seg.NearestPoint( getViewControls()->GetCursorPosition() );
1396 getViewControls()->SetCrossHairCursorPosition( nearest, false );
1397 getViewControls()->WarpMouseCursor( getViewControls()->GetCursorPosition(), true );
1398 }
1399 }
1400
1401 switch( type )
1402 {
1403 case SCH_NO_CONNECT_T:
1404 previewItem = new SCH_NO_CONNECT( cursorPos );
1405 previewItem->SetParent( screen );
1406 description = _( "Add No Connect Flag" );
1407 allowRepeat = true;
1408 break;
1409
1410 case SCH_JUNCTION_T:
1411 previewItem = new SCH_JUNCTION( cursorPos );
1412 previewItem->SetParent( screen );
1413 description = _( "Add Junction" );
1414 break;
1415
1417 previewItem = new SCH_BUS_WIRE_ENTRY( cursorPos );
1418 previewItem->SetParent( screen );
1419 description = _( "Add Wire to Bus Entry" );
1420 allowRepeat = true;
1421 break;
1422
1423 default:
1424 wxASSERT_MSG( false, "Unknown item type in SCH_DRAWING_TOOLS::SingleClickPlace" );
1425 return 0;
1426 }
1427
1429
1430 cursorPos = aEvent.HasPosition() ? aEvent.Position() : controls->GetMousePosition();
1431
1432 m_frame->PushTool( aEvent );
1433
1434 auto setCursor =
1435 [&]()
1436 {
1437 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PLACE );
1438 };
1439
1440 Activate();
1441
1442 // Must be done after Activate() so that it gets set into the correct context
1443 getViewControls()->ShowCursor( true );
1444
1445 // Set initial cursor
1446 setCursor();
1447
1449 m_view->AddToPreview( previewItem->Clone() );
1450
1451 // Prime the pump
1452 if( aEvent.HasPosition() && type != SCH_SHEET_PIN_T )
1453 m_toolMgr->PrimeTool( aEvent.Position() );
1454 else
1456
1457 // Main loop: keep receiving events
1458 while( TOOL_EVENT* evt = Wait() )
1459 {
1460 setCursor();
1461 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1462 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1463
1464 cursorPos = evt->IsPrime() ? evt->Position() : controls->GetMousePosition();
1465 cursorPos = grid.BestSnapAnchor( cursorPos, grid.GetItemGrid( previewItem ), nullptr );
1466 controls->ForceCursorPosition( true, cursorPos );
1467
1468 if( evt->IsCancelInteractive() )
1469 {
1470 m_frame->PopTool( aEvent );
1471 break;
1472 }
1473 else if( evt->IsActivate() )
1474 {
1475 if( evt->IsMoveTool() )
1476 {
1477 // leave ourselves on the stack so we come back after the move
1478 break;
1479 }
1480 else
1481 {
1482 m_frame->PopTool( aEvent );
1483 break;
1484 }
1485 }
1486 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
1487 {
1488 if( !screen->GetItem( cursorPos, 0, type ) )
1489 {
1490 if( type == SCH_JUNCTION_T )
1491 {
1492 if( !screen->IsExplicitJunctionAllowed( cursorPos ) )
1493 {
1494 m_frame->ShowInfoBarError( _( "Junction location contains no joinable "
1495 "wires and/or pins." ) );
1496 loggedInfoBarError = true;
1497 continue;
1498 }
1499 else if( loggedInfoBarError )
1500 {
1502 }
1503 }
1504
1505 SCH_ITEM* newItem = static_cast<SCH_ITEM*>( previewItem->Clone() );
1506 const_cast<KIID&>( newItem->m_Uuid ) = KIID();
1507 newItem->SetPosition( cursorPos );
1508 newItem->SetFlags( IS_NEW );
1509 m_frame->AddToScreen( newItem, screen );
1510
1511 if( allowRepeat )
1512 m_frame->SaveCopyForRepeatItem( newItem );
1513
1514 SCH_COMMIT commit( m_toolMgr );
1515 commit.Added( newItem, screen );
1516
1517 m_frame->SchematicCleanUp( &commit );
1518
1519 commit.Push( description );
1520 }
1521
1522 if( evt->IsDblClick( BUT_LEFT ) || type == SCH_SHEET_PIN_T ) // Finish tool.
1523 {
1524 m_frame->PopTool( aEvent );
1525 break;
1526 }
1527 }
1528 else if( evt->IsClick( BUT_RIGHT ) )
1529 {
1530 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
1531 }
1532 else if( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() )
1533 {
1534 previewItem->SetPosition( cursorPos );
1536 m_view->AddToPreview( previewItem->Clone() );
1537 m_frame->SetMsgPanel( previewItem );
1538 }
1539 else if( evt->Category() == TC_COMMAND )
1540 {
1541 if( ( type == SCH_BUS_WIRE_ENTRY_T ) && ( evt->IsAction( &SCH_ACTIONS::rotateCW )
1542 || evt->IsAction( &SCH_ACTIONS::rotateCCW )
1543 || evt->IsAction( &SCH_ACTIONS::mirrorV )
1544 || evt->IsAction( &SCH_ACTIONS::mirrorH ) ) )
1545 {
1546 SCH_BUS_ENTRY_BASE* busItem = static_cast<SCH_BUS_ENTRY_BASE*>( previewItem );
1547
1548 if( evt->IsAction( &SCH_ACTIONS::rotateCW ) )
1549 {
1550 busItem->Rotate( busItem->GetPosition(), false );
1551 }
1552 else if( evt->IsAction( &SCH_ACTIONS::rotateCCW ) )
1553 {
1554 busItem->Rotate( busItem->GetPosition(), true );
1555 }
1556 else if( evt->IsAction( &SCH_ACTIONS::mirrorV ) )
1557 {
1558 busItem->MirrorVertically( busItem->GetPosition().y );
1559 }
1560 else if( evt->IsAction( &SCH_ACTIONS::mirrorH ) )
1561 {
1562 busItem->MirrorHorizontally( busItem->GetPosition().x );
1563 }
1564
1566 m_view->AddToPreview( previewItem->Clone() );
1567 }
1568 else if( evt->IsAction( &SCH_ACTIONS::properties ) )
1569 {
1570 switch( type )
1571 {
1573 {
1574 std::deque<SCH_ITEM*> strokeItems;
1575 strokeItems.push_back( previewItem );
1576
1577 DIALOG_WIRE_BUS_PROPERTIES dlg( m_frame, strokeItems );
1578 }
1579 break;
1580
1581 case SCH_JUNCTION_T:
1582 {
1583 std::deque<SCH_JUNCTION*> junctions;
1584 junctions.push_back( static_cast<SCH_JUNCTION*>( previewItem ) );
1585
1586 DIALOG_JUNCTION_PROPS dlg( m_frame, junctions );
1587 }
1588 break;
1589 default:
1590 // Do nothing
1591 break;
1592 }
1593
1595 m_view->AddToPreview( previewItem->Clone() );
1596 }
1597 else
1598 {
1599 evt->SetPassEvent();
1600 }
1601 }
1602 else
1603 {
1604 evt->SetPassEvent();
1605 }
1606 }
1607
1608 delete previewItem;
1610
1611 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1612 controls->ForceCursorPosition( false );
1613
1614 return 0;
1615}
1616
1617
1619{
1620 for( SCH_ITEM* item : m_frame->GetScreen()->Items().Overlapping( SCH_LINE_T, aPosition ) )
1621 {
1622 SCH_LINE* line = static_cast<SCH_LINE*>( item );
1623
1624 if( line->GetEditFlags() & STRUCT_DELETED )
1625 continue;
1626
1627 if( line->IsWire() )
1628 return line;
1629 }
1630
1631 return nullptr;
1632}
1633
1634
1636{
1637 wxASSERT( aWire->IsWire() );
1638
1639 SCH_SHEET_PATH sheetPath = m_frame->GetCurrentSheet();
1640
1641 if( SCH_CONNECTION* wireConnection = aWire->Connection( &sheetPath ) )
1642 {
1643 SCH_ITEM* wireDriver = wireConnection->Driver();
1644
1645 if( wireDriver && wireDriver->IsType( { SCH_LABEL_T, SCH_GLOBAL_LABEL_T } ) )
1646 return wireConnection->LocalName();
1647 }
1648
1649 return wxEmptyString;
1650}
1651
1652
1653bool SCH_DRAWING_TOOLS::createNewLabel( const VECTOR2I& aPosition, int aType,
1654 std::list<std::unique_ptr<SCH_LABEL_BASE>>& aLabelList )
1655{
1656 SCHEMATIC* schematic = getModel<SCHEMATIC>();
1657 SCHEMATIC_SETTINGS& settings = schematic->Settings();
1658 SCH_LABEL_BASE* labelItem = nullptr;
1659 SCH_GLOBALLABEL* globalLabel = nullptr;
1660 wxString netName;
1661
1662 switch( aType )
1663 {
1664 case LAYER_LOCLABEL:
1665 labelItem = new SCH_LABEL( aPosition );
1666
1667 if( SCH_LINE* wire = findWire( aPosition ) )
1668 netName = findWireLabelDriverName( wire );
1669
1670 break;
1671
1673 labelItem = new SCH_DIRECTIVE_LABEL( aPosition );
1674 labelItem->SetShape( m_lastNetClassFlagShape );
1675 labelItem->GetFields().emplace_back( labelItem, FIELD_T::USER, wxT( "Netclass" ) );
1676 labelItem->GetFields().emplace_back( labelItem, FIELD_T::USER, wxT( "Component Class" ) );
1677 labelItem->GetFields().back().SetItalic( true );
1678 labelItem->GetFields().back().SetVisible( true );
1679 break;
1680
1681 case LAYER_HIERLABEL:
1682 labelItem = new SCH_HIERLABEL( aPosition );
1683 labelItem->SetShape( m_lastGlobalLabelShape );
1685 break;
1686
1687 case LAYER_GLOBLABEL:
1688 globalLabel = new SCH_GLOBALLABEL( aPosition );
1689 globalLabel->SetShape( m_lastGlobalLabelShape );
1690 globalLabel->GetField( FIELD_T::INTERSHEET_REFS )->SetVisible( settings.m_IntersheetRefsShow );
1692 labelItem = globalLabel;
1693
1694 if( SCH_LINE* wire = findWire( aPosition ) )
1695 netName = findWireLabelDriverName( wire );
1696
1697 break;
1698
1699 default:
1700 wxFAIL_MSG( "SCH_EDIT_FRAME::CreateNewText() unknown layer type" );
1701 return false;
1702 }
1703
1704 labelItem->SetParent( schematic );
1705
1706 labelItem->SetTextSize( VECTOR2I( settings.m_DefaultTextSize, settings.m_DefaultTextSize ) );
1707
1708 if( aType != LAYER_NETCLASS_REFS )
1709 {
1710 // Must be after SetTextSize()
1711 labelItem->SetBold( m_lastTextBold );
1712 labelItem->SetItalic( m_lastTextItalic );
1713 }
1714
1715 labelItem->SetSpinStyle( m_lastTextOrientation );
1716 labelItem->SetFlags( IS_NEW | IS_MOVING );
1717
1718 if( !netName.IsEmpty() )
1719 {
1720 // Auto-create from attached wire
1721 labelItem->SetText( netName );
1722 }
1723 else
1724 {
1725 DIALOG_LABEL_PROPERTIES dlg( m_frame, labelItem, true );
1726
1727 dlg.SetLabelList( &aLabelList );
1728
1729 // QuasiModal required for syntax help and Scintilla auto-complete
1730 if( dlg.ShowQuasiModal() != wxID_OK )
1731 {
1733 delete labelItem;
1734 return false;
1735 }
1736 }
1737
1738 if( aType != LAYER_NETCLASS_REFS )
1739 {
1740 m_lastTextBold = labelItem->IsBold();
1741 m_lastTextItalic = labelItem->IsItalic();
1742 }
1743
1744 m_lastTextOrientation = labelItem->GetSpinStyle();
1745
1746 if( aType == LAYER_GLOBLABEL || aType == LAYER_HIERLABEL )
1747 {
1748 m_lastGlobalLabelShape = labelItem->GetShape();
1750 }
1751 else if( aType == LAYER_NETCLASS_REFS )
1752 {
1753 m_lastNetClassFlagShape = labelItem->GetShape();
1754 }
1755
1756 // Return elements are kept in aLabelList
1757 delete labelItem;
1758 return true;
1759}
1760
1761
1763{
1764 SCHEMATIC* schematic = getModel<SCHEMATIC>();
1765 SCHEMATIC_SETTINGS& settings = schematic->Settings();
1766 SCH_TEXT* textItem = nullptr;
1767
1768 textItem = new SCH_TEXT( aPosition );
1769 textItem->SetParent( schematic );
1770 textItem->SetTextSize( VECTOR2I( settings.m_DefaultTextSize, settings.m_DefaultTextSize ) );
1771 // Must be after SetTextSize()
1772 textItem->SetBold( m_lastTextBold );
1773 textItem->SetItalic( m_lastTextItalic );
1776 textItem->SetTextAngle( m_lastTextAngle );
1777 textItem->SetFlags( IS_NEW | IS_MOVING );
1778
1779 DIALOG_TEXT_PROPERTIES dlg( m_frame, textItem );
1780
1781 // QuasiModal required for syntax help and Scintilla auto-complete
1782 if( dlg.ShowQuasiModal() != wxID_OK )
1783 {
1784 delete textItem;
1785 return nullptr;
1786 }
1787
1788 m_lastTextBold = textItem->IsBold();
1789 m_lastTextItalic = textItem->IsItalic();
1790 m_lastTextHJustify = textItem->GetHorizJustify();
1791 m_lastTextVJustify = textItem->GetVertJustify();
1792 m_lastTextAngle = textItem->GetTextAngle();
1793 return textItem;
1794}
1795
1796
1798{
1799 SCHEMATIC_SETTINGS& settings = aSheet->Schematic()->Settings();
1800 SCH_SHEET_PIN* pin = new SCH_SHEET_PIN( aSheet );
1801
1802 pin->SetFlags( IS_NEW | IS_MOVING );
1803 pin->SetText( std::to_string( aSheet->GetPins().size() + 1 ) );
1804 pin->SetTextSize( VECTOR2I( settings.m_DefaultTextSize, settings.m_DefaultTextSize ) );
1805 pin->SetPosition( aPosition );
1806 pin->ClearSelected();
1807
1808 m_lastSheetPinType = pin->GetShape();
1809
1810 return pin;
1811}
1812
1813
1815 const VECTOR2I& aPosition,
1816 SCH_HIERLABEL* aLabel )
1817{
1818 auto pin = createNewSheetPin( aSheet, aPosition );
1819 pin->SetText( aLabel->GetText() );
1820 pin->SetShape( aLabel->GetShape() );
1821 return pin;
1822}
1823
1824
1826{
1827 SCH_ITEM* item = nullptr;
1830 bool ignorePrimePosition = false;
1831 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
1832 SCH_SHEET* sheet = nullptr;
1833 wxString description;
1834
1835 if( m_inDrawingTool )
1836 return 0;
1837
1839
1840 bool isText = aEvent.IsAction( &SCH_ACTIONS::placeSchematicText );
1841 bool isGlobalLabel = aEvent.IsAction( &SCH_ACTIONS::placeGlobalLabel );
1842 bool isHierLabel = aEvent.IsAction( &SCH_ACTIONS::placeHierLabel );
1843 bool isClassLabel = aEvent.IsAction( &SCH_ACTIONS::placeClassLabel );
1844 bool isNetLabel = aEvent.IsAction( &SCH_ACTIONS::placeLabel );
1845 bool isSheetPin = aEvent.IsAction( &SCH_ACTIONS::placeSheetPin );
1846
1847 GRID_HELPER_GRIDS snapGrid = isText ? GRID_TEXT : GRID_CONNECTABLE;
1848
1849 // If we have a selected sheet use it, otherwise try to get one under the cursor
1850 if( isSheetPin )
1851 sheet = dynamic_cast<SCH_SHEET*>( m_selectionTool->GetSelection().Front() );
1852
1854
1855 m_frame->PushTool( aEvent );
1856
1857 auto setCursor =
1858 [&]()
1859 {
1860 if( item )
1861 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PLACE );
1862 else if( isText )
1863 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::TEXT );
1864 else if( isGlobalLabel )
1865 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_GLOBAL );
1866 else if( isNetLabel )
1867 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_NET );
1868 else if( isClassLabel )
1869 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_NET ); // JEY TODO: netclass directive cursor
1870 else if( isHierLabel )
1871 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::LABEL_HIER );
1872 else
1873 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
1874 };
1875
1876 auto updatePreview =
1877 [&]()
1878 {
1880 m_view->AddToPreview( item, false );
1881 item->RunOnChildren( [&]( SCH_ITEM* aChild )
1882 {
1883 m_view->AddToPreview( aChild, false );
1884 },
1885 RECURSE_MODE::NO_RECURSE );
1886 m_frame->SetMsgPanel( item );
1887 };
1888
1889 auto cleanup =
1890 [&]()
1891 {
1894 delete item;
1895 item = nullptr;
1896 };
1897
1898 auto prepItemForPlacement =
1899 [&]( SCH_ITEM* aItem, const VECTOR2I& cursorPos )
1900 {
1901 item->SetPosition( cursorPos );
1902
1903 item->SetFlags( IS_NEW | IS_MOVING );
1904
1905 // Not placed yet, so pass a nullptr screen reference
1906 item->AutoplaceFields( nullptr, AUTOPLACE_AUTO );
1907
1908 updatePreview();
1911
1912 // update the cursor so it looks correct before another event
1913 setCursor();
1914 };
1915
1916
1917 Activate();
1918
1919 // Must be done after Activate() so that it gets set into the correct context
1920 controls->ShowCursor( true );
1921
1922 // Set initial cursor
1923 setCursor();
1924
1925 if( aEvent.HasPosition() )
1926 {
1927 m_toolMgr->PrimeTool( aEvent.Position() );
1928 }
1929 else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate()
1930 && ( isText || isGlobalLabel || isHierLabel || isClassLabel || isNetLabel ) )
1931 {
1932 m_toolMgr->PrimeTool( { 0, 0 } );
1933 ignorePrimePosition = true;
1934 }
1935
1936 SCH_COMMIT commit( m_toolMgr );
1937 std::list<std::unique_ptr<SCH_LABEL_BASE>> itemsToPlace;
1938
1939 // Main loop: keep receiving events
1940 while( TOOL_EVENT* evt = Wait() )
1941 {
1942 setCursor();
1943 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
1944 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
1945
1946 VECTOR2I cursorPos = controls->GetMousePosition();
1947 cursorPos = grid.BestSnapAnchor( cursorPos, snapGrid, item );
1948 controls->ForceCursorPosition( true, cursorPos );
1949
1950 // The tool hotkey is interpreted as a click when drawing
1951 bool isSyntheticClick = item && evt->IsActivate() && evt->HasPosition()
1952 && evt->Matches( aEvent );
1953
1954 if( evt->IsCancelInteractive() || evt->IsAction( &ACTIONS::undo ) )
1955 {
1957
1958 if( item )
1959 {
1960 cleanup();
1961 }
1962 else
1963 {
1964 m_frame->PopTool( aEvent );
1965 break;
1966 }
1967 }
1968 else if( evt->IsActivate() && !isSyntheticClick )
1969 {
1970 if( item && evt->IsMoveTool() )
1971 {
1972 // we're already moving our own item; ignore the move tool
1973 evt->SetPassEvent( false );
1974 continue;
1975 }
1976
1977 if( item )
1978 {
1979 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel item creation." ) );
1980 evt->SetPassEvent( false );
1981 continue;
1982 }
1983
1984 if( evt->IsPointEditor() )
1985 {
1986 // don't exit (the point editor runs in the background)
1987 }
1988 else if( evt->IsMoveTool() )
1989 {
1990 // leave ourselves on the stack so we come back after the move
1991 break;
1992 }
1993 else
1994 {
1995 m_frame->PopTool( aEvent );
1996 break;
1997 }
1998 }
1999 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) || isSyntheticClick )
2000 {
2001 PLACE_NEXT:
2002 // First click creates...
2003 if( !item )
2004 {
2006
2007 if( isText )
2008 {
2009 item = createNewText( cursorPos );
2010 description = _( "Add Text" );
2011 }
2012 else if( isHierLabel )
2013 {
2014 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->GetPlacementTemplate() )
2015 {
2016 auto pin = static_cast<SCH_HIERLABEL*>(
2017 m_dialogSyncSheetPin->GetPlacementTemplate() );
2018 SCH_HIERLABEL* label = new SCH_HIERLABEL( cursorPos );
2019 SCHEMATIC* schematic = getModel<SCHEMATIC>();
2020 label->SetText( pin->GetText() );
2021 label->SetShape( pin->GetShape() );
2023 label->SetParent( schematic );
2024 label->SetBold( m_lastTextBold );
2025 label->SetItalic( m_lastTextItalic );
2027 label->SetTextSize( VECTOR2I( schematic->Settings().m_DefaultTextSize,
2028 schematic->Settings().m_DefaultTextSize ) );
2029 label->SetFlags( IS_NEW | IS_MOVING );
2030 itemsToPlace.push_back( std::unique_ptr<SCH_LABEL_BASE>( label ) );
2031 }
2032 else
2033 {
2034 createNewLabel( cursorPos, LAYER_HIERLABEL, itemsToPlace );
2035 }
2036
2037 description = _( "Add Hierarchical Label" );
2038 }
2039 else if( isNetLabel )
2040 {
2041 createNewLabel( cursorPos, LAYER_LOCLABEL, itemsToPlace );
2042 description = _( "Add Label" );
2043 }
2044 else if( isGlobalLabel )
2045 {
2046 createNewLabel( cursorPos, LAYER_GLOBLABEL, itemsToPlace );
2047 description = _( "Add Label" );
2048 }
2049 else if( isClassLabel )
2050 {
2051 createNewLabel( cursorPos, LAYER_NETCLASS_REFS, itemsToPlace );
2052 description = _( "Add Label" );
2053 }
2054 else if( isSheetPin )
2055 {
2056 EDA_ITEM* i = nullptr;
2057
2058 // If we didn't have a sheet selected, try to find one under the cursor
2059 if( !sheet && m_selectionTool->SelectPoint( cursorPos, { SCH_SHEET_T }, &i ) )
2060 sheet = dynamic_cast<SCH_SHEET*>( i );
2061
2062 if( !sheet )
2063 {
2064 m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( m_frame );
2065 m_statusPopup->SetText( _( "Click over a sheet." ) );
2067 + wxPoint( 20, 20 ) );
2068 m_statusPopup->PopupFor( 2000 );
2069 item = nullptr;
2070 }
2071 else
2072 {
2073 // User is using the 'Sync Sheet Pins' tool
2074 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->GetPlacementTemplate() )
2075 {
2077 sheet, cursorPos,
2078 static_cast<SCH_HIERLABEL*>(
2079 m_dialogSyncSheetPin->GetPlacementTemplate() ) );
2080 }
2081 else
2082 {
2083 // User is using the 'Place Sheet Pins' tool
2084 SCH_HIERLABEL* label = importHierLabel( sheet );
2085
2086 if( !label )
2087 {
2088 m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( m_frame );
2089 m_statusPopup->SetText( _( "No new hierarchical labels found." ) );
2091 + wxPoint( 20, 20 ) );
2092 m_statusPopup->PopupFor( 2000 );
2093 item = nullptr;
2094
2095 m_frame->PopTool( aEvent );
2096 break;
2097 }
2098
2099 item = createNewSheetPinFromLabel( sheet, cursorPos, label );
2100 }
2101 }
2102
2103 description = _( "Add Sheet Pin" );
2104 }
2105
2106 // If we started with a hotkey which has a position then warp back to that.
2107 // Otherwise update to the current mouse position pinned inside the autoscroll
2108 // boundaries.
2109 if( evt->IsPrime() && !ignorePrimePosition )
2110 {
2111 cursorPos = grid.Align( evt->Position() );
2112 getViewControls()->WarpMouseCursor( cursorPos, true );
2113 }
2114 else
2115 {
2117 cursorPos = getViewControls()->GetMousePosition();
2118 cursorPos = grid.BestSnapAnchor( cursorPos, snapGrid, item );
2119 }
2120
2121 if( !itemsToPlace.empty() )
2122 {
2123 item = itemsToPlace.front().release();
2124 itemsToPlace.pop_front();
2125 }
2126
2127 if( item )
2128 prepItemForPlacement( item, cursorPos );
2129
2130 controls->SetCursorPosition( cursorPos, false );
2131 }
2132 else // ... and second click places:
2133 {
2134 item->ClearFlags( IS_MOVING );
2135
2136 if( item->IsConnectable() )
2138
2139 if( isSheetPin )
2140 {
2141 // Sheet pins are owned by their parent sheet.
2142 commit.Modify( sheet, m_frame->GetScreen() );
2143 sheet->AddPin( (SCH_SHEET_PIN*) item );
2144 }
2145 else
2146 {
2148 m_frame->AddToScreen( item, m_frame->GetScreen() );
2149 commit.Added( item, m_frame->GetScreen() );
2150 }
2151
2153
2154 commit.Push( description );
2155
2157
2158 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->GetPlacementTemplate() )
2159 {
2160 m_dialogSyncSheetPin->EndPlaceItem( item );
2161
2162 if( m_dialogSyncSheetPin->CanPlaceMore() )
2163 {
2164 item = nullptr;
2165 goto PLACE_NEXT;
2166 }
2167
2168 m_frame->PopTool( aEvent );
2170 m_dialogSyncSheetPin->Show( true );
2171 break;
2172 }
2173
2174 item = nullptr;
2175
2176 if( isSheetPin )
2177 {
2178 SCH_HIERLABEL* label = importHierLabel( sheet );
2179
2180 if( !label )
2181 {
2182 m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( m_frame );
2183 m_statusPopup->SetText( _( "No new hierarchical labels found." ) );
2185 + wxPoint( 20, 20 ) );
2186 m_statusPopup->PopupFor( 2000 );
2187
2188 m_frame->PopTool( aEvent );
2189 break;
2190 }
2191
2192 item = createNewSheetPinFromLabel( sheet, cursorPos, label );
2193 }
2194 else if( !itemsToPlace.empty() )
2195 {
2196
2197 item = itemsToPlace.front().release();
2198 itemsToPlace.pop_front();
2199 prepItemForPlacement( item, cursorPos );
2200 }
2201 }
2202 }
2203 else if( evt->IsClick( BUT_RIGHT ) )
2204 {
2205 // Warp after context menu only if dragging...
2206 if( !item )
2208
2209 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
2210 }
2211 else if( item && evt->IsSelectionEvent() )
2212 {
2213 // This happens if our text was replaced out from under us by ConvertTextType()
2215
2216 if( selection.GetSize() == 1 )
2217 {
2218 item = (SCH_ITEM*) selection.Front();
2219 updatePreview();
2220 }
2221 else
2222 {
2223 item = nullptr;
2224 }
2225 }
2226 else if( evt->IsAction( &ACTIONS::increment ) )
2227 {
2229 evt->Parameter<ACTIONS::INCREMENT>() );
2230 }
2231 else if( evt->IsAction( &ACTIONS::duplicate )
2232 || evt->IsAction( &SCH_ACTIONS::repeatDrawItem ) )
2233 {
2234 if( item )
2235 {
2236 // This doesn't really make sense; we'll just end up dragging a stack of
2237 // objects so we ignore the duplicate and just carry on.
2238 wxBell();
2239 continue;
2240 }
2241
2242 // Exit. The duplicate will run in its own loop.
2243 m_frame->PopTool( aEvent );
2244 break;
2245 }
2246 else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
2247 {
2248 item->SetPosition( cursorPos );
2249
2250 // Not placed yet, so pass a nullptr screen reference
2251 item->AutoplaceFields( nullptr, AUTOPLACE_AUTO );
2252
2253 updatePreview();
2254 }
2255 else if( item && evt->IsAction( &ACTIONS::doDelete ) )
2256 {
2257 cleanup();
2258 }
2259 else if( evt->IsAction( &ACTIONS::redo ) )
2260 {
2261 wxBell();
2262 }
2263 else
2264 {
2265 evt->SetPassEvent();
2266 }
2267
2268 // Enable autopanning and cursor capture only when there is an item to be placed
2269 controls->SetAutoPan( item != nullptr );
2270 controls->CaptureCursor( item != nullptr );
2271 }
2272
2273 controls->SetAutoPan( false );
2274 controls->CaptureCursor( false );
2275 controls->ForceCursorPosition( false );
2276 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2277
2278 if( m_dialogSyncSheetPin && m_dialogSyncSheetPin->CanPlaceMore() )
2279 {
2280 m_dialogSyncSheetPin->EndPlacement();
2281 m_dialogSyncSheetPin->Show( true );
2282 }
2283
2284 return 0;
2285}
2286
2287
2289{
2290 SCHEMATIC* schematic = getModel<SCHEMATIC>();
2291 SCHEMATIC_SETTINGS& sch_settings = schematic->Settings();
2292 SCH_SHAPE* item = nullptr;
2293 bool isTextBox = aEvent.IsAction( &SCH_ACTIONS::drawTextBox );
2294 SHAPE_T type = aEvent.Parameter<SHAPE_T>();
2295 wxString description;
2296
2297 if( m_inDrawingTool )
2298 return 0;
2299
2301
2304 VECTOR2I cursorPos;
2305
2306 // We might be running as the same shape in another co-routine. Make sure that one
2307 // gets whacked.
2309
2311
2312 m_frame->PushTool( aEvent );
2313
2314 auto setCursor =
2315 [&]()
2316 {
2317 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
2318 };
2319
2320 auto cleanup =
2321 [&] ()
2322 {
2325 delete item;
2326 item = nullptr;
2327 };
2328
2329 Activate();
2330
2331 // Must be done after Activate() so that it gets set into the correct context
2332 getViewControls()->ShowCursor( true );
2333
2334 // Set initial cursor
2335 setCursor();
2336
2337 if( aEvent.HasPosition() )
2338 m_toolMgr->PrimeTool( aEvent.Position() );
2339
2340 // Main loop: keep receiving events
2341 while( TOOL_EVENT* evt = Wait() )
2342 {
2343 setCursor();
2344 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
2345 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
2346
2347 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
2348 controls->ForceCursorPosition( true, cursorPos );
2349
2350 // The tool hotkey is interpreted as a click when drawing
2351 bool isSyntheticClick = item && evt->IsActivate() && evt->HasPosition()
2352 && evt->Matches( aEvent );
2353
2354 if( evt->IsCancelInteractive() || ( item && evt->IsAction( &ACTIONS::undo ) ) )
2355 {
2356 if( item )
2357 {
2358 cleanup();
2359 }
2360 else
2361 {
2362 m_frame->PopTool( aEvent );
2363 break;
2364 }
2365 }
2366 else if( evt->IsActivate() && !isSyntheticClick )
2367 {
2368 if( item && evt->IsMoveTool() )
2369 {
2370 // we're already drawing our own item; ignore the move tool
2371 evt->SetPassEvent( false );
2372 continue;
2373 }
2374
2375 if( item )
2376 cleanup();
2377
2378 if( evt->IsPointEditor() )
2379 {
2380 // don't exit (the point editor runs in the background)
2381 }
2382 else if( evt->IsMoveTool() )
2383 {
2384 // leave ourselves on the stack so we come back after the move
2385 break;
2386 }
2387 else
2388 {
2389 m_frame->PopTool( aEvent );
2390 break;
2391 }
2392 }
2393 else if( evt->IsClick( BUT_LEFT ) && !item )
2394 {
2396
2397 if( isTextBox )
2398 {
2400
2401 textbox->SetTextSize( VECTOR2I( sch_settings.m_DefaultTextSize,
2402 sch_settings.m_DefaultTextSize ) );
2403
2404 // Must come after SetTextSize()
2405 textbox->SetBold( m_lastTextBold );
2406 textbox->SetItalic( m_lastTextItalic );
2407
2408 textbox->SetTextAngle( m_lastTextboxAngle );
2411 textbox->SetStroke( m_lastTextboxStroke );
2413 textbox->SetParent( schematic );
2414
2415 item = textbox;
2416 description = _( "Add Text Box" );
2417 }
2418 else
2419 {
2420 item = new SCH_SHAPE( type, LAYER_NOTES, 0, m_lastFillStyle );
2421
2422 item->SetStroke( m_lastStroke );
2424 item->SetParent( schematic );
2425 description = wxString::Format( _( "Add %s" ), item->GetFriendlyName() );
2426 }
2427
2428 item->SetFlags( IS_NEW );
2429 item->BeginEdit( cursorPos );
2430
2432 m_view->AddToPreview( item->Clone() );
2433 }
2434 else if( item && ( evt->IsClick( BUT_LEFT )
2435 || evt->IsDblClick( BUT_LEFT )
2436 || isSyntheticClick
2437 || evt->IsAction( &ACTIONS::finishInteractive ) ) )
2438 {
2439 if( evt->IsDblClick( BUT_LEFT )
2440 || evt->IsAction( &ACTIONS::finishInteractive )
2441 || !item->ContinueEdit( cursorPos ) )
2442 {
2443 item->EndEdit();
2444 item->ClearEditFlags();
2445 item->SetFlags( IS_NEW );
2446
2447 if( isTextBox )
2448 {
2449 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( item );
2450 DIALOG_TEXT_PROPERTIES dlg( m_frame, textbox );
2451
2452 getViewControls()->SetAutoPan( false );
2453 getViewControls()->CaptureCursor( false );
2454
2455 // QuasiModal required for syntax help and Scintilla auto-complete
2456 if( dlg.ShowQuasiModal() != wxID_OK )
2457 {
2458 cleanup();
2459 continue;
2460 }
2461
2462 m_lastTextBold = textbox->IsBold();
2463 m_lastTextItalic = textbox->IsItalic();
2464 m_lastTextboxAngle = textbox->GetTextAngle();
2467 m_lastTextboxStroke = textbox->GetStroke();
2470 }
2471 else
2472 {
2473 m_lastStroke = item->GetStroke();
2474 m_lastFillStyle = item->GetFillMode();
2475 m_lastFillColor = item->GetFillColor();
2476 }
2477
2478 SCH_COMMIT commit( m_toolMgr );
2479 commit.Add( item, m_frame->GetScreen() );
2480 commit.Push( wxString::Format( _( "Draw %s" ), item->GetClass() ) );
2481
2483 item = nullptr;
2484
2487 }
2488 }
2489 else if( evt->IsAction( &ACTIONS::duplicate )
2490 || evt->IsAction( &SCH_ACTIONS::repeatDrawItem ) )
2491 {
2492 if( item )
2493 {
2494 // This doesn't really make sense; we'll just end up dragging a stack of
2495 // objects so we ignore the duplicate and just carry on.
2496 wxBell();
2497 continue;
2498 }
2499
2500 // Exit. The duplicate will run in its own loop.
2501 m_frame->PopTool( aEvent );
2502 break;
2503 }
2504 else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
2505 {
2506 item->CalcEdit( cursorPos );
2508 m_view->AddToPreview( item->Clone() );
2509 m_frame->SetMsgPanel( item );
2510 }
2511 else if( evt->IsDblClick( BUT_LEFT ) && !item )
2512 {
2514 }
2515 else if( evt->IsClick( BUT_RIGHT ) )
2516 {
2517 // Warp after context menu only if dragging...
2518 if( !item )
2520
2521 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
2522 }
2523 else if( item && evt->IsAction( &ACTIONS::redo ) )
2524 {
2525 wxBell();
2526 }
2527 else
2528 {
2529 evt->SetPassEvent();
2530 }
2531
2532 // Enable autopanning and cursor capture only when there is a shape being drawn
2533 getViewControls()->SetAutoPan( item != nullptr );
2534 getViewControls()->CaptureCursor( item != nullptr );
2535 }
2536
2537 getViewControls()->SetAutoPan( false );
2538 getViewControls()->CaptureCursor( false );
2539 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2540 return 0;
2541}
2542
2543
2545{
2546 if( m_inDrawingTool )
2547 return 0;
2548
2550 SCOPED_SET_RESET<bool> scopedDrawMode( m_drawingRuleArea, true );
2551
2554 VECTOR2I cursorPos;
2555
2556 RULE_AREA_CREATE_HELPER ruleAreaTool( *getView(), m_frame, m_toolMgr );
2557 POLYGON_GEOM_MANAGER polyGeomMgr( ruleAreaTool );
2558 bool started = false;
2559
2560 // We might be running as the same shape in another co-routine. Make sure that one
2561 // gets whacked.
2563
2565
2566 m_frame->PushTool( aEvent );
2567
2568 auto setCursor =
2569 [&]()
2570 {
2571 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
2572 };
2573
2574 auto cleanup = [&]()
2575 {
2576 polyGeomMgr.Reset();
2577 started = false;
2578 getViewControls()->SetAutoPan( false );
2579 getViewControls()->CaptureCursor( false );
2581 };
2582
2583 Activate();
2584
2585 // Must be done after Activate() so that it gets set into the correct context
2586 getViewControls()->ShowCursor( true );
2587 //m_controls->ForceCursorPosition( false );
2588
2589 // Set initial cursor
2590 setCursor();
2591
2592 if( aEvent.HasPosition() )
2593 m_toolMgr->PrimeTool( aEvent.Position() );
2594
2595 // Main loop: keep receiving events
2596 while( TOOL_EVENT* evt = Wait() )
2597 {
2598 setCursor();
2599
2600 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
2601 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
2602
2603 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_CONNECTABLE );
2604 controls->ForceCursorPosition( true, cursorPos );
2605
2609
2610 if( evt->IsCancelInteractive() )
2611 {
2612 if( started )
2613 {
2614 cleanup();
2615 }
2616 else
2617 {
2618 m_frame->PopTool( aEvent );
2619
2620 // We've handled the cancel event. Don't cancel other tools
2621 evt->SetPassEvent( false );
2622 break;
2623 }
2624 }
2625 else if( evt->IsActivate() )
2626 {
2627 if( started )
2628 cleanup();
2629
2630 if( evt->IsPointEditor() )
2631 {
2632 // don't exit (the point editor runs in the background)
2633 }
2634 else if( evt->IsMoveTool() )
2635 {
2636 // leave ourselves on the stack so we come back after the move
2637 break;
2638 }
2639 else
2640 {
2641 m_frame->PopTool( aEvent );
2642 break;
2643 }
2644 }
2645 else if( evt->IsClick( BUT_RIGHT ) )
2646 {
2647 if( !started )
2649
2650 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
2651 }
2652 // events that lock in nodes
2653 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT )
2654 || evt->IsAction( &SCH_ACTIONS::closeOutline ) )
2655 {
2656 // Check if it is double click / closing line (so we have to finish the zone)
2657 const bool endPolygon = evt->IsDblClick( BUT_LEFT )
2658 || evt->IsAction( &SCH_ACTIONS::closeOutline )
2659 || polyGeomMgr.NewPointClosesOutline( cursorPos );
2660
2661 if( endPolygon )
2662 {
2663 polyGeomMgr.SetFinished();
2664 polyGeomMgr.Reset();
2665
2666 started = false;
2667 getViewControls()->SetAutoPan( false );
2668 getViewControls()->CaptureCursor( false );
2669 }
2670 // adding a corner
2671 else if( polyGeomMgr.AddPoint( cursorPos ) )
2672 {
2673 if( !started )
2674 {
2675 started = true;
2676
2677 getViewControls()->SetAutoPan( true );
2678 getViewControls()->CaptureCursor( true );
2679 }
2680 }
2681 }
2682 else if( started
2683 && ( evt->IsAction( &SCH_ACTIONS::deleteLastPoint )
2684 || evt->IsAction( &ACTIONS::doDelete )
2685 || evt->IsAction( &ACTIONS::undo ) ) )
2686 {
2687 if( std::optional<VECTOR2I> last = polyGeomMgr.DeleteLastCorner() )
2688 {
2689 cursorPos = last.value();
2690 getViewControls()->WarpMouseCursor( cursorPos, true );
2691 getViewControls()->ForceCursorPosition( true, cursorPos );
2692 polyGeomMgr.SetCursorPosition( cursorPos );
2693 }
2694 else
2695 {
2696 cleanup();
2697 }
2698 }
2699 else if( started && ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) )
2700 {
2701 polyGeomMgr.SetCursorPosition( cursorPos );
2702 }
2703 else
2704 {
2705 evt->SetPassEvent();
2706 }
2707
2708 } // end while
2709
2710 getViewControls()->SetAutoPan( false );
2711 getViewControls()->CaptureCursor( false );
2712 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2713 return 0;
2714}
2715
2716
2718{
2719 SCHEMATIC* schematic = getModel<SCHEMATIC>();
2720 SCH_TABLE* table = nullptr;
2721
2722 if( m_inDrawingTool )
2723 return 0;
2724
2726
2729 VECTOR2I cursorPos;
2730
2731 // We might be running as the same shape in another co-routine. Make sure that one
2732 // gets whacked.
2734
2736
2737 m_frame->PushTool( aEvent );
2738
2739 auto setCursor =
2740 [&]()
2741 {
2742 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
2743 };
2744
2745 auto cleanup =
2746 [&] ()
2747 {
2750 delete table;
2751 table = nullptr;
2752 };
2753
2754 Activate();
2755
2756 // Must be done after Activate() so that it gets set into the correct context
2757 getViewControls()->ShowCursor( true );
2758
2759 // Set initial cursor
2760 setCursor();
2761
2762 if( aEvent.HasPosition() )
2763 m_toolMgr->PrimeTool( aEvent.Position() );
2764
2765 // Main loop: keep receiving events
2766 while( TOOL_EVENT* evt = Wait() )
2767 {
2768 setCursor();
2769 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
2770 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
2771
2772 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
2773 controls->ForceCursorPosition( true, cursorPos );
2774
2775 // The tool hotkey is interpreted as a click when drawing
2776 bool isSyntheticClick = table
2777 && evt->IsActivate()
2778 && evt->HasPosition()
2779 && evt->Matches( aEvent );
2780
2781 if( evt->IsCancelInteractive() || ( table && evt->IsAction( &ACTIONS::undo ) ) )
2782 {
2783 if( table )
2784 {
2785 cleanup();
2786 }
2787 else
2788 {
2789 m_frame->PopTool( aEvent );
2790 break;
2791 }
2792 }
2793 else if( evt->IsActivate() && !isSyntheticClick )
2794 {
2795 if( table && evt->IsMoveTool() )
2796 {
2797 // we're already drawing our own item; ignore the move tool
2798 evt->SetPassEvent( false );
2799 continue;
2800 }
2801
2802 if( table )
2803 cleanup();
2804
2805 if( evt->IsPointEditor() )
2806 {
2807 // don't exit (the point editor runs in the background)
2808 }
2809 else if( evt->IsMoveTool() )
2810 {
2811 // leave ourselves on the stack so we come back after the move
2812 break;
2813 }
2814 else
2815 {
2816 m_frame->PopTool( aEvent );
2817 break;
2818 }
2819 }
2820 else if( evt->IsClick( BUT_LEFT ) && !table )
2821 {
2823
2824 table = new SCH_TABLE( 0 );
2825 table->SetColCount( 1 );
2826
2827 SCH_TABLECELL* tableCell = new SCH_TABLECELL();
2828 int defaultTextSize = schematic->Settings().m_DefaultTextSize;
2829
2830 tableCell->SetTextSize( VECTOR2I( defaultTextSize, defaultTextSize ) );
2831 table->AddCell( tableCell );
2832
2833 table->SetParent( schematic );
2834 table->SetFlags( IS_NEW );
2835 table->SetPosition( cursorPos );
2836
2838 m_view->AddToPreview( table->Clone() );
2839 }
2840 else if( table && ( evt->IsClick( BUT_LEFT )
2841 || evt->IsDblClick( BUT_LEFT )
2842 || isSyntheticClick
2843 || evt->IsAction( &SCH_ACTIONS::finishInteractive ) ) )
2844 {
2845 table->ClearEditFlags();
2846 table->SetFlags( IS_NEW );
2847 table->Normalize();
2848
2850
2851 // QuasiModal required for Scintilla auto-complete
2852 if( dlg.ShowQuasiModal() == wxID_OK )
2853 {
2854 SCH_COMMIT commit( m_toolMgr );
2855 commit.Add( table, m_frame->GetScreen() );
2856 commit.Push( _( "Draw Table" ) );
2857
2860 }
2861 else
2862 {
2863 delete table;
2864 }
2865
2866 table = nullptr;
2868 }
2869 else if( table && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
2870 {
2871 VECTOR2I gridSize = grid.GetGridSize( grid.GetItemGrid( table ) );
2872 int fontSize = schematic->Settings().m_DefaultTextSize;
2873 VECTOR2I origin( table->GetPosition() );
2874 VECTOR2I requestedSize( cursorPos - origin );
2875
2876 int colCount = std::max( 1, requestedSize.x / ( fontSize * 15 ) );
2877 int rowCount = std::max( 1, requestedSize.y / ( fontSize * 2 ) );
2878
2879 VECTOR2I cellSize( std::max( gridSize.x * 5, requestedSize.x / colCount ),
2880 std::max( gridSize.y * 2, requestedSize.y / rowCount ) );
2881
2882 cellSize.x = KiROUND( (double) cellSize.x / gridSize.x ) * gridSize.x;
2883 cellSize.y = KiROUND( (double) cellSize.y / gridSize.y ) * gridSize.y;
2884
2885 table->ClearCells();
2886 table->SetColCount( colCount );
2887
2888 for( int col = 0; col < colCount; ++col )
2889 table->SetColWidth( col, cellSize.x );
2890
2891 for( int row = 0; row < rowCount; ++row )
2892 {
2893 table->SetRowHeight( row, cellSize.y );
2894
2895 for( int col = 0; col < colCount; ++col )
2896 {
2897 SCH_TABLECELL* cell = new SCH_TABLECELL();
2898 int defaultTextSize = schematic->Settings().m_DefaultTextSize;
2899
2900 cell->SetTextSize( VECTOR2I( defaultTextSize, defaultTextSize ) );
2901 cell->SetPosition( origin + VECTOR2I( col * cellSize.x, row * cellSize.y ) );
2902 cell->SetEnd( cell->GetPosition() + cellSize );
2903 table->AddCell( cell );
2904 }
2905 }
2906
2908 m_view->AddToPreview( table->Clone() );
2910 }
2911 else if( evt->IsDblClick( BUT_LEFT ) && !table )
2912 {
2914 }
2915 else if( evt->IsClick( BUT_RIGHT ) )
2916 {
2917 // Warp after context menu only if dragging...
2918 if( !table )
2920
2921 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
2922 }
2923 else if( table && evt->IsAction( &ACTIONS::redo ) )
2924 {
2925 wxBell();
2926 }
2927 else
2928 {
2929 evt->SetPassEvent();
2930 }
2931
2932 // Enable autopanning and cursor capture only when there is a shape being drawn
2933 getViewControls()->SetAutoPan( table != nullptr );
2934 getViewControls()->CaptureCursor( table != nullptr );
2935 }
2936
2937 getViewControls()->SetAutoPan( false );
2938 getViewControls()->CaptureCursor( false );
2939 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
2940 return 0;
2941}
2942
2943
2945{
2946 bool isDrawSheetCopy = aEvent.IsAction( &SCH_ACTIONS::drawSheetFromFile );
2947 bool isDrawSheetFromDesignBlock = aEvent.IsAction( &SCH_ACTIONS::drawSheetFromDesignBlock );
2948
2949 DESIGN_BLOCK* designBlock = nullptr;
2950 SCH_SHEET* sheet = nullptr;
2951 wxString filename;
2952
2953 if( isDrawSheetCopy )
2954 {
2955 wxString* ptr = aEvent.Parameter<wxString*>();
2956 wxCHECK( ptr, 0 );
2957
2958 // We own the string if we're importing a sheet
2959 filename = *ptr;
2960 delete ptr;
2961 }
2962 else if( isDrawSheetFromDesignBlock )
2963 {
2964 designBlock = aEvent.Parameter<DESIGN_BLOCK*>();
2965 wxCHECK( designBlock, 0 );
2966 filename = designBlock->GetSchematicFile();
2967 }
2968
2969 if( ( isDrawSheetCopy || isDrawSheetFromDesignBlock ) && !wxFileExists( filename ) )
2970 {
2971 wxMessageBox( wxString::Format( _( "File '%s' does not exist." ), filename ) );
2972 return 0;
2973 }
2974
2975 if( m_inDrawingTool )
2976 return 0;
2977
2979
2981 SCHEMATIC_SETTINGS& schSettings = m_frame->Schematic().Settings();
2984 VECTOR2I cursorPos;
2985
2987
2988 m_frame->PushTool( aEvent );
2989
2990 auto setCursor =
2991 [&]()
2992 {
2993 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
2994 };
2995
2996 auto cleanup =
2997 [&] ()
2998 {
3001 delete sheet;
3002 sheet = nullptr;
3003 };
3004
3005 Activate();
3006
3007 // Must be done after Activate() so that it gets set into the correct context
3008 getViewControls()->ShowCursor( true );
3009
3010 // Set initial cursor
3011 setCursor();
3012
3013 if( aEvent.HasPosition() && !( isDrawSheetCopy || isDrawSheetFromDesignBlock ) )
3014 m_toolMgr->PrimeTool( aEvent.Position() );
3015
3016 // Main loop: keep receiving events
3017 while( TOOL_EVENT* evt = Wait() )
3018 {
3019 setCursor();
3020 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
3021 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
3022
3023 cursorPos = grid.Align( controls->GetMousePosition(), GRID_HELPER_GRIDS::GRID_GRAPHICS );
3024 controls->ForceCursorPosition( true, cursorPos );
3025
3026 // The tool hotkey is interpreted as a click when drawing
3027 bool isSyntheticClick = sheet && evt->IsActivate() && evt->HasPosition()
3028 && evt->Matches( aEvent );
3029
3030 if( evt->IsCancelInteractive() || ( sheet && evt->IsAction( &ACTIONS::undo ) ) )
3031 {
3033
3034 if( sheet )
3035 {
3036 cleanup();
3037 }
3038 else
3039 {
3040 m_frame->PopTool( aEvent );
3041 break;
3042 }
3043 }
3044 else if( evt->IsActivate() && !isSyntheticClick )
3045 {
3046 if( sheet && evt->IsMoveTool() )
3047 {
3048 // we're already drawing our own item; ignore the move tool
3049 evt->SetPassEvent( false );
3050 continue;
3051 }
3052
3053 if( sheet )
3054 {
3055 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel sheet creation." ) );
3056 evt->SetPassEvent( false );
3057 continue;
3058 }
3059
3060 if( evt->IsPointEditor() )
3061 {
3062 // don't exit (the point editor runs in the background)
3063 }
3064 else if( evt->IsMoveTool() )
3065 {
3066 // leave ourselves on the stack so we come back after the move
3067 break;
3068 }
3069 else
3070 {
3071 m_frame->PopTool( aEvent );
3072 break;
3073 }
3074 }
3075 else if( !sheet && ( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) ) )
3076 {
3078
3079 if( selection.Size() == 1
3080 && selection.Front()->Type() == SCH_SHEET_T
3081 && selection.Front()->GetBoundingBox().Contains( cursorPos ) )
3082 {
3083 if( evt->IsClick( BUT_LEFT ) )
3084 {
3085 // sheet already selected
3086 continue;
3087 }
3088 else if( evt->IsDblClick( BUT_LEFT ) )
3089 {
3091 m_frame->PopTool( aEvent );
3092 break;
3093 }
3094 }
3095
3097
3098 sheet = new SCH_SHEET( m_frame->GetCurrentSheet().Last(), cursorPos );
3099 sheet->SetScreen( nullptr );
3100
3101 if( isDrawSheetCopy )
3102 {
3103 wxFileName fn( filename );
3104
3105 sheet->GetField( FIELD_T::SHEET_NAME )->SetText( fn.GetName() );
3106 sheet->GetField( FIELD_T::SHEET_FILENAME )->SetText( fn.GetName() + wxT( "." ) + FILEEXT::KiCadSchematicFileExtension );
3107 }
3108 else if( isDrawSheetFromDesignBlock )
3109 {
3110 wxFileName fn( filename );
3111
3112 sheet->GetField( FIELD_T::SHEET_NAME )->SetText( designBlock->GetLibId().GetLibItemName() );
3113 sheet->GetField( FIELD_T::SHEET_FILENAME )->SetText( fn.GetName() + wxT( "." ) + FILEEXT::KiCadSchematicFileExtension );
3114
3115 std::vector<SCH_FIELD>& sheetFields = sheet->GetFields();
3116
3117 // Copy default fields into the sheet
3118 for( const auto& [fieldName, fieldValue] : designBlock->GetFields() )
3119 {
3120 sheetFields.emplace_back( sheet, FIELD_T::USER, fieldName );
3121 sheetFields.back().SetText( fieldValue );
3122 sheetFields.back().SetVisible( false );
3123 }
3124 }
3125 else
3126 {
3127 sheet->GetField( FIELD_T::SHEET_NAME )->SetText( wxT( "Untitled Sheet" ) );
3128 sheet->GetField( FIELD_T::SHEET_FILENAME )->SetText( wxString::Format( wxT( "untitled.%s" ), FILEEXT::KiCadSchematicFileExtension ) );
3129 }
3130
3131 sheet->SetFlags( IS_NEW | IS_MOVING );
3135 sizeSheet( sheet, cursorPos );
3136
3137 SCH_SHEET_LIST hierarchy = m_frame->Schematic().Hierarchy();
3139 instance.push_back( sheet );
3140 wxString pageNumber;
3141
3142 // Don't try to be too clever when assigning the next availabe page number. Just use
3143 // the number of sheets plus one.
3144 pageNumber.Printf( wxT( "%d" ), static_cast<int>( hierarchy.size() ) + 1 );
3145 instance.SetPageNumber( pageNumber );
3146
3148 m_view->AddToPreview( sheet->Clone() );
3149 }
3150 else if( sheet && ( evt->IsClick( BUT_LEFT )
3151 || evt->IsDblClick( BUT_LEFT )
3152 || isSyntheticClick
3153 || evt->IsAction( &ACTIONS::finishInteractive ) ) )
3154 {
3155 getViewControls()->SetAutoPan( false );
3156 getViewControls()->CaptureCursor( false );
3157
3158 if( m_frame->EditSheetProperties( static_cast<SCH_SHEET*>( sheet ),
3159 &m_frame->GetCurrentSheet(), nullptr, nullptr,
3160 nullptr, &filename ) )
3161 {
3163
3165
3166 // Use the commit we were provided or make our own
3167 SCH_COMMIT tempCommit = SCH_COMMIT( m_toolMgr );
3168 SCH_COMMIT& c = evt->Commit() ? *( (SCH_COMMIT*) evt->Commit() ) : tempCommit;
3169
3170 // We need to manually add the sheet to the screen otherwise annotation will not be able to find
3171 // the sheet and its symbols to annotate.
3172 m_frame->AddToScreen( sheet );
3173 c.Added( sheet, m_frame->GetScreen() );
3174
3175 // This convoluted logic means we always annotate unless we are drawing a copy/design block
3176 // and the user has explicitly requested we keep the annotations via checkbox
3178
3179 if( annotate.automatic
3180 && !( ( isDrawSheetCopy || isDrawSheetFromDesignBlock )
3182 {
3183 // Annotation will remove this from selection, but we add it back later
3184 m_selectionTool->AddItemToSel( sheet );
3185
3186 NULL_REPORTER reporter;
3189 (ANNOTATE_ALGO_T) annotate.method, true /* recursive */,
3190 schSettings.m_AnnotateStartNum, true, false, reporter );
3191 }
3192
3193 c.Push( isDrawSheetCopy ? "Import Sheet Copy" : "Draw Sheet" );
3194
3195 m_selectionTool->AddItemToSel( sheet );
3196 }
3197 else
3198 {
3200 delete sheet;
3201 }
3202
3203 sheet = nullptr;
3204 }
3205 else if( evt->IsAction( &ACTIONS::duplicate )
3206 || evt->IsAction( &SCH_ACTIONS::repeatDrawItem ) )
3207 {
3208 if( sheet )
3209 {
3210 // This doesn't really make sense; we'll just end up dragging a stack of
3211 // objects so we ignore the duplicate and just carry on.
3212 wxBell();
3213 continue;
3214 }
3215
3216 // Exit. The duplicate will run in its own loop.
3217 m_frame->PopTool( aEvent );
3218 break;
3219 }
3220 else if( sheet && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
3221 {
3222 sizeSheet( sheet, cursorPos );
3224 m_view->AddToPreview( sheet->Clone() );
3225 m_frame->SetMsgPanel( sheet );
3226 }
3227 else if( evt->IsClick( BUT_RIGHT ) )
3228 {
3229 // Warp after context menu only if dragging...
3230 if( !sheet )
3232
3233 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
3234 }
3235 else if( sheet && evt->IsAction( &ACTIONS::redo ) )
3236 {
3237 wxBell();
3238 }
3239 else
3240 {
3241 evt->SetPassEvent();
3242 }
3243
3244 // Enable autopanning and cursor capture only when there is a sheet to be placed
3245 getViewControls()->SetAutoPan( sheet != nullptr );
3246 getViewControls()->CaptureCursor( sheet != nullptr );
3247 }
3248
3249 getViewControls()->SetAutoPan( false );
3250 getViewControls()->CaptureCursor( false );
3251 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
3252
3253 return 0;
3254}
3255
3256
3258{
3259 VECTOR2I pos = aSheet->GetPosition();
3260 VECTOR2I size = aPos - pos;
3261
3262 size.x = std::max( size.x, schIUScale.MilsToIU( MIN_SHEET_WIDTH ) );
3263 size.y = std::max( size.y, schIUScale.MilsToIU( MIN_SHEET_HEIGHT ) );
3264
3266 aSheet->Resize( VECTOR2I( grid.x - pos.x, grid.y - pos.y ) );
3267}
3268
3269
3270int SCH_DRAWING_TOOLS::doSyncSheetsPins( std::list<SCH_SHEET_PATH> sheetPaths )
3271{
3272 if( !sheetPaths.size() )
3273 {
3274 return 0;
3275 }
3276
3277 m_dialogSyncSheetPin = std::make_unique<DIALOG_SYNC_SHEET_PINS>(
3278 m_frame, std::move( sheetPaths ),
3279 std::make_shared<SHEET_SYNCHRONIZATION_AGENT>(
3280 [&]( EDA_ITEM* aItem, SCH_SHEET_PATH aPath,
3282 {
3283 SCH_COMMIT commit( m_toolMgr );
3284
3285 if( auto pin = dynamic_cast<SCH_SHEET_PIN*>( aItem ) )
3286 {
3287 commit.Modify( pin->GetParent(), aPath.LastScreen() );
3288 aModify();
3289 commit.Push( _( "Modify sheet pin" ) );
3290 }
3291 else
3292 {
3293 commit.Modify( aItem, aPath.LastScreen() );
3294 aModify();
3295 commit.Push( _( "Modify schematic item" ) );
3296 }
3297
3298 updateItem( aItem, true );
3299 m_frame->OnModify();
3300 },
3301 [&]( EDA_ITEM* aItem, SCH_SHEET_PATH aPath )
3302 {
3304 SCH_ACTIONS::changeSheet, &aPath );
3306 selectionTool->UnbrightenItem( aItem );
3307 selectionTool->AddItemToSel( aItem, true );
3309 },
3310 [&]( SCH_SHEET* aItem, SCH_SHEET_PATH aPath,
3312 std::set<EDA_ITEM*> aTemplates )
3313 {
3314 switch( aOp )
3315 {
3317 {
3318 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
3319 m_dialogSyncSheetPin->Hide();
3320 m_dialogSyncSheetPin->PreparePlacementTemplate(
3322 aTemplates );
3324 SCH_ACTIONS::changeSheet, &aPath );
3326 break;
3327 }
3329 {
3330 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
3331 m_dialogSyncSheetPin->Hide();
3332 m_dialogSyncSheetPin->PreparePlacementTemplate(
3334 aTemplates );
3336 SCH_ACTIONS::changeSheet, &aPath );
3337 m_toolMgr->GetTool<SCH_SELECTION_TOOL>()->SyncSelection( {}, nullptr,
3338 { sheet } );
3340 break;
3341 }
3342 }
3343 },
3344 m_toolMgr, m_frame ) );
3345 m_dialogSyncSheetPin->Show( true );
3346 return 0;
3347}
3348
3349
3351{
3352 SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( m_selectionTool->GetSelection().Front() );
3353
3354 if( !sheet )
3355 {
3356 VECTOR2I cursorPos = getViewControls()->GetMousePosition();
3357
3358 if( EDA_ITEM* i = nullptr; static_cast<void>(m_selectionTool->SelectPoint( cursorPos, { SCH_SHEET_T }, &i ) ) , i != nullptr )
3359 {
3360 sheet = dynamic_cast<SCH_SHEET*>( i );
3361 }
3362 }
3363
3364 if ( sheet )
3365 {
3367 current.push_back( sheet );
3368 return doSyncSheetsPins( { current } );
3369 }
3370
3371 return 0;
3372}
3373
3374
3376{
3377 if( m_inDrawingTool )
3378 return 0;
3379
3381
3382 SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( m_selectionTool->GetSelection().Front() );
3383 std::vector<SCH_HIERLABEL*> labels = importHierLabels( sheet );
3384
3385 if( labels.empty() )
3386 {
3387 m_frame->PushTool( aEvent );
3388 m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( m_frame );
3389 m_statusPopup->SetText( _( "No new hierarchical labels found." ) );
3390 m_statusPopup->Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, 20 ) );
3391 m_statusPopup->PopupFor( 2000 );
3392 m_frame->PopTool( aEvent );
3395 return 0;
3396 }
3397
3399
3400 SCH_COMMIT commit( m_toolMgr );
3401 BOX2I boundingBox = sheet->GetBoundingBox();
3402 VECTOR2I cursorPos = boundingBox.GetPosition();
3403 SCH_ITEM* lastPlacedLabel = nullptr;
3404
3405 auto calculatePositionForLabel = [&]( const SCH_ITEM* lastLabel,
3406 const SCH_HIERLABEL* currentLabel ) -> VECTOR2I
3407 {
3408 if( !lastLabel )
3409 return cursorPos;
3410
3411 int lastX = lastLabel->GetPosition().x;
3412 int lastY = lastLabel->GetPosition().y;
3413 int lastWidth = lastLabel->GetBoundingBox().GetWidth();
3414 int lastHeight = lastLabel->GetBoundingBox().GetHeight();
3415
3416 int currentWidth = currentLabel->GetBoundingBox().GetWidth();
3417 int currentHeight = currentLabel->GetBoundingBox().GetHeight();
3418
3419 // If there is enough space, place the label to the right of the last placed label
3420 if( ( lastX + lastWidth + currentWidth )
3422 return { lastX + lastWidth, lastY };
3423
3424 // If not enough space to the right, move to the next row if vertical space allows
3425 if( ( lastY + lastHeight + currentHeight )
3427 return { boundingBox.GetPosition().x, lastY + lastHeight };
3428
3429 return cursorPos;
3430 };
3431
3432 for( SCH_HIERLABEL* label : labels )
3433 {
3434 if( !lastPlacedLabel )
3435 {
3436 std::vector<SCH_SHEET_PIN*> existingPins = sheet->GetPins();
3437
3438 if( !existingPins.empty() )
3439 {
3440 std::sort( existingPins.begin(), existingPins.end(),
3441 []( const SCH_ITEM* a, const SCH_ITEM* b )
3442 {
3443 return ( a->GetPosition().x < b->GetPosition().x )
3444 || ( a->GetPosition().x == b->GetPosition().x
3445 && a->GetPosition().y < b->GetPosition().y );
3446 } );
3447
3448 lastPlacedLabel = existingPins.back();
3449 }
3450 }
3451
3452 cursorPos = calculatePositionForLabel( lastPlacedLabel, label );
3453 SCH_ITEM* item = createNewSheetPinFromLabel( sheet, cursorPos, label );
3454
3455 if( item )
3456 {
3457 item->SetFlags( IS_NEW | IS_MOVING );
3458 item->AutoplaceFields( nullptr, AUTOPLACE_AUTO );
3459 item->ClearFlags( IS_MOVING );
3460
3461 if( item->IsConnectable() )
3463
3464 commit.Modify( sheet, m_frame->GetScreen() );
3465
3466 sheet->AddPin( static_cast<SCH_SHEET_PIN*>( item ) );
3468
3469 commit.Push( _( "Add Sheet Pin" ) );
3470
3471 lastPlacedLabel = item;
3472 }
3473 }
3474
3475 return 0;
3476}
3477
3478
3480{
3481 static const std::function<void( std::list<SCH_SHEET_PATH>&, SCH_SCREEN*,
3482 std::set<SCH_SCREEN*>&, SCH_SHEET_PATH const& )>
3483 getSheetChildren = []( std::list<SCH_SHEET_PATH>& aPaths, SCH_SCREEN* aScene,
3484 std::set<SCH_SCREEN*>& aVisited, SCH_SHEET_PATH const& aCurPath )
3485 {
3486 if( ! aScene || aVisited.find(aScene) != aVisited.end() )
3487 return ;
3488
3489 std::vector<SCH_ITEM*> sheetChildren;
3490 aScene->GetSheets( &sheetChildren );
3491 aVisited.insert( aScene );
3492
3493 for( SCH_ITEM* child : sheetChildren )
3494 {
3495 SCH_SHEET_PATH cp = aCurPath;
3496 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( child );
3497 cp.push_back( sheet );
3498 aPaths.push_back( cp );
3499 getSheetChildren( aPaths, sheet->GetScreen(), aVisited, cp );
3500 }
3501 };
3502
3503 std::list<SCH_SHEET_PATH> sheetPaths;
3504 std::set<SCH_SCREEN*> visited;
3505 SCH_SHEET_PATH current;
3506 current.push_back( &m_frame->Schematic().Root() );
3507 getSheetChildren( sheetPaths, m_frame->Schematic().Root().GetScreen(), visited, current );
3508
3509 if( sheetPaths.size() == 0 )
3510 {
3511 m_frame->ShowInfoBarMsg( _( "No sub schematic found in the current project" ) );
3512 return 0;
3513 }
3514
3515
3516 return doSyncSheetsPins( std::move( sheetPaths ) );
3517}
3518
3520{
3521 if( !aSheet->GetScreen() )
3522 return nullptr;
3523
3524 std::vector<SCH_HIERLABEL*> labels;
3525 for( EDA_ITEM* item : aSheet->GetScreen()->Items().OfType( SCH_HIER_LABEL_T ) )
3526 {
3527 SCH_HIERLABEL* label = static_cast<SCH_HIERLABEL*>( item );
3528 labels.push_back( label );
3529 }
3530
3531 std::sort( labels.begin(), labels.end(),
3532 []( const SCH_HIERLABEL* label1, const SCH_HIERLABEL* label2 )
3533 {
3534 return StrNumCmp( label1->GetText(), label2->GetText(), true ) < 0;
3535 } );
3536
3537 for( SCH_HIERLABEL* label : labels )
3538 {
3539 if( !aSheet->HasPin( label->GetText() ) )
3540 return label;
3541 }
3542
3543 return nullptr;
3544}
3545
3546
3547std::vector<SCH_HIERLABEL*> SCH_DRAWING_TOOLS::importHierLabels( SCH_SHEET* aSheet )
3548{
3549 if( !aSheet->GetScreen() )
3550 return {};
3551
3552 std::vector<SCH_HIERLABEL*> labels;
3553
3554 for( EDA_ITEM* item : aSheet->GetScreen()->Items().OfType( SCH_HIER_LABEL_T ) )
3555 {
3556 SCH_HIERLABEL* label = static_cast<SCH_HIERLABEL*>( item );
3557
3558 if( !aSheet->HasPin( label->GetText() ) )
3559 {
3560 labels.push_back( label );
3561 }
3562 }
3563
3564 return labels;
3565}
3566
3567
3569{
3570 // clang-format off
3600 // clang-format on
3601}
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:112
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
static TOOL_ACTION cancelInteractive
Definition: actions.h:72
static TOOL_ACTION undo
Definition: actions.h:75
static TOOL_ACTION duplicate
Definition: actions.h:84
static TOOL_ACTION activatePointEditor
Definition: actions.h:266
static TOOL_ACTION doDelete
Definition: actions.h:85
static TOOL_ACTION redo
Definition: actions.h:76
static TOOL_ACTION increment
Definition: actions.h:94
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: actions.h:220
static TOOL_ACTION refreshPreview
Definition: actions.h:156
static TOOL_ACTION finishInteractive
Definition: actions.h:73
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Definition: actions.h:228
PANEL_DESIGN_BLOCK_CHOOSER m_DesignBlockChooserPanel
Definition: app_settings.h:216
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:96
virtual VECTOR2I GetPosition() const
Definition: eda_item.h:256
virtual void ClearEditFlags()
Definition: eda_item.h:152
virtual void SetPosition(const VECTOR2I &aPos)
Definition: eda_item.h:257
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:84
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:144
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:138
const KIID m_Uuid
Definition: eda_item.h:502
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:108
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:140
virtual bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const
Compare the item against the search criteria in aSearchData.
Definition: eda_item.h:390
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:111
virtual wxString GetFriendlyName() const
Definition: eda_item.cpp:374
virtual EDA_ITEM * Clone() const
Create a duplicate of this item with linked list members set to NULL.
Definition: eda_item.cpp:92
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:166
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:144
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition: eda_text.cpp:533
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:97
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition: eda_text.cpp:417
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition: eda_text.h:197
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:386
void SetBold(bool aBold)
Set the text to be bold - this will also update the font if needed.
Definition: eda_text.cpp:335
bool IsBold() const
Definition: eda_text.h:181
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition: eda_text.h:200
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:270
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:299
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
Definition: eda_text.cpp:307
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition: eda_text.cpp:409
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
void Update(const KIGFX::VIEW_ITEM *aItem, int aUpdateFlags) const override
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: sch_view.cpp:60
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
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:476
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:424
void SetLocalPower()
Definition: lib_symbol.cpp:440
bool IsGlobalPower() const override
Definition: lib_symbol.cpp:454
A singleton reporter that reports to nowhere.
Definition: reporter.h:217
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:119
static TOOL_ACTION placeClassLabel
Definition: sch_actions.h:77
static TOOL_ACTION placeSheetPin
Definition: sch_actions.h:83
static TOOL_ACTION placeNextSymbolUnit
Definition: sch_actions.h:67
static TOOL_ACTION mirrorV
Definition: sch_actions.h:120
static TOOL_ACTION drawSheetFromFile
Definition: sch_actions.h:81
static TOOL_ACTION placeGlobalLabel
Definition: sch_actions.h:78
static TOOL_ACTION drawTextBox
Definition: sch_actions.h:91
static TOOL_ACTION syncAllSheetsPins
Definition: sch_actions.h:89
static TOOL_ACTION closeOutline
Definition: sch_actions.h:103
static TOOL_ACTION drawArc
Definition: sch_actions.h:95
static TOOL_ACTION drawSheet
Definition: sch_actions.h:80
static TOOL_ACTION properties
Definition: sch_actions.h:123
static TOOL_ACTION leaveSheet
Definition: sch_actions.h:218
static TOOL_ACTION autoplaceAllSheetPins
Definition: sch_actions.h:84
static TOOL_ACTION drawRectangle
Definition: sch_actions.h:93
static TOOL_ACTION placeHierLabel
Definition: sch_actions.h:79
static TOOL_ACTION placeLabel
Definition: sch_actions.h:76
static TOOL_ACTION drawCircle
Definition: sch_actions.h:94
static TOOL_ACTION importGraphics
Definition: sch_actions.h:254
static TOOL_ACTION placeBusWireEntry
Definition: sch_actions.h:75
static TOOL_ACTION drawBezier
Definition: sch_actions.h:96
static TOOL_ACTION rotateCW
Definition: sch_actions.h:118
static TOOL_ACTION importSheet
Definition: sch_actions.h:85
static TOOL_ACTION placeJunction
Definition: sch_actions.h:74
static TOOL_ACTION drawRuleArea
Definition: sch_actions.h:101
static TOOL_ACTION placeSymbol
Definition: sch_actions.h:66
static TOOL_ACTION placeImage
Definition: sch_actions.h:98
static TOOL_ACTION deleteLastPoint
Definition: sch_actions.h:102
static TOOL_ACTION drawSheetFromDesignBlock
Definition: sch_actions.h:82
static TOOL_ACTION mirrorH
Definition: sch_actions.h:121
static TOOL_ACTION placeDesignBlock
Definition: sch_actions.h:69
static TOOL_ACTION drawTable
Definition: sch_actions.h:92
static TOOL_ACTION placeSchematicText
Definition: sch_actions.h:90
static TOOL_ACTION changeSheet
Definition: sch_actions.h:216
static TOOL_ACTION enterSheet
Definition: sch_actions.h:217
static TOOL_ACTION repeatDrawItem
Definition: sch_actions.h:117
static TOOL_ACTION placeNoConnect
Definition: sch_actions.h:73
static TOOL_ACTION move
Definition: sch_actions.h:115
static TOOL_ACTION syncSheetPins
Definition: sch_actions.h:87
static TOOL_ACTION placePower
Definition: sch_actions.h:68
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:487
virtual void Revert() override
Revert the commit by restoring the modified items state.
Definition: sch_commit.cpp:565
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:1095
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this label.
Definition: sch_label.cpp:1838
A set of SCH_ITEMs (i.e., without duplicates).
Definition: sch_group.h:52
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:167
virtual bool IsConnectable() const
Definition: sch_item.h:475
virtual void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo)
Definition: sch_item.h:577
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode)
Definition: sch_item.h:579
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:177
int GetUnit() const
Definition: sch_item.h:236
virtual void SetUnit(int aUnit)
Definition: sch_item.h:235
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:245
bool IsType(const std::vector< KICAD_T > &aScanTypes) const override
Check whether the item is one of the listed types.
Definition: sch_item.h:182
bool AutoRotateOnPlacement() const
autoRotateOnPlacement
Definition: sch_label.cpp: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:939
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:402
bool IsExplicitJunctionAllowed(const VECTOR2I &aPosition) const
Indicate that a junction dot may be placed at the given location.
Definition: sch_screen.cpp:504
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()
SCH_SELECTION & RequestSelection(const std::vector< KICAD_T > &aScanTypes={ SCH_LOCATE_ANY_T }, bool aPromoteCellSelections=false, bool aPromoteGroups=false)
Return either an existing selection (filtered), or the selection at the current cursor position if th...
void SetPosition(const VECTOR2I &aPos) override
Definition: sch_shape.h:84
void BeginEdit(const VECTOR2I &aStartPoint) override
Begin drawing a symbol library draw item at aPosition.
Definition: sch_shape.h:88
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:91
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:89
void CalcEdit(const VECTOR2I &aPosition) override
Calculate the attributes of an item at aPosition when it is being edited.
Definition: sch_shape.h:90
wxString GetClass() const override
Return the class name.
Definition: sch_shape.h:43
STROKE_PARAMS GetStroke() const override
Definition: sch_shape.h:56
VECTOR2I GetPosition() const override
Definition: sch_shape.h:83
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:756
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
Definition: sch_symbol.cpp:612
A foundation class for a tool operating on a schematic or symbol.
Definition: sch_tool_base.h:49
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:65
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:365
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
const std::string & GetName() const
Return the name of the tool.
Definition: tool_base.h:136
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:404
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
Definition: eda_item.h:552
#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.
Class to handle a set of SCH_ITEMs.
@ AUTOPLACE_AUTO
Definition: sch_item.h:70
LABEL_FLAG_SHAPE
Definition: sch_label.h:99
@ F_ROUND
Definition: sch_label.h:108
@ L_INPUT
Definition: sch_label.h:100
ANNOTATE_ORDER_T
Schematic annotation order options.
@ ANNOTATE_SELECTION
Annotate the selection.
ANNOTATE_ALGO_T
Schematic annotation type options.
#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:95
LIB_ID LibId
Definition: sch_screen.h:80
SCH_SYMBOL * m_Symbol
< Provide a symbol to place
Definition: sch_actions.h:305
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:175
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:169
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:174
@ 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.