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{
1813 EE_SELECTION sel =
1815
1816 if( sel.Size() != 1 )
1817 return 0;
1818
1819 bool clearSelection = sel.IsHover();
1820 EDA_ITEM* item = sel.Front();
1821
1822 if( item->Type() == SCH_FIELD_T )
1823 {
1824 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
1825
1826 if( ( aEvent.IsAction( &EE_ACTIONS::editReference ) && field->GetId() != REFERENCE_FIELD )
1827 || ( aEvent.IsAction( &EE_ACTIONS::editValue ) && field->GetId() != VALUE_FIELD )
1828 || ( aEvent.IsAction( &EE_ACTIONS::editFootprint ) && field->GetId() != FOOTPRINT_FIELD ) )
1829 {
1830 item = field->GetParentSymbol();
1833 }
1834 }
1835
1836 if( item->Type() == SCH_SYMBOL_T )
1837 {
1838 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1839
1840 if( aEvent.IsAction( &EE_ACTIONS::editReference ) )
1841 {
1843 }
1844 else if( aEvent.IsAction( &EE_ACTIONS::editValue ) )
1845 {
1846 editFieldText( symbol->GetField( VALUE_FIELD ) );
1847 }
1848 else if( aEvent.IsAction( &EE_ACTIONS::editFootprint ) )
1849 {
1850 if( !symbol->IsPower() )
1852 }
1853 }
1854 else if( item->Type() == SCH_FIELD_T )
1855 {
1856 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
1857
1858 editFieldText( field );
1859
1860 if( !field->IsVisible() )
1861 clearSelection = true;
1862 }
1863 else if( item->Type() == SCH_PIN_T )
1864 {
1865 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item->GetParent() );
1866
1867 if( symbol )
1868 {
1869 if( aEvent.IsAction( &EE_ACTIONS::editReference ) )
1870 {
1872 }
1873 else if( aEvent.IsAction( &EE_ACTIONS::editValue ) )
1874 {
1875 editFieldText( symbol->GetField( VALUE_FIELD ) );
1876 }
1877 else if( aEvent.IsAction( &EE_ACTIONS::editFootprint ) )
1878 {
1879 if( !symbol->IsPower() )
1881 }
1882 }
1883 }
1884
1885 if( clearSelection )
1887
1888 return 0;
1889}
1890
1891
1893{
1895 SCH_COMMIT commit( m_toolMgr );
1896 SCH_ITEM* head = static_cast<SCH_ITEM*>( selection.Front() );
1897 bool moving = head && head->IsMoving();
1898
1899 if( selection.Empty() )
1900 return 0;
1901
1902 std::vector<SCH_ITEM*> autoplaceItems;
1903
1904 for( unsigned ii = 0; ii < selection.GetSize(); ii++ )
1905 {
1906 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.GetItem( ii ) );
1907
1908 if( item->IsType( EE_COLLECTOR::FieldOwners ) )
1909 autoplaceItems.push_back( item );
1910 else if( item->GetParent() && item->GetParent()->IsType( EE_COLLECTOR::FieldOwners ) )
1911 autoplaceItems.push_back( static_cast<SCH_ITEM*>( item->GetParent() ) );
1912 }
1913
1914 for( SCH_ITEM* sch_item : autoplaceItems )
1915 {
1916 if( !moving && !sch_item->IsNew() )
1917 commit.Modify( sch_item, m_frame->GetScreen() );
1918
1919 sch_item->AutoplaceFields( m_frame->GetScreen(), AUTOPLACE_MANUAL );
1920
1921 updateItem( sch_item, true );
1922 }
1923
1924 if( moving )
1925 {
1927 }
1928 else
1929 {
1930 if( !commit.Empty() )
1931 commit.Push( _( "Autoplace Fields" ) );
1932
1933 if( selection.IsHover() )
1935 }
1936
1937 return 0;
1938}
1939
1940
1942{
1943 SCH_SYMBOL* selectedSymbol = nullptr;
1945
1946 if( !selection.Empty() )
1947 selectedSymbol = dynamic_cast<SCH_SYMBOL*>( selection.Front() );
1948
1950
1951 if( aEvent.IsAction( &EE_ACTIONS::changeSymbol )
1952 || aEvent.IsAction( &EE_ACTIONS::changeSymbols ) )
1953 {
1955 }
1956
1957 DIALOG_CHANGE_SYMBOLS dlg( m_frame, selectedSymbol, mode );
1958
1959 // QuasiModal required to invoke symbol browser
1960 dlg.ShowQuasiModal();
1961
1962 return 0;
1963}
1964
1965
1967{
1969
1970 if( selection.Empty() )
1971 return 0;
1972
1973 SCH_SYMBOL* symbol = (SCH_SYMBOL*) selection.Front();
1974
1976 && symbol->GetBodyStyle() == BODY_STYLE::BASE )
1977 {
1978 return 0;
1979 }
1980
1982 && symbol->GetBodyStyle() == BODY_STYLE::DEMORGAN )
1983 {
1984 return 0;
1985 }
1986
1987 SCH_COMMIT commit( m_toolMgr );
1988
1989 if( !symbol->IsNew() )
1990 commit.Modify( symbol, m_frame->GetScreen() );
1991
1992 m_frame->FlipBodyStyle( symbol );
1993
1994 if( symbol->IsNew() )
1996
1997 if( !commit.Empty() )
1998 commit.Push( _( "Change Body Style" ) );
1999
2000 if( selection.IsHover() )
2002
2003 return 0;
2004}
2005
2006
2008{
2010 bool clearSelection = selection.IsHover();
2011
2012 if( selection.Empty() )
2013 {
2014 if( getView()->IsLayerVisible( LAYER_SCHEMATIC_DRAWINGSHEET ) )
2015 {
2017 VECTOR2D cursorPos = getViewControls()->GetCursorPosition( false );
2018
2019 if( ds && ds->HitTestDrawingSheetItems( getView(), cursorPos ) )
2021 }
2022
2023 return 0;
2024 }
2025
2026 EDA_ITEM* curr_item = selection.Front();
2027
2028 // If a single pin is selected, promote to its parent symbol
2029 if( ( selection.GetSize() == 1 ) && ( curr_item->Type() == SCH_PIN_T ) )
2030 {
2031 EDA_ITEM* parent = curr_item->GetParent();
2032
2033 if( parent->Type() == SCH_SYMBOL_T )
2034 curr_item = parent;
2035 }
2036
2037 switch( curr_item->Type() )
2038 {
2039 case SCH_LINE_T:
2041 case SCH_JUNCTION_T:
2042 case SCH_TABLECELL_T:
2043 break;
2044
2045 default:
2046 if( selection.Size() > 1 )
2047 return 0;
2048
2049 break;
2050 }
2051
2052 switch( curr_item->Type() )
2053 {
2054 case SCH_SYMBOL_T:
2055 {
2056 int retval;
2057 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( curr_item );
2058
2059 // This needs to be scoped so the dialog destructor removes blocking status
2060 // before we launch the next dialog.
2061 {
2062 DIALOG_SYMBOL_PROPERTIES symbolPropsDialog( m_frame, symbol );
2063
2064 // This dialog itself subsequently can invoke a KIWAY_PLAYER as a quasimodal
2065 // frame. Therefore this dialog as a modal frame parent, MUST be run under
2066 // quasimodal mode for the quasimodal frame support to work. So don't use
2067 // the QUASIMODAL macros here.
2068 retval = symbolPropsDialog.ShowQuasiModal();
2069 }
2070
2071 if( retval == SYMBOL_PROPS_EDIT_OK )
2072 {
2074 {
2075 AUTOPLACE_ALGO fieldsAutoplaced = symbol->GetFieldsAutoplaced();
2076
2077 if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
2078 symbol->AutoplaceFields( m_frame->GetScreen(), fieldsAutoplaced );
2079 }
2080
2081 m_frame->OnModify();
2082 }
2083 else if( retval == SYMBOL_PROPS_EDIT_SCHEMATIC_SYMBOL )
2084 {
2085 if( KIWAY_PLAYER* frame = m_frame->Kiway().Player( FRAME_SCH_SYMBOL_EDITOR, true ) )
2086 {
2087 SYMBOL_EDIT_FRAME* editor = static_cast<SYMBOL_EDIT_FRAME*>( frame );
2088
2089 if( wxWindow* blocking_win = editor->Kiway().GetBlockingDialog() )
2090 blocking_win->Close( true );
2091
2092 // The broken library symbol link indicator cannot be edited.
2093 if( symbol->IsMissingLibSymbol() )
2094 return 0;
2095
2096 editor->LoadSymbolFromSchematic( symbol );
2097 editor->Show( true );
2098 editor->Raise();
2099 }
2100 }
2101 else if( retval == SYMBOL_PROPS_EDIT_LIBRARY_SYMBOL )
2102 {
2103 if( KIWAY_PLAYER* frame = m_frame->Kiway().Player( FRAME_SCH_SYMBOL_EDITOR, true ) )
2104 {
2105 SYMBOL_EDIT_FRAME* editor = static_cast<SYMBOL_EDIT_FRAME*>( frame );
2106
2107 if( wxWindow* blocking_win = editor->Kiway().GetBlockingDialog() )
2108 blocking_win->Close( true );
2109
2110 editor->LoadSymbol( symbol->GetLibId(), symbol->GetUnit(), symbol->GetBodyStyle() );
2111 editor->Show( true );
2112 editor->Raise();
2113 }
2114 }
2115 else if( retval == SYMBOL_PROPS_WANT_UPDATE_SYMBOL )
2116 {
2118 dlg.ShowQuasiModal();
2119 }
2120 else if( retval == SYMBOL_PROPS_WANT_EXCHANGE_SYMBOL )
2121 {
2123 dlg.ShowQuasiModal();
2124 }
2125
2126 break;
2127 }
2128
2129 case SCH_SHEET_T:
2130 {
2131 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( curr_item );
2132 bool isUndoable = false;
2133 bool doClearAnnotation = false;
2134 bool okPressed = false;
2135 bool updateHierarchyNavigator = false;
2136
2137 // Keep track of existing sheet paths. EditSheet() can modify this list.
2138 // Note that we use the validity checking/repairing version here just to make sure
2139 // we've got a valid hierarchy to begin with.
2140 SCH_SHEET_LIST originalHierarchy;
2141 originalHierarchy.BuildSheetList( &m_frame->Schematic().Root(), true );
2142
2143 SCH_COMMIT commit( m_toolMgr );
2144 commit.Modify( sheet, m_frame->GetScreen() );
2145 okPressed = m_frame->EditSheetProperties( sheet, &m_frame->GetCurrentSheet(), &isUndoable,
2146 &doClearAnnotation, &updateHierarchyNavigator );
2147
2148 if( okPressed )
2149 {
2150 if( isUndoable )
2151 {
2152 commit.Push( _( "Edit Sheet Properties" ) );
2153 }
2154 else
2155 {
2156 std::vector<SCH_ITEM*> items;
2157
2158 items.emplace_back( sheet );
2159 m_frame->Schematic().OnItemsRemoved( items );
2160 m_frame->Schematic().OnItemsAdded( items );
2161 m_frame->OnModify();
2164 }
2165 }
2166 else
2167 {
2168 // If we are renaming files, the undo/redo list becomes invalid and must be cleared.
2170 m_frame->OnModify();
2171 }
2172
2173 // If the sheet file is changed and new sheet contents are loaded then we have to
2174 // clear the annotations on the new content (as it may have been set from some other
2175 // sheet path reference)
2176 if( doClearAnnotation )
2177 {
2178 SCH_SCREENS screensList( &m_frame->Schematic().Root() );
2179
2180 // We clear annotation of new sheet paths here:
2181 screensList.ClearAnnotationOfNewSheetPaths( originalHierarchy );
2182
2183 // Clear annotation of g_CurrentSheet itself, because its sheetpath is not a new
2184 // path, but symbols managed by its sheet path must have their annotation cleared
2185 // because they are new:
2186 sheet->GetScreen()->ClearAnnotation( &m_frame->GetCurrentSheet(), false );
2187 }
2188
2189 if( okPressed )
2191
2192 if( updateHierarchyNavigator )
2194
2195 break;
2196 }
2197
2198 case SCH_SHEET_PIN_T:
2199 {
2200 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( curr_item );
2202
2203 // QuasiModal required for help dialog
2204 dlg.ShowQuasiModal();
2205 break;
2206 }
2207
2208 case SCH_TEXT_T:
2209 case SCH_TEXTBOX_T:
2210 {
2211 DIALOG_TEXT_PROPERTIES dlg( m_frame, static_cast<SCH_ITEM*>( curr_item ) );
2212
2213 // QuasiModal required for syntax help and Scintilla auto-complete
2214 dlg.ShowQuasiModal();
2215 break;
2216 }
2217
2218 case SCH_TABLECELL_T:
2219 if( SELECTION_CONDITIONS::OnlyTypes( { SCH_TABLECELL_T } )( selection ) )
2220 {
2221 std::vector<SCH_TABLECELL*> cells;
2222
2223 for( EDA_ITEM* item : selection.Items() )
2224 cells.push_back( static_cast<SCH_TABLECELL*>( item ) );
2225
2227
2228 dlg.ShowModal();
2229
2231 {
2232 SCH_TABLE* table = static_cast<SCH_TABLE*>( cells[0]->GetParent() );
2233 DIALOG_TABLE_PROPERTIES tableDlg( m_frame, table );
2234
2235 tableDlg.ShowModal();
2236 }
2237 }
2238
2239 break;
2240
2241 case SCH_TABLE_T:
2242 {
2243 DIALOG_TABLE_PROPERTIES dlg( m_frame, static_cast<SCH_TABLE*>( curr_item ) );
2244
2245 // QuasiModal required for Scintilla auto-complete
2246 dlg.ShowQuasiModal();
2247 break;
2248 }
2249
2250 case SCH_LABEL_T:
2251 case SCH_GLOBAL_LABEL_T:
2252 case SCH_HIER_LABEL_T:
2254 {
2255 DIALOG_LABEL_PROPERTIES dlg( m_frame, static_cast<SCH_LABEL_BASE*>( curr_item ) );
2256
2257 // QuasiModal for syntax help and Scintilla auto-complete
2258 dlg.ShowQuasiModal();
2259 break;
2260 }
2261
2262 case SCH_FIELD_T:
2263 {
2264 SCH_FIELD* field = static_cast<SCH_FIELD*>( curr_item );
2265
2266 editFieldText( field );
2267
2268 if( !field->IsVisible() )
2269 clearSelection = true;
2270
2271 break;
2272 }
2273
2274 case SCH_SHAPE_T:
2275 {
2276 DIALOG_SHAPE_PROPERTIES dlg( m_frame, static_cast<SCH_SHAPE*>( curr_item ) );
2277
2278 dlg.ShowModal();
2279 break;
2280 }
2281
2282 case SCH_BITMAP_T:
2283 {
2284 SCH_BITMAP& bitmap = static_cast<SCH_BITMAP&>( *curr_item );
2285 DIALOG_IMAGE_PROPERTIES dlg( m_frame, bitmap );
2286
2287 if( dlg.ShowModal() == wxID_OK )
2288 {
2289 // The bitmap is cached in Opengl: clear the cache in case it has become invalid
2291 }
2292
2293 break;
2294 }
2295
2296 case SCH_RULE_AREA_T:
2297 {
2298 DIALOG_SHAPE_PROPERTIES dlg( m_frame, static_cast<SCH_SHAPE*>( curr_item ) );
2299 dlg.SetTitle( _( "Rule Area Properties" ) );
2300
2301 dlg.ShowModal();
2302 break;
2303 }
2304
2305 case SCH_LINE_T:
2307 case SCH_JUNCTION_T:
2309 {
2310 std::deque<SCH_LINE*> lines;
2311
2312 for( EDA_ITEM* selItem : selection.Items() )
2313 lines.push_back( static_cast<SCH_LINE*>( selItem ) );
2314
2315 DIALOG_LINE_PROPERTIES dlg( m_frame, lines );
2316
2317 dlg.ShowModal();
2318 }
2319 else if( SELECTION_CONDITIONS::OnlyTypes( { SCH_JUNCTION_T } )( selection ) )
2320 {
2321 std::deque<SCH_JUNCTION*> junctions;
2322
2323 for( EDA_ITEM* selItem : selection.Items() )
2324 junctions.push_back( static_cast<SCH_JUNCTION*>( selItem ) );
2325
2326 DIALOG_JUNCTION_PROPS dlg( m_frame, junctions );
2327
2328 dlg.ShowModal();
2329 }
2333 SCH_JUNCTION_T } )( selection ) )
2334 {
2335 std::deque<SCH_ITEM*> items;
2336
2337 for( EDA_ITEM* selItem : selection.Items() )
2338 items.push_back( static_cast<SCH_ITEM*>( selItem ) );
2339
2340 DIALOG_WIRE_BUS_PROPERTIES dlg( m_frame, items );
2341
2342 dlg.ShowModal();
2343 }
2344 else
2345 {
2346 return 0;
2347 }
2348
2349 break;
2350
2351 case SCH_MARKER_T:
2352 if( SELECTION_CONDITIONS::OnlyTypes( { SCH_MARKER_T } )( selection ) )
2353 {
2355
2356 if( inspectionTool )
2357 inspectionTool->CrossProbe( static_cast<SCH_MARKER*> ( selection.Front() ) );
2358 }
2359 break;
2360
2361 case SCH_NO_CONNECT_T:
2362 case SCH_PIN_T:
2363 break;
2364
2365 default: // Unexpected item
2366 wxFAIL_MSG( wxString( "Cannot edit schematic item type " ) + curr_item->GetClass() );
2367 }
2368
2369 updateItem( curr_item, true );
2370
2371 if( clearSelection )
2373
2374 return 0;
2375}
2376
2377
2379{
2380 KICAD_T convertTo = aEvent.Parameter<KICAD_T>();
2382 SCH_TEXT_T,
2383 SCH_TEXTBOX_T } );
2384 SCH_COMMIT commit( m_toolMgr );
2385
2386 for( unsigned int i = 0; i < selection.GetSize(); ++i )
2387 {
2388 SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( selection.GetItem( i ) );
2389
2390 if( item && item->Type() != convertTo )
2391 {
2392 EDA_TEXT* sourceText = dynamic_cast<EDA_TEXT*>( item );
2393 bool selected = item->IsSelected();
2394 SCH_ITEM* newtext = nullptr;
2395 VECTOR2I position = item->GetPosition();
2396 wxString txt;
2397 wxString href;
2399 LABEL_FLAG_SHAPE shape = LABEL_FLAG_SHAPE::L_UNSPECIFIED;
2400
2401 switch( item->Type() )
2402 {
2403 case SCH_LABEL_T:
2404 case SCH_GLOBAL_LABEL_T:
2405 case SCH_HIER_LABEL_T:
2406 {
2407 SCH_LABEL_BASE* label = static_cast<SCH_LABEL_BASE*>( item );
2408
2409 txt = UnescapeString( label->GetText() );
2410 spinStyle = label->GetSpinStyle();
2411 shape = label->GetShape();
2412 href = label->GetHyperlink();
2413 break;
2414 }
2415
2417 {
2418 SCH_DIRECTIVE_LABEL* dirlabel = static_cast<SCH_DIRECTIVE_LABEL*>( item );
2419
2420 // a SCH_DIRECTIVE_LABEL has no text
2421 txt = _( "<empty>" );
2422
2423 spinStyle = dirlabel->GetSpinStyle();
2424 href = dirlabel->GetHyperlink();
2425 break;
2426 }
2427
2428 case SCH_TEXT_T:
2429 {
2430 SCH_TEXT* text = static_cast<SCH_TEXT*>( item );
2431
2432 txt = text->GetText();
2433 href = text->GetHyperlink();
2434 break;
2435 }
2436
2437 case SCH_TEXTBOX_T:
2438 {
2439 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( item );
2440 BOX2I bbox = textbox->GetBoundingBox();
2441
2442 bbox.SetOrigin( bbox.GetLeft() + textbox->GetMarginLeft(),
2443 bbox.GetTop() + textbox->GetMarginTop() );
2444 bbox.SetEnd( bbox.GetRight() - textbox->GetMarginRight(),
2445 bbox.GetBottom() - textbox->GetMarginBottom() );
2446
2447 if( convertTo == SCH_LABEL_T
2448 || convertTo == SCH_HIER_LABEL_T
2449 || convertTo == SCH_GLOBAL_LABEL_T )
2450 {
2451 EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item );
2452 wxCHECK( text, 0 );
2453 int textSize = text->GetTextSize().y;
2454 bbox.Inflate( KiROUND( item->Schematic()->Settings().m_LabelSizeRatio * textSize ) );
2455 }
2456
2457 txt = textbox->GetText();
2458
2459 if( textbox->GetTextAngle().IsVertical() )
2460 {
2461 if( textbox->GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
2462 {
2463 spinStyle = SPIN_STYLE::SPIN::BOTTOM;
2464 position = VECTOR2I( bbox.Centre().x, bbox.GetOrigin().y );
2465 }
2466 else
2467 {
2468 spinStyle = SPIN_STYLE::SPIN::UP;
2469 position = VECTOR2I( bbox.Centre().x, bbox.GetEnd().y );
2470 }
2471 }
2472 else
2473 {
2474 if( textbox->GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
2475 {
2476 spinStyle = SPIN_STYLE::SPIN::LEFT;
2477 position = VECTOR2I( bbox.GetEnd().x, bbox.Centre().y );
2478 }
2479 else
2480 {
2481 spinStyle = SPIN_STYLE::SPIN::RIGHT;
2482 position = VECTOR2I( bbox.GetOrigin().x, bbox.Centre().y );
2483 }
2484 }
2485
2486 position = m_frame->GetNearestGridPosition( position );
2487 href = textbox->GetHyperlink();
2488 break;
2489 }
2490
2491 default:
2492 UNIMPLEMENTED_FOR( item->GetClass() );
2493 break;
2494 }
2495
2496 auto getValidNetname =
2497 []( const wxString& aText )
2498 {
2499 wxString local_txt = aText;
2500 local_txt.Replace( "\n", "_" );
2501 local_txt.Replace( "\r", "_" );
2502 local_txt.Replace( "\t", "_" );
2503
2504 // Bus groups can have spaces; bus vectors and signal names cannot
2505 if( !NET_SETTINGS::ParseBusGroup( aText, nullptr, nullptr ) )
2506 local_txt.Replace( " ", "_" );
2507
2508 // label strings are "escaped" i.e. a '/' is replaced by "{slash}"
2509 local_txt = EscapeString( local_txt, CTX_NETNAME );
2510
2511 if( local_txt.IsEmpty() )
2512 return _( "<empty>" );
2513 else
2514 return local_txt;
2515 };
2516
2517 switch( convertTo )
2518 {
2519 case SCH_LABEL_T:
2520 {
2521 SCH_LABEL_BASE* new_label = new SCH_LABEL( position, getValidNetname( txt ) );
2522
2523 new_label->SetShape( shape );
2524 new_label->SetAttributes( *sourceText, false );
2525 new_label->SetSpinStyle( spinStyle );
2526 new_label->SetHyperlink( href );
2527
2528 if( item->Type() == SCH_GLOBAL_LABEL_T || item->Type() == SCH_HIER_LABEL_T )
2529 {
2530 if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::UP )
2531 new_label->MirrorVertically( position.y );
2532 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::BOTTOM )
2533 new_label->MirrorVertically( position.y );
2534 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::LEFT )
2535 new_label->MirrorHorizontally( position.x );
2536 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::RIGHT )
2537 new_label->MirrorHorizontally( position.x );
2538 }
2539
2540 newtext = new_label;
2541 break;
2542 }
2543
2544 case SCH_GLOBAL_LABEL_T:
2545 {
2546 SCH_LABEL_BASE* new_label = new SCH_GLOBALLABEL( position, getValidNetname( txt ) );
2547
2548 new_label->SetShape( shape );
2549 new_label->SetAttributes( *sourceText, false );
2550 new_label->SetSpinStyle( spinStyle );
2551 new_label->SetHyperlink( href );
2552
2553 if( item->Type() == SCH_LABEL_T )
2554 {
2555 if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::UP )
2556 new_label->MirrorVertically( position.y );
2557 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::BOTTOM )
2558 new_label->MirrorVertically( position.y );
2559 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::LEFT )
2560 new_label->MirrorHorizontally( position.x );
2561 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::RIGHT )
2562 new_label->MirrorHorizontally( position.x );
2563 }
2564
2565 newtext = new_label;
2566 break;
2567 }
2568
2569 case SCH_HIER_LABEL_T:
2570 {
2571 SCH_LABEL_BASE* new_label = new SCH_HIERLABEL( position, getValidNetname( txt ) );
2572
2573 new_label->SetShape( shape );
2574 new_label->SetAttributes( *sourceText, false );
2575 new_label->SetSpinStyle( spinStyle );
2576 new_label->SetHyperlink( href );
2577
2578 if( item->Type() == SCH_LABEL_T )
2579 {
2580 if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::UP )
2581 new_label->MirrorVertically( position.y );
2582 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::BOTTOM )
2583 new_label->MirrorVertically( position.y );
2584 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::LEFT )
2585 new_label->MirrorHorizontally( position.x );
2586 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::RIGHT )
2587 new_label->MirrorHorizontally( position.x );
2588 }
2589
2590 newtext = new_label;
2591 break;
2592 }
2593
2595 {
2596 SCH_LABEL_BASE* new_label = new SCH_DIRECTIVE_LABEL( position );
2597
2598 // A SCH_DIRECTIVE_LABEL usually has at least one field containing the net class
2599 // name. If we're copying from a text object assume the text is the netclass
2600 // name. Otherwise, we'll just copy the fields which will either have a netclass
2601 // or not.
2602 if( !dynamic_cast<SCH_LABEL_BASE*>( item ) )
2603 {
2604 SCH_FIELD netclass( position, 0, new_label, wxT( "Netclass" ) );
2605 netclass.SetText( txt );
2606 netclass.SetVisible( true );
2607 new_label->GetFields().push_back( netclass );
2608 }
2609
2610 new_label->SetShape( LABEL_FLAG_SHAPE::F_ROUND );
2611 new_label->SetAttributes( *sourceText, false );
2612 new_label->SetSpinStyle( spinStyle );
2613 new_label->SetHyperlink( href );
2614 newtext = new_label;
2615 break;
2616 }
2617
2618 case SCH_TEXT_T:
2619 {
2620 SCH_TEXT* new_text = new SCH_TEXT( position, txt );
2621
2622 new_text->SetAttributes( *sourceText, false );
2623 new_text->SetHyperlink( href );
2624 newtext = new_text;
2625 break;
2626 }
2627
2628 case SCH_TEXTBOX_T:
2629 {
2630 SCH_TEXTBOX* new_textbox = new SCH_TEXTBOX( LAYER_NOTES, 0, FILL_T::NO_FILL, txt );
2631 BOX2I bbox = item->GetBoundingBox();
2632
2633 if( SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( item ) )
2634 bbox.Inflate( -label->GetLabelBoxExpansion() );
2635
2636 new_textbox->SetAttributes( *sourceText, false );
2637
2638 bbox.SetOrigin( bbox.GetLeft() - new_textbox->GetMarginLeft(),
2639 bbox.GetTop() - new_textbox->GetMarginTop() );
2640 bbox.SetEnd( bbox.GetRight() + new_textbox->GetMarginRight(),
2641 bbox.GetBottom() + new_textbox->GetMarginBottom() );
2642
2643 VECTOR2I topLeft = bbox.GetPosition();
2644 VECTOR2I botRight = bbox.GetEnd();
2645
2646 // Add 1/20 of the margin at the end to reduce line-breaking changes.
2647 int slop = new_textbox->GetLegacyTextMargin() / 20;
2648
2649 if( sourceText->GetTextAngle() == ANGLE_VERTICAL )
2650 {
2651 if( sourceText->GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
2652 botRight.y += slop;
2653 else
2654 topLeft.y -= slop;
2655 }
2656 else
2657 {
2658 if( sourceText->GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
2659 topLeft.x -= slop;
2660 else
2661 botRight.x += slop;
2662 }
2663
2664 new_textbox->SetPosition( topLeft );
2665 new_textbox->SetEnd( botRight );
2666
2667 new_textbox->SetHyperlink( href );
2668 newtext = new_textbox;
2669 break;
2670 }
2671
2672 default:
2673 UNIMPLEMENTED_FOR( wxString::Format( "%d.", convertTo ) );
2674 break;
2675 }
2676
2677 wxCHECK2( newtext, continue );
2678
2679 // Copy the old text item settings to the new one. Justifications are not copied
2680 // because they are not used in labels. Justifications will be set to default value
2681 // in the new text item type.
2682 //
2683 newtext->SetFlags( item->GetEditFlags() );
2684
2685 EDA_TEXT* eda_text = dynamic_cast<EDA_TEXT*>( item );
2686 EDA_TEXT* new_eda_text = dynamic_cast<EDA_TEXT*>( newtext );
2687
2688 wxCHECK2( eda_text && new_eda_text, continue );
2689
2690 new_eda_text->SetFont( eda_text->GetFont() );
2691 new_eda_text->SetTextSize( eda_text->GetTextSize() );
2692 new_eda_text->SetTextThickness( eda_text->GetTextThickness() );
2693
2694 // Must be after SetTextSize()
2695 new_eda_text->SetBold( eda_text->IsBold() );
2696 new_eda_text->SetItalic( eda_text->IsItalic() );
2697
2699
2700 SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( item );
2701 SCH_LABEL_BASE* new_label = dynamic_cast<SCH_LABEL_BASE*>( newtext );
2702
2703 if( label && new_label )
2704 {
2705 new_label->AddFields( label->GetFields() );
2706
2707 // A SCH_GLOBALLABEL has a specific field, that has no meaning for
2708 // other labels, and expected to be the first field in list.
2709 // It is the first field in list for this kind of label
2710 // So remove field named "Intersheetrefs" if exists for other labels
2711 int min_idx = new_label->Type() == SCH_GLOBAL_LABEL_T ? 1 : 0;
2712 std::vector<SCH_FIELD>& fields = new_label->GetFields();
2713
2714 for( int ii = fields.size()-1; ii >= min_idx; ii-- )
2715 {
2716 if( fields[ii].GetCanonicalName() == wxT( "Intersheetrefs" ) )
2717 fields.erase( fields.begin() + ii );
2718 }
2719 }
2720
2721 if( selected )
2723
2724 if( !item->IsNew() )
2725 {
2727 commit.Removed( item, m_frame->GetScreen() );
2728
2729 m_frame->AddToScreen( newtext, m_frame->GetScreen() );
2730 commit.Added( newtext, m_frame->GetScreen() );
2731 }
2732
2733 if( selected )
2735
2736 // Otherwise, pointer is owned by the undo stack
2737 if( item->IsNew() )
2738 delete item;
2739 }
2740 }
2741
2742 if( !commit.Empty() )
2743 commit.Push( _( "Change To" ) );
2744
2745 if( selection.IsHover() )
2747
2748 return 0;
2749}
2750
2751
2753{
2754 static std::vector<KICAD_T> justifiableItems = {
2756 SCH_TEXT_T,
2759 };
2760
2761 EE_SELECTION& selection = m_selectionTool->RequestSelection( justifiableItems );
2762
2763 if( selection.GetSize() == 0 )
2764 return 0;
2765
2766 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.Front() );
2767 bool moving = item->IsMoving();
2768 SCH_COMMIT localCommit( m_toolMgr );
2769 SCH_COMMIT* commit = dynamic_cast<SCH_COMMIT*>( aEvent.Commit() );
2770
2771 if( !commit )
2772 commit = &localCommit;
2773
2774 auto setJustify =
2775 [&]( EDA_TEXT* aTextItem )
2776 {
2777 if( aEvent.Matches( ACTIONS::leftJustify.MakeEvent() ) )
2778 aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
2779 else if( aEvent.Matches( ACTIONS::centerJustify.MakeEvent() ) )
2780 aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER );
2781 else
2782 aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
2783 };
2784
2785 for( EDA_ITEM* edaItem : selection )
2786 {
2787 item = static_cast<SCH_ITEM*>( edaItem );
2788
2789 if( !moving )
2790 commit->Modify( item, m_frame->GetScreen() );
2791
2792 if( item->Type() == SCH_FIELD_T )
2793 {
2794 setJustify( static_cast<SCH_FIELD*>( item ) );
2795
2796 // Now that we're re-justifying a field, they're no longer autoplaced.
2797 static_cast<SCH_ITEM*>( item->GetParent() )->SetFieldsAutoplaced( AUTOPLACE_NONE );
2798 }
2799 else if( item->Type() == SCH_TEXT_T )
2800 {
2801 setJustify( static_cast<SCH_TEXT*>( item ) );
2802 }
2803 else if( item->Type() == SCH_TEXTBOX_T )
2804 {
2805 setJustify( static_cast<SCH_TEXTBOX*>( item ) );
2806 }
2807 else if( item->Type() == SCH_LABEL_T )
2808 {
2809 SCH_LABEL* label = static_cast<SCH_LABEL*>( item );
2810
2811 if( label->GetTextAngle() == ANGLE_HORIZONTAL )
2812 setJustify( label );
2813 }
2814
2815 m_frame->UpdateItem( item, false, true );
2816 }
2817
2818 // Update R-Tree for modified items
2819 for( EDA_ITEM* selected : selection )
2820 updateItem( selected, true );
2821
2822 if( item->IsMoving() )
2823 {
2825 }
2826 else
2827 {
2828 EE_SELECTION selectionCopy = selection;
2829
2830 if( selection.IsHover() )
2832
2833 if( !localCommit.Empty() )
2834 {
2835 if( aEvent.Matches( ACTIONS::leftJustify.MakeEvent() ) )
2836 localCommit.Push( _( "Left Justify" ) );
2837 else if( aEvent.Matches( ACTIONS::centerJustify.MakeEvent() ) )
2838 localCommit.Push( _( "Center Justify" ) );
2839 else
2840 localCommit.Push( _( "Right Justify" ) );
2841 }
2842 }
2843
2844 return 0;
2845}
2846
2847
2849{
2850 bool isSlice = aEvent.Matches( EE_ACTIONS::slice.MakeEvent() );
2853 SCH_SCREEN* screen = m_frame->GetScreen();
2854 SCH_COMMIT commit( m_toolMgr );
2855 std::vector<SCH_LINE*> lines;
2856
2857 for( EDA_ITEM* item : selection )
2858 {
2859 if( item->Type() == SCH_LINE_T )
2860 {
2861 SCH_LINE* line = static_cast<SCH_LINE*>( item );
2862
2863 if( !line->IsEndPoint( cursorPos ) )
2864 lines.push_back( line );
2865 }
2866 }
2867
2869
2870 for( SCH_LINE* line : lines )
2871 {
2872 SCH_LINE* newLine;
2873
2874 // We let the user select the break point if they're on a single line
2875 if( lines.size() == 1 && line->HitTest( cursorPos ) )
2876 m_frame->BreakSegment( &commit, line, cursorPos, &newLine, screen );
2877 else
2878 m_frame->BreakSegment( &commit, line, line->GetMidPoint(), &newLine, screen );
2879
2880 // Make sure both endpoints are deselected
2881 newLine->ClearFlags();
2882
2884 line->SetFlags( ENDPOINT );
2885
2886 // If we're a break, we want to drag both wires.
2887 // Side note: the drag/move tool only checks whether the first item is
2888 // new to determine if it should append undo or not, someday this should
2889 // be cleaned up and explictly controlled but for now the newLine
2890 // selection addition must be after the existing line.
2891 if( !isSlice )
2892 {
2893 m_selectionTool->AddItemToSel( newLine );
2894 newLine->SetFlags( STARTPOINT );
2895 }
2896 }
2897
2898 if( !lines.empty() )
2899 {
2901
2902 if( m_toolMgr->RunSynchronousAction( EE_ACTIONS::drag, &commit, isSlice ) )
2903 commit.Push( isSlice ? _( "Slice Wire" ) : _( "Break Wire" ) );
2904 else
2905 commit.Revert();
2906 }
2907
2908 return 0;
2909}
2910
2911
2913{
2915 SCH_SHEET* sheet = (SCH_SHEET*) selection.Front();
2916 SCH_COMMIT commit( m_toolMgr );
2917
2918 if( !sheet || !sheet->HasUndefinedPins() )
2919 return 0;
2920
2921 if( !IsOK( m_frame, _( "Do you wish to delete the unreferenced pins from this sheet?" ) ) )
2922 return 0;
2923
2924 commit.Modify( sheet, m_frame->GetScreen() );
2925
2926 sheet->CleanupSheet();
2927
2928 updateItem( sheet, true );
2929
2930 commit.Push( _( "Cleanup Sheet Pins" ) );
2931
2932 if( selection.IsHover() )
2934
2935 return 0;
2936}
2937
2938
2940{
2942
2943 if( selection.GetSize() > 1 )
2944 return 0;
2945
2946 SCH_SHEET* sheet = (SCH_SHEET*) selection.Front();
2947
2949
2950 SCH_SCREEN* screen;
2951
2952 if( sheet )
2953 {
2954 // When changing the page number of a selected sheet, the current screen owns the sheet.
2955 screen = m_frame->GetScreen();
2956
2957 instance.push_back( sheet );
2958 }
2959 else
2960 {
2961 SCH_SHEET_PATH prevInstance = instance;
2962
2963 // When change the page number in the screen, the previous screen owns the sheet.
2964 if( prevInstance.size() )
2965 {
2966 prevInstance.pop_back();
2967 screen = prevInstance.LastScreen();
2968 }
2969 else
2970 {
2971 // The root sheet and root screen are effectively the same thing.
2972 screen = m_frame->GetScreen();
2973 }
2974
2975 sheet = m_frame->GetCurrentSheet().Last();
2976 }
2977
2978 wxString msg;
2979 wxString sheetPath = instance.PathHumanReadable( false );
2980 wxString pageNumber = instance.GetPageNumber();
2981
2982 msg.Printf( _( "Enter page number for sheet path%s" ),
2983 ( sheetPath.Length() > 20 ) ? "\n" + sheetPath : " " + sheetPath );
2984
2985 wxTextEntryDialog dlg( m_frame, msg, _( "Edit Sheet Page Number" ), pageNumber );
2986
2987 dlg.SetTextValidator( wxFILTER_ALPHANUMERIC ); // No white space.
2988
2989 if( dlg.ShowModal() == wxID_CANCEL || dlg.GetValue() == instance.GetPageNumber() )
2990 return 0;
2991
2992 SCH_COMMIT commit( m_frame );
2993
2994 commit.Modify( sheet, screen );
2995
2996 instance.SetPageNumber( dlg.GetValue() );
2997
2998 if( instance == m_frame->GetCurrentSheet() )
2999 {
3000 m_frame->GetScreen()->SetPageNumber( dlg.GetValue() );
3002 }
3003
3004 commit.Push( wxS( "Change Sheet Page Number" ) );
3005 return 0;
3006}
3007
3008
3010{
3011 const ACTIONS::INCREMENT incParam = aEvent.Parameter<ACTIONS::INCREMENT>();
3012 static const std::vector<KICAD_T> incrementable = { SCH_LABEL_T, SCH_GLOBAL_LABEL_T,
3014 EE_SELECTION& selection = m_selectionTool->RequestSelection( incrementable );
3015
3016 if( selection.Empty() )
3017 return 0;
3018
3019 KICAD_T type = selection.Front()->Type();
3020 bool allSameType = true;
3021 for( EDA_ITEM* item : selection )
3022 {
3023 if( item->Type() != type )
3024 {
3025 allSameType = false;
3026 break;
3027 }
3028 }
3029
3030 // Incrementing multiple types at once seems confusing
3031 // though it would work.
3032 if( !allSameType )
3033 return 0;
3034
3035 STRING_INCREMENTER incrementer;
3036 // In schematics, it's probably less common to be operating
3037 // on pin numbers which are usually IOSQXZ-skippy.
3038 incrementer.SetSkipIOSQXZ( false );
3039
3040 // If we're coming via another action like 'Move', use that commit
3041 SCH_COMMIT localCommit( m_toolMgr );
3042 SCH_COMMIT* commit = dynamic_cast<SCH_COMMIT*>( aEvent.Commit() );
3043
3044 if( !commit )
3045 commit = &localCommit;
3046
3047 const auto modifyItem = [&]( EDA_ITEM& aItem )
3048 {
3049 if( aItem.IsNew() )
3051 else
3052 commit->Modify( &aItem, m_frame->GetScreen() );
3053 };
3054
3055 for( EDA_ITEM* item : selection )
3056 {
3057 switch( item->Type() )
3058 {
3059 case SCH_LABEL_T:
3060 case SCH_GLOBAL_LABEL_T:
3061 case SCH_HIER_LABEL_T:
3062 case SCH_TEXT_T:
3063 {
3064 SCH_TEXT& label = static_cast<SCH_TEXT&>( *item );
3065
3066 std::optional<wxString> newLabel =
3067 incrementer.Increment( label.GetText(), incParam.Delta, incParam.Index );
3068 if( newLabel )
3069 {
3070 modifyItem( label );
3071 label.SetText( *newLabel );
3072 }
3073 break;
3074 }
3075 default:
3076 // No increment for other items (yet)
3077 break;
3078 }
3079 }
3080
3081 commit->Push( _( "Increment" ) );
3082
3083 return 0;
3084}
3085
3086
3088{
3089 return m_toolMgr->RunAction( EE_ACTIONS::importSheet, aEvent.Parameter<wxString*>() );
3090}
3091
3092
3094 std::set<std::pair<SCH_SYMBOL*, SCH_SCREEN*>>& aCollectedUnits )
3095{
3096 for( EDA_ITEM* item : aSelection )
3097 {
3098 if( item->Type() == SCH_SYMBOL_T )
3099 {
3100 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
3101
3102 aCollectedUnits.insert( { symbol, m_frame->GetScreen() } );
3103
3104 // The attributes should be kept in sync in multi-unit parts.
3105 // Of course the symbol must be annotated to collect other units.
3106 if( symbol->IsAnnotated( &m_frame->GetCurrentSheet() ) )
3107 {
3108 wxString ref = symbol->GetRef( &m_frame->GetCurrentSheet() );
3109 int unit = symbol->GetUnit();
3110 LIB_ID libId = symbol->GetLibId();
3111
3112 for( SCH_SHEET_PATH& sheet : m_frame->Schematic().Hierarchy() )
3113 {
3114 SCH_SCREEN* screen = sheet.LastScreen();
3115 std::vector<SCH_SYMBOL*> otherUnits;
3116
3117 CollectOtherUnits( ref, unit, libId, sheet, &otherUnits );
3118
3119 for( SCH_SYMBOL* otherUnit : otherUnits )
3120 aCollectedUnits.insert( { otherUnit, screen } );
3121 }
3122 }
3123 }
3124 }
3125}
3126
3127
3129{
3131 SCH_COMMIT commit( m_toolMgr );
3132
3133 std::set<std::pair<SCH_SYMBOL*, SCH_SCREEN*>> collectedUnits;
3134
3135 collectUnits( selection, collectedUnits );
3136
3137 for( const auto& [symbol, screen] : collectedUnits )
3138 {
3139 commit.Modify( symbol, screen );
3140
3141 if( aEvent.IsAction( &EE_ACTIONS::setDNP ) )
3142 symbol->SetDNP( true );
3143
3145 symbol->SetExcludedFromSim( true );
3146
3148 symbol->SetExcludedFromBOM( true );
3149
3151 symbol->SetExcludedFromBoard( true );
3152 }
3153
3154 if( !commit.Empty() )
3155 commit.Push( _( "Set Attribute" ) );
3156
3157 return 0;
3158}
3159
3160
3162{
3164 SCH_COMMIT commit( m_toolMgr );
3165
3166 std::set<std::pair<SCH_SYMBOL*, SCH_SCREEN*>> collectedUnits;
3167
3168 collectUnits( selection, collectedUnits );
3169
3170 for( const auto& [symbol, screen] : collectedUnits )
3171 {
3172 commit.Modify( symbol, screen );
3173
3174 if( aEvent.IsAction( &EE_ACTIONS::unsetDNP ) )
3175 symbol->SetDNP( false );
3176
3178 symbol->SetExcludedFromSim( false );
3179
3181 symbol->SetExcludedFromBOM( false );
3182
3184 symbol->SetExcludedFromBoard( false );
3185 }
3186
3187 if( !commit.Empty() )
3188 commit.Push( _( "Clear Attribute" ) );
3189
3190 return 0;
3191}
3192
3193
3195{
3197 SCH_COMMIT commit( m_toolMgr );
3198
3199 std::set<std::pair<SCH_SYMBOL*, SCH_SCREEN*>> collectedUnits;
3200
3201 collectUnits( selection, collectedUnits );
3202
3203 for( const auto& [symbol, screen] : collectedUnits )
3204 {
3205 commit.Modify( symbol, screen );
3206
3207 if( aEvent.IsAction( &EE_ACTIONS::toggleDNP ) )
3208 symbol->SetDNP( !symbol->GetDNP() );
3209
3211 symbol->SetExcludedFromSim( !symbol->GetExcludedFromSim() );
3212
3214 symbol->SetExcludedFromBOM( !symbol->GetExcludedFromBOM() );
3215
3217 symbol->SetExcludedFromBoard( !symbol->GetExcludedFromBoard() );
3218 }
3219
3220 if( !commit.Empty() )
3221 commit.Push( _( "Toggle Attribute" ) );
3222
3223 return 0;
3224}
3225
3226
3228{
3229 // clang-format off
3235 Go( &SCH_EDIT_TOOL::Swap, EE_ACTIONS::swap.MakeEvent() );
3238
3244
3266
3269
3282
3286
3288 // clang-format on
3289}
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:214
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:178
LABEL_FLAG_SHAPE GetShape() const
Definition: sch_label.h:177
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
Definition: sch_label.cpp:464
std::vector< SCH_FIELD > & GetFields()
Definition: sch_label.h:201
virtual void SetSpinStyle(SPIN_STYLE aSpinStyle)
Definition: sch_label.cpp:296
Tool responsible for drawing/placing items (symbols, wires, buses, labels, etc.)
int AddJunctionsIfNeeded(SCH_COMMIT *aCommit, EE_SELECTION *aSelection)
Handle the addition of junctions to a selection of objects.
int TrimOverLappingWires(SCH_COMMIT *aCommit, EE_SELECTION *aSelection)
Logic to remove wires when overlapping correct items.
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:392
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:419
@ LAYER_SCHEMATIC_DRAWINGSHEET
Definition: layer_ids.h:447
#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