KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_edit_tool.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 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 <kiway.h>
26#include <tool/picker_tool.h>
27#include <tools/sch_edit_tool.h>
30#include <tools/sch_move_tool.h>
32#include <confirm.h>
33#include <ee_actions.h>
34#include <ee_tool_utils.h>
35#include <increment.h>
36#include <string_utils.h>
37#include <sch_bitmap.h>
38#include <sch_bus_entry.h>
39#include <sch_commit.h>
40#include <sch_junction.h>
41#include <sch_marker.h>
42#include <sch_rule_area.h>
43#include <sch_sheet_pin.h>
44#include <sch_textbox.h>
45#include <sch_table.h>
47#include <eeschema_id.h>
58#include <dialogs/dialog_text_properties.h>
59#include <dialogs/dialog_tablecell_properties.h>
60#include <dialogs/dialog_table_properties.h>
61#include <pgm_base.h>
64#include <core/kicad_algo.h>
65#include <view/view_controls.h>
66#include <wx/textdlg.h>
68
69
71{
72public:
74 ACTION_MENU( true )
75 {
76 SetIcon( BITMAPS::component_select_unit );
77 SetTitle( _( "Symbol Unit" ) );
78 }
79
80protected:
81 ACTION_MENU* create() const override
82 {
83 return new SYMBOL_UNIT_MENU();
84 }
85
86private:
87 void update() override
88 {
90 EE_SELECTION& selection = selTool->GetSelection();
91 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( selection.Front() );
92
93 Clear();
94
95 wxCHECK( symbol, /* void */ );
96
97 const int unit = symbol->GetUnit();
98 const int nUnits = symbol->GetLibSymbolRef()->GetUnitCount();
99 const std::set<int> missingUnits = GetUnplacedUnitsForSymbol( *symbol );
100
101 for( int ii = 0; ii < nUnits; ii++ )
102 {
103 wxString unit_text;
104
105 if( symbol->GetLibSymbolRef()->HasUnitDisplayName( ii + 1 ) )
106 unit_text = symbol->GetLibSymbolRef()->GetUnitDisplayName( ii + 1 );
107 else
108 unit_text.Printf( _( "Unit %s" ), symbol->SubReference( ii + 1, false ) );
109
110 if( missingUnits.count( ii + 1 ) == 0 )
111 unit_text += _( " (already placed)" );
112
113 wxMenuItem* item = Append( ID_POPUP_SCH_SELECT_UNIT1 + ii, unit_text, wxEmptyString,
114 wxITEM_CHECK );
115
116 if( unit == ii + 1 )
117 item->Check( true );
118
119 // The ID max for these submenus is ID_POPUP_SCH_SELECT_UNIT_END
120 // See eeschema_id to modify this value.
122 break; // We have used all IDs for these submenus
123 }
124
125 {
126 AppendSeparator();
127
128 wxMenuItem* item = Add( EE_ACTIONS::placeNextSymbolUnit );
129 item->Enable( missingUnits.size() );
130 }
131 }
132};
133
134
136{
137public:
139 ACTION_MENU( true )
140 {
141 SetIcon( BITMAPS::component_select_alternate_shape );
142 SetTitle( _( "Body Style" ) );
143 }
144
145protected:
146 ACTION_MENU* create() const override
147 {
148 return new BODY_STYLE_MENU();
149 }
150
151private:
152 void update() override
153 {
155 EE_SELECTION& selection = selTool->GetSelection();
156 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( selection.Front() );
157 wxMenuItem* item;
158
159 Clear();
160
161 wxCHECK( symbol, /* void */ );
162
163 item = Append( ID_POPUP_SCH_SELECT_BASE, _( "Standard" ), wxEmptyString, wxITEM_CHECK );
164 item->Check( symbol->GetBodyStyle() == BODY_STYLE::BASE );
165
166 item = Append( ID_POPUP_SCH_SELECT_ALT, _( "Alternate" ), wxEmptyString, wxITEM_CHECK );
167 item->Check( symbol->GetBodyStyle() != BODY_STYLE::BASE );
168 }
169};
170
171
173{
174public:
176 ACTION_MENU( true )
177 {
178 SetIcon( BITMAPS::component_select_unit );
179 SetTitle( _( "Pin Function" ) );
180 }
181
182protected:
183 ACTION_MENU* create() const override
184 {
185 return new ALT_PIN_FUNCTION_MENU();
186 }
187
188private:
189 void update() override
190 {
192 EE_SELECTION& selection = selTool->GetSelection();
193 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( selection.Front() );
194 SCH_PIN* libPin = pin ? pin->GetLibPin() : nullptr;
195
196 Clear();
197
198 wxCHECK( libPin, /* void */ );
199
200 wxMenuItem* item = Append( ID_POPUP_SCH_ALT_PIN_FUNCTION, libPin->GetName(), wxEmptyString,
201 wxITEM_CHECK );
202
203 if( pin->GetAlt().IsEmpty() )
204 item->Check( true );
205
206 int ii = 1;
207
208 for( const auto& [ name, definition ] : libPin->GetAlternates() )
209 {
210 item = Append( ID_POPUP_SCH_ALT_PIN_FUNCTION + ii, name, wxEmptyString, wxITEM_CHECK );
211
212 if( name == pin->GetAlt() )
213 item->Check( true );
214
215 // The ID max for these submenus is ID_POPUP_SCH_ALT_PIN_FUNCTION_END
216 // See eeschema_id to modify this value.
218 break; // We have used all IDs for these submenus
219 }
220 }
221};
222
223
225{
226public:
228 {
229 SetIcon( BITMAPS::pin );
230 SetTitle( _( "Pin Helpers" ) );
231 }
232
233protected:
234 ACTION_MENU* create() const override { return new PIN_TRICKS_MENU(); }
235
236private:
237 void update() override
238 {
240 EE_SELECTION& selection = selTool->GetSelection();
241 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( selection.Front() );
242 SCH_SHEET_PIN* sheetPin = dynamic_cast<SCH_SHEET_PIN*>( selection.Front() );
243
244 Clear();
245
246 if( !pin && !sheetPin )
247 return;
248
249 Add( _( "Wire" ), ID_POPUP_SCH_PIN_TRICKS_WIRE, BITMAPS::add_line );
250 Add( _( "No Connect" ), ID_POPUP_SCH_PIN_TRICKS_NO_CONNECT, BITMAPS::noconn );
251 Add( _( "Net Label" ), ID_POPUP_SCH_PIN_TRICKS_NET_LABEL, BITMAPS::add_label );
252 Add( _( "Hierarchical Label" ), ID_POPUP_SCH_PIN_TRICKS_HIER_LABEL, BITMAPS::add_hierarchical_label );
253 Add( _( "Global Label" ), ID_POPUP_SCH_PIN_TRICKS_GLOBAL_LABEL, BITMAPS::add_glabel );
254 }
255};
256
257
259 EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.InteractiveEdit" )
260{
261 m_pickerItem = nullptr;
262}
263
264
266
268{
270
273
274 wxASSERT_MSG( drawingTools, "eeshema.InteractiveDrawing tool is not available" );
275
276 auto hasElements =
277 [this]( const SELECTION& aSel )
278 {
279 return !m_frame->GetScreen()->Items().empty();
280 };
281
282 auto sheetHasUndefinedPins =
283 []( const SELECTION& aSel )
284 {
285 if( aSel.Size() == 1 && aSel.Front()->Type() == SCH_SHEET_T )
286 return static_cast<SCH_SHEET*>( aSel.Front() )->HasUndefinedPins();
287
288 return false;
289 };
290
291 static const std::vector<KICAD_T> sheetTypes = { SCH_SHEET_T };
292
293 auto sheetSelection = E_C::Count( 1 ) && E_C::OnlyTypes( sheetTypes );
294
295 auto haveHighlight =
296 [&]( const SELECTION& sel )
297 {
298 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
299
300 return editFrame && !editFrame->GetHighlightedConnection().IsEmpty();
301 };
302
303 auto anyTextTool =
304 [this]( const SELECTION& aSel )
305 {
311 };
312
313 auto duplicateCondition =
314 []( const SELECTION& aSel )
315 {
317 return false;
318
319 return true;
320 };
321
322 auto orientCondition =
323 []( const SELECTION& aSel )
324 {
326 return false;
327
329 };
330
331 auto propertiesCondition =
332 [&]( const SELECTION& aSel )
333 {
334 if( aSel.GetSize() == 0 )
335 {
337 {
340
341 if( ds && ds->HitTestDrawingSheetItems( getView(), cursor ) )
342 return true;
343 }
344
345 return false;
346 }
347
348 SCH_ITEM* firstItem = dynamic_cast<SCH_ITEM*>( aSel.Front() );
349 const EE_SELECTION* eeSelection = dynamic_cast<const EE_SELECTION*>( &aSel );
350
351 if( !firstItem || !eeSelection )
352 return false;
353
354 switch( firstItem->Type() )
355 {
356 case SCH_SYMBOL_T:
357 case SCH_SHEET_T:
358 case SCH_SHEET_PIN_T:
359 case SCH_TEXT_T:
360 case SCH_TEXTBOX_T:
361 case SCH_TABLE_T:
362 case SCH_TABLECELL_T:
363 case SCH_LABEL_T:
365 case SCH_HIER_LABEL_T:
367 case SCH_RULE_AREA_T:
368 case SCH_FIELD_T:
369 case SCH_SHAPE_T:
370 case SCH_BITMAP_T:
371 return aSel.GetSize() == 1;
372
373 case SCH_LINE_T:
375 case SCH_JUNCTION_T:
376 if( std::all_of( aSel.Items().begin(), aSel.Items().end(),
377 [&]( const EDA_ITEM* item )
378 {
379 return item->Type() == SCH_LINE_T
380 && static_cast<const SCH_LINE*>( item )->IsGraphicLine();
381 } ) )
382 {
383 return true;
384 }
385 else if( std::all_of( aSel.Items().begin(), aSel.Items().end(),
386 [&]( const EDA_ITEM* item )
387 {
388 return item->Type() == SCH_JUNCTION_T;
389 } ) )
390 {
391 return true;
392 }
393 else if( std::all_of( aSel.Items().begin(), aSel.Items().end(),
394 [&]( const EDA_ITEM* item )
395 {
396 const SCH_ITEM* schItem = dynamic_cast<const SCH_ITEM*>( item );
397
398 wxCHECK( schItem, false );
399
400 return ( schItem->HasLineStroke() && schItem->IsConnectable() )
401 || item->Type() == SCH_JUNCTION_T;
402 } ) )
403 {
404 return true;
405 }
406
407 return false;
408
409 default:
410 return false;
411 }
412 };
413
414 auto autoplaceCondition =
415 []( const SELECTION& aSel )
416 {
417 for( const EDA_ITEM* item : aSel )
418 {
419 if( item->IsType( EE_COLLECTOR::FieldOwners ) )
420 return true;
421 }
422
423 return false;
424 };
425
426 // allTextTypes does not include SCH_SHEET_PIN_T because one cannot convert other
427 // types to/from this type, living only in a SHEET
428 static const std::vector<KICAD_T> allTextTypes = { SCH_LABEL_T,
434
435 auto toChangeCondition = ( E_C::OnlyTypes( allTextTypes ) );
436
437 static const std::vector<KICAD_T> toLabelTypes = { SCH_DIRECTIVE_LABEL_T,
442
443 auto toLabelCondition = ( E_C::Count( 1 ) && E_C::OnlyTypes( toLabelTypes ) )
444 || ( E_C::MoreThan( 1 ) && E_C::OnlyTypes( allTextTypes ) );
445
446 static const std::vector<KICAD_T> toCLabelTypes = { SCH_LABEL_T,
451
452 auto toCLabelCondition = ( E_C::Count( 1 ) && E_C::OnlyTypes( toCLabelTypes ) )
453 || ( E_C::MoreThan( 1 ) && E_C::OnlyTypes( allTextTypes ) );
454
455 static const std::vector<KICAD_T> toHLabelTypes = { SCH_LABEL_T,
460
461 auto toHLabelCondition = ( E_C::Count( 1 ) && E_C::OnlyTypes( toHLabelTypes ) )
462 || ( E_C::MoreThan( 1 ) && E_C::OnlyTypes( allTextTypes ) );
463
464 static const std::vector<KICAD_T> toGLabelTypes = { SCH_LABEL_T,
469
470 auto toGLabelCondition = ( E_C::Count( 1 ) && E_C::OnlyTypes( toGLabelTypes ) )
471 || ( E_C::MoreThan( 1 ) && E_C::OnlyTypes( allTextTypes ) );
472
473 static const std::vector<KICAD_T> toTextTypes = { SCH_LABEL_T,
478
479 auto toTextCondition = ( E_C::Count( 1 ) && E_C::OnlyTypes( toTextTypes ) )
480 || ( E_C::MoreThan( 1 ) && E_C::OnlyTypes( allTextTypes ) );
481
482 static const std::vector<KICAD_T> toTextBoxTypes = { SCH_LABEL_T,
486 SCH_TEXT_T };
487
488 auto toTextBoxCondition = ( E_C::Count( 1 ) && E_C::OnlyTypes( toTextBoxTypes ) )
489 || ( E_C::MoreThan( 1 ) && E_C::OnlyTypes( allTextTypes ) );
490
491 static const std::vector<KICAD_T> busEntryTypes = { SCH_BUS_WIRE_ENTRY_T, SCH_BUS_BUS_ENTRY_T};
492
493 auto entryCondition = E_C::MoreThan( 0 ) && E_C::OnlyTypes( busEntryTypes );
494
495 auto singleSheetCondition = E_C::Count( 1 ) && E_C::OnlyTypes( sheetTypes );
496
497 auto makeSymbolUnitMenu =
498 [&]( TOOL_INTERACTIVE* tool )
499 {
500 std::shared_ptr<SYMBOL_UNIT_MENU> menu = std::make_shared<SYMBOL_UNIT_MENU>();
501 menu->SetTool( tool );
502 tool->GetToolMenu().RegisterSubMenu( menu );
503 return menu.get();
504 };
505
506 auto makeBodyStyleMenu =
507 [&]( TOOL_INTERACTIVE* tool )
508 {
509 std::shared_ptr<BODY_STYLE_MENU> menu = std::make_shared<BODY_STYLE_MENU>();
510 menu->SetTool( tool );
511 tool->GetToolMenu().RegisterSubMenu( menu );
512 return menu.get();
513 };
514
515 auto makePinFunctionMenu =
516 [&]( TOOL_INTERACTIVE* tool )
517 {
518 std::shared_ptr<ALT_PIN_FUNCTION_MENU> menu = std::make_shared<ALT_PIN_FUNCTION_MENU>();
519 menu->SetTool( tool );
520 tool->GetToolMenu().RegisterSubMenu( menu );
521 return menu.get();
522 };
523
524 auto makePinTricksMenu =
525 [&]( TOOL_INTERACTIVE* tool )
526 {
527 std::shared_ptr<PIN_TRICKS_MENU> menu = std::make_shared<PIN_TRICKS_MENU>();
528 menu->SetTool( tool );
529 tool->GetToolMenu().RegisterSubMenu( menu );
530 return menu.get();
531 };
532
533 auto makeTransformMenu =
534 [&]()
535 {
536 CONDITIONAL_MENU* menu = new CONDITIONAL_MENU( moveTool );
537 menu->SetTitle( _( "Transform Selection" ) );
538
539 menu->AddItem( EE_ACTIONS::rotateCCW, orientCondition );
540 menu->AddItem( EE_ACTIONS::rotateCW, orientCondition );
541 menu->AddItem( EE_ACTIONS::mirrorV, orientCondition );
542 menu->AddItem( EE_ACTIONS::mirrorH, orientCondition );
543
544 return menu;
545 };
546
547 auto makeAttributesMenu =
548 [&]()
549 {
550 CONDITIONAL_MENU* menu = new CONDITIONAL_MENU( moveTool );
551 menu->SetTitle( _( "Attributes" ) );
552
556
557 menu->AddSeparator();
561
562 menu->AddSeparator();
566
567 menu->AddSeparator();
571
572 return menu;
573 };
574
575 auto makeEditFieldsMenu =
576 [&]()
577 {
579 menu->SetTitle( _( "Edit Main Fields" ) );
580
584
585 return menu;
586 };
587
588 auto makeConvertToMenu =
589 [&]()
590 {
592 menu->SetTitle( _( "Change To" ) );
593 menu->SetIcon( BITMAPS::right );
594
595 menu->AddItem( EE_ACTIONS::toLabel, toLabelCondition );
596 menu->AddItem( EE_ACTIONS::toCLabel, toCLabelCondition );
597 menu->AddItem( EE_ACTIONS::toHLabel, toHLabelCondition );
598 menu->AddItem( EE_ACTIONS::toGLabel, toGLabelCondition );
599 menu->AddItem( EE_ACTIONS::toText, toTextCondition );
600 menu->AddItem( EE_ACTIONS::toTextBox, toTextBoxCondition );
601
602 return menu;
603 };
604
605 const auto canCopyText = EE_CONDITIONS::OnlyTypes( {
614 SCH_PIN_T,
617 } );
618
619 //
620 // Add edit actions to the move tool menu
621 //
622 CONDITIONAL_MENU& moveMenu = moveTool->GetToolMenu().GetMenu();
623
624 moveMenu.AddSeparator();
625 moveMenu.AddMenu( makeSymbolUnitMenu( moveTool ), E_C::SingleMultiUnitSymbol, 1 );
626 moveMenu.AddMenu( makeBodyStyleMenu( moveTool ), E_C::SingleDeMorganSymbol, 1 );
627
628 moveMenu.AddMenu( makeTransformMenu(), orientCondition, 200 );
629 moveMenu.AddMenu( makeAttributesMenu(), E_C::HasType( SCH_SYMBOL_T ), 200 );
630 moveMenu.AddItem( EE_ACTIONS::swap, SELECTION_CONDITIONS::MoreThan( 1 ), 200);
631 moveMenu.AddItem( EE_ACTIONS::properties, propertiesCondition, 200 );
632 moveMenu.AddMenu( makeEditFieldsMenu(), E_C::SingleSymbol, 200 );
633
634 moveMenu.AddSeparator();
635 moveMenu.AddItem( ACTIONS::cut, E_C::IdleSelection );
636 moveMenu.AddItem( ACTIONS::copy, E_C::IdleSelection );
637 moveMenu.AddItem( ACTIONS::copyAsText, canCopyText && E_C::IdleSelection );
638 moveMenu.AddItem( ACTIONS::doDelete, E_C::NotEmpty );
639 moveMenu.AddItem( ACTIONS::duplicate, duplicateCondition );
640
641 //
642 // Add editing actions to the drawing tool menu
643 //
644 CONDITIONAL_MENU& drawMenu = drawingTools->GetToolMenu().GetMenu();
645
646 drawMenu.AddItem( EE_ACTIONS::clearHighlight, haveHighlight && EE_CONDITIONS::Idle, 1 );
647 drawMenu.AddSeparator( haveHighlight && EE_CONDITIONS::Idle, 1 );
648
649 drawMenu.AddItem( EE_ACTIONS::enterSheet, sheetSelection && EE_CONDITIONS::Idle, 1 );
650 drawMenu.AddSeparator( sheetSelection && EE_CONDITIONS::Idle, 1 );
651
652 drawMenu.AddMenu( makeSymbolUnitMenu( drawingTools ), E_C::SingleMultiUnitSymbol, 1 );
653 drawMenu.AddMenu( makeBodyStyleMenu( drawingTools ), E_C::SingleDeMorganSymbol, 1 );
654
655 drawMenu.AddMenu( makeTransformMenu(), orientCondition, 200 );
656 drawMenu.AddMenu( makeAttributesMenu(), E_C::HasType( SCH_SYMBOL_T ), 200 );
657 drawMenu.AddItem( EE_ACTIONS::properties, propertiesCondition, 200 );
658 drawMenu.AddMenu( makeEditFieldsMenu(), E_C::SingleSymbol, 200 );
659 drawMenu.AddItem( EE_ACTIONS::autoplaceFields, autoplaceCondition, 200 );
660
662
663 drawMenu.AddItem( EE_ACTIONS::toLabel, anyTextTool && E_C::Idle, 200 );
664 drawMenu.AddItem( EE_ACTIONS::toHLabel, anyTextTool && E_C::Idle, 200 );
665 drawMenu.AddItem( EE_ACTIONS::toGLabel, anyTextTool && E_C::Idle, 200 );
666 drawMenu.AddItem( EE_ACTIONS::toText, anyTextTool && E_C::Idle, 200 );
667 drawMenu.AddItem( EE_ACTIONS::toTextBox, anyTextTool && E_C::Idle, 200 );
668
669 //
670 // Add editing actions to the selection tool menu
671 //
673
674 selToolMenu.AddMenu( makeSymbolUnitMenu( m_selectionTool ), E_C::SingleMultiUnitSymbol, 1 );
675 selToolMenu.AddMenu( makeBodyStyleMenu( m_selectionTool ), E_C::SingleDeMorganSymbol, 1 );
676 selToolMenu.AddMenu( makePinFunctionMenu( m_selectionTool ), E_C::SingleMultiFunctionPin, 1 );
677 selToolMenu.AddMenu( makePinTricksMenu( m_selectionTool ), E_C::AllPinsOrSheetPins, 1 );
678
679 selToolMenu.AddMenu( makeTransformMenu(), orientCondition, 200 );
680 selToolMenu.AddMenu( makeAttributesMenu(), E_C::HasType( SCH_SYMBOL_T ), 200 );
682 selToolMenu.AddItem( EE_ACTIONS::properties, propertiesCondition, 200 );
683 selToolMenu.AddMenu( makeEditFieldsMenu(), E_C::SingleSymbol, 200 );
684 selToolMenu.AddItem( EE_ACTIONS::autoplaceFields, autoplaceCondition, 200 );
685
691 selToolMenu.AddMenu( makeConvertToMenu(), toChangeCondition, 200 );
692
693 selToolMenu.AddItem( EE_ACTIONS::cleanupSheetPins, sheetHasUndefinedPins, 250 );
694
695 selToolMenu.AddSeparator( 300 );
696 selToolMenu.AddItem( ACTIONS::cut, E_C::IdleSelection, 300 );
697 selToolMenu.AddItem( ACTIONS::copy, E_C::IdleSelection, 300 );
698 selToolMenu.AddItem( ACTIONS::copyAsText, canCopyText && E_C::IdleSelection, 300 );
699 selToolMenu.AddItem( ACTIONS::paste, E_C::Idle, 300 );
700 selToolMenu.AddItem( ACTIONS::pasteSpecial, E_C::Idle, 300 );
701 selToolMenu.AddItem( ACTIONS::doDelete, E_C::NotEmpty, 300 );
702 selToolMenu.AddItem( ACTIONS::duplicate, duplicateCondition, 300 );
703
704 selToolMenu.AddSeparator( 400 );
705 selToolMenu.AddItem( ACTIONS::selectAll, hasElements, 400 );
706 selToolMenu.AddItem( ACTIONS::unselectAll, hasElements, 400 );
707
708 return true;
709}
710
711
712const std::vector<KICAD_T> SCH_EDIT_TOOL::RotatableItems = {
718 SCH_TABLECELL_T, // will be promoted to parent table(s)
733};
734
735
737{
738 bool clockwise = ( aEvent.Matches( EE_ACTIONS::rotateCW.MakeEvent() ) );
740
741 if( selection.GetSize() == 0 )
742 return 0;
743
744 SCH_ITEM* head = nullptr;
745 int principalItemCount = 0; // User-selected items (as opposed to connected wires)
746 VECTOR2I rotPoint;
747 bool moving = false;
748 SCH_COMMIT localCommit( m_toolMgr );
749 SCH_COMMIT* commit = dynamic_cast<SCH_COMMIT*>( aEvent.Commit() );
750
751 if( !commit )
752 commit = &localCommit;
753
754 for( unsigned ii = 0; ii < selection.GetSize(); ii++ )
755 {
756 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.GetItem( ii ) );
757
758 if( item->HasFlag( SELECTED_BY_DRAG ) )
759 continue;
760
761 principalItemCount++;
762
763 if( !head )
764 head = item;
765 }
766
767 if( head && head->IsMoving() )
768 moving = true;
769
770 if( principalItemCount == 1 )
771 {
772 if( moving && selection.HasReferencePoint() )
773 rotPoint = selection.GetReferencePoint();
774 else if( head->IsConnectable() )
775 rotPoint = head->GetPosition();
776 else
778
779 if( !moving )
780 commit->Modify( head, m_frame->GetScreen() );
781
782 switch( head->Type() )
783 {
784 case SCH_SYMBOL_T:
785 {
786 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( head );
787
788 symbol->Rotate( rotPoint, !clockwise );
789
791 {
792 AUTOPLACE_ALGO fieldsAutoplaced = symbol->GetFieldsAutoplaced();
793
794 if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
795 symbol->AutoplaceFields( m_frame->GetScreen(), fieldsAutoplaced );
796 }
797
798 break;
799 }
800
801 case SCH_TEXT_T:
802 case SCH_LABEL_T:
804 case SCH_HIER_LABEL_T:
806 {
807 SCH_TEXT* textItem = static_cast<SCH_TEXT*>( head );
808 textItem->Rotate90( clockwise );
809 break;
810 }
811
812 case SCH_SHEET_PIN_T:
813 {
814 // Rotate pin within parent sheet
815 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( head );
816 SCH_SHEET* sheet = pin->GetParent();
817
818 pin->Rotate( sheet->GetBoundingBox().GetCenter(), !clockwise );
819
820 break;
821 }
822
823 case SCH_LINE_T:
824 {
825 SCH_LINE* line = static_cast<SCH_LINE*>( head );
826
827 // Equal checks for both and neither. We need this because on undo
828 // the item will have both flags cleared, but will be selected, so it is possible
829 // for the user to get a selected line with neither endpoint selected. We
830 // set flags to make sure Rotate() works when we call it.
831 if( line->HasFlag( STARTPOINT ) == line->HasFlag( ENDPOINT ) )
832 {
833 line->SetFlags( STARTPOINT | ENDPOINT );
834
835 // When we allow off grid items, the rotPoint should be set to the midpoint
836 // of the line to allow rotation around the center, and the next if
837 // should become an else-if
838 }
839
840 if( line->HasFlag( STARTPOINT ) )
841 rotPoint = line->GetEndPoint();
842 else if( line->HasFlag( ENDPOINT ) )
843 rotPoint = line->GetStartPoint();
844 }
845
847 case SCH_JUNCTION_T:
848 case SCH_NO_CONNECT_T:
851 head->Rotate( rotPoint, !clockwise );
852
853 break;
854
855 case SCH_FIELD_T:
856 {
857 SCH_FIELD* field = static_cast<SCH_FIELD*>( head );
858
859 if( field->GetTextAngle().IsHorizontal() )
861 else
863
864 // Now that we're moving a field, they're no longer autoplaced.
865 static_cast<SCH_ITEM*>( head->GetParent() )->SetFieldsAutoplaced( AUTOPLACE_NONE );
866
867 break;
868 }
869
870 case SCH_RULE_AREA_T:
871 case SCH_SHAPE_T:
872 case SCH_TEXTBOX_T:
873 head->Rotate( rotPoint, !clockwise );
874
875 break;
876
877 case SCH_TABLE_T:
878 {
879 // Rotate the table on itself. Tables do not have an anchor point.
880 SCH_TABLE* table = static_cast<SCH_TABLE*>( head );
881 rotPoint = m_frame->GetNearestHalfGridPosition( table->GetCenter() );
882
883 table->Rotate( rotPoint, !clockwise );
884
885 table->Move( rotPoint - m_frame->GetNearestHalfGridPosition( table->GetCenter() ) );
886
887 break;
888 }
889
890 case SCH_BITMAP_T:
891 head->Rotate( rotPoint, !clockwise );
892
893 // The bitmap is cached in Opengl: clear the cache to redraw
895 break;
896
897 case SCH_SHEET_T:
898 {
899 // Rotate the sheet on itself. Sheets do not have an anchor point.
900 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( head );
901
903 sheet->Rotate( rotPoint, !clockwise );
904
905 break;
906 }
907
908 default:
909 UNIMPLEMENTED_FOR( head->GetClass() );
910 }
911
912 m_frame->UpdateItem( head, false, true );
913 }
914 else
915 {
916 if( moving && selection.HasReferencePoint() )
917 rotPoint = selection.GetReferencePoint();
918 else
919 rotPoint = m_frame->GetNearestHalfGridPosition( selection.GetCenter() );
920 }
921
922 for( EDA_ITEM* edaItem : selection )
923 {
924 SCH_ITEM* item = static_cast<SCH_ITEM*>( edaItem );
925
926 // We've already rotated the user selected item if there was only one. We're just
927 // here to rotate the ends of wires that were attached to it.
928 if( principalItemCount == 1 && !item->HasFlag( SELECTED_BY_DRAG ) )
929 continue;
930
931 if( !moving )
932 commit->Modify( item, m_frame->GetScreen() );
933
934 if( item->Type() == SCH_LINE_T )
935 {
936 SCH_LINE* line = (SCH_LINE*) item;
937
938 line->Rotate( rotPoint, !clockwise );
939 }
940 else if( item->Type() == SCH_SHEET_PIN_T )
941 {
942 if( item->GetParent()->IsSelected() )
943 {
944 // parent will rotate us
945 }
946 else
947 {
948 // rotate within parent
949 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( item );
950 SCH_SHEET* sheet = pin->GetParent();
951
952 pin->Rotate( sheet->GetBodyBoundingBox().GetCenter(), !clockwise );
953 }
954 }
955 else if( item->Type() == SCH_FIELD_T )
956 {
957 if( item->GetParent()->IsSelected() )
958 {
959 // parent will rotate us
960 }
961 else
962 {
963 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
964
965 field->Rotate( rotPoint, !clockwise );
966
967 if( field->GetTextAngle().IsHorizontal() )
969 else
971
972 // Now that we're moving a field, they're no longer autoplaced.
973 static_cast<SCH_ITEM*>( field->GetParent() )->SetFieldsAutoplaced( AUTOPLACE_NONE );
974 }
975 }
976 else if( item->Type() == SCH_TABLE_T )
977 {
978 SCH_TABLE* table = static_cast<SCH_TABLE*>( item );
979 VECTOR2I beforeCenter = table->GetCenter();
980
981 table->Rotate( rotPoint, !clockwise );
982 RotatePoint( beforeCenter, rotPoint, clockwise ? -ANGLE_90 : ANGLE_90 );
983
984 table->Move( beforeCenter - table->GetCenter() );
985 }
986 else
987 {
988 item->Rotate( rotPoint, !clockwise );
989 }
990
991 m_frame->UpdateItem( item, false, true );
992 updateItem( item, true );
993 }
994
995 if( moving )
996 {
998 }
999 else
1000 {
1001 EE_SELECTION selectionCopy = selection;
1002
1003 if( selection.IsHover() )
1005
1007 lwbTool->TrimOverLappingWires( commit, &selectionCopy );
1008 lwbTool->AddJunctionsIfNeeded( commit, &selectionCopy );
1009
1010 m_frame->SchematicCleanUp( commit );
1011
1012 if( !localCommit.Empty() )
1013 localCommit.Push( _( "Rotate" ) );
1014 }
1015
1016 return 0;
1017}
1018
1019
1021{
1023
1024 if( selection.GetSize() == 0 )
1025 return 0;
1026
1027 bool vertical = ( aEvent.Matches( EE_ACTIONS::mirrorV.MakeEvent() ) );
1028 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.Front() );
1029 bool connections = false;
1030 bool moving = item->IsMoving();
1031 SCH_COMMIT localCommit( m_toolMgr );
1032 SCH_COMMIT* commit = dynamic_cast<SCH_COMMIT*>( aEvent.Commit() );
1033
1034 if( !commit )
1035 commit = &localCommit;
1036
1037 if( selection.GetSize() == 1 )
1038 {
1039 if( !moving )
1040 commit->Modify( item, m_frame->GetScreen() );
1041
1042 switch( item->Type() )
1043 {
1044 case SCH_SYMBOL_T:
1045 {
1046 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1047
1048 if( vertical )
1049 symbol->SetOrientation( SYM_MIRROR_X );
1050 else
1051 symbol->SetOrientation( SYM_MIRROR_Y );
1052
1054 break;
1055 }
1056
1057 case SCH_TEXT_T:
1058 case SCH_LABEL_T:
1059 case SCH_GLOBAL_LABEL_T:
1060 case SCH_HIER_LABEL_T:
1062 {
1063 SCH_TEXT* textItem = static_cast<SCH_TEXT*>( item );
1064 textItem->MirrorSpinStyle( !vertical );
1065 break;
1066 }
1067
1068 case SCH_SHEET_PIN_T:
1069 {
1070 // mirror within parent sheet
1071 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( item );
1072 SCH_SHEET* sheet = pin->GetParent();
1073
1074 if( vertical )
1075 pin->MirrorVertically( sheet->GetBoundingBox().GetCenter().y );
1076 else
1077 pin->MirrorHorizontally( sheet->GetBoundingBox().GetCenter().x );
1078
1079 break;
1080 }
1081
1082 case SCH_FIELD_T:
1083 {
1084 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
1085
1086 if( vertical )
1088 else
1090
1091 // Now that we're re-justifying a field, they're no longer autoplaced.
1092 static_cast<SCH_ITEM*>( field->GetParent() )->SetFieldsAutoplaced( AUTOPLACE_NONE );
1093
1094 break;
1095 }
1096
1097 case SCH_BITMAP_T:
1098 if( vertical )
1099 item->MirrorVertically( item->GetPosition().y );
1100 else
1101 item->MirrorHorizontally( item->GetPosition().x );
1102
1103 // The bitmap is cached in Opengl: clear the cache to redraw
1105 break;
1106
1107 case SCH_SHEET_T:
1108 {
1109 // Mirror the sheet on itself. Sheets do not have a anchor point.
1111
1112 if( vertical )
1113 item->MirrorVertically( mirrorPoint.y );
1114 else
1115 item->MirrorHorizontally( mirrorPoint.x );
1116
1117 break;
1118 }
1119
1120 default:
1121 if( vertical )
1122 item->MirrorVertically( item->GetPosition().y );
1123 else
1124 item->MirrorHorizontally( item->GetPosition().x );
1125
1126 break;
1127 }
1128
1129 connections = item->IsConnectable();
1130 m_frame->UpdateItem( item, false, true );
1131 }
1132 else if( selection.GetSize() > 1 )
1133 {
1134 VECTOR2I mirrorPoint = m_frame->GetNearestHalfGridPosition( selection.GetCenter() );
1135
1136 for( EDA_ITEM* edaItem : selection )
1137 {
1138 item = static_cast<SCH_ITEM*>( edaItem );
1139
1140 if( !moving )
1141 commit->Modify( item, m_frame->GetScreen() );
1142
1143 if( item->Type() == SCH_SHEET_PIN_T )
1144 {
1145 if( item->GetParent()->IsSelected() )
1146 {
1147 // parent will mirror us
1148 }
1149 else
1150 {
1151 // mirror within parent sheet
1152 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( item );
1153 SCH_SHEET* sheet = pin->GetParent();
1154
1155 if( vertical )
1156 pin->MirrorVertically( sheet->GetBoundingBox().GetCenter().y );
1157 else
1158 pin->MirrorHorizontally( sheet->GetBoundingBox().GetCenter().x );
1159 }
1160 }
1161 else if( item->Type() == SCH_FIELD_T )
1162 {
1163 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
1164
1165 if( vertical )
1167 else
1169
1170 // Now that we're re-justifying a field, they're no longer autoplaced.
1171 static_cast<SCH_ITEM*>( field->GetParent() )->SetFieldsAutoplaced( AUTOPLACE_NONE );
1172 }
1173 else
1174 {
1175 if( vertical )
1176 item->MirrorVertically( mirrorPoint.y );
1177 else
1178 item->MirrorHorizontally( mirrorPoint.x );
1179 }
1180
1181 connections |= item->IsConnectable();
1182 m_frame->UpdateItem( item, false, true );
1183 }
1184 }
1185
1186 // Update R-Tree for modified items
1187 for( EDA_ITEM* selected : selection )
1188 updateItem( selected, true );
1189
1190 if( item->IsMoving() )
1191 {
1193 }
1194 else
1195 {
1196 EE_SELECTION selectionCopy = selection;
1197
1198 if( selection.IsHover() )
1200
1201 if( connections )
1202 {
1204 lwbTool->TrimOverLappingWires( commit, &selectionCopy );
1205 lwbTool->AddJunctionsIfNeeded( commit, &selectionCopy );
1206
1207 m_frame->SchematicCleanUp( commit );
1208 }
1209
1210 if( !localCommit.Empty() )
1211 localCommit.Push( _( "Mirror" ) );
1212 }
1213
1214 return 0;
1215}
1216
1217
1218const std::vector<KICAD_T> swappableItems = {
1221 SCH_TEXT_T,
1234};
1235
1236
1247static void swapFieldPositionsWithMatching( std::vector<SCH_FIELD>& aAFields,
1248 std::vector<SCH_FIELD>& aBFields,
1249 unsigned aFallbackRotationsCCW )
1250{
1251 std::set<wxString> handledKeys;
1252
1253 const auto swapFieldTextProps = []( SCH_FIELD& aField, SCH_FIELD& bField )
1254 {
1255 const VECTOR2I aRelPos = aField.GetPosition() - aField.GetParentPosition();
1256 const GR_TEXT_H_ALIGN_T aTextJustifyH = aField.GetHorizJustify();
1257 const GR_TEXT_V_ALIGN_T aTextJustifyV = aField.GetVertJustify();
1258 const EDA_ANGLE aTextAngle = aField.GetTextAngle();
1259
1260 const VECTOR2I bRelPos = bField.GetPosition() - bField.GetParentPosition();
1261 const GR_TEXT_H_ALIGN_T bTextJustifyH = bField.GetHorizJustify();
1262 const GR_TEXT_V_ALIGN_T bTextJustifyV = bField.GetVertJustify();
1263 const EDA_ANGLE bTextAngle = bField.GetTextAngle();
1264
1265 aField.SetPosition( aField.GetParentPosition() + bRelPos );
1266 aField.SetHorizJustify( bTextJustifyH );
1267 aField.SetVertJustify( bTextJustifyV );
1268 aField.SetTextAngle( bTextAngle );
1269
1270 bField.SetPosition( bField.GetParentPosition() + aRelPos );
1271 bField.SetHorizJustify( aTextJustifyH );
1272 bField.SetVertJustify( aTextJustifyV );
1273 bField.SetTextAngle( aTextAngle );
1274 };
1275
1276 for( SCH_FIELD& aField : aAFields )
1277 {
1278 const wxString name = aField.GetCanonicalName();
1279
1280 auto it = std::find_if( aBFields.begin(), aBFields.end(),
1281 [name]( const SCH_FIELD& bField )
1282 {
1283 return bField.GetCanonicalName() == name;
1284 } );
1285
1286 if( it != aBFields.end() )
1287 {
1288 // We have a field with the same key in both labels
1289 SCH_FIELD& bField = *it;
1290 swapFieldTextProps( aField, bField );
1291 }
1292 else
1293 {
1294 // We only have this field in A, so just rotate it
1295 for( unsigned ii = 0; ii < aFallbackRotationsCCW; ii++ )
1296 {
1297 aField.Rotate( aField.GetParentPosition(), true );
1298 }
1299 }
1300
1301 // And keep track that we did this one
1302 handledKeys.insert( name );
1303 }
1304
1305 // Any fields in B that weren't in A weren't handled and need to be rotated
1306 // in reverse
1307 for( SCH_FIELD& bField : aBFields )
1308 {
1309 const wxString bName = bField.GetCanonicalName();
1310 if( handledKeys.find( bName ) == handledKeys.end() )
1311 {
1312 for( unsigned ii = 0; ii < aFallbackRotationsCCW; ii++ )
1313 {
1314 bField.Rotate( bField.GetParentPosition(), false );
1315 }
1316 }
1317 }
1318}
1319
1320
1322{
1324 std::vector<EDA_ITEM*> sorted = selection.GetItemsSortedBySelectionOrder();
1325
1326 // Sheet pins are special, we need to make sure if we have any sheet pins,
1327 // that we only have sheet pins, and that they have the same parent
1328 if( selection.CountType( SCH_SHEET_PIN_T ) > 0 )
1329 {
1330 if( !selection.OnlyContains( { SCH_SHEET_PIN_T } ) )
1331 return 0;
1332
1333 SCH_SHEET_PIN* firstPin = static_cast<SCH_SHEET_PIN*>( selection.Front() );
1334 SCH_SHEET* parent = firstPin->GetParent();
1335
1336 for( EDA_ITEM* item : selection )
1337 {
1338 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( item );
1339
1340 if( pin->GetParent() != parent )
1341 return 0;
1342 }
1343 }
1344
1345 if( selection.Size() < 2 )
1346 return 0;
1347
1348 bool isMoving = selection.Front()->IsMoving();
1349 bool appendUndo = isMoving;
1350 bool connections = false;
1351
1352 for( size_t i = 0; i < sorted.size() - 1; i++ )
1353 {
1354 SCH_ITEM* a = static_cast<SCH_ITEM*>( sorted[i] );
1355 SCH_ITEM* b = static_cast<SCH_ITEM*>( sorted[( i + 1 ) % sorted.size()] );
1356
1357 VECTOR2I aPos = a->GetPosition(), bPos = b->GetPosition();
1358 std::swap( aPos, bPos );
1359
1360 saveCopyInUndoList( a, UNDO_REDO::CHANGED, appendUndo );
1361 appendUndo = true;
1362 saveCopyInUndoList( b, UNDO_REDO::CHANGED, appendUndo );
1363
1364 // Sheet pins need to have their sides swapped before we change their
1365 // positions
1366 if( a->Type() == SCH_SHEET_PIN_T )
1367 {
1368 SCH_SHEET_PIN* aPin = static_cast<SCH_SHEET_PIN*>( a );
1369 SCH_SHEET_PIN* bPin = static_cast<SCH_SHEET_PIN*>( b );
1370 SHEET_SIDE aSide = aPin->GetSide(), bSide = bPin->GetSide();
1371 std::swap( aSide, bSide );
1372 aPin->SetSide( aSide );
1373 bPin->SetSide( bSide );
1374 }
1375
1376 a->SetPosition( aPos );
1377 b->SetPosition( bPos );
1378
1379 if( a->Type() == b->Type() )
1380 {
1381 switch( a->Type() )
1382 {
1383 case SCH_LABEL_T:
1384 case SCH_GLOBAL_LABEL_T:
1385 case SCH_HIER_LABEL_T:
1387 {
1388 SCH_LABEL_BASE& aLabelBase = static_cast<SCH_LABEL_BASE&>( *a );
1389 SCH_LABEL_BASE& bLabelBase = static_cast<SCH_LABEL_BASE&>( *b );
1390
1391 const SPIN_STYLE aSpinStyle = aLabelBase.GetSpinStyle();
1392 const SPIN_STYLE bSpinStyle = bLabelBase.GetSpinStyle();
1393
1394 // First, swap the label orientations
1395 aLabelBase.SetSpinStyle( bSpinStyle );
1396 bLabelBase.SetSpinStyle( aSpinStyle );
1397
1398 // And swap the fields as best we can
1399 std::vector<SCH_FIELD>& aFields = aLabelBase.GetFields();
1400 std::vector<SCH_FIELD>& bFields = bLabelBase.GetFields();
1401
1402 const unsigned rotationsAtoB = aSpinStyle.CCWRotationsTo( bSpinStyle );
1403
1404 swapFieldPositionsWithMatching( aFields, bFields, rotationsAtoB );
1405 break;
1406 }
1407 case SCH_SYMBOL_T:
1408 {
1409 SCH_SYMBOL* aSymbol = static_cast<SCH_SYMBOL*>( a );
1410 SCH_SYMBOL* bSymbol = static_cast<SCH_SYMBOL*>( b );
1411 int aOrient = aSymbol->GetOrientation(), bOrient = bSymbol->GetOrientation();
1412 std::swap( aOrient, bOrient );
1413 aSymbol->SetOrientation( aOrient );
1414 bSymbol->SetOrientation( bOrient );
1415 break;
1416 }
1417 default: break;
1418 }
1419 }
1420
1421 connections |= a->IsConnectable();
1422 connections |= b->IsConnectable();
1423 m_frame->UpdateItem( a, false, true );
1424 m_frame->UpdateItem( b, false, true );
1425 }
1426
1427 // Update R-Tree for modified items
1428 for( EDA_ITEM* selected : selection )
1429 updateItem( selected, true );
1430
1431 if( isMoving )
1432 {
1434 }
1435 else
1436 {
1437 if( selection.IsHover() )
1439
1440 if( connections )
1442
1443 m_frame->OnModify();
1444 }
1445
1446 return 0;
1447}
1448
1449
1451{
1452 const std::vector<std::unique_ptr<SCH_ITEM>>& sourceItems = m_frame->GetRepeatItems();
1453
1454 if( sourceItems.empty() )
1455 return 0;
1456
1458
1459 SCH_COMMIT commit( m_toolMgr );
1460 EE_SELECTION newItems;
1461
1462 for( const std::unique_ptr<SCH_ITEM>& item : sourceItems )
1463 {
1464 SCH_ITEM* newItem = item->Duplicate();
1466 EESCHEMA_SETTINGS* cfg = mgr.GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" );
1467 bool restore_state = false;
1468
1469 // Ensure newItem has a suitable parent: the current screen, because an item from
1470 // a list of items to repeat must be attached to this current screen
1471 newItem->SetParent( m_frame->GetScreen() );
1472
1473 if( SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( newItem ) )
1474 {
1475 // If incrementing tries to go below zero, tell user why the value is repeated
1476
1477 if( !label->IncrementLabel( cfg->m_Drawing.repeat_label_increment ) )
1478 m_frame->ShowInfoBarWarning( _( "Label value cannot go below zero" ), true );
1479 }
1480
1481 // If cloning a symbol then put into 'move' mode.
1482 if( newItem->Type() == SCH_SYMBOL_T )
1483 {
1484 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( true );
1485 newItem->Move( cursorPos - newItem->GetPosition() );
1486 }
1487 else
1488 {
1491 }
1492
1493 // If cloning a sheet, check that we aren't going to create recursion
1494 if( newItem->Type() == SCH_SHEET_T )
1495 {
1496 SCH_SHEET_PATH* currentSheet = &m_frame->GetCurrentSheet();
1497 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( newItem );
1498
1499 if( m_frame->CheckSheetForRecursion( sheet, currentSheet ) )
1500 {
1501 // Clear out the filename so that the user can pick a new one
1502 const wxString originalFileName = sheet->GetFileName();
1503 const wxString originalScreenFileName = sheet->GetScreen()->GetFileName();
1504
1505 sheet->SetFileName( wxEmptyString );
1506 sheet->GetScreen()->SetFileName( wxEmptyString );
1507 restore_state = !m_frame->EditSheetProperties( sheet, currentSheet );
1508
1509 if( restore_state )
1510 {
1511 sheet->SetFileName( originalFileName );
1512 sheet->GetScreen()->SetFileName( originalScreenFileName );
1513 }
1514 }
1515 }
1516
1518 newItem->SetFlags( IS_NEW );
1519 m_frame->AddToScreen( newItem, m_frame->GetScreen() );
1520 commit.Added( newItem, m_frame->GetScreen() );
1521
1522 if( newItem->Type() == SCH_SYMBOL_T )
1523 {
1525 SCHEMATIC_SETTINGS& projSettings = m_frame->Schematic().Settings();
1526 int annotateStartNum = projSettings.m_AnnotateStartNum;
1527
1528 if( annotate.automatic )
1529 {
1530 static_cast<SCH_SYMBOL*>( newItem )->ClearAnnotation( nullptr, false );
1531 NULL_REPORTER reporter;
1533 (ANNOTATE_ORDER_T) annotate.sort_order,
1534 (ANNOTATE_ALGO_T) annotate.method, true /* recursive */,
1535 annotateStartNum, false, false, reporter );
1536 }
1537
1538 // Annotation clears the selection so re-add the item
1540
1541 restore_state = !m_toolMgr->RunSynchronousAction( EE_ACTIONS::move, &commit );
1542 }
1543
1544 if( restore_state )
1545 {
1546 commit.Revert();
1547 }
1548 else
1549 {
1550 newItems.Add( newItem );
1551
1553 lwbTool->TrimOverLappingWires( &commit, &newItems );
1554 lwbTool->AddJunctionsIfNeeded( &commit, &newItems );
1555
1556 m_frame->SchematicCleanUp( &commit );
1557 commit.Push( _( "Repeat Item" ) );
1558 }
1559
1560 }
1561
1562 if( !newItems.Empty() )
1563 m_frame->SaveCopyForRepeatItem( static_cast<SCH_ITEM*>( newItems[0] ) );
1564
1565 for( size_t ii = 1; ii < newItems.GetSize(); ++ii )
1566 m_frame->AddCopyForRepeatItem( static_cast<SCH_ITEM*>( newItems[ii] ) );
1567
1568 return 0;
1569}
1570
1571
1572static std::vector<KICAD_T> deletableItems =
1573{
1576 SCH_LINE_T,
1581 SCH_TEXT_T,
1583 SCH_TABLECELL_T, // Clear contents
1593 SCH_FIELD_T, // Will be hidden
1595};
1596
1597
1599{
1600 SCH_SCREEN* screen = m_frame->GetScreen();
1601 std::deque<EDA_ITEM*> items = m_selectionTool->RequestSelection( deletableItems ).GetItems();
1602 SCH_COMMIT commit( m_toolMgr );
1603 std::vector<VECTOR2I> pts;
1604 bool updateHierarchy = false;
1605
1606 if( items.empty() )
1607 return 0;
1608
1609 // Don't leave a freed pointer in the selection
1611
1612 for( EDA_ITEM* item : items )
1613 item->ClearFlags( STRUCT_DELETED );
1614
1615 for( EDA_ITEM* item : items )
1616 {
1617 SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( item );
1618
1619 if( !sch_item )
1620 continue;
1621
1622 if( sch_item->IsConnectable() )
1623 {
1624 std::vector<VECTOR2I> tmp_pts = sch_item->GetConnectionPoints();
1625 pts.insert( pts.end(), tmp_pts.begin(), tmp_pts.end() );
1626 }
1627
1628 if( sch_item->Type() == SCH_JUNCTION_T )
1629 {
1630 sch_item->SetFlags( STRUCT_DELETED );
1631 // clean up junctions at the end
1632 }
1633 else if( sch_item->Type() == SCH_SHEET_PIN_T )
1634 {
1635 SCH_SHEET_PIN* pin = (SCH_SHEET_PIN*) sch_item;
1636 SCH_SHEET* sheet = pin->GetParent();
1637
1638 if( !alg::contains( items, sheet ) )
1639 {
1640 commit.Modify( sheet, m_frame->GetScreen() );
1641 sheet->RemovePin( pin );
1642 }
1643 }
1644 else if( sch_item->Type() == SCH_FIELD_T )
1645 {
1646 // Hide field
1647 commit.Modify( item, m_frame->GetScreen() );
1648 static_cast<SCH_FIELD*>( sch_item )->SetVisible( false );
1649 }
1650 else if( sch_item->Type() == SCH_TABLECELL_T )
1651 {
1652 // Clear contents of table cell
1653 commit.Modify( item, m_frame->GetScreen() );
1654 static_cast<SCH_TABLECELL*>( sch_item )->SetText( wxEmptyString );
1655 }
1656 else if( sch_item->Type() == SCH_RULE_AREA_T )
1657 {
1658 sch_item->SetFlags( STRUCT_DELETED );
1659 commit.Remove( item, m_frame->GetScreen() );
1660 }
1661 else
1662 {
1663 sch_item->SetFlags( STRUCT_DELETED );
1664 commit.Remove( item, m_frame->GetScreen() );
1665 updateHierarchy |= ( sch_item->Type() == SCH_SHEET_T );
1666 }
1667 }
1668
1669 for( const VECTOR2I& point : pts )
1670 {
1671 SCH_ITEM* junction = screen->GetItem( point, 0, SCH_JUNCTION_T );
1672
1673 if( !junction )
1674 continue;
1675
1676 if( junction->HasFlag( STRUCT_DELETED ) || !screen->IsExplicitJunction( point ) )
1677 m_frame->DeleteJunction( &commit, junction );
1678 }
1679
1680 commit.Push( _( "Delete" ) );
1681
1682 if( updateHierarchy )
1684
1685 return 0;
1686}
1687
1688
1689#define HITTEST_THRESHOLD_PIXELS 5
1690
1691
1693{
1695
1697 m_pickerItem = nullptr;
1698
1699 // Deactivate other tools; particularly important if another PICKER is currently running
1700 Activate();
1701
1702 picker->SetCursor( KICURSOR::REMOVE );
1703 picker->SetSnapping( false );
1704
1705 picker->SetClickHandler(
1706 [this]( const VECTOR2D& aPosition ) -> bool
1707 {
1708 if( m_pickerItem )
1709 {
1711 selectionTool->UnbrightenItem( m_pickerItem );
1712 selectionTool->AddItemToSel( m_pickerItem, true /*quiet mode*/ );
1714 m_pickerItem = nullptr;
1715 }
1716
1717 return true;
1718 } );
1719
1720 picker->SetMotionHandler(
1721 [this]( const VECTOR2D& aPos )
1722 {
1723 EE_COLLECTOR collector;
1724 collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
1725 collector.Collect( m_frame->GetScreen(), deletableItems, aPos );
1726
1728 selectionTool->GuessSelectionCandidates( collector, aPos );
1729
1730 EDA_ITEM* item = collector.GetCount() == 1 ? collector[ 0 ] : nullptr;
1731
1732 if( m_pickerItem != item )
1733 {
1734 if( m_pickerItem )
1735 selectionTool->UnbrightenItem( m_pickerItem );
1736
1737 m_pickerItem = item;
1738
1739 if( m_pickerItem )
1740 selectionTool->BrightenItem( m_pickerItem );
1741 }
1742 } );
1743
1744 picker->SetFinalizeHandler(
1745 [this]( const int& aFinalState )
1746 {
1747 if( m_pickerItem )
1748 m_toolMgr->GetTool<EE_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
1749
1750 // Wake the selection tool after exiting to ensure the cursor gets updated
1752 } );
1753
1755
1756 return 0;
1757}
1758
1759
1761{
1762 KICAD_T parentType = aField->GetParent() ? aField->GetParent()->Type() : SCHEMATIC_T;
1763 SCH_COMMIT commit( m_toolMgr );
1764
1765 // Save old symbol in undo list if not already in edit, or moving.
1766 if( aField->GetEditFlags() == 0 ) // i.e. not edited, or moved
1767 commit.Modify( aField, m_frame->GetScreen() );
1768
1769 if( parentType == SCH_SYMBOL_T && aField->GetId() == REFERENCE_FIELD )
1770 static_cast<SCH_ITEM*>( aField->GetParent() )->SetConnectivityDirty();
1771
1772 wxString caption;
1773
1774 // Use title caps for mandatory fields. "Edit Sheet name Field" looks dorky.
1775 if( parentType == SCH_SYMBOL_T && aField->IsMandatory() )
1776 {
1777 wxString fieldName = GetDefaultFieldName( aField->GetId(), DO_TRANSLATE );
1778 caption.Printf( _( "Edit %s Field" ), TitleCaps( fieldName ) );
1779 }
1780 else if( parentType == SCH_SHEET_T && aField->IsMandatory() )
1781 {
1782 caption.Printf( _( "Edit %s Field" ), TitleCaps( aField->GetName() ) );
1783 }
1784 else
1785 {
1786 caption.Printf( _( "Edit '%s' Field" ), aField->GetName() );
1787 }
1788
1789 DIALOG_FIELD_PROPERTIES dlg( m_frame, caption, aField );
1790
1791 // The footprint field dialog can invoke a KIWAY_PLAYER so we must use a quasi-modal
1792 if( dlg.ShowQuasiModal() != wxID_OK )
1793 return;
1794
1795 dlg.UpdateField( &commit, aField, &m_frame->GetCurrentSheet() );
1796
1797 if( m_frame->eeconfig()->m_AutoplaceFields.enable || parentType == SCH_SHEET_T )
1798 {
1799 SCH_ITEM* parent = static_cast<SCH_ITEM*>( aField->GetParent() );
1800 AUTOPLACE_ALGO fieldsAutoplaced = parent->GetFieldsAutoplaced();
1801
1802 if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
1803 parent->AutoplaceFields( m_frame->GetScreen(), fieldsAutoplaced );
1804 }
1805
1806 if( !commit.Empty() )
1807 commit.Push( caption );
1808}
1809
1810
1812{
1815 SCH_PIN_T } );
1816
1817 if( sel.Size() != 1 )
1818 return 0;
1819
1820 bool clearSelection = sel.IsHover();
1821 EDA_ITEM* item = sel.Front();
1822
1823 if( item->Type() == SCH_FIELD_T )
1824 {
1825 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
1826
1827 if( ( aEvent.IsAction( &EE_ACTIONS::editReference ) && field->GetId() != REFERENCE_FIELD )
1828 || ( aEvent.IsAction( &EE_ACTIONS::editValue ) && field->GetId() != VALUE_FIELD )
1829 || ( aEvent.IsAction( &EE_ACTIONS::editFootprint ) && field->GetId() != FOOTPRINT_FIELD ) )
1830 {
1831 item = field->GetParentSymbol();
1834 }
1835 }
1836
1837 if( item->Type() == SCH_SYMBOL_T )
1838 {
1839 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1840
1841 if( aEvent.IsAction( &EE_ACTIONS::editReference ) )
1842 {
1844 }
1845 else if( aEvent.IsAction( &EE_ACTIONS::editValue ) )
1846 {
1847 editFieldText( symbol->GetField( VALUE_FIELD ) );
1848 }
1849 else if( aEvent.IsAction( &EE_ACTIONS::editFootprint ) )
1850 {
1851 if( !symbol->IsPower() )
1853 }
1854 }
1855 else if( item->Type() == SCH_FIELD_T )
1856 {
1857 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
1858
1859 editFieldText( field );
1860
1861 if( !field->IsVisible() )
1862 clearSelection = true;
1863 }
1864 else if( item->Type() == SCH_PIN_T )
1865 {
1866 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item->GetParent() );
1867
1868 if( symbol )
1869 {
1870 if( aEvent.IsAction( &EE_ACTIONS::editReference ) )
1871 {
1873 }
1874 else if( aEvent.IsAction( &EE_ACTIONS::editValue ) )
1875 {
1876 editFieldText( symbol->GetField( VALUE_FIELD ) );
1877 }
1878 else if( aEvent.IsAction( &EE_ACTIONS::editFootprint ) )
1879 {
1880 if( !symbol->IsPower() )
1882 }
1883 }
1884 }
1885
1886 if( clearSelection )
1888
1889 return 0;
1890}
1891
1892
1894{
1896 SCH_COMMIT commit( m_toolMgr );
1897 SCH_ITEM* head = static_cast<SCH_ITEM*>( selection.Front() );
1898 bool moving = head && head->IsMoving();
1899
1900 if( selection.Empty() )
1901 return 0;
1902
1903 std::vector<SCH_ITEM*> autoplaceItems;
1904
1905 for( unsigned ii = 0; ii < selection.GetSize(); ii++ )
1906 {
1907 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.GetItem( ii ) );
1908
1909 if( item->IsType( EE_COLLECTOR::FieldOwners ) )
1910 autoplaceItems.push_back( item );
1911 else if( item->GetParent() && item->GetParent()->IsType( EE_COLLECTOR::FieldOwners ) )
1912 autoplaceItems.push_back( static_cast<SCH_ITEM*>( item->GetParent() ) );
1913 }
1914
1915 for( SCH_ITEM* sch_item : autoplaceItems )
1916 {
1917 if( !moving && !sch_item->IsNew() )
1918 commit.Modify( sch_item, m_frame->GetScreen() );
1919
1920 sch_item->AutoplaceFields( m_frame->GetScreen(), AUTOPLACE_MANUAL );
1921
1922 updateItem( sch_item, true );
1923 }
1924
1925 if( moving )
1926 {
1928 }
1929 else
1930 {
1931 if( !commit.Empty() )
1932 commit.Push( _( "Autoplace Fields" ) );
1933
1934 if( selection.IsHover() )
1936 }
1937
1938 return 0;
1939}
1940
1941
1943{
1944 SCH_SYMBOL* selectedSymbol = nullptr;
1946
1947 if( !selection.Empty() )
1948 selectedSymbol = dynamic_cast<SCH_SYMBOL*>( selection.Front() );
1949
1951
1952 if( aEvent.IsAction( &EE_ACTIONS::changeSymbol )
1953 || aEvent.IsAction( &EE_ACTIONS::changeSymbols ) )
1954 {
1956 }
1957
1958 DIALOG_CHANGE_SYMBOLS dlg( m_frame, selectedSymbol, mode );
1959
1960 // QuasiModal required to invoke symbol browser
1961 dlg.ShowQuasiModal();
1962
1963 if( selection.IsHover() )
1965
1966 return 0;
1967}
1968
1969
1971{
1973
1974 if( selection.Empty() )
1975 return 0;
1976
1977 SCH_SYMBOL* symbol = (SCH_SYMBOL*) selection.Front();
1978
1980 && symbol->GetBodyStyle() == BODY_STYLE::BASE )
1981 {
1982 return 0;
1983 }
1984
1986 && symbol->GetBodyStyle() == BODY_STYLE::DEMORGAN )
1987 {
1988 return 0;
1989 }
1990
1991 SCH_COMMIT commit( m_toolMgr );
1992
1993 if( !symbol->IsNew() )
1994 commit.Modify( symbol, m_frame->GetScreen() );
1995
1996 m_frame->FlipBodyStyle( symbol );
1997
1998 if( symbol->IsNew() )
2000
2001 if( !commit.Empty() )
2002 commit.Push( _( "Change Body Style" ) );
2003
2004 if( selection.IsHover() )
2006
2007 return 0;
2008}
2009
2010
2012{
2014 bool clearSelection = selection.IsHover();
2015
2016 if( selection.Empty() )
2017 {
2018 if( getView()->IsLayerVisible( LAYER_SCHEMATIC_DRAWINGSHEET ) )
2019 {
2021 VECTOR2D cursorPos = getViewControls()->GetCursorPosition( false );
2022
2023 if( ds && ds->HitTestDrawingSheetItems( getView(), cursorPos ) )
2025 }
2026
2027 return 0;
2028 }
2029
2030 EDA_ITEM* curr_item = selection.Front();
2031
2032 // If a single pin is selected, promote to its parent symbol
2033 if( ( selection.GetSize() == 1 ) && ( curr_item->Type() == SCH_PIN_T ) )
2034 {
2035 EDA_ITEM* parent = curr_item->GetParent();
2036
2037 if( parent->Type() == SCH_SYMBOL_T )
2038 curr_item = parent;
2039 }
2040
2041 switch( curr_item->Type() )
2042 {
2043 case SCH_LINE_T:
2045 case SCH_JUNCTION_T:
2046 case SCH_TABLECELL_T:
2047 break;
2048
2049 default:
2050 if( selection.Size() > 1 )
2051 return 0;
2052
2053 break;
2054 }
2055
2056 switch( curr_item->Type() )
2057 {
2058 case SCH_SYMBOL_T:
2059 {
2060 int retval;
2061 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( curr_item );
2062
2063 // This needs to be scoped so the dialog destructor removes blocking status
2064 // before we launch the next dialog.
2065 {
2066 DIALOG_SYMBOL_PROPERTIES symbolPropsDialog( m_frame, symbol );
2067
2068 // This dialog itself subsequently can invoke a KIWAY_PLAYER as a quasimodal
2069 // frame. Therefore this dialog as a modal frame parent, MUST be run under
2070 // quasimodal mode for the quasimodal frame support to work. So don't use
2071 // the QUASIMODAL macros here.
2072 retval = symbolPropsDialog.ShowQuasiModal();
2073 }
2074
2075 if( retval == SYMBOL_PROPS_EDIT_OK )
2076 {
2078 {
2079 AUTOPLACE_ALGO fieldsAutoplaced = symbol->GetFieldsAutoplaced();
2080
2081 if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
2082 symbol->AutoplaceFields( m_frame->GetScreen(), fieldsAutoplaced );
2083 }
2084
2085 m_frame->OnModify();
2086 }
2087 else if( retval == SYMBOL_PROPS_EDIT_SCHEMATIC_SYMBOL )
2088 {
2089 if( KIWAY_PLAYER* frame = m_frame->Kiway().Player( FRAME_SCH_SYMBOL_EDITOR, true ) )
2090 {
2091 SYMBOL_EDIT_FRAME* editor = static_cast<SYMBOL_EDIT_FRAME*>( frame );
2092
2093 if( wxWindow* blocking_win = editor->Kiway().GetBlockingDialog() )
2094 blocking_win->Close( true );
2095
2096 // The broken library symbol link indicator cannot be edited.
2097 if( symbol->IsMissingLibSymbol() )
2098 return 0;
2099
2100 editor->LoadSymbolFromSchematic( symbol );
2101 editor->Show( true );
2102 editor->Raise();
2103 }
2104 }
2105 else if( retval == SYMBOL_PROPS_EDIT_LIBRARY_SYMBOL )
2106 {
2107 if( KIWAY_PLAYER* frame = m_frame->Kiway().Player( FRAME_SCH_SYMBOL_EDITOR, true ) )
2108 {
2109 SYMBOL_EDIT_FRAME* editor = static_cast<SYMBOL_EDIT_FRAME*>( frame );
2110
2111 if( wxWindow* blocking_win = editor->Kiway().GetBlockingDialog() )
2112 blocking_win->Close( true );
2113
2114 editor->LoadSymbol( symbol->GetLibId(), symbol->GetUnit(), symbol->GetBodyStyle() );
2115 editor->Show( true );
2116 editor->Raise();
2117 }
2118 }
2119 else if( retval == SYMBOL_PROPS_WANT_UPDATE_SYMBOL )
2120 {
2122 dlg.ShowQuasiModal();
2123 }
2124 else if( retval == SYMBOL_PROPS_WANT_EXCHANGE_SYMBOL )
2125 {
2127 dlg.ShowQuasiModal();
2128 }
2129
2130 break;
2131 }
2132
2133 case SCH_SHEET_T:
2134 {
2135 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( curr_item );
2136 bool isUndoable = false;
2137 bool doClearAnnotation = false;
2138 bool okPressed = false;
2139 bool updateHierarchyNavigator = false;
2140
2141 // Keep track of existing sheet paths. EditSheet() can modify this list.
2142 // Note that we use the validity checking/repairing version here just to make sure
2143 // we've got a valid hierarchy to begin with.
2144 SCH_SHEET_LIST originalHierarchy;
2145 originalHierarchy.BuildSheetList( &m_frame->Schematic().Root(), true );
2146
2147 SCH_COMMIT commit( m_toolMgr );
2148 commit.Modify( sheet, m_frame->GetScreen() );
2149 okPressed = m_frame->EditSheetProperties( sheet, &m_frame->GetCurrentSheet(), &isUndoable,
2150 &doClearAnnotation, &updateHierarchyNavigator );
2151
2152 if( okPressed )
2153 {
2154 if( isUndoable )
2155 {
2156 commit.Push( _( "Edit Sheet Properties" ) );
2157 }
2158 else
2159 {
2160 std::vector<SCH_ITEM*> items;
2161
2162 items.emplace_back( sheet );
2163 m_frame->Schematic().OnItemsRemoved( items );
2164 m_frame->Schematic().OnItemsAdded( items );
2165 m_frame->OnModify();
2168 }
2169 }
2170 else
2171 {
2172 // If we are renaming files, the undo/redo list becomes invalid and must be cleared.
2174 m_frame->OnModify();
2175 }
2176
2177 // If the sheet file is changed and new sheet contents are loaded then we have to
2178 // clear the annotations on the new content (as it may have been set from some other
2179 // sheet path reference)
2180 if( doClearAnnotation )
2181 {
2182 SCH_SCREENS screensList( &m_frame->Schematic().Root() );
2183
2184 // We clear annotation of new sheet paths here:
2185 screensList.ClearAnnotationOfNewSheetPaths( originalHierarchy );
2186
2187 // Clear annotation of g_CurrentSheet itself, because its sheetpath is not a new
2188 // path, but symbols managed by its sheet path must have their annotation cleared
2189 // because they are new:
2190 sheet->GetScreen()->ClearAnnotation( &m_frame->GetCurrentSheet(), false );
2191 }
2192
2193 if( okPressed )
2195
2196 if( updateHierarchyNavigator )
2198
2199 break;
2200 }
2201
2202 case SCH_SHEET_PIN_T:
2203 {
2204 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( curr_item );
2206
2207 // QuasiModal required for help dialog
2208 dlg.ShowQuasiModal();
2209 break;
2210 }
2211
2212 case SCH_TEXT_T:
2213 case SCH_TEXTBOX_T:
2214 {
2215 DIALOG_TEXT_PROPERTIES dlg( m_frame, static_cast<SCH_ITEM*>( curr_item ) );
2216
2217 // QuasiModal required for syntax help and Scintilla auto-complete
2218 dlg.ShowQuasiModal();
2219 break;
2220 }
2221
2222 case SCH_TABLECELL_T:
2223 if( SELECTION_CONDITIONS::OnlyTypes( { SCH_TABLECELL_T } )( selection ) )
2224 {
2225 std::vector<SCH_TABLECELL*> cells;
2226
2227 for( EDA_ITEM* item : selection.Items() )
2228 cells.push_back( static_cast<SCH_TABLECELL*>( item ) );
2229
2231
2232 dlg.ShowModal();
2233
2235 {
2236 SCH_TABLE* table = static_cast<SCH_TABLE*>( cells[0]->GetParent() );
2237 DIALOG_TABLE_PROPERTIES tableDlg( m_frame, table );
2238
2239 tableDlg.ShowModal();
2240 }
2241 }
2242
2243 break;
2244
2245 case SCH_TABLE_T:
2246 {
2247 DIALOG_TABLE_PROPERTIES dlg( m_frame, static_cast<SCH_TABLE*>( curr_item ) );
2248
2249 // QuasiModal required for Scintilla auto-complete
2250 dlg.ShowQuasiModal();
2251 break;
2252 }
2253
2254 case SCH_LABEL_T:
2255 case SCH_GLOBAL_LABEL_T:
2256 case SCH_HIER_LABEL_T:
2258 {
2259 DIALOG_LABEL_PROPERTIES dlg( m_frame, static_cast<SCH_LABEL_BASE*>( curr_item ) );
2260
2261 // QuasiModal for syntax help and Scintilla auto-complete
2262 dlg.ShowQuasiModal();
2263 break;
2264 }
2265
2266 case SCH_FIELD_T:
2267 {
2268 SCH_FIELD* field = static_cast<SCH_FIELD*>( curr_item );
2269
2270 editFieldText( field );
2271
2272 if( !field->IsVisible() )
2273 clearSelection = true;
2274
2275 break;
2276 }
2277
2278 case SCH_SHAPE_T:
2279 {
2280 DIALOG_SHAPE_PROPERTIES dlg( m_frame, static_cast<SCH_SHAPE*>( curr_item ) );
2281
2282 dlg.ShowModal();
2283 break;
2284 }
2285
2286 case SCH_BITMAP_T:
2287 {
2288 SCH_BITMAP& bitmap = static_cast<SCH_BITMAP&>( *curr_item );
2289 DIALOG_IMAGE_PROPERTIES dlg( m_frame, bitmap );
2290
2291 if( dlg.ShowModal() == wxID_OK )
2292 {
2293 // The bitmap is cached in Opengl: clear the cache in case it has become invalid
2295 }
2296
2297 break;
2298 }
2299
2300 case SCH_RULE_AREA_T:
2301 {
2302 DIALOG_SHAPE_PROPERTIES dlg( m_frame, static_cast<SCH_SHAPE*>( curr_item ) );
2303 dlg.SetTitle( _( "Rule Area Properties" ) );
2304
2305 dlg.ShowModal();
2306 break;
2307 }
2308
2309 case SCH_LINE_T:
2311 case SCH_JUNCTION_T:
2313 {
2314 std::deque<SCH_LINE*> lines;
2315
2316 for( EDA_ITEM* selItem : selection.Items() )
2317 lines.push_back( static_cast<SCH_LINE*>( selItem ) );
2318
2319 DIALOG_LINE_PROPERTIES dlg( m_frame, lines );
2320
2321 dlg.ShowModal();
2322 }
2323 else if( SELECTION_CONDITIONS::OnlyTypes( { SCH_JUNCTION_T } )( selection ) )
2324 {
2325 std::deque<SCH_JUNCTION*> junctions;
2326
2327 for( EDA_ITEM* selItem : selection.Items() )
2328 junctions.push_back( static_cast<SCH_JUNCTION*>( selItem ) );
2329
2330 DIALOG_JUNCTION_PROPS dlg( m_frame, junctions );
2331
2332 dlg.ShowModal();
2333 }
2337 SCH_JUNCTION_T } )( selection ) )
2338 {
2339 std::deque<SCH_ITEM*> items;
2340
2341 for( EDA_ITEM* selItem : selection.Items() )
2342 items.push_back( static_cast<SCH_ITEM*>( selItem ) );
2343
2344 DIALOG_WIRE_BUS_PROPERTIES dlg( m_frame, items );
2345
2346 dlg.ShowModal();
2347 }
2348 else
2349 {
2350 return 0;
2351 }
2352
2353 break;
2354
2355 case SCH_MARKER_T:
2356 if( SELECTION_CONDITIONS::OnlyTypes( { SCH_MARKER_T } )( selection ) )
2357 {
2359
2360 if( inspectionTool )
2361 inspectionTool->CrossProbe( static_cast<SCH_MARKER*> ( selection.Front() ) );
2362 }
2363 break;
2364
2365 case SCH_NO_CONNECT_T:
2366 case SCH_PIN_T:
2367 break;
2368
2369 default: // Unexpected item
2370 wxFAIL_MSG( wxString( "Cannot edit schematic item type " ) + curr_item->GetClass() );
2371 }
2372
2373 updateItem( curr_item, true );
2374
2375 if( clearSelection )
2377
2378 return 0;
2379}
2380
2381
2383{
2384 KICAD_T convertTo = aEvent.Parameter<KICAD_T>();
2386 SCH_TEXT_T,
2387 SCH_TEXTBOX_T } );
2388 SCH_COMMIT commit( m_toolMgr );
2389
2390 for( unsigned int i = 0; i < selection.GetSize(); ++i )
2391 {
2392 SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( selection.GetItem( i ) );
2393
2394 if( item && item->Type() != convertTo )
2395 {
2396 EDA_TEXT* sourceText = dynamic_cast<EDA_TEXT*>( item );
2397 bool selected = item->IsSelected();
2398 SCH_ITEM* newtext = nullptr;
2399 VECTOR2I position = item->GetPosition();
2400 wxString txt;
2401 wxString href;
2403 LABEL_FLAG_SHAPE shape = LABEL_FLAG_SHAPE::L_UNSPECIFIED;
2404
2405 switch( item->Type() )
2406 {
2407 case SCH_LABEL_T:
2408 case SCH_GLOBAL_LABEL_T:
2409 case SCH_HIER_LABEL_T:
2410 {
2411 SCH_LABEL_BASE* label = static_cast<SCH_LABEL_BASE*>( item );
2412
2413 txt = UnescapeString( label->GetText() );
2414 spinStyle = label->GetSpinStyle();
2415 shape = label->GetShape();
2416 href = label->GetHyperlink();
2417 break;
2418 }
2419
2421 {
2422 SCH_DIRECTIVE_LABEL* dirlabel = static_cast<SCH_DIRECTIVE_LABEL*>( item );
2423
2424 // a SCH_DIRECTIVE_LABEL has no text
2425 txt = _( "<empty>" );
2426
2427 spinStyle = dirlabel->GetSpinStyle();
2428 href = dirlabel->GetHyperlink();
2429 break;
2430 }
2431
2432 case SCH_TEXT_T:
2433 {
2434 SCH_TEXT* text = static_cast<SCH_TEXT*>( item );
2435
2436 txt = text->GetText();
2437 href = text->GetHyperlink();
2438 break;
2439 }
2440
2441 case SCH_TEXTBOX_T:
2442 {
2443 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( item );
2444 BOX2I bbox = textbox->GetBoundingBox();
2445
2446 bbox.SetOrigin( bbox.GetLeft() + textbox->GetMarginLeft(),
2447 bbox.GetTop() + textbox->GetMarginTop() );
2448 bbox.SetEnd( bbox.GetRight() - textbox->GetMarginRight(),
2449 bbox.GetBottom() - textbox->GetMarginBottom() );
2450
2451 if( convertTo == SCH_LABEL_T
2452 || convertTo == SCH_HIER_LABEL_T
2453 || convertTo == SCH_GLOBAL_LABEL_T )
2454 {
2455 EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item );
2456 wxCHECK( text, 0 );
2457 int textSize = text->GetTextSize().y;
2458 bbox.Inflate( KiROUND( item->Schematic()->Settings().m_LabelSizeRatio * textSize ) );
2459 }
2460
2461 txt = textbox->GetText();
2462
2463 if( textbox->GetTextAngle().IsVertical() )
2464 {
2465 if( textbox->GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
2466 {
2467 spinStyle = SPIN_STYLE::SPIN::BOTTOM;
2468 position = VECTOR2I( bbox.Centre().x, bbox.GetOrigin().y );
2469 }
2470 else
2471 {
2472 spinStyle = SPIN_STYLE::SPIN::UP;
2473 position = VECTOR2I( bbox.Centre().x, bbox.GetEnd().y );
2474 }
2475 }
2476 else
2477 {
2478 if( textbox->GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
2479 {
2480 spinStyle = SPIN_STYLE::SPIN::LEFT;
2481 position = VECTOR2I( bbox.GetEnd().x, bbox.Centre().y );
2482 }
2483 else
2484 {
2485 spinStyle = SPIN_STYLE::SPIN::RIGHT;
2486 position = VECTOR2I( bbox.GetOrigin().x, bbox.Centre().y );
2487 }
2488 }
2489
2490 position = m_frame->GetNearestGridPosition( position );
2491 href = textbox->GetHyperlink();
2492 break;
2493 }
2494
2495 default:
2496 UNIMPLEMENTED_FOR( item->GetClass() );
2497 break;
2498 }
2499
2500 auto getValidNetname =
2501 []( const wxString& aText )
2502 {
2503 wxString local_txt = aText;
2504 local_txt.Replace( "\n", "_" );
2505 local_txt.Replace( "\r", "_" );
2506 local_txt.Replace( "\t", "_" );
2507
2508 // Bus groups can have spaces; bus vectors and signal names cannot
2509 if( !NET_SETTINGS::ParseBusGroup( aText, nullptr, nullptr ) )
2510 local_txt.Replace( " ", "_" );
2511
2512 // label strings are "escaped" i.e. a '/' is replaced by "{slash}"
2513 local_txt = EscapeString( local_txt, CTX_NETNAME );
2514
2515 if( local_txt.IsEmpty() )
2516 return _( "<empty>" );
2517 else
2518 return local_txt;
2519 };
2520
2521 switch( convertTo )
2522 {
2523 case SCH_LABEL_T:
2524 {
2525 SCH_LABEL_BASE* new_label = new SCH_LABEL( position, getValidNetname( txt ) );
2526
2527 new_label->SetShape( shape );
2528 new_label->SetAttributes( *sourceText, false );
2529 new_label->SetSpinStyle( spinStyle );
2530 new_label->SetHyperlink( href );
2531
2532 if( item->Type() == SCH_GLOBAL_LABEL_T || item->Type() == SCH_HIER_LABEL_T )
2533 {
2534 if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::UP )
2535 new_label->MirrorVertically( position.y );
2536 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::BOTTOM )
2537 new_label->MirrorVertically( position.y );
2538 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::LEFT )
2539 new_label->MirrorHorizontally( position.x );
2540 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::RIGHT )
2541 new_label->MirrorHorizontally( position.x );
2542 }
2543
2544 newtext = new_label;
2545 break;
2546 }
2547
2548 case SCH_GLOBAL_LABEL_T:
2549 {
2550 SCH_LABEL_BASE* new_label = new SCH_GLOBALLABEL( position, getValidNetname( txt ) );
2551
2552 new_label->SetShape( shape );
2553 new_label->SetAttributes( *sourceText, false );
2554 new_label->SetSpinStyle( spinStyle );
2555 new_label->SetHyperlink( href );
2556
2557 if( item->Type() == SCH_LABEL_T )
2558 {
2559 if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::UP )
2560 new_label->MirrorVertically( position.y );
2561 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::BOTTOM )
2562 new_label->MirrorVertically( position.y );
2563 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::LEFT )
2564 new_label->MirrorHorizontally( position.x );
2565 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::RIGHT )
2566 new_label->MirrorHorizontally( position.x );
2567 }
2568
2569 newtext = new_label;
2570 break;
2571 }
2572
2573 case SCH_HIER_LABEL_T:
2574 {
2575 SCH_LABEL_BASE* new_label = new SCH_HIERLABEL( position, getValidNetname( txt ) );
2576
2577 new_label->SetShape( shape );
2578 new_label->SetAttributes( *sourceText, false );
2579 new_label->SetSpinStyle( spinStyle );
2580 new_label->SetHyperlink( href );
2581
2582 if( item->Type() == SCH_LABEL_T )
2583 {
2584 if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::UP )
2585 new_label->MirrorVertically( position.y );
2586 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::BOTTOM )
2587 new_label->MirrorVertically( position.y );
2588 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::LEFT )
2589 new_label->MirrorHorizontally( position.x );
2590 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::RIGHT )
2591 new_label->MirrorHorizontally( position.x );
2592 }
2593
2594 newtext = new_label;
2595 break;
2596 }
2597
2599 {
2600 SCH_LABEL_BASE* new_label = new SCH_DIRECTIVE_LABEL( position );
2601
2602 // A SCH_DIRECTIVE_LABEL usually has at least one field containing the net class
2603 // name. If we're copying from a text object assume the text is the netclass
2604 // name. Otherwise, we'll just copy the fields which will either have a netclass
2605 // or not.
2606 if( !dynamic_cast<SCH_LABEL_BASE*>( item ) )
2607 {
2608 SCH_FIELD netclass( position, 0, new_label, wxT( "Netclass" ) );
2609 netclass.SetText( txt );
2610 netclass.SetVisible( true );
2611 new_label->GetFields().push_back( netclass );
2612 }
2613
2614 new_label->SetShape( LABEL_FLAG_SHAPE::F_ROUND );
2615 new_label->SetAttributes( *sourceText, false );
2616 new_label->SetSpinStyle( spinStyle );
2617 new_label->SetHyperlink( href );
2618 newtext = new_label;
2619 break;
2620 }
2621
2622 case SCH_TEXT_T:
2623 {
2624 SCH_TEXT* new_text = new SCH_TEXT( position, txt );
2625
2626 new_text->SetAttributes( *sourceText, false );
2627 new_text->SetHyperlink( href );
2628 newtext = new_text;
2629 break;
2630 }
2631
2632 case SCH_TEXTBOX_T:
2633 {
2634 SCH_TEXTBOX* new_textbox = new SCH_TEXTBOX( LAYER_NOTES, 0, FILL_T::NO_FILL, txt );
2635 BOX2I bbox = item->GetBoundingBox();
2636
2637 if( SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( item ) )
2638 bbox.Inflate( -label->GetLabelBoxExpansion() );
2639
2640 new_textbox->SetAttributes( *sourceText, false );
2641
2642 bbox.SetOrigin( bbox.GetLeft() - new_textbox->GetMarginLeft(),
2643 bbox.GetTop() - new_textbox->GetMarginTop() );
2644 bbox.SetEnd( bbox.GetRight() + new_textbox->GetMarginRight(),
2645 bbox.GetBottom() + new_textbox->GetMarginBottom() );
2646
2647 VECTOR2I topLeft = bbox.GetPosition();
2648 VECTOR2I botRight = bbox.GetEnd();
2649
2650 // Add 1/20 of the margin at the end to reduce line-breaking changes.
2651 int slop = new_textbox->GetLegacyTextMargin() / 20;
2652
2653 if( sourceText->GetTextAngle() == ANGLE_VERTICAL )
2654 {
2655 if( sourceText->GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
2656 botRight.y += slop;
2657 else
2658 topLeft.y -= slop;
2659 }
2660 else
2661 {
2662 if( sourceText->GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
2663 topLeft.x -= slop;
2664 else
2665 botRight.x += slop;
2666 }
2667
2668 new_textbox->SetPosition( topLeft );
2669 new_textbox->SetEnd( botRight );
2670
2671 new_textbox->SetHyperlink( href );
2672 newtext = new_textbox;
2673 break;
2674 }
2675
2676 default:
2677 UNIMPLEMENTED_FOR( wxString::Format( "%d.", convertTo ) );
2678 break;
2679 }
2680
2681 wxCHECK2( newtext, continue );
2682
2683 // Copy the old text item settings to the new one. Justifications are not copied
2684 // because they are not used in labels. Justifications will be set to default value
2685 // in the new text item type.
2686 //
2687 newtext->SetFlags( item->GetEditFlags() );
2688
2689 EDA_TEXT* eda_text = dynamic_cast<EDA_TEXT*>( item );
2690 EDA_TEXT* new_eda_text = dynamic_cast<EDA_TEXT*>( newtext );
2691
2692 wxCHECK2( eda_text && new_eda_text, continue );
2693
2694 new_eda_text->SetFont( eda_text->GetFont() );
2695 new_eda_text->SetTextSize( eda_text->GetTextSize() );
2696 new_eda_text->SetTextThickness( eda_text->GetTextThickness() );
2697
2698 // Must be after SetTextSize()
2699 new_eda_text->SetBold( eda_text->IsBold() );
2700 new_eda_text->SetItalic( eda_text->IsItalic() );
2701
2703
2704 SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( item );
2705 SCH_LABEL_BASE* new_label = dynamic_cast<SCH_LABEL_BASE*>( newtext );
2706
2707 if( label && new_label )
2708 {
2709 new_label->AddFields( label->GetFields() );
2710
2711 // A SCH_GLOBALLABEL has a specific field, that has no meaning for
2712 // other labels, and expected to be the first field in list.
2713 // It is the first field in list for this kind of label
2714 // So remove field named "Intersheetrefs" if exists for other labels
2715 int min_idx = new_label->Type() == SCH_GLOBAL_LABEL_T ? 1 : 0;
2716 std::vector<SCH_FIELD>& fields = new_label->GetFields();
2717
2718 for( int ii = fields.size()-1; ii >= min_idx; ii-- )
2719 {
2720 if( fields[ii].GetCanonicalName() == wxT( "Intersheetrefs" ) )
2721 fields.erase( fields.begin() + ii );
2722 }
2723 }
2724
2725 if( selected )
2727
2728 if( !item->IsNew() )
2729 {
2731 commit.Removed( item, m_frame->GetScreen() );
2732
2733 m_frame->AddToScreen( newtext, m_frame->GetScreen() );
2734 commit.Added( newtext, m_frame->GetScreen() );
2735 }
2736
2737 if( selected )
2739
2740 // Otherwise, pointer is owned by the undo stack
2741 if( item->IsNew() )
2742 delete item;
2743 }
2744 }
2745
2746 if( !commit.Empty() )
2747 commit.Push( _( "Change To" ) );
2748
2749 if( selection.IsHover() )
2751
2752 return 0;
2753}
2754
2755
2757{
2758 static std::vector<KICAD_T> justifiableItems = {
2760 SCH_TEXT_T,
2763 };
2764
2765 EE_SELECTION& selection = m_selectionTool->RequestSelection( justifiableItems );
2766
2767 if( selection.GetSize() == 0 )
2768 return 0;
2769
2770 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.Front() );
2771 bool moving = item->IsMoving();
2772 SCH_COMMIT localCommit( m_toolMgr );
2773 SCH_COMMIT* commit = dynamic_cast<SCH_COMMIT*>( aEvent.Commit() );
2774
2775 if( !commit )
2776 commit = &localCommit;
2777
2778 auto setJustify =
2779 [&]( EDA_TEXT* aTextItem )
2780 {
2781 if( aEvent.Matches( ACTIONS::leftJustify.MakeEvent() ) )
2782 aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
2783 else if( aEvent.Matches( ACTIONS::centerJustify.MakeEvent() ) )
2784 aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER );
2785 else
2786 aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
2787 };
2788
2789 for( EDA_ITEM* edaItem : selection )
2790 {
2791 item = static_cast<SCH_ITEM*>( edaItem );
2792
2793 if( !moving )
2794 commit->Modify( item, m_frame->GetScreen() );
2795
2796 if( item->Type() == SCH_FIELD_T )
2797 {
2798 setJustify( static_cast<SCH_FIELD*>( item ) );
2799
2800 // Now that we're re-justifying a field, they're no longer autoplaced.
2801 static_cast<SCH_ITEM*>( item->GetParent() )->SetFieldsAutoplaced( AUTOPLACE_NONE );
2802 }
2803 else if( item->Type() == SCH_TEXT_T )
2804 {
2805 setJustify( static_cast<SCH_TEXT*>( item ) );
2806 }
2807 else if( item->Type() == SCH_TEXTBOX_T )
2808 {
2809 setJustify( static_cast<SCH_TEXTBOX*>( item ) );
2810 }
2811 else if( item->Type() == SCH_LABEL_T )
2812 {
2813 SCH_LABEL* label = static_cast<SCH_LABEL*>( item );
2814
2815 if( label->GetTextAngle() == ANGLE_HORIZONTAL )
2816 setJustify( label );
2817 }
2818
2819 m_frame->UpdateItem( item, false, true );
2820 }
2821
2822 // Update R-Tree for modified items
2823 for( EDA_ITEM* selected : selection )
2824 updateItem( selected, true );
2825
2826 if( item->IsMoving() )
2827 {
2829 }
2830 else
2831 {
2832 EE_SELECTION selectionCopy = selection;
2833
2834 if( selection.IsHover() )
2836
2837 if( !localCommit.Empty() )
2838 {
2839 if( aEvent.Matches( ACTIONS::leftJustify.MakeEvent() ) )
2840 localCommit.Push( _( "Left Justify" ) );
2841 else if( aEvent.Matches( ACTIONS::centerJustify.MakeEvent() ) )
2842 localCommit.Push( _( "Center Justify" ) );
2843 else
2844 localCommit.Push( _( "Right Justify" ) );
2845 }
2846 }
2847
2848 return 0;
2849}
2850
2851
2853{
2854 bool isSlice = aEvent.Matches( EE_ACTIONS::slice.MakeEvent() );
2857 SCH_SCREEN* screen = m_frame->GetScreen();
2858 SCH_COMMIT commit( m_toolMgr );
2859 std::vector<SCH_LINE*> lines;
2860
2861 for( EDA_ITEM* item : selection )
2862 {
2863 if( item->Type() == SCH_LINE_T )
2864 {
2865 SCH_LINE* line = static_cast<SCH_LINE*>( item );
2866
2867 if( !line->IsEndPoint( cursorPos ) )
2868 lines.push_back( line );
2869 }
2870 }
2871
2873
2874 for( SCH_LINE* line : lines )
2875 {
2876 SCH_LINE* newLine;
2877
2878 // We let the user select the break point if they're on a single line
2879 if( lines.size() == 1 && line->HitTest( cursorPos ) )
2880 m_frame->BreakSegment( &commit, line, cursorPos, &newLine, screen );
2881 else
2882 m_frame->BreakSegment( &commit, line, line->GetMidPoint(), &newLine, screen );
2883
2884 // Make sure both endpoints are deselected
2885 newLine->ClearFlags();
2886
2888 line->SetFlags( ENDPOINT );
2889
2890 // If we're a break, we want to drag both wires.
2891 // Side note: the drag/move tool only checks whether the first item is
2892 // new to determine if it should append undo or not, someday this should
2893 // be cleaned up and explictly controlled but for now the newLine
2894 // selection addition must be after the existing line.
2895 if( !isSlice )
2896 {
2897 m_selectionTool->AddItemToSel( newLine );
2898 newLine->SetFlags( STARTPOINT );
2899 }
2900 }
2901
2902 if( !lines.empty() )
2903 {
2905
2906 if( m_toolMgr->RunSynchronousAction( EE_ACTIONS::drag, &commit, isSlice ) )
2907 commit.Push( isSlice ? _( "Slice Wire" ) : _( "Break Wire" ) );
2908 else
2909 commit.Revert();
2910 }
2911
2912 if( selection.IsHover() )
2914
2915 return 0;
2916}
2917
2918
2920{
2922 SCH_SHEET* sheet = (SCH_SHEET*) selection.Front();
2923 SCH_COMMIT commit( m_toolMgr );
2924
2925 if( !sheet || !sheet->HasUndefinedPins() )
2926 return 0;
2927
2928 if( !IsOK( m_frame, _( "Do you wish to delete the unreferenced pins from this sheet?" ) ) )
2929 return 0;
2930
2931 commit.Modify( sheet, m_frame->GetScreen() );
2932
2933 sheet->CleanupSheet();
2934
2935 updateItem( sheet, true );
2936
2937 commit.Push( _( "Cleanup Sheet Pins" ) );
2938
2939 if( selection.IsHover() )
2941
2942 return 0;
2943}
2944
2945
2947{
2949
2950 if( selection.GetSize() > 1 )
2951 return 0;
2952
2953 SCH_SHEET* sheet = (SCH_SHEET*) selection.Front();
2954
2956
2957 SCH_SCREEN* screen;
2958
2959 if( sheet )
2960 {
2961 // When changing the page number of a selected sheet, the current screen owns the sheet.
2962 screen = m_frame->GetScreen();
2963
2964 instance.push_back( sheet );
2965 }
2966 else
2967 {
2968 SCH_SHEET_PATH prevInstance = instance;
2969
2970 // When change the page number in the screen, the previous screen owns the sheet.
2971 if( prevInstance.size() )
2972 {
2973 prevInstance.pop_back();
2974 screen = prevInstance.LastScreen();
2975 }
2976 else
2977 {
2978 // The root sheet and root screen are effectively the same thing.
2979 screen = m_frame->GetScreen();
2980 }
2981
2982 sheet = m_frame->GetCurrentSheet().Last();
2983 }
2984
2985 wxString msg;
2986 wxString sheetPath = instance.PathHumanReadable( false );
2987 wxString pageNumber = instance.GetPageNumber();
2988
2989 msg.Printf( _( "Enter page number for sheet path%s" ),
2990 ( sheetPath.Length() > 20 ) ? "\n" + sheetPath : " " + sheetPath );
2991
2992 wxTextEntryDialog dlg( m_frame, msg, _( "Edit Sheet Page Number" ), pageNumber );
2993
2994 dlg.SetTextValidator( wxFILTER_ALPHANUMERIC ); // No white space.
2995
2996 if( dlg.ShowModal() == wxID_CANCEL || dlg.GetValue() == instance.GetPageNumber() )
2997 return 0;
2998
2999 SCH_COMMIT commit( m_frame );
3000
3001 commit.Modify( sheet, screen );
3002
3003 instance.SetPageNumber( dlg.GetValue() );
3004
3005 if( instance == m_frame->GetCurrentSheet() )
3006 {
3007 m_frame->GetScreen()->SetPageNumber( dlg.GetValue() );
3009 }
3010
3011 commit.Push( wxS( "Change Sheet Page Number" ) );
3012
3013 if( selection.IsHover() )
3015
3016 return 0;
3017}
3018
3019
3021{
3022 const ACTIONS::INCREMENT incParam = aEvent.Parameter<ACTIONS::INCREMENT>();
3023 static const std::vector<KICAD_T> incrementable = { SCH_LABEL_T, SCH_GLOBAL_LABEL_T,
3025 EE_SELECTION& selection = m_selectionTool->RequestSelection( incrementable );
3026
3027 if( selection.Empty() )
3028 return 0;
3029
3030 KICAD_T type = selection.Front()->Type();
3031 bool allSameType = true;
3032
3033 for( EDA_ITEM* item : selection )
3034 {
3035 if( item->Type() != type )
3036 {
3037 allSameType = false;
3038 break;
3039 }
3040 }
3041
3042 // Incrementing multiple types at once seems confusing
3043 // though it would work.
3044 if( !allSameType )
3045 return 0;
3046
3047 STRING_INCREMENTER incrementer;
3048 // In schematics, it's probably less common to be operating
3049 // on pin numbers which are usually IOSQXZ-skippy.
3050 incrementer.SetSkipIOSQXZ( false );
3051
3052 // If we're coming via another action like 'Move', use that commit
3053 SCH_COMMIT localCommit( m_toolMgr );
3054 SCH_COMMIT* commit = dynamic_cast<SCH_COMMIT*>( aEvent.Commit() );
3055
3056 if( !commit )
3057 commit = &localCommit;
3058
3059 const auto modifyItem =
3060 [&]( EDA_ITEM& aItem )
3061 {
3062 if( aItem.IsNew() )
3064 else
3065 commit->Modify( &aItem, m_frame->GetScreen() );
3066 };
3067
3068 for( EDA_ITEM* item : selection )
3069 {
3070 switch( item->Type() )
3071 {
3072 case SCH_LABEL_T:
3073 case SCH_GLOBAL_LABEL_T:
3074 case SCH_HIER_LABEL_T:
3075 case SCH_TEXT_T:
3076 {
3077 SCH_TEXT& label = static_cast<SCH_TEXT&>( *item );
3078
3079 std::optional<wxString> newLabel = incrementer.Increment( label.GetText(),
3080 incParam.Delta,
3081 incParam.Index );
3082
3083 if( newLabel )
3084 {
3085 modifyItem( label );
3086 label.SetText( *newLabel );
3087 }
3088 break;
3089 }
3090 default:
3091 // No increment for other items (yet)
3092 break;
3093 }
3094 }
3095
3096 commit->Push( _( "Increment" ) );
3097
3098 if( selection.IsHover() )
3100
3101 return 0;
3102}
3103
3104
3106{
3107 return m_toolMgr->RunAction( EE_ACTIONS::importSheet, aEvent.Parameter<wxString*>() );
3108}
3109
3110
3112 std::set<std::pair<SCH_SYMBOL*, SCH_SCREEN*>>& aCollectedUnits )
3113{
3114 for( EDA_ITEM* item : aSelection )
3115 {
3116 if( item->Type() == SCH_SYMBOL_T )
3117 {
3118 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
3119
3120 aCollectedUnits.insert( { symbol, m_frame->GetScreen() } );
3121
3122 // The attributes should be kept in sync in multi-unit parts.
3123 // Of course the symbol must be annotated to collect other units.
3124 if( symbol->IsAnnotated( &m_frame->GetCurrentSheet() ) )
3125 {
3126 wxString ref = symbol->GetRef( &m_frame->GetCurrentSheet() );
3127 int unit = symbol->GetUnit();
3128 LIB_ID libId = symbol->GetLibId();
3129
3130 for( SCH_SHEET_PATH& sheet : m_frame->Schematic().Hierarchy() )
3131 {
3132 SCH_SCREEN* screen = sheet.LastScreen();
3133 std::vector<SCH_SYMBOL*> otherUnits;
3134
3135 CollectOtherUnits( ref, unit, libId, sheet, &otherUnits );
3136
3137 for( SCH_SYMBOL* otherUnit : otherUnits )
3138 aCollectedUnits.insert( { otherUnit, screen } );
3139 }
3140 }
3141 }
3142 }
3143}
3144
3145
3147{
3149 SCH_COMMIT commit( m_toolMgr );
3150
3151 std::set<std::pair<SCH_SYMBOL*, SCH_SCREEN*>> collectedUnits;
3152
3153 collectUnits( selection, collectedUnits );
3154
3155 for( const auto& [symbol, screen] : collectedUnits )
3156 {
3157 commit.Modify( symbol, screen );
3158
3159 if( aEvent.IsAction( &EE_ACTIONS::setDNP ) )
3160 symbol->SetDNP( true );
3161
3163 symbol->SetExcludedFromSim( true );
3164
3166 symbol->SetExcludedFromBOM( true );
3167
3169 symbol->SetExcludedFromBoard( true );
3170 }
3171
3172 if( !commit.Empty() )
3173 commit.Push( _( "Set Attribute" ) );
3174
3175 if( selection.IsHover() )
3177
3178 return 0;
3179}
3180
3181
3183{
3185 SCH_COMMIT commit( m_toolMgr );
3186
3187 std::set<std::pair<SCH_SYMBOL*, SCH_SCREEN*>> collectedUnits;
3188
3189 collectUnits( selection, collectedUnits );
3190
3191 for( const auto& [symbol, screen] : collectedUnits )
3192 {
3193 commit.Modify( symbol, screen );
3194
3195 if( aEvent.IsAction( &EE_ACTIONS::unsetDNP ) )
3196 symbol->SetDNP( false );
3197
3199 symbol->SetExcludedFromSim( false );
3200
3202 symbol->SetExcludedFromBOM( false );
3203
3205 symbol->SetExcludedFromBoard( false );
3206 }
3207
3208 if( !commit.Empty() )
3209 commit.Push( _( "Clear Attribute" ) );
3210
3211 if( selection.IsHover() )
3213
3214 return 0;
3215}
3216
3217
3219{
3221 SCH_COMMIT commit( m_toolMgr );
3222
3223 std::set<std::pair<SCH_SYMBOL*, SCH_SCREEN*>> collectedUnits;
3224
3225 collectUnits( selection, collectedUnits );
3226
3227 for( const auto& [symbol, screen] : collectedUnits )
3228 {
3229 commit.Modify( symbol, screen );
3230
3231 if( aEvent.IsAction( &EE_ACTIONS::toggleDNP ) )
3232 symbol->SetDNP( !symbol->GetDNP() );
3233
3235 symbol->SetExcludedFromSim( !symbol->GetExcludedFromSim() );
3236
3238 symbol->SetExcludedFromBOM( !symbol->GetExcludedFromBOM() );
3239
3241 symbol->SetExcludedFromBoard( !symbol->GetExcludedFromBoard() );
3242 }
3243
3244 if( !commit.Empty() )
3245 commit.Push( _( "Toggle Attribute" ) );
3246
3247 if( selection.IsHover() )
3249
3250 return 0;
3251}
3252
3253
3255{
3256 // clang-format off
3262 Go( &SCH_EDIT_TOOL::Swap, EE_ACTIONS::swap.MakeEvent() );
3265
3271
3293
3296
3309
3313
3315 // clang-format on
3316}
const char * name
Definition: DXF_plotter.cpp:59
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
static TOOL_ACTION decrementPrimary
Definition: actions.h:89
static TOOL_ACTION paste
Definition: actions.h:73
static TOOL_ACTION unselectAll
Definition: actions.h:76
static TOOL_ACTION decrementSecondary
Definition: actions.h:91
static TOOL_ACTION copy
Definition: actions.h:71
static TOOL_ACTION pickerTool
Definition: actions.h:204
static TOOL_ACTION pasteSpecial
Definition: actions.h:74
static TOOL_ACTION rightJustify
Definition: actions.h:82
static TOOL_ACTION pageSettings
Definition: actions.h:56
static TOOL_ACTION incrementSecondary
Definition: actions.h:90
static TOOL_ACTION duplicate
Definition: actions.h:77
static TOOL_ACTION incrementPrimary
Definition: actions.h:88
static TOOL_ACTION doDelete
Definition: actions.h:78
static TOOL_ACTION deleteTool
Definition: actions.h:79
static TOOL_ACTION increment
Definition: actions.h:87
static TOOL_ACTION leftJustify
Definition: actions.h:80
static TOOL_ACTION cut
Definition: actions.h:70
static TOOL_ACTION copyAsText
Definition: actions.h:72
static TOOL_ACTION refreshPreview
Definition: actions.h:149
static TOOL_ACTION selectAll
Definition: actions.h:75
static TOOL_ACTION centerJustify
Definition: actions.h:81
Define the structure of a menu based on ACTIONs.
Definition: action_menu.h:49
TOOL_MANAGER * getToolManager() const
Return an instance of TOOL_MANAGER class.
void Clear()
Remove all the entries from the menu (as well as its title).
void SetTitle(const wxString &aTitle) override
Set title for the menu.
Definition: action_menu.cpp:92
void SetIcon(BITMAPS aIcon)
Assign an icon for the entry.
Definition: action_menu.cpp:78
wxMenuItem * Add(const wxString &aLabel, int aId, BITMAPS aIcon)
Add a wxWidgets-style entry to the menu.
ACTION_MENU * create() const override
Return an instance of this class. It has to be overridden in inheriting classes.
void update() override
Update menu state stub.
void SetPageNumber(const wxString &aPageNumber)
Definition: base_screen.h:79
void update() override
Update menu state stub.
ACTION_MENU * create() const override
Return an instance of this class. It has to be overridden in inheriting classes.
constexpr const Vec & GetPosition() const
Definition: box2.h:211
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:558
constexpr const Vec GetEnd() const
Definition: box2.h:212
constexpr void SetOrigin(const Vec &pos)
Definition: box2.h:237
constexpr Vec Centre() const
Definition: box2.h:97
constexpr const Vec GetCenter() const
Definition: box2.h:230
constexpr coord_type GetLeft() const
Definition: box2.h:228
constexpr const Vec & GetOrigin() const
Definition: box2.h:210
constexpr coord_type GetRight() const
Definition: box2.h:217
constexpr void SetEnd(coord_type x, coord_type y)
Definition: box2.h:297
constexpr coord_type GetTop() const
Definition: box2.h:229
constexpr coord_type GetBottom() const
Definition: box2.h:222
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:81
int m_Threshold
Definition: collector.h:234
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
Definition: commit.h:92
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
bool Empty() const
Definition: commit.h:150
COMMIT & Removed(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Definition: commit.h:98
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.
void AddSeparator(int aOrder=ANY_ORDER)
Add a separator to the menu.
void AddMenu(ACTION_MENU *aMenu, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Add a submenu to the menu.
Dialog to update or change schematic library symbols.
This class is setup in expectation of its children possibly using Kiway player so DIALOG_SHIM::ShowQu...
void UpdateField(SCH_FIELD *aField)
int ShowQuasiModal()
int ShowModal() override
Dialog used to edit SCH_SYMBOL objects in a schematic.
bool HitTestDrawingSheetItems(KIGFX::VIEW *aView, const VECTOR2I &aPosition)
bool IsHorizontal() const
Definition: eda_angle.h:138
bool IsVertical() const
Definition: eda_angle.h:143
virtual void ClearUndoRedoList()
Clear the undo and redo list using ClearUndoORRedoList()
void ShowInfoBarWarning(const wxString &aWarningMsg, bool aShowCloseButton=false)
Show the WX_INFOBAR displayed on the top of the canvas with a message and a warning icon on the left ...
VECTOR2I GetNearestGridPosition(const VECTOR2I &aPosition) const
Return the nearest aGridSize location to aPosition.
VECTOR2I GetNearestHalfGridPosition(const VECTOR2I &aPosition) const
Return the nearest aGridSize / 2 location to aPosition.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:89
virtual VECTOR2I GetPosition() const
Definition: eda_item.h:244
virtual void SetPosition(const VECTOR2I &aPos)
Definition: eda_item.h:245
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:77
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:133
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:127
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:129
bool IsSelected() const
Definition: eda_item.h:110
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition: eda_item.h:176
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:104
EDA_ITEM * GetParent() const
Definition: eda_item.h:103
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition: eda_item.h:131
virtual wxString GetClass() const =0
Return the class name.
bool IsMoving() const
Definition: eda_item.h:108
bool IsNew() const
Definition: eda_item.h:107
void SetEnd(const VECTOR2I &aEnd)
Definition: eda_shape.h:178
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:80
bool IsItalic() const
Definition: eda_text.h:156
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:134
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition: eda_text.cpp:524
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:98
virtual bool IsVisible() const
Definition: eda_text.h:174
KIFONT::FONT * GetFont() const
Definition: eda_text.h:234
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
Definition: eda_text.cpp:424
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition: eda_text.cpp:408
wxString GetHyperlink() const
Definition: eda_text.h:387
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition: eda_text.h:187
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:377
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:282
void SetBold(bool aBold)
Set the text to be bold - this will also update the font if needed.
Definition: eda_text.cpp:326
bool IsBold() const
Definition: eda_text.h:171
void SetHyperlink(wxString aLink)
Definition: eda_text.h:388
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition: eda_text.h:190
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:268
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:290
int GetTextThickness() const
Definition: eda_text.h:126
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
Definition: eda_text.cpp:298
void SetFont(KIFONT::FONT *aFont)
Definition: eda_text.cpp:490
VECTOR2I GetTextSize() const
Definition: eda_text.h:248
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition: eda_text.cpp:400
PANEL_ANNOTATE m_AnnotatePanel
AUTOPLACE_FIELDS m_AutoplaceFields
static TOOL_ACTION mirrorV
Definition: ee_actions.h:132
static TOOL_ACTION unsetDNP
Definition: ee_actions.h:202
static TOOL_ACTION selectionActivate
Activation of the selection tool.
Definition: ee_actions.h:46
static TOOL_ACTION properties
Definition: ee_actions.h:135
static TOOL_ACTION toggleExcludeFromSimulation
Definition: ee_actions.h:197
static TOOL_ACTION unsetExcludeFromSimulation
Definition: ee_actions.h:196
static TOOL_ACTION setExcludeFromBoard
Definition: ee_actions.h:198
static TOOL_ACTION move
Definition: ee_actions.h:127
static TOOL_ACTION clearHighlight
Definition: ee_actions.h:309
static TOOL_ACTION toGLabel
Definition: ee_actions.h:147
static TOOL_ACTION toggleExcludeFromBoard
Definition: ee_actions.h:200
static TOOL_ACTION setDNP
Definition: ee_actions.h:201
static TOOL_ACTION cleanupSheetPins
Definition: ee_actions.h:243
static TOOL_ACTION slice
Definition: ee_actions.h:151
static TOOL_ACTION clearSelection
Clears the current selection.
Definition: ee_actions.h:56
static TOOL_ACTION drag
Definition: ee_actions.h:128
static TOOL_ACTION toText
Definition: ee_actions.h:148
static TOOL_ACTION placeClassLabel
Definition: ee_actions.h:90
static TOOL_ACTION placeNextSymbolUnit
Definition: ee_actions.h:80
static TOOL_ACTION showDeMorganAlternate
Definition: ee_actions.h:142
static TOOL_ACTION toggleExcludeFromBOM
Definition: ee_actions.h:194
static TOOL_ACTION autoplaceFields
Definition: ee_actions.h:139
static TOOL_ACTION showDeMorganStandard
Definition: ee_actions.h:141
static TOOL_ACTION rotateCCW
Definition: ee_actions.h:131
static TOOL_ACTION editValue
Definition: ee_actions.h:137
static TOOL_ACTION toLabel
Definition: ee_actions.h:144
static TOOL_ACTION toTextBox
Definition: ee_actions.h:149
static TOOL_ACTION breakWire
Definition: ee_actions.h:150
static TOOL_ACTION mirrorH
Definition: ee_actions.h:133
static TOOL_ACTION rotateCW
Definition: ee_actions.h:130
static TOOL_ACTION unsetExcludeFromBOM
Definition: ee_actions.h:193
static TOOL_ACTION editWithLibEdit
Definition: ee_actions.h:179
static TOOL_ACTION placeGlobalLabel
Definition: ee_actions.h:91
static TOOL_ACTION removeItemFromSel
Definition: ee_actions.h:60
static TOOL_ACTION ddAppendFile
Definition: ee_actions.h:315
static TOOL_ACTION placeHierLabel
Definition: ee_actions.h:92
static TOOL_ACTION addItemToSel
Selects an item (specified as the event parameter).
Definition: ee_actions.h:59
static TOOL_ACTION editPageNumber
Definition: ee_actions.h:170
static TOOL_ACTION changeSymbol
Definition: ee_actions.h:165
static TOOL_ACTION editFootprint
Definition: ee_actions.h:138
static TOOL_ACTION enterSheet
Definition: ee_actions.h:232
static TOOL_ACTION editReference
Definition: ee_actions.h:136
static TOOL_ACTION updateSymbols
Definition: ee_actions.h:164
static TOOL_ACTION placeSchematicText
Definition: ee_actions.h:102
static TOOL_ACTION setExcludeFromBOM
Definition: ee_actions.h:192
static TOOL_ACTION changeSymbols
Definition: ee_actions.h:163
static TOOL_ACTION setExcludeFromSimulation
Definition: ee_actions.h:195
static TOOL_ACTION unsetExcludeFromBoard
Definition: ee_actions.h:199
static TOOL_ACTION toCLabel
Definition: ee_actions.h:145
static TOOL_ACTION placeLabel
Definition: ee_actions.h:89
static TOOL_ACTION repeatDrawItem
Definition: ee_actions.h:129
static TOOL_ACTION toHLabel
Definition: ee_actions.h:146
static TOOL_ACTION editTextAndGraphics
Definition: ee_actions.h:244
static TOOL_ACTION toggleDNP
Definition: ee_actions.h:203
static TOOL_ACTION importSheet
Definition: ee_actions.h:97
static TOOL_ACTION swap
Definition: ee_actions.h:134
static TOOL_ACTION toggleDeMorgan
Definition: ee_actions.h:140
static TOOL_ACTION updateSymbol
Definition: ee_actions.h:166
void Collect(SCH_SCREEN *aScreen, const std::vector< KICAD_T > &aScanTypes, const VECTOR2I &aPos, int aUnit=0, int aConvert=0)
Scan a EDA_ITEM using this class's Inspector method which does the collection.
static const std::vector< KICAD_T > FieldOwners
Definition: ee_collectors.h:44
static SELECTION_CONDITION SingleSymbol
static SELECTION_CONDITION AllPinsOrSheetPins
static SELECTION_CONDITION SingleMultiFunctionPin
static SELECTION_CONDITION SingleSymbolOrPower
static SELECTION_CONDITION SingleMultiUnitSymbol
static SELECTION_CONDITION SingleDeMorganSymbol
static SELECTION_CONDITION MultipleSymbolsOrPower
int CrossProbe(const TOOL_EVENT &aEvent)
Called when clicking on a item:
bool empty() const
Definition: sch_rtree.h:176
void GuessSelectionCandidates(EE_COLLECTOR &collector, const VECTOR2I &aPos)
Apply heuristics to try and determine a single object when multiple are found under the cursor.
EE_SELECTION & RequestSelection(const std::vector< KICAD_T > &aScanTypes={ SCH_LOCATE_ANY_T }, bool aPromoteCellSelections=false)
Return either an existing selection (filtered), or the selection at the current cursor position if th...
int ClearSelection(const TOOL_EVENT &aEvent)
Select all visible items in sheet.
EE_SELECTION & GetSelection()
A foundation class for a tool operating on a schematic or symbol.
Definition: ee_tool_base.h:48
void updateItem(EDA_ITEM *aItem, bool aUpdateRTree) const
Similar to getView()->Update(), but handles items that are redrawn by their parents and updating the ...
Definition: ee_tool_base.h:109
void saveCopyInUndoList(EDA_ITEM *aItem, UNDO_REDO aType, bool aAppend=false, bool aDirtyConnectivity=true)
Definition: ee_tool_base.h:143
EE_SELECTION_TOOL * m_selectionTool
Definition: ee_tool_base.h:200
bool Init() override
Init() is called once upon a registration of the tool.
Definition: ee_tool_base.h:64
DS_PROXY_VIEW_ITEM * GetDrawingSheet() const
Definition: sch_view.h:120
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
void RecacheAllItems()
Rebuild GAL display lists.
Definition: view.cpp:1439
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:418
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:55
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
Definition: kiway_player.h:65
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:406
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
static bool ParseBusGroup(const wxString &aGroup, wxString *name, std::vector< wxString > *aMemberList)
Parse a bus group label into the name and a list of components.
A singleton reporter that reports to nowhere.
Definition: reporter.h:203
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:125
void SetMotionHandler(MOTION_HANDLER aHandler)
Set a handler for mouse motion.
Definition: picker_tool.h:84
void SetClickHandler(CLICK_HANDLER aHandler)
Set a handler for mouse click event.
Definition: picker_tool.h:73
void SetSnapping(bool aSnap)
Definition: picker_tool.h:66
void SetCursor(KICURSOR aCursor)
Definition: picker_tool.h:64
void SetFinalizeHandler(FINALIZE_HANDLER aHandler)
Set a handler for the finalize event.
Definition: picker_tool.h:104
void update() override
Update menu state stub.
ACTION_MENU * create() const override
Return an instance of this class. It has to be overridden in inheriting classes.
These are loaded from Eeschema settings but then overwritten by the project settings.
void OnItemsAdded(std::vector< SCH_ITEM * > &aNewItems)
Must be used if Add() is used using a BULK_x ADD_MODE to generate a change event for listeners.
Definition: schematic.cpp:784
void OnItemsRemoved(std::vector< SCH_ITEM * > &aRemovedItems)
Must be used if Remove() is used using a BULK_x REMOVE_MODE to generate a change event for listeners.
Definition: schematic.cpp:790
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:312
SCH_SHEET_LIST Hierarchy() const override
Return the full schematic flattened hierarchical sheet list.
Definition: schematic.cpp:214
SCH_SHEET & Root() const
Definition: schematic.h:130
void RefreshHierarchy()
Definition: schematic.cpp:222
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.
EESCHEMA_SETTINGS * eeconfig() const
void RemoveFromScreen(EDA_ITEM *aItem, SCH_SCREEN *aScreen)
Remove an item from the screen (and view) aScreen is the screen the item is located on,...
Object to handle a bitmap image that can be inserted in a schematic.
Definition: sch_bitmap.h:40
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
Definition: sch_commit.cpp:432
virtual void Revert() override
Revert the commit by restoring the modified items state.
Definition: sch_commit.cpp:510
Tool responsible for drawing/placing items (symbols, wires, buses, labels, etc.).
KIGFX::SCH_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
Schematic editor (Eeschema) main window.
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag and update other data struc...
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
void SchematicCleanUp(SCH_COMMIT *aCommit, SCH_SCREEN *aScreen=nullptr)
Perform routine schematic cleaning including breaking wire and buses and deleting identical objects s...
void UpdateHierarchyNavigator(bool aRefreshNetNavigator=true)
Update the hierarchy navigation tree and history.
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
SCH_SHEET_PATH & GetCurrentSheet() const
SCHEMATIC & Schematic() const
const std::vector< std::unique_ptr< SCH_ITEM > > & GetRepeatItems() const
Return the items which are to be repeated with the insert key.
bool EditSheetProperties(SCH_SHEET *aSheet, SCH_SHEET_PATH *aHierarchy, bool *aIsUndoable=nullptr, bool *aClearAnnotationNewItems=nullptr, bool *aUpdateHierarchyNavigator=nullptr, wxString *aSourceSheetFilename=nullptr)
Edit an existing sheet or add a new sheet to the schematic.
Definition: sheet.cpp:603
void FlipBodyStyle(SCH_SYMBOL *aSymbol)
Definition: picksymbol.cpp:181
void OnPageSettingsChange() override
Called when modifying the page settings.
bool CheckSheetForRecursion(SCH_SHEET *aSheet, SCH_SHEET_PATH *aCurrentSheet)
Verify that aSheet will not cause a recursion error in aCurrentSheet.
Definition: sheet.cpp:54
void BreakSegment(SCH_COMMIT *aCommit, SCH_LINE *aSegment, const VECTOR2I &aPoint, SCH_LINE **aNewSegment, SCH_SCREEN *aScreen)
Break a single segment into two at the specified point.
const wxString & GetHighlightedConnection() const
void UpdateItem(EDA_ITEM *aItem, bool isAddOrDelete=false, bool aUpdateRtree=false) override
Mark an item for refresh.
void AddCopyForRepeatItem(const SCH_ITEM *aItem)
void TestDanglingEnds()
Test all of the connectable objects in the schematic for unused connection points.
void DeleteJunction(SCH_COMMIT *aCommit, SCH_ITEM *aItem)
Removes a given junction and heals any wire segments under the junction.
void SaveCopyForRepeatItem(const SCH_ITEM *aItem)
Clone aItem and owns that clone in this container.
int ChangeBodyStyle(const TOOL_EVENT &aEvent)
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
static const std::vector< KICAD_T > RotatableItems
Definition: sch_edit_tool.h:42
EDA_ITEM * m_pickerItem
int EditField(const TOOL_EVENT &aEvent)
int EditPageNumber(const TOOL_EVENT &aEvent)
int DoDelete(const TOOL_EVENT &aEvent)
Run the deletion tool.
int UnsetAttribute(const TOOL_EVENT &aEvent)
bool Init() override
Init() is called once upon a registration of the tool.
int CleanupSheetPins(const TOOL_EVENT &aEvent)
void editFieldText(SCH_FIELD *aField)
int Mirror(const TOOL_EVENT &aEvent)
int GlobalEdit(const TOOL_EVENT &aEvent)
Delete the selected items, or the item under the cursor.
int SetAttribute(const TOOL_EVENT &aEvent)
Modify Attributes.
int Properties(const TOOL_EVENT &aEvent)
int Rotate(const TOOL_EVENT &aEvent)
int Increment(const TOOL_EVENT &aEvent)
Increment/decrement something about an item.
int BreakWire(const TOOL_EVENT &aEvent)
int DdAppendFile(const TOOL_EVENT &aEvent)
Drag and drop.
int JustifyText(const TOOL_EVENT &aEvent)
int ToggleAttribute(const TOOL_EVENT &aEvent)
int AutoplaceFields(const TOOL_EVENT &aEvent)
void collectUnits(const EE_SELECTION &aSelection, std::set< std::pair< SCH_SYMBOL *, SCH_SCREEN * > > &aCollectedUnits)
Set up handlers for various events.
int Swap(const TOOL_EVENT &aEvent)
int ChangeSymbols(const TOOL_EVENT &aEvent)
int ChangeTextType(const TOOL_EVENT &aEvent)
Change a text type to another one.
int InteractiveDelete(const TOOL_EVENT &aEvent)
int RepeatDrawItem(const TOOL_EVENT &aEvent)
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:51
bool IsMandatory() const
Definition: sch_field.cpp:1508
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
Definition: sch_field.cpp:1028
VECTOR2I GetPosition() const override
Definition: sch_field.cpp:1486
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
Definition: sch_field.cpp:1255
int GetId() const
Definition: sch_field.h:133
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: sch_field.cpp:1230
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_field.cpp:1466
void SetText(const wxString &aText) override
Definition: sch_field.cpp:1215
VECTOR2I GetParentPosition() const
Definition: sch_field.cpp:1502
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:167
virtual bool IsConnectable() const
Definition: sch_item.h:450
virtual void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo)
Definition: sch_item.h:552
const SYMBOL * GetParentSymbol() const
Definition: sch_item.cpp:166
SCHEMATIC * Schematic() const
Searches the item hierarchy to find a SCHEMATIC.
Definition: sch_item.cpp:150
int GetBodyStyle() const
Definition: sch_item.h:233
virtual void MirrorHorizontally(int aCenter)
Mirror item horizontally about aCenter.
Definition: sch_item.h:344
virtual void Move(const VECTOR2I &aMoveVector)
Move the item by aMoveVector to a new position.
Definition: sch_item.h:336
int GetUnit() const
Definition: sch_item.h:230
void SetFieldsAutoplaced(AUTOPLACE_ALGO aAlgo)
Definition: sch_item.h:550
virtual void Rotate(const VECTOR2I &aCenter, bool aRotateCCW)
Rotate the item around aCenter 90 degrees in the clockwise direction.
Definition: sch_item.h:360
AUTOPLACE_ALGO GetFieldsAutoplaced() const
Return whether the fields have been automatically placed.
Definition: sch_item.h:549
wxString GetClass() const override
Return the class name.
Definition: sch_item.h:177
virtual bool HasLineStroke() const
Check if this schematic item has line stoke properties.
Definition: sch_item.h:565
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition: sch_item.h:465
SCH_ITEM * Duplicate(bool doClone=false) const
Routine to create a new copy of given item.
Definition: sch_item.cpp:131
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
virtual void MirrorVertically(int aCenter)
Mirror item vertically about aCenter.
Definition: sch_item.h:352
void AddFields(const std::vector< SCH_FIELD > &aFields)
Definition: sch_label.h:225
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
Definition: sch_label.cpp:445
SPIN_STYLE GetSpinStyle() const
Definition: sch_label.cpp:331
void SetShape(LABEL_FLAG_SHAPE aShape)
Definition: sch_label.h:189
LABEL_FLAG_SHAPE GetShape() const
Definition: sch_label.h:188
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
Definition: sch_label.cpp:464
std::vector< SCH_FIELD > & GetFields()
Definition: sch_label.h:212
virtual void SetSpinStyle(SPIN_STYLE aSpinStyle)
Definition: sch_label.cpp:296
Tool responsible for drawing/placing items (symbols, wires, buses, labels, etc.)
int AddJunctionsIfNeeded(SCH_COMMIT *aCommit, EE_SELECTION *aSelection)
Handle the addition of junctions to a selection of objects.
int TrimOverLappingWires(SCH_COMMIT *aCommit, EE_SELECTION *aSelection)
Logic to remove wires when overlapping correct items.
static bool IsDrawingLineWireOrBus(const SELECTION &aSelection)
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:41
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
Definition: sch_line.cpp:401
VECTOR2I GetEndPoint() const
Definition: sch_line.h:141
VECTOR2I GetStartPoint() const
Definition: sch_line.h:136
bool IsEndPoint(const VECTOR2I &aPoint) const
Definition: sch_line.h:90
const std::map< wxString, ALT > & GetAlternates() const
Definition: sch_pin.h:126
const wxString & GetName() const
Definition: sch_pin.cpp:388
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:712
void ClearAnnotationOfNewSheetPaths(SCH_SHEET_LIST &aInitialSheetPathList)
Clear the annotation for the symbols inside new sheetpaths when a complex hierarchy is modified and n...
bool IsExplicitJunction(const VECTOR2I &aPosition) const
Indicates that a junction dot is necessary at the given location.
Definition: sch_screen.cpp:487
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:108
const wxString & GetFileName() const
Definition: sch_screen.h:143
SCH_ITEM * GetItem(const VECTOR2I &aPosition, int aAccuracy=0, KICAD_T aType=SCH_LOCATE_ANY_T) const
Check aPosition within a distance of aAccuracy for items of type aFilter.
Definition: sch_screen.cpp:392
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:118
void ClearAnnotation(SCH_SHEET_PATH *aSheetPath, bool aResetPrefix)
Clear the annotation for the symbols in aSheetPath on the screen.
void SetPosition(const VECTOR2I &aPos) override
Definition: sch_shape.h:73
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_shape.cpp:276
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
void BuildSheetList(SCH_SHEET *aSheet, bool aCheckIntegrity)
Build the list of sheets and their sheet path from aSheet.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
wxString PathHumanReadable(bool aUseShortRootName=true, bool aStripTrailingSeparator=false) const
Return the sheet path in a human readable form made from the sheet names.
SCH_SCREEN * LastScreen()
wxString GetPageNumber() const
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.
size_t size() const
Forwarded method from std::vector.
void pop_back()
Forwarded method from std::vector.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:66
SHEET_SIDE GetSide() const
SCH_SHEET * GetParent() const
Get the parent sheet object of this sheet pin.
void SetSide(SHEET_SIDE aEdge)
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:59
void SetFileName(const wxString &aFilename)
Definition: sch_sheet.h:313
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition: sch_sheet.h:307
VECTOR2I GetRotationCenter() const
Rotating around the boundingBox's center can cause walking when the sheetname or filename is longer t...
Definition: sch_sheet.cpp:746
void CleanupSheet()
Delete sheet label which do not have a corresponding hierarchical label.
Definition: sch_sheet.cpp:612
void RemovePin(const SCH_SHEET_PIN *aSheetPin)
Remove aSheetPin from the sheet.
Definition: sch_sheet.cpp:436
bool HasUndefinedPins() const
Check all sheet labels against schematic for undefined hierarchical labels.
Definition: sch_sheet.cpp:498
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:111
const BOX2I GetBodyBoundingBox() const
Return a bounding box for the sheet body but not the fields.
Definition: sch_sheet.cpp:714
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_sheet.cpp:735
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
Definition: sch_sheet.cpp:913
Schematic symbol object.
Definition: sch_symbol.h:77
wxString SubReference(int aUnit, bool aAddSeparator=true) const
Definition: sch_symbol.cpp:823
bool IsAnnotated(const SCH_SHEET_PATH *aSheet) const
Check if the symbol has a valid annotation (reference) for the given sheet path.
Definition: sch_symbol.cpp:782
void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo) override
Automatically orient all the fields in the symbol.
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:906
void SetOrientation(int aOrientation)
Compute the new transform matrix based on aOrientation for the symbol which is applied to the current...
bool IsMissingLibSymbol() const
Check to see if the library symbol is set to the dummy library symbol.
Definition: sch_symbol.cpp:209
const LIB_ID & GetLibId() const override
Definition: sch_symbol.h:166
int GetOrientation() const override
Get the display symbol orientation.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:185
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
Definition: sch_symbol.cpp:704
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
bool IsPower() const override
VECTOR2I GetCenter() const
Definition: sch_table.cpp:121
void Move(const VECTOR2I &aMoveVector) override
Move the item by aMoveVector to a new position.
Definition: sch_table.cpp:200
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
Definition: sch_table.cpp:219
int GetMarginBottom() const
Definition: sch_textbox.h:66
int GetLegacyTextMargin() const
Definition: sch_textbox.cpp:76
int GetMarginLeft() const
Definition: sch_textbox.h:63
int GetMarginRight() const
Definition: sch_textbox.h:65
int GetMarginTop() const
Definition: sch_textbox.h:64
virtual void Rotate90(bool aClockwise)
Definition: sch_text.cpp:209
virtual void MirrorSpinStyle(bool aLeftRight)
Definition: sch_text.cpp:221
static SELECTION_CONDITION HasTypes(std::vector< KICAD_T > aTypes)
Create a functor that tests if among the selected items there is at least one of a given types.
static SELECTION_CONDITION HasType(KICAD_T aType)
Create a functor that tests if among the selected items there is at least one of a given type.
static bool NotEmpty(const SELECTION &aSelection)
Test if there are any items selected.
static SELECTION_CONDITION MoreThan(int aNumber)
Create a functor that tests if the number of selected items is greater than the value given as parame...
static bool Idle(const SELECTION &aSelection)
Test if there no items selected or being edited.
static bool IdleSelection(const SELECTION &aSelection)
Test if all selected items are not being edited.
static SELECTION_CONDITION Count(int aNumber)
Create a functor that tests if the number of selected items is equal to the value given as parameter.
static bool ShowAlways(const SELECTION &aSelection)
The default condition function (always returns true).
static SELECTION_CONDITION OnlyTypes(std::vector< KICAD_T > aTypes)
Create a functor that tests if the selected items are only of given types.
void BrightenItem(EDA_ITEM *aItem)
int AddItemToSel(const TOOL_EVENT &aEvent)
void UnbrightenItem(EDA_ITEM *aItem)
virtual void Add(EDA_ITEM *aItem)
Definition: selection.cpp:42
virtual KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
Definition: selection.cpp:75
const std::deque< EDA_ITEM * > GetItems() const
Definition: selection.h:121
VECTOR2I GetReferencePoint() const
Definition: selection.cpp:169
virtual VECTOR2I GetCenter() const
Returns the center point of the selection area bounding box.
Definition: selection.cpp:92
bool IsHover() const
Definition: selection.h:84
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition: selection.h:100
EDA_ITEM * Front() const
Definition: selection.h:172
int Size() const
Returns the number of selected parts.
Definition: selection.h:116
std::deque< EDA_ITEM * > & Items()
Definition: selection.h:177
std::vector< EDA_ITEM * > GetItemsSortedBySelectionOrder() const
Definition: selection.cpp:263
bool OnlyContains(std::vector< KICAD_T > aList) const
Checks if all items in the selection have a type in aList.
Definition: selection.cpp:211
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:110
bool HasReferencePoint() const
Definition: selection.h:211
size_t CountType(KICAD_T aType) const
Definition: selection.cpp:155
T * GetAppSettings(const wxString &aFilename)
Return a handle to the a given settings by type.
unsigned CCWRotationsTo(const SPIN_STYLE &aOther) const
Get CCW rotation needed to get to the given spin style.
Definition: sch_label.cpp:155
Heuristically increment a string's n'th part from the right.
Definition: increment.h:48
void SetSkipIOSQXZ(bool aSkip)
If a alphabetic part is found, skip the letters I, O, S, Q, X, Z.
Definition: increment.h:54
std::optional< wxString > Increment(const wxString &aStr, int aDelta, size_t aRightIndex) const
Increment the n-th part from the right of the given string.
Definition: increment.cpp:86
The symbol library editor main window.
void update() override
Update menu state stub.
ACTION_MENU * create() const override
Return an instance of this class. It has to be overridden in inheriting classes.
bool IsCurrentTool(const TOOL_ACTION &aAction) const
TOOL_EVENT MakeEvent() const
Return the event associated with the action (i.e.
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 DisableGridSnapping() const
Definition: tool_event.h:368
bool Matches(const TOOL_EVENT &aEvent) const
Test whether two events match in terms of category & action or command.
Definition: tool_event.h:389
COMMIT * Commit() const
Definition: tool_event.h:280
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).
TOOL_MENU & GetToolMenu()
void Activate()
Run the 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
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
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:44
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:250
This file is part of the common library.
@ SYMBOL_PROPS_EDIT_SCHEMATIC_SYMBOL
@ SYMBOL_PROPS_WANT_EXCHANGE_SYMBOL
@ SYMBOL_PROPS_WANT_UPDATE_SYMBOL
@ SYMBOL_PROPS_EDIT_LIBRARY_SYMBOL
@ SYMBOL_PROPS_EDIT_OK
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition: eda_angle.h:403
static constexpr EDA_ANGLE ANGLE_VERTICAL
Definition: eda_angle.h:398
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition: eda_angle.h:397
#define IS_NEW
New item, just created.
#define SELECTED_BY_DRAG
Item was algorithmically selected as a dragged item.
#define STRUCT_DELETED
flag indication structures to be erased
#define ENDPOINT
ends. (Used to support dragging.)
#define STARTPOINT
When a line is selected, these flags indicate which.
void CollectOtherUnits(const wxString &aRef, int aUnit, const LIB_ID &aLibId, SCH_SHEET_PATH &aSheet, std::vector< SCH_SYMBOL * > *otherUnits)
#define HITTEST_THRESHOLD_PIXELS
static std::vector< KICAD_T > sheetTypes
std::set< int > GetUnplacedUnitsForSymbol(const SCH_SYMBOL &aSym)
Get a list of unplaced (i.e.
@ ID_POPUP_SCH_PIN_TRICKS_HIER_LABEL
Definition: eeschema_id.h:95
@ ID_POPUP_SCH_PIN_TRICKS_WIRE
Definition: eeschema_id.h:93
@ ID_POPUP_SCH_ALT_PIN_FUNCTION
Definition: eeschema_id.h:99
@ ID_POPUP_SCH_SELECT_UNIT1
Definition: eeschema_id.h:83
@ 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_PIN_TRICKS_NET_LABEL
Definition: eeschema_id.h:94
@ ID_POPUP_SCH_PIN_TRICKS_NO_CONNECT
Definition: eeschema_id.h:92
@ ID_POPUP_SCH_SELECT_UNIT_END
Definition: eeschema_id.h:86
@ ID_POPUP_SCH_ALT_PIN_FUNCTION_END
Definition: eeschema_id.h:100
@ ID_POPUP_SCH_PIN_TRICKS_GLOBAL_LABEL
Definition: eeschema_id.h:96
@ FRAME_SCH_SYMBOL_EDITOR
Definition: frame_type.h:35
@ LAYER_NOTES
Definition: layer_ids.h:455
@ LAYER_SCHEMATIC_DRAWINGSHEET
Definition: layer_ids.h:483
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
#define UNIMPLEMENTED_FOR(type)
Definition: macros.h:96
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:100
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:1073
see class PGM_BASE
static void swapFieldPositionsWithMatching(std::vector< SCH_FIELD > &aAFields, std::vector< SCH_FIELD > &aBFields, unsigned aFallbackRotationsCCW)
Swap the positions of the fields in the two lists, aAFields and aBFields, relative to their parent po...
static std::vector< KICAD_T > deletableItems
const std::vector< KICAD_T > swappableItems
AUTOPLACE_ALGO
Definition: sch_item.h:68
@ AUTOPLACE_MANUAL
Definition: sch_item.h:71
@ AUTOPLACE_NONE
Definition: sch_item.h:69
@ AUTOPLACE_AUTO
Definition: sch_item.h:70
LABEL_FLAG_SHAPE
Definition: sch_label.h:98
ANNOTATE_ORDER_T
Schematic annotation order options.
@ ANNOTATE_SELECTION
Annotate the selection.
ANNOTATE_ALGO_T
Schematic annotation type options.
SHEET_SIDE
Define the edge of the sheet that the sheet pin is positioned.
Definition: sch_sheet_pin.h:46
wxString UnescapeString(const wxString &aSource)
wxString TitleCaps(const wxString &aString)
Capitalize the first letter in each word.
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_NETNAME
Definition: string_utils.h:53
constexpr int MilsToIU(int mils) const
Definition: base_units.h:93
@ SYM_MIRROR_Y
Definition: symbol.h:44
@ SYM_MIRROR_X
Definition: symbol.h:43
wxString GetDefaultFieldName(int aFieldNdx, bool aTranslateForHI)
Return a default symbol field name for field aFieldNdx for all components.
#define DO_TRANSLATE
@ FOOTPRINT_FIELD
Field Name Module PCB, i.e. "16DIP300".
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
GR_TEXT_H_ALIGN_T
This is API surface mapped to common.types.HorizontalAlignment.
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
GR_TEXT_V_ALIGN_T
This is API surface mapped to common.types.VertialAlignment.
constexpr GR_TEXT_H_ALIGN_T GetFlippedAlignment(GR_TEXT_H_ALIGN_T aAlign)
Get the reverse alignment: left-right are swapped, others are unchanged.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition: trigo.cpp:229
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ SCH_TABLE_T
Definition: typeinfo.h:165
@ SCH_LINE_T
Definition: typeinfo.h:163
@ SCH_NO_CONNECT_T
Definition: typeinfo.h:160
@ SCH_SYMBOL_T
Definition: typeinfo.h:172
@ SCH_TABLECELL_T
Definition: typeinfo.h:166
@ SCH_ITEM_LOCATE_WIRE_T
Definition: typeinfo.h:185
@ SCH_FIELD_T
Definition: typeinfo.h:150
@ SCH_DIRECTIVE_LABEL_T
Definition: typeinfo.h:171
@ SCH_LABEL_T
Definition: typeinfo.h:167
@ SCH_SHEET_T
Definition: typeinfo.h:174
@ SCH_ITEM_LOCATE_BUS_T
Definition: typeinfo.h:186
@ SCH_MARKER_T
Definition: typeinfo.h:158
@ SCH_SHAPE_T
Definition: typeinfo.h:149
@ SCH_RULE_AREA_T
Definition: typeinfo.h:170
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:169
@ SCH_BUS_BUS_ENTRY_T
Definition: typeinfo.h:162
@ SCH_LABEL_LOCATE_ANY_T
Definition: typeinfo.h:190
@ SCH_ITEM_LOCATE_GRAPHIC_LINE_T
Definition: typeinfo.h:187
@ SCHEMATIC_T
Definition: typeinfo.h:203
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:173
@ SCH_TEXT_T
Definition: typeinfo.h:151
@ SCH_BUS_WIRE_ENTRY_T
Definition: typeinfo.h:161
@ SCH_BITMAP_T
Definition: typeinfo.h:164
@ SCH_TEXTBOX_T
Definition: typeinfo.h:152
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:168
@ SCH_JUNCTION_T
Definition: typeinfo.h:159
@ SCH_PIN_T
Definition: typeinfo.h:153
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695