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 (C) 2019-2024 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 <ee_actions.h>
33#include <confirm.h>
34#include <string_utils.h>
35#include <sch_bitmap.h>
36#include <sch_bus_entry.h>
37#include <sch_commit.h>
38#include <sch_junction.h>
39#include <sch_marker.h>
40#include <sch_rule_area.h>
41#include <sch_sheet_pin.h>
42#include <sch_textbox.h>
43#include <sch_table.h>
45#include <eeschema_id.h>
56#include <dialogs/dialog_text_properties.h>
57#include <dialogs/dialog_tablecell_properties.h>
58#include <dialogs/dialog_table_properties.h>
59#include <pgm_base.h>
62#include <core/kicad_algo.h>
63#include <view/view_controls.h>
64#include <wx/textdlg.h>
66
68{
69public:
71 ACTION_MENU( true )
72 {
73 SetIcon( BITMAPS::component_select_unit );
74 SetTitle( _( "Symbol Unit" ) );
75 }
76
77protected:
78 ACTION_MENU* create() const override
79 {
80 return new SYMBOL_UNIT_MENU();
81 }
82
83private:
84 void update() override
85 {
87 EE_SELECTION& selection = selTool->GetSelection();
88 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( selection.Front() );
89
90 Clear();
91
92 wxCHECK( symbol, /* void */ );
93
94 int unit = symbol->GetUnit();
95
96 for( int ii = 0; ii < symbol->GetLibSymbolRef()->GetUnitCount(); ii++ )
97 {
98 wxString unit_text;
99
100 if( symbol->GetLibSymbolRef()->HasUnitDisplayName( ii + 1 ) )
101 unit_text = symbol->GetLibSymbolRef()->GetUnitDisplayName( ii + 1 );
102 else
103 unit_text.Printf( _( "Unit %s" ), symbol->SubReference( ii + 1, false ) );
104
105 wxMenuItem* item = Append( ID_POPUP_SCH_SELECT_UNIT1 + ii, unit_text, wxEmptyString,
106 wxITEM_CHECK );
107
108 if( unit == ii + 1 )
109 item->Check( true );
110
111 // The ID max for these submenus is ID_POPUP_SCH_SELECT_UNIT_END
112 // See eeschema_id to modify this value.
114 break; // We have used all IDs for these submenus
115 }
116 }
117};
118
119
121{
122public:
124 ACTION_MENU( true )
125 {
126 SetIcon( BITMAPS::component_select_alternate_shape );
127 SetTitle( _( "Body Style" ) );
128 }
129
130protected:
131 ACTION_MENU* create() const override
132 {
133 return new BODY_STYLE_MENU();
134 }
135
136private:
137 void update() override
138 {
140 EE_SELECTION& selection = selTool->GetSelection();
141 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( selection.Front() );
142 wxMenuItem* item;
143
144 Clear();
145
146 wxCHECK( symbol, /* void */ );
147
148 item = Append( ID_POPUP_SCH_SELECT_BASE, _( "Standard" ), wxEmptyString, wxITEM_CHECK );
149 item->Check( symbol->GetBodyStyle() == BODY_STYLE::BASE );
150
151 item = Append( ID_POPUP_SCH_SELECT_ALT, _( "Alternate" ), wxEmptyString, wxITEM_CHECK );
152 item->Check( symbol->GetBodyStyle() != BODY_STYLE::BASE );
153 }
154};
155
156
158{
159public:
161 ACTION_MENU( true )
162 {
163 SetIcon( BITMAPS::component_select_unit );
164 SetTitle( _( "Pin Function" ) );
165 }
166
167protected:
168 ACTION_MENU* create() const override
169 {
170 return new ALT_PIN_FUNCTION_MENU();
171 }
172
173private:
174 void update() override
175 {
177 EE_SELECTION& selection = selTool->GetSelection();
178 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( selection.Front() );
179 SCH_PIN* libPin = pin ? pin->GetLibPin() : nullptr;
180
181 Clear();
182
183 wxCHECK( libPin, /* void */ );
184
185 wxMenuItem* item = Append( ID_POPUP_SCH_ALT_PIN_FUNCTION, libPin->GetName(), wxEmptyString,
186 wxITEM_CHECK );
187
188 if( pin->GetAlt().IsEmpty() )
189 item->Check( true );
190
191 int ii = 1;
192
193 for( const auto& [ name, definition ] : libPin->GetAlternates() )
194 {
195 item = Append( ID_POPUP_SCH_ALT_PIN_FUNCTION + ii, name, wxEmptyString, wxITEM_CHECK );
196
197 if( name == pin->GetAlt() )
198 item->Check( true );
199
200 // The ID max for these submenus is ID_POPUP_SCH_ALT_PIN_FUNCTION_END
201 // See eeschema_id to modify this value.
203 break; // We have used all IDs for these submenus
204 }
205 }
206};
207
208
210{
211public:
213 {
214 SetIcon( BITMAPS::pin );
215 SetTitle( _( "Pin Helpers" ) );
216 }
217
218protected:
219 ACTION_MENU* create() const override { return new PIN_TRICKS_MENU(); }
220
221private:
222 void update() override
223 {
225 EE_SELECTION& selection = selTool->GetSelection();
226 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( selection.Front() );
227 SCH_SHEET_PIN* sheetPin = dynamic_cast<SCH_SHEET_PIN*>( selection.Front() );
228
229 Clear();
230
231 if( !pin && !sheetPin )
232 return;
233
234 Add( _( "Wire" ), ID_POPUP_SCH_PIN_TRICKS_WIRE, BITMAPS::add_line );
235 Add( _( "No Connect" ), ID_POPUP_SCH_PIN_TRICKS_NO_CONNECT, BITMAPS::noconn );
236 Add( _( "Net Label" ), ID_POPUP_SCH_PIN_TRICKS_NET_LABEL, BITMAPS::add_label );
237 Add( _( "Hierarchical Label" ), ID_POPUP_SCH_PIN_TRICKS_HIER_LABEL, BITMAPS::add_hierarchical_label );
238 Add( _( "Global Label" ), ID_POPUP_SCH_PIN_TRICKS_GLOBAL_LABEL, BITMAPS::add_glabel );
239 }
240};
241
242
244 EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.InteractiveEdit" )
245{
246 m_pickerItem = nullptr;
247}
248
249
251
253{
255
258
259 wxASSERT_MSG( drawingTools, "eeshema.InteractiveDrawing tool is not available" );
260
261 auto hasElements =
262 [this]( const SELECTION& aSel )
263 {
264 return !m_frame->GetScreen()->Items().empty();
265 };
266
267 auto sheetHasUndefinedPins =
268 []( const SELECTION& aSel )
269 {
270 if( aSel.Size() == 1 && aSel.Front()->Type() == SCH_SHEET_T )
271 return static_cast<SCH_SHEET*>( aSel.Front() )->HasUndefinedPins();
272
273 return false;
274 };
275
276 static const std::vector<KICAD_T> sheetTypes = { SCH_SHEET_T };
277
278 auto sheetSelection = E_C::Count( 1 ) && E_C::OnlyTypes( sheetTypes );
279
280 auto haveHighlight =
281 [&]( const SELECTION& sel )
282 {
283 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
284
285 return editFrame && !editFrame->GetHighlightedConnection().IsEmpty();
286 };
287
288 auto anyTextTool =
289 [this]( const SELECTION& aSel )
290 {
296 };
297
298 auto duplicateCondition =
299 []( const SELECTION& aSel )
300 {
302 return false;
303
304 return true;
305 };
306
307 auto orientCondition =
308 []( const SELECTION& aSel )
309 {
311 return false;
312
314 };
315
316 auto propertiesCondition =
317 [&]( const SELECTION& aSel )
318 {
319 if( aSel.GetSize() == 0 )
320 {
322 {
325
326 if( ds && ds->HitTestDrawingSheetItems( getView(), cursor ) )
327 return true;
328 }
329
330 return false;
331 }
332
333 SCH_ITEM* firstItem = dynamic_cast<SCH_ITEM*>( aSel.Front() );
334 const EE_SELECTION* eeSelection = dynamic_cast<const EE_SELECTION*>( &aSel );
335
336 if( !firstItem || !eeSelection )
337 return false;
338
339 switch( firstItem->Type() )
340 {
341 case SCH_SYMBOL_T:
342 case SCH_SHEET_T:
343 case SCH_SHEET_PIN_T:
344 case SCH_TEXT_T:
345 case SCH_TEXTBOX_T:
346 case SCH_TABLE_T:
347 case SCH_TABLECELL_T:
348 case SCH_LABEL_T:
350 case SCH_HIER_LABEL_T:
352 case SCH_RULE_AREA_T:
353 case SCH_FIELD_T:
354 case SCH_SHAPE_T:
355 case SCH_BITMAP_T:
356 return aSel.GetSize() == 1;
357
358 case SCH_LINE_T:
360 case SCH_JUNCTION_T:
361 if( std::all_of( aSel.Items().begin(), aSel.Items().end(),
362 [&]( const EDA_ITEM* item )
363 {
364 return item->Type() == SCH_LINE_T
365 && static_cast<const SCH_LINE*>( item )->IsGraphicLine();
366 } ) )
367 {
368 return true;
369 }
370 else if( std::all_of( aSel.Items().begin(), aSel.Items().end(),
371 [&]( const EDA_ITEM* item )
372 {
373 return item->Type() == SCH_JUNCTION_T;
374 } ) )
375 {
376 return true;
377 }
378 else if( std::all_of( aSel.Items().begin(), aSel.Items().end(),
379 [&]( const EDA_ITEM* item )
380 {
381 const SCH_ITEM* schItem = dynamic_cast<const SCH_ITEM*>( item );
382
383 wxCHECK( schItem, false );
384
385 return ( schItem->HasLineStroke() && schItem->IsConnectable() )
386 || item->Type() == SCH_JUNCTION_T;
387 } ) )
388 {
389 return true;
390 }
391
392 return false;
393
394 default:
395 return false;
396 }
397 };
398
399 auto autoplaceCondition =
400 []( const SELECTION& aSel )
401 {
402 for( const EDA_ITEM* item : aSel )
403 {
404 if( item->IsType( EE_COLLECTOR::FieldOwners ) )
405 return true;
406 }
407
408 return false;
409 };
410
411 // allTextTypes does not include SCH_SHEET_PIN_T because one cannot convert other
412 // types to/from this type, living only in a SHEET
413 static const std::vector<KICAD_T> allTextTypes = { SCH_LABEL_T,
419
420 auto toChangeCondition = ( E_C::OnlyTypes( allTextTypes ) );
421
422 static const std::vector<KICAD_T> toLabelTypes = { SCH_DIRECTIVE_LABEL_T,
427
428 auto toLabelCondition = ( E_C::Count( 1 ) && E_C::OnlyTypes( toLabelTypes ) )
429 || ( E_C::MoreThan( 1 ) && E_C::OnlyTypes( allTextTypes ) );
430
431 static const std::vector<KICAD_T> toCLabelTypes = { SCH_LABEL_T,
436
437 auto toCLabelCondition = ( E_C::Count( 1 ) && E_C::OnlyTypes( toCLabelTypes ) )
438 || ( E_C::MoreThan( 1 ) && E_C::OnlyTypes( allTextTypes ) );
439
440 static const std::vector<KICAD_T> toHLabelTypes = { SCH_LABEL_T,
445
446 auto toHLabelCondition = ( E_C::Count( 1 ) && E_C::OnlyTypes( toHLabelTypes ) )
447 || ( E_C::MoreThan( 1 ) && E_C::OnlyTypes( allTextTypes ) );
448
449 static const std::vector<KICAD_T> toGLabelTypes = { SCH_LABEL_T,
454
455 auto toGLabelCondition = ( E_C::Count( 1 ) && E_C::OnlyTypes( toGLabelTypes ) )
456 || ( E_C::MoreThan( 1 ) && E_C::OnlyTypes( allTextTypes ) );
457
458 static const std::vector<KICAD_T> toTextTypes = { SCH_LABEL_T,
463
464 auto toTextCondition = ( E_C::Count( 1 ) && E_C::OnlyTypes( toTextTypes ) )
465 || ( E_C::MoreThan( 1 ) && E_C::OnlyTypes( allTextTypes ) );
466
467 static const std::vector<KICAD_T> toTextBoxTypes = { SCH_LABEL_T,
471 SCH_TEXT_T };
472
473 auto toTextBoxCondition = ( E_C::Count( 1 ) && E_C::OnlyTypes( toTextBoxTypes ) )
474 || ( E_C::MoreThan( 1 ) && E_C::OnlyTypes( allTextTypes ) );
475
476 static const std::vector<KICAD_T> busEntryTypes = { SCH_BUS_WIRE_ENTRY_T, SCH_BUS_BUS_ENTRY_T};
477
478 auto entryCondition = E_C::MoreThan( 0 ) && E_C::OnlyTypes( busEntryTypes );
479
480 auto singleSheetCondition = E_C::Count( 1 ) && E_C::OnlyTypes( sheetTypes );
481
482 auto makeSymbolUnitMenu =
483 [&]( TOOL_INTERACTIVE* tool )
484 {
485 std::shared_ptr<SYMBOL_UNIT_MENU> menu = std::make_shared<SYMBOL_UNIT_MENU>();
486 menu->SetTool( tool );
487 tool->GetToolMenu().RegisterSubMenu( menu );
488 return menu.get();
489 };
490
491 auto makeBodyStyleMenu =
492 [&]( TOOL_INTERACTIVE* tool )
493 {
494 std::shared_ptr<BODY_STYLE_MENU> menu = std::make_shared<BODY_STYLE_MENU>();
495 menu->SetTool( tool );
496 tool->GetToolMenu().RegisterSubMenu( menu );
497 return menu.get();
498 };
499
500 auto makePinFunctionMenu =
501 [&]( TOOL_INTERACTIVE* tool )
502 {
503 std::shared_ptr<ALT_PIN_FUNCTION_MENU> menu = std::make_shared<ALT_PIN_FUNCTION_MENU>();
504 menu->SetTool( tool );
505 tool->GetToolMenu().RegisterSubMenu( menu );
506 return menu.get();
507 };
508
509 auto makePinTricksMenu =
510 [&]( TOOL_INTERACTIVE* tool )
511 {
512 std::shared_ptr<PIN_TRICKS_MENU> menu = std::make_shared<PIN_TRICKS_MENU>();
513 menu->SetTool( tool );
514 tool->GetToolMenu().RegisterSubMenu( menu );
515 return menu.get();
516 };
517
518 auto makeTransformMenu =
519 [&]()
520 {
521 CONDITIONAL_MENU* menu = new CONDITIONAL_MENU( moveTool );
522 menu->SetTitle( _( "Transform Selection" ) );
523
524 menu->AddItem( EE_ACTIONS::rotateCCW, orientCondition );
525 menu->AddItem( EE_ACTIONS::rotateCW, orientCondition );
526 menu->AddItem( EE_ACTIONS::mirrorV, orientCondition );
527 menu->AddItem( EE_ACTIONS::mirrorH, orientCondition );
528
529 return menu;
530 };
531
532 auto makeAttributesMenu =
533 [&]()
534 {
535 CONDITIONAL_MENU* menu = new CONDITIONAL_MENU( moveTool );
536 menu->SetTitle( _( "Attributes" ) );
537
541
542 menu->AddSeparator();
546
547 menu->AddSeparator();
551
552 menu->AddSeparator();
556
557 return menu;
558 };
559
560 auto makeEditFieldsMenu =
561 [&]()
562 {
564 menu->SetTitle( _( "Edit Main Fields" ) );
565
569
570 return menu;
571 };
572
573 auto makeConvertToMenu =
574 [&]()
575 {
577 menu->SetTitle( _( "Change To" ) );
578 menu->SetIcon( BITMAPS::right );
579
580 menu->AddItem( EE_ACTIONS::toLabel, toLabelCondition );
581 menu->AddItem( EE_ACTIONS::toCLabel, toCLabelCondition );
582 menu->AddItem( EE_ACTIONS::toHLabel, toHLabelCondition );
583 menu->AddItem( EE_ACTIONS::toGLabel, toGLabelCondition );
584 menu->AddItem( EE_ACTIONS::toText, toTextCondition );
585 menu->AddItem( EE_ACTIONS::toTextBox, toTextBoxCondition );
586
587 return menu;
588 };
589
590 //
591 // Add edit actions to the move tool menu
592 //
593 CONDITIONAL_MENU& moveMenu = moveTool->GetToolMenu().GetMenu();
594
595 moveMenu.AddSeparator();
596 moveMenu.AddMenu( makeSymbolUnitMenu( moveTool ), E_C::SingleMultiUnitSymbol, 1 );
597 moveMenu.AddMenu( makeBodyStyleMenu( moveTool ), E_C::SingleDeMorganSymbol, 1 );
598
599 moveMenu.AddMenu( makeTransformMenu(), orientCondition, 200 );
600 moveMenu.AddMenu( makeAttributesMenu(), E_C::HasType( SCH_SYMBOL_T ), 200 );
602 moveMenu.AddItem( EE_ACTIONS::properties, propertiesCondition, 200 );
603 moveMenu.AddMenu( makeEditFieldsMenu(), E_C::SingleSymbol, 200 );
604
605 moveMenu.AddSeparator();
609 moveMenu.AddItem( ACTIONS::duplicate, duplicateCondition );
610
611 //
612 // Add editing actions to the drawing tool menu
613 //
614 CONDITIONAL_MENU& drawMenu = drawingTools->GetToolMenu().GetMenu();
615
616 drawMenu.AddItem( EE_ACTIONS::clearHighlight, haveHighlight && EE_CONDITIONS::Idle, 1 );
617 drawMenu.AddSeparator( haveHighlight && EE_CONDITIONS::Idle, 1 );
618
619 drawMenu.AddItem( EE_ACTIONS::enterSheet, sheetSelection && EE_CONDITIONS::Idle, 1 );
620 drawMenu.AddSeparator( sheetSelection && EE_CONDITIONS::Idle, 1 );
621
622 drawMenu.AddMenu( makeSymbolUnitMenu( drawingTools ), E_C::SingleMultiUnitSymbol, 1 );
623 drawMenu.AddMenu( makeBodyStyleMenu( drawingTools ), E_C::SingleDeMorganSymbol, 1 );
624
625 drawMenu.AddMenu( makeTransformMenu(), orientCondition, 200 );
626 drawMenu.AddMenu( makeAttributesMenu(), E_C::HasType( SCH_SYMBOL_T ), 200 );
627 drawMenu.AddItem( EE_ACTIONS::properties, propertiesCondition, 200 );
628 drawMenu.AddMenu( makeEditFieldsMenu(), E_C::SingleSymbol, 200 );
629 drawMenu.AddItem( EE_ACTIONS::autoplaceFields, autoplaceCondition, 200 );
630
632
633 drawMenu.AddItem( EE_ACTIONS::toLabel, anyTextTool && E_C::Idle, 200 );
634 drawMenu.AddItem( EE_ACTIONS::toHLabel, anyTextTool && E_C::Idle, 200 );
635 drawMenu.AddItem( EE_ACTIONS::toGLabel, anyTextTool && E_C::Idle, 200 );
636 drawMenu.AddItem( EE_ACTIONS::toText, anyTextTool && E_C::Idle, 200 );
637 drawMenu.AddItem( EE_ACTIONS::toTextBox, anyTextTool && E_C::Idle, 200 );
638
639 //
640 // Add editing actions to the selection tool menu
641 //
643
644 selToolMenu.AddMenu( makeSymbolUnitMenu( m_selectionTool ), E_C::SingleMultiUnitSymbol, 1 );
645 selToolMenu.AddMenu( makeBodyStyleMenu( m_selectionTool ), E_C::SingleDeMorganSymbol, 1 );
646 selToolMenu.AddMenu( makePinFunctionMenu( m_selectionTool ), E_C::SingleMultiFunctionPin, 1 );
647 selToolMenu.AddMenu( makePinTricksMenu( m_selectionTool ), E_C::AllPinsOrSheetPins, 1 );
648
649 selToolMenu.AddMenu( makeTransformMenu(), orientCondition, 200 );
650 selToolMenu.AddMenu( makeAttributesMenu(), E_C::HasType( SCH_SYMBOL_T ), 200 );
652 selToolMenu.AddItem( EE_ACTIONS::properties, propertiesCondition, 200 );
653 selToolMenu.AddMenu( makeEditFieldsMenu(), E_C::SingleSymbol, 200 );
654 selToolMenu.AddItem( EE_ACTIONS::autoplaceFields, autoplaceCondition, 200 );
655
661 selToolMenu.AddMenu( makeConvertToMenu(), toChangeCondition, 200 );
662
663 selToolMenu.AddItem( EE_ACTIONS::cleanupSheetPins, sheetHasUndefinedPins, 250 );
664
665 selToolMenu.AddSeparator( 300 );
666 selToolMenu.AddItem( ACTIONS::cut, E_C::IdleSelection, 300 );
667 selToolMenu.AddItem( ACTIONS::copy, E_C::IdleSelection, 300 );
668 selToolMenu.AddItem( ACTIONS::paste, E_C::Idle, 300 );
669 selToolMenu.AddItem( ACTIONS::pasteSpecial, E_C::Idle, 300 );
670 selToolMenu.AddItem( ACTIONS::doDelete, E_C::NotEmpty, 300 );
671 selToolMenu.AddItem( ACTIONS::duplicate, duplicateCondition, 300 );
672
673 selToolMenu.AddSeparator( 400 );
674 selToolMenu.AddItem( ACTIONS::selectAll, hasElements, 400 );
675 selToolMenu.AddItem( ACTIONS::unselectAll, hasElements, 400 );
676
677 return true;
678}
679
680
681const std::vector<KICAD_T> SCH_EDIT_TOOL::RotatableItems = {
687 SCH_TABLECELL_T, // will be promoted to parent table(s)
702};
703
704
706{
707 bool clockwise = ( aEvent.Matches( EE_ACTIONS::rotateCW.MakeEvent() ) );
709
710 if( selection.GetSize() == 0 )
711 return 0;
712
713 SCH_ITEM* head = nullptr;
714 int principalItemCount = 0; // User-selected items (as opposed to connected wires)
715 VECTOR2I rotPoint;
716 bool moving = false;
717 SCH_COMMIT localCommit( m_toolMgr );
718 SCH_COMMIT* commit = dynamic_cast<SCH_COMMIT*>( aEvent.Commit() );
719
720 if( !commit )
721 commit = &localCommit;
722
723 for( unsigned ii = 0; ii < selection.GetSize(); ii++ )
724 {
725 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.GetItem( ii ) );
726
727 if( item->HasFlag( SELECTED_BY_DRAG ) )
728 continue;
729
730 principalItemCount++;
731
732 if( !head )
733 head = item;
734 }
735
736 if( head && head->IsMoving() )
737 moving = true;
738
739 if( principalItemCount == 1 )
740 {
741 if( moving && selection.HasReferencePoint() )
742 rotPoint = selection.GetReferencePoint();
743 else if( head->IsConnectable() )
744 rotPoint = head->GetPosition();
745 else
747
748 if( !moving )
749 commit->Modify( head, m_frame->GetScreen() );
750
751 switch( head->Type() )
752 {
753 case SCH_SYMBOL_T:
754 {
755 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( head );
756
757 symbol->Rotate( rotPoint, !clockwise );
758
761
762 break;
763 }
764
765 case SCH_TEXT_T:
766 case SCH_LABEL_T:
768 case SCH_HIER_LABEL_T:
770 {
771 SCH_TEXT* textItem = static_cast<SCH_TEXT*>( head );
772 textItem->Rotate90( clockwise );
773 break;
774 }
775
776 case SCH_SHEET_PIN_T:
777 {
778 // Rotate pin within parent sheet
779 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( head );
780 SCH_SHEET* sheet = pin->GetParent();
781
782 pin->Rotate( sheet->GetBoundingBox().GetCenter(), !clockwise );
783
784 break;
785 }
786
787 case SCH_LINE_T:
788 {
789 SCH_LINE* line = static_cast<SCH_LINE*>( head );
790
791 // Equal checks for both and neither. We need this because on undo
792 // the item will have both flags cleared, but will be selected, so it is possible
793 // for the user to get a selected line with neither endpoint selected. We
794 // set flags to make sure Rotate() works when we call it.
795 if( line->HasFlag( STARTPOINT ) == line->HasFlag( ENDPOINT ) )
796 {
797 line->SetFlags( STARTPOINT | ENDPOINT );
798
799 // When we allow off grid items, the rotPoint should be set to the midpoint
800 // of the line to allow rotation around the center, and the next if
801 // should become an else-if
802 }
803
804 if( line->HasFlag( STARTPOINT ) )
805 rotPoint = line->GetEndPoint();
806 else if( line->HasFlag( ENDPOINT ) )
807 rotPoint = line->GetStartPoint();
808 }
809
811 case SCH_JUNCTION_T:
812 case SCH_NO_CONNECT_T:
815 head->Rotate( rotPoint, !clockwise );
816
817 break;
818
819 case SCH_FIELD_T:
820 {
821 SCH_FIELD* field = static_cast<SCH_FIELD*>( head );
822
823 if( field->GetTextAngle().IsHorizontal() )
825 else
827
828 // Now that we're moving a field, they're no longer autoplaced.
829 static_cast<SCH_ITEM*>( head->GetParent() )->ClearFieldsAutoplaced();
830
831 break;
832 }
833
834 case SCH_RULE_AREA_T:
835 case SCH_SHAPE_T:
836 case SCH_TEXTBOX_T:
837 head->Rotate( rotPoint, !clockwise );
838
839 break;
840
841 case SCH_TABLE_T:
842 {
843 // Rotate the table on itself. Tables do not have an anchor point.
844 SCH_TABLE* table = static_cast<SCH_TABLE*>( head );
845 BOX2I box( table->GetPosition(), table->GetEnd() - table->GetPosition() );
846 rotPoint = m_frame->GetNearestHalfGridPosition( box.GetCenter() );
847
848 head->Rotate( rotPoint, !clockwise );
849
850 break;
851 }
852
853 case SCH_BITMAP_T:
854 head->Rotate( rotPoint, !clockwise );
855
856 // The bitmap is cached in Opengl: clear the cache to redraw
858 break;
859
860 case SCH_SHEET_T:
861 {
862 // Rotate the sheet on itself. Sheets do not have an anchor point.
863 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( head );
864
866 sheet->Rotate( rotPoint, !clockwise );
867
868 break;
869 }
870
871 default:
872 UNIMPLEMENTED_FOR( head->GetClass() );
873 }
874
875 m_frame->UpdateItem( head, false, true );
876 }
877 else
878 {
879 if( moving && selection.HasReferencePoint() )
880 rotPoint = selection.GetReferencePoint();
881 else
882 rotPoint = m_frame->GetNearestHalfGridPosition( selection.GetCenter() );
883 }
884
885 for( EDA_ITEM* edaItem : selection )
886 {
887 SCH_ITEM* item = static_cast<SCH_ITEM*>( edaItem );
888
889 // We've already rotated the user selected item if there was only one. We're just
890 // here to rotate the ends of wires that were attached to it.
891 if( principalItemCount == 1 && !item->HasFlag( SELECTED_BY_DRAG ) )
892 continue;
893
894 if( !moving )
895 commit->Modify( item, m_frame->GetScreen() );
896
897 if( item->Type() == SCH_LINE_T )
898 {
899 SCH_LINE* line = (SCH_LINE*) item;
900
901 line->Rotate( rotPoint, !clockwise );
902 }
903 else if( item->Type() == SCH_SHEET_PIN_T )
904 {
905 if( item->GetParent()->IsSelected() )
906 {
907 // parent will rotate us
908 }
909 else
910 {
911 // rotate within parent
912 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( item );
913 SCH_SHEET* sheet = pin->GetParent();
914
915 pin->Rotate( sheet->GetBodyBoundingBox().GetCenter(), !clockwise );
916 }
917 }
918 else if( item->Type() == SCH_FIELD_T )
919 {
920 if( item->GetParent()->IsSelected() )
921 {
922 // parent will rotate us
923 }
924 else
925 {
926 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
927
928 field->Rotate( rotPoint, !clockwise );
929
930 if( field->GetTextAngle().IsHorizontal() )
932 else
934
935 // Now that we're moving a field, they're no longer autoplaced.
936 static_cast<SCH_ITEM*>( field->GetParent() )->ClearFieldsAutoplaced();
937 }
938 }
939 else
940 {
941 item->Rotate( rotPoint, !clockwise );
942 }
943
944 m_frame->UpdateItem( item, false, true );
945 updateItem( item, true );
946 }
947
948 if( moving )
949 {
951 }
952 else
953 {
954 EE_SELECTION selectionCopy = selection;
955
956 if( selection.IsHover() )
958
960 lwbTool->TrimOverLappingWires( commit, &selectionCopy );
961 lwbTool->AddJunctionsIfNeeded( commit, &selectionCopy );
962
963 m_frame->SchematicCleanUp( commit );
964
965 if( !localCommit.Empty() )
966 localCommit.Push( _( "Rotate" ) );
967 }
968
969 return 0;
970}
971
972
974{
976
977 if( selection.GetSize() == 0 )
978 return 0;
979
980 bool vertical = ( aEvent.Matches( EE_ACTIONS::mirrorV.MakeEvent() ) );
981 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.Front() );
982 bool connections = false;
983 bool moving = item->IsMoving();
984 SCH_COMMIT localCommit( m_toolMgr );
985 SCH_COMMIT* commit = dynamic_cast<SCH_COMMIT*>( aEvent.Commit() );
986
987 if( !commit )
988 commit = &localCommit;
989
990 if( selection.GetSize() == 1 )
991 {
992 if( !moving )
993 commit->Modify( item, m_frame->GetScreen() );
994
995 switch( item->Type() )
996 {
997 case SCH_SYMBOL_T:
998 {
999 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1000
1001 if( vertical )
1002 symbol->SetOrientation( SYM_MIRROR_X );
1003 else
1004 symbol->SetOrientation( SYM_MIRROR_Y );
1005
1006 symbol->ClearFieldsAutoplaced();
1007 break;
1008 }
1009
1010 case SCH_TEXT_T:
1011 case SCH_LABEL_T:
1012 case SCH_GLOBAL_LABEL_T:
1013 case SCH_HIER_LABEL_T:
1015 {
1016 SCH_TEXT* textItem = static_cast<SCH_TEXT*>( item );
1017 textItem->MirrorSpinStyle( !vertical );
1018 break;
1019 }
1020
1021 case SCH_SHEET_PIN_T:
1022 {
1023 // mirror within parent sheet
1024 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( item );
1025 SCH_SHEET* sheet = pin->GetParent();
1026
1027 if( vertical )
1028 pin->MirrorVertically( sheet->GetBoundingBox().GetCenter().y );
1029 else
1030 pin->MirrorHorizontally( sheet->GetBoundingBox().GetCenter().x );
1031
1032 break;
1033 }
1034
1035 case SCH_FIELD_T:
1036 {
1037 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
1038
1039 if( vertical )
1040 field->SetVertJustify( TO_VJUSTIFY( -field->GetVertJustify() ) );
1041 else
1042 field->SetHorizJustify( TO_HJUSTIFY( -field->GetHorizJustify() ) );
1043
1044 // Now that we're re-justifying a field, they're no longer autoplaced.
1045 static_cast<SCH_ITEM*>( field->GetParent() )->ClearFieldsAutoplaced();
1046
1047 break;
1048 }
1049
1050 case SCH_BITMAP_T:
1051 if( vertical )
1052 item->MirrorVertically( item->GetPosition().y );
1053 else
1054 item->MirrorHorizontally( item->GetPosition().x );
1055
1056 // The bitmap is cached in Opengl: clear the cache to redraw
1058 break;
1059
1060 case SCH_SHEET_T:
1061 {
1062 // Mirror the sheet on itself. Sheets do not have a anchor point.
1064
1065 if( vertical )
1066 item->MirrorVertically( mirrorPoint.y );
1067 else
1068 item->MirrorHorizontally( mirrorPoint.x );
1069
1070 break;
1071 }
1072
1073 default:
1074 if( vertical )
1075 item->MirrorVertically( item->GetPosition().y );
1076 else
1077 item->MirrorHorizontally( item->GetPosition().x );
1078
1079 break;
1080 }
1081
1082 connections = item->IsConnectable();
1083 m_frame->UpdateItem( item, false, true );
1084 }
1085 else if( selection.GetSize() > 1 )
1086 {
1087 VECTOR2I mirrorPoint = m_frame->GetNearestHalfGridPosition( selection.GetCenter() );
1088
1089 for( EDA_ITEM* edaItem : selection )
1090 {
1091 item = static_cast<SCH_ITEM*>( edaItem );
1092
1093 if( !moving )
1094 commit->Modify( item, m_frame->GetScreen() );
1095
1096 if( item->Type() == SCH_SHEET_PIN_T )
1097 {
1098 if( item->GetParent()->IsSelected() )
1099 {
1100 // parent will mirror us
1101 }
1102 else
1103 {
1104 // mirror within parent sheet
1105 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( item );
1106 SCH_SHEET* sheet = pin->GetParent();
1107
1108 if( vertical )
1109 pin->MirrorVertically( sheet->GetBoundingBox().GetCenter().y );
1110 else
1111 pin->MirrorHorizontally( sheet->GetBoundingBox().GetCenter().x );
1112 }
1113 }
1114 else if( item->Type() == SCH_FIELD_T )
1115 {
1116 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
1117
1118 if( vertical )
1119 field->SetVertJustify( TO_VJUSTIFY( -field->GetVertJustify() ) );
1120 else
1121 field->SetHorizJustify( TO_HJUSTIFY( -field->GetHorizJustify() ) );
1122
1123 // Now that we're re-justifying a field, they're no longer autoplaced.
1124 static_cast<SCH_ITEM*>( field->GetParent() )->ClearFieldsAutoplaced();
1125 }
1126 else
1127 {
1128 if( vertical )
1129 item->MirrorVertically( mirrorPoint.y );
1130 else
1131 item->MirrorHorizontally( mirrorPoint.x );
1132 }
1133
1134 connections |= item->IsConnectable();
1135 m_frame->UpdateItem( item, false, true );
1136 }
1137 }
1138
1139 // Update R-Tree for modified items
1140 for( EDA_ITEM* selected : selection )
1141 updateItem( selected, true );
1142
1143 if( item->IsMoving() )
1144 {
1146 }
1147 else
1148 {
1149 EE_SELECTION selectionCopy = selection;
1150
1151 if( selection.IsHover() )
1153
1154 if( connections )
1155 {
1157 lwbTool->TrimOverLappingWires( commit, &selectionCopy );
1158 lwbTool->AddJunctionsIfNeeded( commit, &selectionCopy );
1159
1160 m_frame->SchematicCleanUp( commit );
1161 }
1162
1163 if( !localCommit.Empty() )
1164 localCommit.Push( _( "Mirror" ) );
1165 }
1166
1167 return 0;
1168}
1169
1170
1171const std::vector<KICAD_T> swappableItems = {
1174 SCH_TEXT_T,
1187};
1188
1189
1200static void swapFieldPositionsWithMatching( std::vector<SCH_FIELD>& aAFields,
1201 std::vector<SCH_FIELD>& aBFields,
1202 unsigned aFallbackRotationsCCW )
1203{
1204 std::set<wxString> handledKeys;
1205
1206 const auto swapFieldTextProps = []( SCH_FIELD& aField, SCH_FIELD& bField )
1207 {
1208 const VECTOR2I aRelPos = aField.GetPosition() - aField.GetParentPosition();
1209 const GR_TEXT_H_ALIGN_T aTextJustifyH = aField.GetHorizJustify();
1210 const GR_TEXT_V_ALIGN_T aTextJustifyV = aField.GetVertJustify();
1211 const EDA_ANGLE aTextAngle = aField.GetTextAngle();
1212
1213 const VECTOR2I bRelPos = bField.GetPosition() - bField.GetParentPosition();
1214 const GR_TEXT_H_ALIGN_T bTextJustifyH = bField.GetHorizJustify();
1215 const GR_TEXT_V_ALIGN_T bTextJustifyV = bField.GetVertJustify();
1216 const EDA_ANGLE bTextAngle = bField.GetTextAngle();
1217
1218 aField.SetPosition( aField.GetParentPosition() + bRelPos );
1219 aField.SetHorizJustify( bTextJustifyH );
1220 aField.SetVertJustify( bTextJustifyV );
1221 aField.SetTextAngle( bTextAngle );
1222
1223 bField.SetPosition( bField.GetParentPosition() + aRelPos );
1224 bField.SetHorizJustify( aTextJustifyH );
1225 bField.SetVertJustify( aTextJustifyV );
1226 bField.SetTextAngle( aTextAngle );
1227 };
1228
1229 for( SCH_FIELD& aField : aAFields )
1230 {
1231 const wxString name = aField.GetCanonicalName();
1232
1233 auto it = std::find_if( aBFields.begin(), aBFields.end(),
1234 [name]( const SCH_FIELD& bField )
1235 {
1236 return bField.GetCanonicalName() == name;
1237 } );
1238
1239 if( it != aBFields.end() )
1240 {
1241 // We have a field with the same key in both labels
1242 SCH_FIELD& bField = *it;
1243 swapFieldTextProps( aField, bField );
1244 }
1245 else
1246 {
1247 // We only have this field in A, so just rotate it
1248 for( unsigned ii = 0; ii < aFallbackRotationsCCW; ii++ )
1249 {
1250 aField.Rotate( aField.GetParentPosition(), true );
1251 }
1252 }
1253
1254 // And keep track that we did this one
1255 handledKeys.insert( name );
1256 }
1257
1258 // Any fields in B that weren't in A weren't handled and need to be rotated
1259 // in reverse
1260 for( SCH_FIELD& bField : aBFields )
1261 {
1262 const wxString bName = bField.GetCanonicalName();
1263 if( handledKeys.find( bName ) == handledKeys.end() )
1264 {
1265 for( unsigned ii = 0; ii < aFallbackRotationsCCW; ii++ )
1266 {
1267 bField.Rotate( bField.GetParentPosition(), false );
1268 }
1269 }
1270 }
1271}
1272
1273
1275{
1277 std::vector<EDA_ITEM*> sorted = selection.GetItemsSortedBySelectionOrder();
1278
1279 // Sheet pins are special, we need to make sure if we have any sheet pins,
1280 // that we only have sheet pins, and that they have the same parent
1281 if( selection.CountType( SCH_SHEET_PIN_T ) > 0 )
1282 {
1283 if( !selection.OnlyContains( { SCH_SHEET_PIN_T } ) )
1284 return 0;
1285
1286 SCH_SHEET_PIN* firstPin = static_cast<SCH_SHEET_PIN*>( selection.Front() );
1287 SCH_SHEET* parent = firstPin->GetParent();
1288
1289 for( EDA_ITEM* item : selection )
1290 {
1291 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( item );
1292
1293 if( pin->GetParent() != parent )
1294 return 0;
1295 }
1296 }
1297
1298 if( selection.Size() < 2 )
1299 return 0;
1300
1301 bool isMoving = selection.Front()->IsMoving();
1302 bool appendUndo = isMoving;
1303 bool connections = false;
1304
1305 for( size_t i = 0; i < sorted.size() - 1; i++ )
1306 {
1307 SCH_ITEM* a = static_cast<SCH_ITEM*>( sorted[i] );
1308 SCH_ITEM* b = static_cast<SCH_ITEM*>( sorted[( i + 1 ) % sorted.size()] );
1309
1310 VECTOR2I aPos = a->GetPosition(), bPos = b->GetPosition();
1311 std::swap( aPos, bPos );
1312
1313 saveCopyInUndoList( a, UNDO_REDO::CHANGED, appendUndo );
1314 appendUndo = true;
1315 saveCopyInUndoList( b, UNDO_REDO::CHANGED, appendUndo );
1316
1317 // Sheet pins need to have their sides swapped before we change their
1318 // positions
1319 if( a->Type() == SCH_SHEET_PIN_T )
1320 {
1321 SCH_SHEET_PIN* aPin = static_cast<SCH_SHEET_PIN*>( a );
1322 SCH_SHEET_PIN* bPin = static_cast<SCH_SHEET_PIN*>( b );
1323 SHEET_SIDE aSide = aPin->GetSide(), bSide = bPin->GetSide();
1324 std::swap( aSide, bSide );
1325 aPin->SetSide( aSide );
1326 bPin->SetSide( bSide );
1327 }
1328
1329 a->SetPosition( aPos );
1330 b->SetPosition( bPos );
1331
1332 if( a->Type() == b->Type() )
1333 {
1334 switch( a->Type() )
1335 {
1336 case SCH_LABEL_T:
1337 case SCH_GLOBAL_LABEL_T:
1338 case SCH_HIER_LABEL_T:
1340 {
1341 SCH_LABEL_BASE& aLabelBase = static_cast<SCH_LABEL_BASE&>( *a );
1342 SCH_LABEL_BASE& bLabelBase = static_cast<SCH_LABEL_BASE&>( *b );
1343
1344 const SPIN_STYLE aSpinStyle = aLabelBase.GetSpinStyle();
1345 const SPIN_STYLE bSpinStyle = bLabelBase.GetSpinStyle();
1346
1347 // First, swap the label orientations
1348 aLabelBase.SetSpinStyle( bSpinStyle );
1349 bLabelBase.SetSpinStyle( aSpinStyle );
1350
1351 // And swap the fields as best we can
1352 std::vector<SCH_FIELD>& aFields = aLabelBase.GetFields();
1353 std::vector<SCH_FIELD>& bFields = bLabelBase.GetFields();
1354
1355 const unsigned rotationsAtoB = aSpinStyle.CCWRotationsTo( bSpinStyle );
1356
1357 swapFieldPositionsWithMatching( aFields, bFields, rotationsAtoB );
1358 break;
1359 }
1360 case SCH_SYMBOL_T:
1361 {
1362 SCH_SYMBOL* aSymbol = static_cast<SCH_SYMBOL*>( a );
1363 SCH_SYMBOL* bSymbol = static_cast<SCH_SYMBOL*>( b );
1364 int aOrient = aSymbol->GetOrientation(), bOrient = bSymbol->GetOrientation();
1365 std::swap( aOrient, bOrient );
1366 aSymbol->SetOrientation( aOrient );
1367 bSymbol->SetOrientation( bOrient );
1368 break;
1369 }
1370 default: break;
1371 }
1372 }
1373
1374 connections |= a->IsConnectable();
1375 connections |= b->IsConnectable();
1376 m_frame->UpdateItem( a, false, true );
1377 m_frame->UpdateItem( b, false, true );
1378 }
1379
1380 // Update R-Tree for modified items
1381 for( EDA_ITEM* selected : selection )
1382 updateItem( selected, true );
1383
1384 if( isMoving )
1385 {
1387 }
1388 else
1389 {
1390 if( selection.IsHover() )
1392
1393 if( connections )
1395
1396 m_frame->OnModify();
1397 }
1398
1399 return 0;
1400}
1401
1402
1404{
1405 const std::vector<std::unique_ptr<SCH_ITEM>>& sourceItems = m_frame->GetRepeatItems();
1406
1407 if( sourceItems.empty() )
1408 return 0;
1409
1411
1412 SCH_COMMIT commit( m_toolMgr );
1413 EE_SELECTION newItems;
1414
1415 for( const std::unique_ptr<SCH_ITEM>& item : sourceItems )
1416 {
1417 SCH_ITEM* newItem = item->Duplicate();
1419 bool restore_state = false;
1420
1421 if( SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( newItem ) )
1422 {
1423 // If incrementing tries to go below zero, tell user why the value is repeated
1424
1425 if( !label->IncrementLabel( cfg->m_Drawing.repeat_label_increment ) )
1426 m_frame->ShowInfoBarWarning( _( "Label value cannot go below zero" ), true );
1427 }
1428
1429 // If cloning a symbol then put into 'move' mode.
1430 if( newItem->Type() == SCH_SYMBOL_T )
1431 {
1432 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( true );
1433 newItem->Move( cursorPos - newItem->GetPosition() );
1434 }
1435 else
1436 {
1439 }
1440
1441 // If cloning a sheet, check that we aren't going to create recursion
1442 if( newItem->Type() == SCH_SHEET_T )
1443 {
1444 SCH_SHEET_PATH* currentSheet = &m_frame->GetCurrentSheet();
1445 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( newItem );
1446
1447 if( m_frame->CheckSheetForRecursion( sheet, currentSheet ) )
1448 {
1449 // Clear out the filename so that the user can pick a new one
1450 const wxString originalFileName = sheet->GetFileName();
1451 const wxString originalScreenFileName = sheet->GetScreen()->GetFileName();
1452
1453 sheet->SetFileName( wxEmptyString );
1454 sheet->GetScreen()->SetFileName( wxEmptyString );
1455 restore_state = !m_frame->EditSheetProperties( sheet, currentSheet );
1456
1457 if( restore_state )
1458 {
1459 sheet->SetFileName( originalFileName );
1460 sheet->GetScreen()->SetFileName( originalScreenFileName );
1461 }
1462 }
1463 }
1464
1466 newItem->SetFlags( IS_NEW );
1467 m_frame->AddToScreen( newItem, m_frame->GetScreen() );
1468 commit.Added( newItem, m_frame->GetScreen() );
1469
1470 if( newItem->Type() == SCH_SYMBOL_T )
1471 {
1473 SCHEMATIC_SETTINGS& projSettings = m_frame->Schematic().Settings();
1474 int annotateStartNum = projSettings.m_AnnotateStartNum;
1475
1476 if( annotate.automatic )
1477 {
1478 static_cast<SCH_SYMBOL*>( newItem )->ClearAnnotation( nullptr, false );
1479 NULL_REPORTER reporter;
1481 (ANNOTATE_ORDER_T) annotate.sort_order,
1482 (ANNOTATE_ALGO_T) annotate.method, true /* recursive */,
1483 annotateStartNum, false, false, reporter );
1484 }
1485
1486 restore_state = !m_toolMgr->RunSynchronousAction( EE_ACTIONS::move, &commit );
1487 }
1488
1489 if( restore_state )
1490 {
1491 commit.Revert();
1492 }
1493 else
1494 {
1495 newItems.Add( newItem );
1496
1498 lwbTool->TrimOverLappingWires( &commit, &newItems );
1499 lwbTool->AddJunctionsIfNeeded( &commit, &newItems );
1500
1501 m_frame->SchematicCleanUp( &commit );
1502 commit.Push( _( "Repeat Item" ) );
1503 }
1504
1505 }
1506
1507 if( !newItems.Empty() )
1508 m_frame->SaveCopyForRepeatItem( static_cast<SCH_ITEM*>( newItems[0] ) );
1509
1510 for( size_t ii = 1; ii < newItems.GetSize(); ++ii )
1511 m_frame->AddCopyForRepeatItem( static_cast<SCH_ITEM*>( newItems[ii] ) );
1512
1513 return 0;
1514}
1515
1516
1517static std::vector<KICAD_T> deletableItems =
1518{
1521 SCH_LINE_T,
1526 SCH_TEXT_T,
1528 SCH_TABLECELL_T, // Clear contents
1538 SCH_FIELD_T, // Will be hidden
1540};
1541
1542
1544{
1545 SCH_SCREEN* screen = m_frame->GetScreen();
1546 std::deque<EDA_ITEM*> items = m_selectionTool->RequestSelection( deletableItems ).GetItems();
1547 SCH_COMMIT commit( m_toolMgr );
1548 std::vector<VECTOR2I> pts;
1549 bool updateHierarchy = false;
1550
1551 if( items.empty() )
1552 return 0;
1553
1554 // Don't leave a freed pointer in the selection
1556
1557 for( EDA_ITEM* item : items )
1558 item->ClearFlags( STRUCT_DELETED );
1559
1560 for( EDA_ITEM* item : items )
1561 {
1562 SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( item );
1563
1564 if( !sch_item )
1565 continue;
1566
1567 if( sch_item->IsConnectable() )
1568 {
1569 std::vector<VECTOR2I> tmp_pts = sch_item->GetConnectionPoints();
1570 pts.insert( pts.end(), tmp_pts.begin(), tmp_pts.end() );
1571 }
1572
1573 if( sch_item->Type() == SCH_JUNCTION_T )
1574 {
1575 sch_item->SetFlags( STRUCT_DELETED );
1576 // clean up junctions at the end
1577 }
1578 else if( sch_item->Type() == SCH_SHEET_PIN_T )
1579 {
1580 SCH_SHEET_PIN* pin = (SCH_SHEET_PIN*) sch_item;
1581 SCH_SHEET* sheet = pin->GetParent();
1582
1583 if( !alg::contains( items, sheet ) )
1584 {
1585 commit.Modify( sheet, m_frame->GetScreen() );
1586 sheet->RemovePin( pin );
1587 }
1588 }
1589 else if( sch_item->Type() == SCH_FIELD_T )
1590 {
1591 // Hide field
1592 commit.Modify( item, m_frame->GetScreen() );
1593 static_cast<SCH_FIELD*>( sch_item )->SetVisible( false );
1594 }
1595 else if( sch_item->Type() == SCH_TABLECELL_T )
1596 {
1597 // Clear contents of table cell
1598 commit.Modify( item, m_frame->GetScreen() );
1599 static_cast<SCH_TABLECELL*>( sch_item )->SetText( wxEmptyString );
1600 }
1601 else if( sch_item->Type() == SCH_RULE_AREA_T )
1602 {
1603 sch_item->SetFlags( STRUCT_DELETED );
1604 commit.Remove( item, m_frame->GetScreen() );
1605 }
1606 else
1607 {
1608 sch_item->SetFlags( STRUCT_DELETED );
1609 commit.Remove( item, m_frame->GetScreen() );
1610 updateHierarchy |= ( sch_item->Type() == SCH_SHEET_T );
1611 }
1612 }
1613
1614 for( const VECTOR2I& point : pts )
1615 {
1616 SCH_ITEM* junction = screen->GetItem( point, 0, SCH_JUNCTION_T );
1617
1618 if( !junction )
1619 continue;
1620
1621 if( junction->HasFlag( STRUCT_DELETED ) || !screen->IsExplicitJunction( point ) )
1622 m_frame->DeleteJunction( &commit, junction );
1623 }
1624
1625 commit.Push( _( "Delete" ) );
1626
1627 if( updateHierarchy )
1629
1630 return 0;
1631}
1632
1633
1634#define HITTEST_THRESHOLD_PIXELS 5
1635
1636
1638{
1640
1642 m_pickerItem = nullptr;
1643
1644 // Deactivate other tools; particularly important if another PICKER is currently running
1645 Activate();
1646
1647 picker->SetCursor( KICURSOR::REMOVE );
1648 picker->SetSnapping( false );
1649
1650 picker->SetClickHandler(
1651 [this]( const VECTOR2D& aPosition ) -> bool
1652 {
1653 if( m_pickerItem )
1654 {
1656 selectionTool->UnbrightenItem( m_pickerItem );
1657 selectionTool->AddItemToSel( m_pickerItem, true /*quiet mode*/ );
1659 m_pickerItem = nullptr;
1660 }
1661
1662 return true;
1663 } );
1664
1665 picker->SetMotionHandler(
1666 [this]( const VECTOR2D& aPos )
1667 {
1668 EE_COLLECTOR collector;
1669 collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
1670 collector.Collect( m_frame->GetScreen(), deletableItems, aPos );
1671
1673 selectionTool->GuessSelectionCandidates( collector, aPos );
1674
1675 EDA_ITEM* item = collector.GetCount() == 1 ? collector[ 0 ] : nullptr;
1676
1677 if( m_pickerItem != item )
1678 {
1679 if( m_pickerItem )
1680 selectionTool->UnbrightenItem( m_pickerItem );
1681
1682 m_pickerItem = item;
1683
1684 if( m_pickerItem )
1685 selectionTool->BrightenItem( m_pickerItem );
1686 }
1687 } );
1688
1689 picker->SetFinalizeHandler(
1690 [this]( const int& aFinalState )
1691 {
1692 if( m_pickerItem )
1693 m_toolMgr->GetTool<EE_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
1694
1695 // Wake the selection tool after exiting to ensure the cursor gets updated
1697 } );
1698
1700
1701 return 0;
1702}
1703
1704
1706{
1707 KICAD_T parentType = aField->GetParent() ? aField->GetParent()->Type() : SCHEMATIC_T;
1708 SCH_COMMIT commit( m_toolMgr );
1709
1710 // Save old symbol in undo list if not already in edit, or moving.
1711 if( aField->GetEditFlags() == 0 ) // i.e. not edited, or moved
1712 commit.Modify( aField, m_frame->GetScreen() );
1713
1714 if( parentType == SCH_SYMBOL_T && aField->GetId() == REFERENCE_FIELD )
1715 static_cast<SCH_ITEM*>( aField->GetParent() )->SetConnectivityDirty();
1716
1717 wxString caption;
1718
1719 // Use title caps for mandatory fields. "Edit Sheet name Field" looks dorky.
1720 if( parentType == SCH_SYMBOL_T && aField->IsMandatory() )
1721 {
1722 wxString translated_fieldname = TEMPLATE_FIELDNAME::GetDefaultFieldName( aField->GetId(),
1723 DO_TRANSLATE );
1724 caption.Printf( _( "Edit %s Field" ), TitleCaps( translated_fieldname ) );
1725 }
1726 else if( parentType == SCH_SHEET_T && aField->IsMandatory() )
1727 caption.Printf( _( "Edit %s Field" ), TitleCaps( aField->GetName() ) );
1728 else
1729 caption.Printf( _( "Edit '%s' Field" ), aField->GetName() );
1730
1731 DIALOG_FIELD_PROPERTIES dlg( m_frame, caption, aField );
1732
1733 // The footprint field dialog can invoke a KIWAY_PLAYER so we must use a quasi-modal
1734 if( dlg.ShowQuasiModal() != wxID_OK )
1735 return;
1736
1737 dlg.UpdateField( &commit, aField, &m_frame->GetCurrentSheet() );
1738
1739 if( m_frame->eeconfig()->m_AutoplaceFields.enable || parentType == SCH_SHEET_T )
1740 static_cast<SCH_ITEM*>( aField->GetParent() )->AutoAutoplaceFields( m_frame->GetScreen() );
1741
1742 if( !commit.Empty() )
1743 commit.Push( caption );
1744}
1745
1746
1748{
1750
1751 if( sel.Size() != 1 )
1752 return 0;
1753
1754 bool clearSelection = sel.IsHover();
1755 EDA_ITEM* item = sel.Front();
1756
1757 if( item->Type() == SCH_FIELD_T )
1758 {
1759 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
1760
1761 if( ( aEvent.IsAction( &EE_ACTIONS::editReference ) && field->GetId() != REFERENCE_FIELD )
1762 || ( aEvent.IsAction( &EE_ACTIONS::editValue ) && field->GetId() != VALUE_FIELD )
1763 || ( aEvent.IsAction( &EE_ACTIONS::editFootprint ) && field->GetId() != FOOTPRINT_FIELD ) )
1764 {
1765 item = field->GetParentSymbol();
1768 }
1769 }
1770
1771 if( item->Type() == SCH_SYMBOL_T )
1772 {
1773 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1774
1775 if( aEvent.IsAction( &EE_ACTIONS::editReference ) )
1776 {
1778 }
1779 else if( aEvent.IsAction( &EE_ACTIONS::editValue ) )
1780 {
1781 editFieldText( symbol->GetField( VALUE_FIELD ) );
1782 }
1783 else if( aEvent.IsAction( &EE_ACTIONS::editFootprint ) )
1784 {
1785 if( !symbol->IsPower() )
1787 }
1788 }
1789 else if( item->Type() == SCH_FIELD_T )
1790 {
1791 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
1792
1793 editFieldText( field );
1794
1795 if( !field->IsVisible() )
1796 clearSelection = true;
1797 }
1798
1799 if( clearSelection )
1801
1802 return 0;
1803}
1804
1805
1807{
1809 SCH_COMMIT commit( m_toolMgr );
1810 SCH_ITEM* head = static_cast<SCH_ITEM*>( selection.Front() );
1811 bool moving = head && head->IsMoving();
1812
1813 if( selection.Empty() )
1814 return 0;
1815
1816 std::vector<SCH_ITEM*> autoplaceItems;
1817
1818 for( unsigned ii = 0; ii < selection.GetSize(); ii++ )
1819 {
1820 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.GetItem( ii ) );
1821
1822 if( item->IsType( EE_COLLECTOR::FieldOwners ) )
1823 autoplaceItems.push_back( item );
1824 else if( item->GetParent() && item->GetParent()->IsType( EE_COLLECTOR::FieldOwners ) )
1825 autoplaceItems.push_back( static_cast<SCH_ITEM*>( item->GetParent() ) );
1826 }
1827
1828 for( SCH_ITEM* sch_item : autoplaceItems )
1829 {
1830 if( !moving && !sch_item->IsNew() )
1831 commit.Modify( sch_item, m_frame->GetScreen() );
1832
1833 sch_item->AutoplaceFields( m_frame->GetScreen(), /* aManual */ true );
1834
1835 updateItem( sch_item, true );
1836 }
1837
1838 if( moving )
1839 {
1841 }
1842 else
1843 {
1844 if( !commit.Empty() )
1845 commit.Push( _( "Autoplace Fields" ) );
1846
1847 if( selection.IsHover() )
1849 }
1850
1851 return 0;
1852}
1853
1854
1856{
1857 SCH_SYMBOL* selectedSymbol = nullptr;
1859
1860 if( !selection.Empty() )
1861 selectedSymbol = dynamic_cast<SCH_SYMBOL*>( selection.Front() );
1862
1864
1865 if( aEvent.IsAction( &EE_ACTIONS::changeSymbol )
1866 || aEvent.IsAction( &EE_ACTIONS::changeSymbols ) )
1867 {
1869 }
1870
1871 DIALOG_CHANGE_SYMBOLS dlg( m_frame, selectedSymbol, mode );
1872
1873 // QuasiModal required to invoke symbol browser
1874 dlg.ShowQuasiModal();
1875
1876 return 0;
1877}
1878
1879
1881{
1883
1884 if( selection.Empty() )
1885 return 0;
1886
1887 SCH_SYMBOL* symbol = (SCH_SYMBOL*) selection.Front();
1888
1890 && symbol->GetBodyStyle() == BODY_STYLE::BASE )
1891 {
1892 return 0;
1893 }
1894
1896 && symbol->GetBodyStyle() == BODY_STYLE::DEMORGAN )
1897 {
1898 return 0;
1899 }
1900
1901 SCH_COMMIT commit( m_toolMgr );
1902
1903 if( !symbol->IsNew() )
1904 commit.Modify( symbol, m_frame->GetScreen() );
1905
1906 m_frame->FlipBodyStyle( symbol );
1907
1908 if( symbol->IsNew() )
1910
1911 if( !commit.Empty() )
1912 commit.Push( _( "Change Body Style" ) );
1913
1914 if( selection.IsHover() )
1916
1917 return 0;
1918}
1919
1920
1922{
1924 bool clearSelection = selection.IsHover();
1925
1926 if( selection.Empty() )
1927 {
1928 if( getView()->IsLayerVisible( LAYER_SCHEMATIC_DRAWINGSHEET ) )
1929 {
1931 VECTOR2D cursorPos = getViewControls()->GetCursorPosition( false );
1932
1933 if( ds && ds->HitTestDrawingSheetItems( getView(), cursorPos ) )
1935 }
1936
1937 return 0;
1938 }
1939
1940 EDA_ITEM* curr_item = selection.Front();
1941
1942 switch( curr_item->Type() )
1943 {
1944 case SCH_LINE_T:
1946 case SCH_JUNCTION_T:
1947 case SCH_TABLECELL_T:
1948 break;
1949
1950 default:
1951 if( selection.Size() > 1 )
1952 return 0;
1953
1954 break;
1955 }
1956
1957 switch( curr_item->Type() )
1958 {
1959 case SCH_SYMBOL_T:
1960 {
1961 int retval;
1962 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( curr_item );
1963
1964 // This needs to be scoped so the dialog destructor removes blocking status
1965 // before we launch the next dialog.
1966 {
1967 DIALOG_SYMBOL_PROPERTIES symbolPropsDialog( m_frame, symbol );
1968
1969 // This dialog itself subsequently can invoke a KIWAY_PLAYER as a quasimodal
1970 // frame. Therefore this dialog as a modal frame parent, MUST be run under
1971 // quasimodal mode for the quasimodal frame support to work. So don't use
1972 // the QUASIMODAL macros here.
1973 retval = symbolPropsDialog.ShowQuasiModal();
1974 }
1975
1976 if( retval == SYMBOL_PROPS_EDIT_OK )
1977 {
1980
1981 m_frame->OnModify();
1982 }
1983 else if( retval == SYMBOL_PROPS_EDIT_SCHEMATIC_SYMBOL )
1984 {
1985 if( KIWAY_PLAYER* frame = m_frame->Kiway().Player( FRAME_SCH_SYMBOL_EDITOR, true ) )
1986 {
1987 SYMBOL_EDIT_FRAME* editor = static_cast<SYMBOL_EDIT_FRAME*>( frame );
1988
1989 if( wxWindow* blocking_win = editor->Kiway().GetBlockingDialog() )
1990 blocking_win->Close( true );
1991
1992 // The broken library symbol link indicator cannot be edited.
1993 if( symbol->IsMissingLibSymbol() )
1994 return 0;
1995
1996 editor->LoadSymbolFromSchematic( symbol );
1997 editor->Show( true );
1998 editor->Raise();
1999 }
2000 }
2001 else if( retval == SYMBOL_PROPS_EDIT_LIBRARY_SYMBOL )
2002 {
2003 if( KIWAY_PLAYER* frame = m_frame->Kiway().Player( FRAME_SCH_SYMBOL_EDITOR, true ) )
2004 {
2005 SYMBOL_EDIT_FRAME* editor = static_cast<SYMBOL_EDIT_FRAME*>( frame );
2006
2007 if( wxWindow* blocking_win = editor->Kiway().GetBlockingDialog() )
2008 blocking_win->Close( true );
2009
2010 editor->LoadSymbol( symbol->GetLibId(), symbol->GetUnit(), symbol->GetBodyStyle() );
2011 editor->Show( true );
2012 editor->Raise();
2013 }
2014 }
2015 else if( retval == SYMBOL_PROPS_WANT_UPDATE_SYMBOL )
2016 {
2018 dlg.ShowQuasiModal();
2019 }
2020 else if( retval == SYMBOL_PROPS_WANT_EXCHANGE_SYMBOL )
2021 {
2023 dlg.ShowQuasiModal();
2024 }
2025
2026 break;
2027 }
2028
2029 case SCH_SHEET_T:
2030 {
2031 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( curr_item );
2032 bool isUndoable = false;
2033 bool doClearAnnotation = false;
2034 bool okPressed = false;
2035 bool updateHierarchyNavigator = false;
2036
2037 // Keep track of existing sheet paths. EditSheet() can modify this list.
2038 // Note that we use the validity checking/repairing version here just to make sure
2039 // we've got a valid hierarchy to begin with.
2040 SCH_SHEET_LIST originalHierarchy;
2041 originalHierarchy.BuildSheetList( &m_frame->Schematic().Root(), true );
2042
2043 SCH_COMMIT commit( m_toolMgr );
2044 commit.Modify( sheet, m_frame->GetScreen() );
2045 okPressed = m_frame->EditSheetProperties( sheet, &m_frame->GetCurrentSheet(), &isUndoable,
2046 &doClearAnnotation, &updateHierarchyNavigator );
2047
2048 if( okPressed )
2049 {
2050 if( isUndoable )
2051 commit.Push( _( "Edit Sheet Properties" ) );
2052 }
2053 else
2054 {
2055 // If we are renaming files, the undo/redo list becomes invalid and must be cleared.
2057 m_frame->OnModify();
2058 }
2059
2060 // If the sheet file is changed and new sheet contents are loaded then we have to
2061 // clear the annotations on the new content (as it may have been set from some other
2062 // sheet path reference)
2063 if( doClearAnnotation )
2064 {
2065 SCH_SCREENS screensList( &m_frame->Schematic().Root() );
2066
2067 // We clear annotation of new sheet paths here:
2068 screensList.ClearAnnotationOfNewSheetPaths( originalHierarchy );
2069
2070 // Clear annotation of g_CurrentSheet itself, because its sheetpath is not a new
2071 // path, but symbols managed by its sheet path must have their annotation cleared
2072 // because they are new:
2073 sheet->GetScreen()->ClearAnnotation( &m_frame->GetCurrentSheet(), false );
2074 }
2075
2076 if( okPressed )
2078
2079 if( updateHierarchyNavigator )
2081
2082 break;
2083 }
2084
2085 case SCH_SHEET_PIN_T:
2086 {
2087 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( curr_item );
2089
2090 // QuasiModal required for help dialog
2091 dlg.ShowQuasiModal();
2092 break;
2093 }
2094
2095 case SCH_TEXT_T:
2096 case SCH_TEXTBOX_T:
2097 {
2098 DIALOG_TEXT_PROPERTIES dlg( m_frame, static_cast<SCH_ITEM*>( curr_item ) );
2099
2100 // QuasiModal required for syntax help and Scintilla auto-complete
2101 dlg.ShowQuasiModal();
2102 break;
2103 }
2104
2105 case SCH_TABLECELL_T:
2106 if( SELECTION_CONDITIONS::OnlyTypes( { SCH_TABLECELL_T } )( selection ) )
2107 {
2108 std::vector<SCH_TABLECELL*> cells;
2109
2110 for( EDA_ITEM* item : selection.Items() )
2111 cells.push_back( static_cast<SCH_TABLECELL*>( item ) );
2112
2114
2115 dlg.ShowModal();
2116
2118 {
2119 SCH_TABLE* table = static_cast<SCH_TABLE*>( cells[0]->GetParent() );
2120 DIALOG_TABLE_PROPERTIES tableDlg( m_frame, table );
2121
2122 tableDlg.ShowModal();
2123 }
2124 }
2125
2126 break;
2127
2128 case SCH_TABLE_T:
2129 {
2130 DIALOG_TABLE_PROPERTIES dlg( m_frame, static_cast<SCH_TABLE*>( curr_item ) );
2131
2132 // QuasiModal required for Scintilla auto-complete
2133 dlg.ShowQuasiModal();
2134 break;
2135 }
2136
2137 case SCH_LABEL_T:
2138 case SCH_GLOBAL_LABEL_T:
2139 case SCH_HIER_LABEL_T:
2141 {
2142 DIALOG_LABEL_PROPERTIES dlg( m_frame, static_cast<SCH_LABEL_BASE*>( curr_item ) );
2143
2144 // QuasiModal for syntax help and Scintilla auto-complete
2145 dlg.ShowQuasiModal();
2146 break;
2147 }
2148
2149 case SCH_FIELD_T:
2150 {
2151 SCH_FIELD* field = static_cast<SCH_FIELD*>( curr_item );
2152
2153 editFieldText( field );
2154
2155 if( !field->IsVisible() )
2156 clearSelection = true;
2157
2158 break;
2159 }
2160
2161 case SCH_SHAPE_T:
2162 {
2163 DIALOG_SHAPE_PROPERTIES dlg( m_frame, static_cast<SCH_SHAPE*>( curr_item ) );
2164
2165 dlg.ShowModal();
2166 break;
2167 }
2168
2169 case SCH_BITMAP_T:
2170 {
2171 SCH_BITMAP* bitmap = static_cast<SCH_BITMAP*>( curr_item );
2172 DIALOG_IMAGE_PROPERTIES dlg( m_frame, bitmap );
2173
2174 if( dlg.ShowModal() == wxID_OK )
2175 {
2176 // The bitmap is cached in Opengl: clear the cache in case it has become invalid
2178 }
2179
2180 break;
2181 }
2182
2183 case SCH_RULE_AREA_T:
2184 {
2185 DIALOG_SHAPE_PROPERTIES dlg( m_frame, static_cast<SCH_SHAPE*>( curr_item ) );
2186 dlg.SetTitle( _( "Rule Area Properties" ) );
2187
2188 dlg.ShowModal();
2189 break;
2190 }
2191
2192 case SCH_LINE_T:
2194 case SCH_JUNCTION_T:
2196 {
2197 std::deque<SCH_LINE*> lines;
2198
2199 for( EDA_ITEM* selItem : selection.Items() )
2200 lines.push_back( static_cast<SCH_LINE*>( selItem ) );
2201
2202 DIALOG_LINE_PROPERTIES dlg( m_frame, lines );
2203
2204 dlg.ShowModal();
2205 }
2206 else if( SELECTION_CONDITIONS::OnlyTypes( { SCH_JUNCTION_T } )( selection ) )
2207 {
2208 std::deque<SCH_JUNCTION*> junctions;
2209
2210 for( EDA_ITEM* selItem : selection.Items() )
2211 junctions.push_back( static_cast<SCH_JUNCTION*>( selItem ) );
2212
2213 DIALOG_JUNCTION_PROPS dlg( m_frame, junctions );
2214
2215 dlg.ShowModal();
2216 }
2220 SCH_JUNCTION_T } )( selection ) )
2221 {
2222 std::deque<SCH_ITEM*> items;
2223
2224 for( EDA_ITEM* selItem : selection.Items() )
2225 items.push_back( static_cast<SCH_ITEM*>( selItem ) );
2226
2227 DIALOG_WIRE_BUS_PROPERTIES dlg( m_frame, items );
2228
2229 dlg.ShowModal();
2230 }
2231 else
2232 {
2233 return 0;
2234 }
2235
2236 break;
2237
2238 case SCH_MARKER_T:
2239 if( SELECTION_CONDITIONS::OnlyTypes( { SCH_MARKER_T } )( selection ) )
2240 {
2242
2243 if( inspectionTool )
2244 inspectionTool->CrossProbe( static_cast<SCH_MARKER*> ( selection.Front() ) );
2245 }
2246 break;
2247
2248 case SCH_NO_CONNECT_T:
2249 case SCH_PIN_T:
2250 break;
2251
2252 default: // Unexpected item
2253 wxFAIL_MSG( wxString( "Cannot edit schematic item type " ) + curr_item->GetClass() );
2254 }
2255
2256 updateItem( curr_item, true );
2257
2258 if( clearSelection )
2260
2261 return 0;
2262}
2263
2264
2266{
2267 KICAD_T convertTo = aEvent.Parameter<KICAD_T>();
2269 SCH_TEXT_T,
2270 SCH_TEXTBOX_T } );
2271 SCH_COMMIT commit( m_toolMgr );
2272
2273 for( unsigned int i = 0; i < selection.GetSize(); ++i )
2274 {
2275 SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( selection.GetItem( i ) );
2276
2277 if( item && item->Type() != convertTo )
2278 {
2279 EDA_TEXT* sourceText = dynamic_cast<EDA_TEXT*>( item );
2280 bool selected = item->IsSelected();
2281 SCH_ITEM* newtext = nullptr;
2282 VECTOR2I position = item->GetPosition();
2283 wxString txt;
2284 wxString href;
2286 LABEL_FLAG_SHAPE shape = LABEL_FLAG_SHAPE::L_UNSPECIFIED;
2287
2288 switch( item->Type() )
2289 {
2290 case SCH_LABEL_T:
2291 case SCH_GLOBAL_LABEL_T:
2292 case SCH_HIER_LABEL_T:
2293 {
2294 SCH_LABEL_BASE* label = static_cast<SCH_LABEL_BASE*>( item );
2295
2296 txt = UnescapeString( label->GetText() );
2297 spinStyle = label->GetSpinStyle();
2298 shape = label->GetShape();
2299 href = label->GetHyperlink();
2300 break;
2301 }
2302
2304 {
2305 SCH_DIRECTIVE_LABEL* dirlabel = static_cast<SCH_DIRECTIVE_LABEL*>( item );
2306
2307 // a SCH_DIRECTIVE_LABEL has no text
2308 txt = _( "<empty>" );
2309
2310 spinStyle = dirlabel->GetSpinStyle();
2311 href = dirlabel->GetHyperlink();
2312 break;
2313 }
2314
2315 case SCH_TEXT_T:
2316 {
2317 SCH_TEXT* text = static_cast<SCH_TEXT*>( item );
2318
2319 txt = text->GetText();
2320 href = text->GetHyperlink();
2321 break;
2322 }
2323
2324 case SCH_TEXTBOX_T:
2325 {
2326 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( item );
2327 BOX2I bbox = textbox->GetBoundingBox();
2328
2329 bbox.SetOrigin( bbox.GetLeft() + textbox->GetMarginLeft(),
2330 bbox.GetTop() + textbox->GetMarginTop() );
2331 bbox.SetEnd( bbox.GetRight() - textbox->GetMarginRight(),
2332 bbox.GetBottom() - textbox->GetMarginBottom() );
2333
2334 if( convertTo == SCH_LABEL_T
2335 || convertTo == SCH_HIER_LABEL_T
2336 || convertTo == SCH_GLOBAL_LABEL_T )
2337 {
2338 EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item );
2339 wxCHECK( text, 0 );
2340 int textSize = text->GetTextSize().y;
2341 bbox.Inflate( KiROUND( item->Schematic()->Settings().m_LabelSizeRatio * textSize ) );
2342 }
2343
2344 txt = textbox->GetText();
2345
2346 if( textbox->GetTextAngle().IsVertical() )
2347 {
2348 if( textbox->GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
2349 {
2350 spinStyle = SPIN_STYLE::SPIN::BOTTOM;
2351 position = VECTOR2I( bbox.Centre().x, bbox.GetOrigin().y );
2352 }
2353 else
2354 {
2355 spinStyle = SPIN_STYLE::SPIN::UP;
2356 position = VECTOR2I( bbox.Centre().x, bbox.GetEnd().y );
2357 }
2358 }
2359 else
2360 {
2361 if( textbox->GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
2362 {
2363 spinStyle = SPIN_STYLE::SPIN::LEFT;
2364 position = VECTOR2I( bbox.GetEnd().x, bbox.Centre().y );
2365 }
2366 else
2367 {
2368 spinStyle = SPIN_STYLE::SPIN::RIGHT;
2369 position = VECTOR2I( bbox.GetOrigin().x, bbox.Centre().y );
2370 }
2371 }
2372
2373 position = m_frame->GetNearestGridPosition( position );
2374 href = textbox->GetHyperlink();
2375 break;
2376 }
2377
2378 default:
2379 UNIMPLEMENTED_FOR( item->GetClass() );
2380 break;
2381 }
2382
2383 auto getValidNetname =
2384 []( const wxString& aText )
2385 {
2386 wxString local_txt = aText;
2387 local_txt.Replace( "\n", "_" );
2388 local_txt.Replace( "\r", "_" );
2389 local_txt.Replace( "\t", "_" );
2390
2391 // Bus groups can have spaces; bus vectors and signal names cannot
2392 if( !NET_SETTINGS::ParseBusGroup( aText, nullptr, nullptr ) )
2393 local_txt.Replace( " ", "_" );
2394
2395 // label strings are "escaped" i.e. a '/' is replaced by "{slash}"
2396 local_txt = EscapeString( local_txt, CTX_NETNAME );
2397
2398 if( local_txt.IsEmpty() )
2399 return _( "<empty>" );
2400 else
2401 return local_txt;
2402 };
2403
2404 switch( convertTo )
2405 {
2406 case SCH_LABEL_T:
2407 {
2408 SCH_LABEL_BASE* new_label = new SCH_LABEL( position, getValidNetname( txt ) );
2409
2410 new_label->SetShape( shape );
2411 new_label->SetAttributes( *sourceText, false );
2412 new_label->SetSpinStyle( spinStyle );
2413 new_label->SetHyperlink( href );
2414
2415 if( item->Type() == SCH_GLOBAL_LABEL_T || item->Type() == SCH_HIER_LABEL_T )
2416 {
2417 if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::UP )
2418 new_label->MirrorVertically( position.y );
2419 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::BOTTOM )
2420 new_label->MirrorVertically( position.y );
2421 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::LEFT )
2422 new_label->MirrorHorizontally( position.x );
2423 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::RIGHT )
2424 new_label->MirrorHorizontally( position.x );
2425 }
2426
2427 newtext = new_label;
2428 break;
2429 }
2430
2431 case SCH_GLOBAL_LABEL_T:
2432 {
2433 SCH_LABEL_BASE* new_label = new SCH_GLOBALLABEL( position, getValidNetname( txt ) );
2434
2435 new_label->SetShape( shape );
2436 new_label->SetAttributes( *sourceText, false );
2437 new_label->SetSpinStyle( spinStyle );
2438 new_label->SetHyperlink( href );
2439
2440 if( item->Type() == SCH_LABEL_T )
2441 {
2442 if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::UP )
2443 new_label->MirrorVertically( position.y );
2444 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::BOTTOM )
2445 new_label->MirrorVertically( position.y );
2446 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::LEFT )
2447 new_label->MirrorHorizontally( position.x );
2448 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::RIGHT )
2449 new_label->MirrorHorizontally( position.x );
2450 }
2451
2452 newtext = new_label;
2453 break;
2454 }
2455
2456 case SCH_HIER_LABEL_T:
2457 {
2458 SCH_LABEL_BASE* new_label = new SCH_HIERLABEL( position, getValidNetname( txt ) );
2459
2460 new_label->SetShape( shape );
2461 new_label->SetAttributes( *sourceText, false );
2462 new_label->SetSpinStyle( spinStyle );
2463 new_label->SetHyperlink( href );
2464
2465 if( item->Type() == SCH_LABEL_T )
2466 {
2467 if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::UP )
2468 new_label->MirrorVertically( position.y );
2469 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::BOTTOM )
2470 new_label->MirrorVertically( position.y );
2471 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::LEFT )
2472 new_label->MirrorHorizontally( position.x );
2473 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::RIGHT )
2474 new_label->MirrorHorizontally( position.x );
2475 }
2476
2477 newtext = new_label;
2478 break;
2479 }
2480
2482 {
2483 SCH_LABEL_BASE* new_label = new SCH_DIRECTIVE_LABEL( position );
2484
2485 // A SCH_DIRECTIVE_LABEL usually has at least one field containing the net class
2486 // name. If we're copying from a text object assume the text is the netclass
2487 // name. Otherwise, we'll just copy the fields which will either have a netclass
2488 // or not.
2489 if( !dynamic_cast<SCH_LABEL_BASE*>( item ) )
2490 {
2491 SCH_FIELD netclass( position, 0, new_label, wxT( "Netclass" ) );
2492 netclass.SetText( txt );
2493 netclass.SetVisible( true );
2494 new_label->GetFields().push_back( netclass );
2495 }
2496
2497 new_label->SetShape( LABEL_FLAG_SHAPE::F_ROUND );
2498 new_label->SetAttributes( *sourceText, false );
2499 new_label->SetSpinStyle( spinStyle );
2500 new_label->SetHyperlink( href );
2501 newtext = new_label;
2502 break;
2503 }
2504
2505 case SCH_TEXT_T:
2506 {
2507 SCH_TEXT* new_text = new SCH_TEXT( position, txt );
2508
2509 new_text->SetAttributes( *sourceText, false );
2510 new_text->SetHyperlink( href );
2511 newtext = new_text;
2512 break;
2513 }
2514
2515 case SCH_TEXTBOX_T:
2516 {
2517 SCH_TEXTBOX* new_textbox = new SCH_TEXTBOX( LAYER_NOTES, 0, FILL_T::NO_FILL, txt );
2518 BOX2I bbox = item->GetBoundingBox();
2519
2520 if( SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( item ) )
2521 bbox.Inflate( -label->GetLabelBoxExpansion() );
2522
2523 new_textbox->SetAttributes( *sourceText, false );
2524
2525 bbox.SetOrigin( bbox.GetLeft() - new_textbox->GetMarginLeft(),
2526 bbox.GetTop() - new_textbox->GetMarginTop() );
2527 bbox.SetEnd( bbox.GetRight() + new_textbox->GetMarginRight(),
2528 bbox.GetBottom() + new_textbox->GetMarginBottom() );
2529
2530 VECTOR2I topLeft = bbox.GetPosition();
2531 VECTOR2I botRight = bbox.GetEnd();
2532
2533 // Add 1/20 of the margin at the end to reduce line-breaking changes.
2534 int slop = new_textbox->GetLegacyTextMargin() / 20;
2535
2536 if( sourceText->GetTextAngle() == ANGLE_VERTICAL )
2537 {
2538 if( sourceText->GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
2539 botRight.y += slop;
2540 else
2541 topLeft.y -= slop;
2542 }
2543 else
2544 {
2545 if( sourceText->GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
2546 topLeft.x -= slop;
2547 else
2548 botRight.x += slop;
2549 }
2550
2551 new_textbox->SetPosition( topLeft );
2552 new_textbox->SetEnd( botRight );
2553
2554 new_textbox->SetHyperlink( href );
2555 newtext = new_textbox;
2556 break;
2557 }
2558
2559 default:
2560 UNIMPLEMENTED_FOR( wxString::Format( "%d.", convertTo ) );
2561 break;
2562 }
2563
2564 wxCHECK2( newtext, continue );
2565
2566 // Copy the old text item settings to the new one. Justifications are not copied
2567 // because they are not used in labels. Justifications will be set to default value
2568 // in the new text item type.
2569 //
2570 newtext->SetFlags( item->GetEditFlags() );
2571
2572 EDA_TEXT* eda_text = dynamic_cast<EDA_TEXT*>( item );
2573 EDA_TEXT* new_eda_text = dynamic_cast<EDA_TEXT*>( newtext );
2574
2575 wxCHECK2( eda_text && new_eda_text, continue );
2576
2577 new_eda_text->SetFont( eda_text->GetFont() );
2578 new_eda_text->SetTextSize( eda_text->GetTextSize() );
2579 new_eda_text->SetTextThickness( eda_text->GetTextThickness() );
2580
2581 // Must be after SetTextSize()
2582 new_eda_text->SetBold( eda_text->IsBold() );
2583 new_eda_text->SetItalic( eda_text->IsItalic() );
2584
2585 newtext->AutoplaceFields( m_frame->GetScreen(), false );
2586
2587 SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( item );
2588 SCH_LABEL_BASE* new_label = dynamic_cast<SCH_LABEL_BASE*>( newtext );
2589
2590 if( label && new_label )
2591 {
2592 new_label->AddFields( label->GetFields() );
2593
2594 // A SCH_GLOBALLABEL has a specific field, that has no meaning for
2595 // other labels, and expected to be the first field in list.
2596 // It is the first field in list for this kind of label
2597 // So remove field named "Intersheetrefs" if exists for other labels
2598 int min_idx = new_label->Type() == SCH_GLOBAL_LABEL_T ? 1 : 0;
2599 std::vector<SCH_FIELD>& fields = new_label->GetFields();
2600
2601 for( int ii = fields.size()-1; ii >= min_idx; ii-- )
2602 {
2603 if( fields[ii].GetCanonicalName() == wxT( "Intersheetrefs" ) )
2604 fields.erase( fields.begin() + ii );
2605 }
2606 }
2607
2608 if( selected )
2610
2611 if( !item->IsNew() )
2612 {
2614 commit.Removed( item, m_frame->GetScreen() );
2615
2616 m_frame->AddToScreen( newtext, m_frame->GetScreen() );
2617 commit.Added( newtext, m_frame->GetScreen() );
2618 }
2619
2620 if( selected )
2622
2623 // Otherwise, pointer is owned by the undo stack
2624 if( item->IsNew() )
2625 delete item;
2626 }
2627 }
2628
2629 if( !commit.Empty() )
2630 commit.Push( _( "Change To" ) );
2631
2632 if( selection.IsHover() )
2634
2635 return 0;
2636}
2637
2638
2640{
2641 static std::vector<KICAD_T> justifiableItems = {
2643 SCH_TEXT_T,
2646 };
2647
2648 EE_SELECTION& selection = m_selectionTool->RequestSelection( justifiableItems );
2649
2650 if( selection.GetSize() == 0 )
2651 return 0;
2652
2653 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.Front() );
2654 bool moving = item->IsMoving();
2655 SCH_COMMIT localCommit( m_toolMgr );
2656 SCH_COMMIT* commit = dynamic_cast<SCH_COMMIT*>( aEvent.Commit() );
2657
2658 if( !commit )
2659 commit = &localCommit;
2660
2661 auto setJustify =
2662 [&]( EDA_TEXT* aTextItem )
2663 {
2664 if( aEvent.Matches( ACTIONS::leftJustify.MakeEvent() ) )
2665 aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
2666 else if( aEvent.Matches( ACTIONS::centerJustify.MakeEvent() ) )
2667 aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER );
2668 else
2669 aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
2670 };
2671
2672 for( EDA_ITEM* edaItem : selection )
2673 {
2674 item = static_cast<SCH_ITEM*>( edaItem );
2675
2676 if( !moving )
2677 commit->Modify( item, m_frame->GetScreen() );
2678
2679 if( item->Type() == SCH_FIELD_T )
2680 {
2681 setJustify( static_cast<SCH_FIELD*>( item ) );
2682
2683 // Now that we're re-justifying a field, they're no longer autoplaced.
2684 static_cast<SCH_ITEM*>( item->GetParent() )->ClearFieldsAutoplaced();
2685 }
2686 else if( item->Type() == SCH_TEXT_T )
2687 {
2688 setJustify( static_cast<SCH_TEXT*>( item ) );
2689 }
2690 else if( item->Type() == SCH_TEXTBOX_T )
2691 {
2692 setJustify( static_cast<SCH_TEXTBOX*>( item ) );
2693 }
2694 else if( item->Type() == SCH_LABEL_T )
2695 {
2696 SCH_LABEL* label = static_cast<SCH_LABEL*>( item );
2697
2698 if( label->GetTextAngle() == ANGLE_HORIZONTAL )
2699 setJustify( label );
2700 }
2701
2702 m_frame->UpdateItem( item, false, true );
2703 }
2704
2705 // Update R-Tree for modified items
2706 for( EDA_ITEM* selected : selection )
2707 updateItem( selected, true );
2708
2709 if( item->IsMoving() )
2710 {
2712 }
2713 else
2714 {
2715 EE_SELECTION selectionCopy = selection;
2716
2717 if( selection.IsHover() )
2719
2720 if( !localCommit.Empty() )
2721 {
2722 if( aEvent.Matches( ACTIONS::leftJustify.MakeEvent() ) )
2723 localCommit.Push( _( "Left Justify" ) );
2724 else if( aEvent.Matches( ACTIONS::centerJustify.MakeEvent() ) )
2725 localCommit.Push( _( "Center Justify" ) );
2726 else
2727 localCommit.Push( _( "Right Justify" ) );
2728 }
2729 }
2730
2731 return 0;
2732}
2733
2734
2736{
2737 bool isSlice = aEvent.Matches( EE_ACTIONS::slice.MakeEvent() );
2740 SCH_SCREEN* screen = m_frame->GetScreen();
2741 SCH_COMMIT commit( m_toolMgr );
2742 std::vector<SCH_LINE*> lines;
2743
2744 for( EDA_ITEM* item : selection )
2745 {
2746 if( item->Type() == SCH_LINE_T )
2747 {
2748 SCH_LINE* line = static_cast<SCH_LINE*>( item );
2749
2750 if( !line->IsEndPoint( cursorPos ) )
2751 lines.push_back( line );
2752 }
2753 }
2754
2756
2757 for( SCH_LINE* line : lines )
2758 {
2759 SCH_LINE* newLine;
2760
2761 // We let the user select the break point if they're on a single line
2762 if( lines.size() == 1 && line->HitTest( cursorPos ) )
2763 m_frame->BreakSegment( &commit, line, cursorPos, &newLine, screen );
2764 else
2765 m_frame->BreakSegment( &commit, line, line->GetMidPoint(), &newLine, screen );
2766
2767 // Make sure both endpoints are deselected
2768 newLine->ClearFlags();
2769
2771 line->SetFlags( ENDPOINT );
2772
2773 // If we're a break, we want to drag both wires.
2774 // Side note: the drag/move tool only checks whether the first item is
2775 // new to determine if it should append undo or not, someday this should
2776 // be cleaned up and explictly controlled but for now the newLine
2777 // selection addition must be after the existing line.
2778 if( !isSlice )
2779 {
2780 m_selectionTool->AddItemToSel( newLine );
2781 newLine->SetFlags( STARTPOINT );
2782 }
2783 }
2784
2785 if( !lines.empty() )
2786 {
2788
2789 if( m_toolMgr->RunSynchronousAction( EE_ACTIONS::drag, &commit, isSlice ) )
2790 commit.Push( isSlice ? _( "Slice Wire" ) : _( "Break Wire" ) );
2791 else
2792 commit.Revert();
2793 }
2794
2795 return 0;
2796}
2797
2798
2800{
2802 SCH_SHEET* sheet = (SCH_SHEET*) selection.Front();
2803 SCH_COMMIT commit( m_toolMgr );
2804
2805 if( !sheet || !sheet->HasUndefinedPins() )
2806 return 0;
2807
2808 if( !IsOK( m_frame, _( "Do you wish to delete the unreferenced pins from this sheet?" ) ) )
2809 return 0;
2810
2811 commit.Modify( sheet, m_frame->GetScreen() );
2812
2813 sheet->CleanupSheet();
2814
2815 updateItem( sheet, true );
2816
2817 commit.Push( _( "Cleanup Sheet Pins" ) );
2818
2819 if( selection.IsHover() )
2821
2822 return 0;
2823}
2824
2825
2827{
2829
2830 if( selection.GetSize() > 1 )
2831 return 0;
2832
2833 SCH_SHEET* sheet = (SCH_SHEET*) selection.Front();
2834
2836
2837 SCH_SCREEN* screen;
2838
2839 if( sheet )
2840 {
2841 // When changing the page number of a selected sheet, the current screen owns the sheet.
2842 screen = m_frame->GetScreen();
2843
2844 instance.push_back( sheet );
2845 }
2846 else
2847 {
2848 SCH_SHEET_PATH prevInstance = instance;
2849
2850 // When change the page number in the screen, the previous screen owns the sheet.
2851 if( prevInstance.size() )
2852 {
2853 prevInstance.pop_back();
2854 screen = prevInstance.LastScreen();
2855 }
2856 else
2857 {
2858 // The root sheet and root screen are effectively the same thing.
2859 screen = m_frame->GetScreen();
2860 }
2861
2862 sheet = m_frame->GetCurrentSheet().Last();
2863 }
2864
2865 wxString msg;
2866 wxString sheetPath = instance.PathHumanReadable( false );
2867 wxString pageNumber = instance.GetPageNumber();
2868
2869 msg.Printf( _( "Enter page number for sheet path%s" ),
2870 ( sheetPath.Length() > 20 ) ? "\n" + sheetPath : " " + sheetPath );
2871
2872 wxTextEntryDialog dlg( m_frame, msg, _( "Edit Sheet Page Number" ), pageNumber );
2873
2874 dlg.SetTextValidator( wxFILTER_ALPHANUMERIC ); // No white space.
2875
2876 if( dlg.ShowModal() == wxID_CANCEL || dlg.GetValue() == instance.GetPageNumber() )
2877 return 0;
2878
2879 m_frame->SaveCopyInUndoList( screen, sheet, UNDO_REDO::CHANGED, false );
2880
2881 instance.SetPageNumber( dlg.GetValue() );
2882
2883 if( instance == m_frame->GetCurrentSheet() )
2884 {
2885 m_frame->GetScreen()->SetPageNumber( dlg.GetValue() );
2887 }
2888
2889 m_frame->OnModify();
2890
2891 // Update the hierarchy navigator labels if needed
2892 if( pageNumber != dlg.GetValue() )
2894
2895 return 0;
2896}
2897
2898
2900{
2901 wxString aFileName = *aEvent.Parameter<wxString*>();
2902 return ( m_frame->AddSheetAndUpdateDisplay( aFileName ) ? 0 : 1 );
2903}
2904
2905
2907{
2909 SCH_COMMIT commit( m_toolMgr );
2910
2911 if( selection.Empty() )
2912 return 0;
2913
2914 for( EDA_ITEM* item : selection )
2915 {
2916 if( item->Type() == SCH_SYMBOL_T )
2917 {
2918 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2919
2920 commit.Modify( symbol, m_frame->GetScreen() );
2921
2922 if( aEvent.IsAction( &EE_ACTIONS::setDNP ) )
2923 symbol->SetDNP( true );
2924
2926 symbol->SetExcludedFromSim( true );
2927
2929 symbol->SetExcludedFromBOM( true );
2930
2932 symbol->SetExcludedFromBoard( true );
2933 }
2934 }
2935
2936 if( !commit.Empty() )
2937 commit.Push( _( "Set Attribute" ) );
2938
2939 return 0;
2940}
2941
2942
2944{
2946 SCH_COMMIT commit( m_toolMgr );
2947
2948 if( selection.Empty() )
2949 return 0;
2950
2951 for( EDA_ITEM* item : selection )
2952 {
2953 if( item->Type() == SCH_SYMBOL_T )
2954 {
2955 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2956
2957 commit.Modify( symbol, m_frame->GetScreen() );
2958
2959 if( aEvent.IsAction( &EE_ACTIONS::unsetDNP ) )
2960 symbol->SetDNP( false );
2961
2963 symbol->SetExcludedFromSim( false );
2964
2966 symbol->SetExcludedFromBOM( false );
2967
2969 symbol->SetExcludedFromBoard( false );
2970 }
2971 }
2972
2973 if( !commit.Empty() )
2974 commit.Push( _( "Clear Attribute" ) );
2975
2976 return 0;
2977}
2978
2979
2981{
2983 SCH_COMMIT commit( m_toolMgr );
2984
2985 if( selection.Empty() )
2986 return 0;
2987
2988 for( EDA_ITEM* item : selection )
2989 {
2990 if( item->Type() == SCH_SYMBOL_T )
2991 {
2992 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
2993
2994 commit.Modify( symbol, m_frame->GetScreen() );
2995
2996 if( aEvent.IsAction( &EE_ACTIONS::toggleDNP ) )
2997 symbol->SetDNP( !symbol->GetDNP() );
2998
3000 symbol->SetExcludedFromSim( !symbol->GetExcludedFromSim() );
3001
3003 symbol->SetExcludedFromBOM( !symbol->GetExcludedFromBOM() );
3004
3006 symbol->SetExcludedFromBoard( !symbol->GetExcludedFromBoard() );
3007 }
3008 }
3009
3010 if( !commit.Empty() )
3011 commit.Push( _( "Toggle Attribute" ) );
3012
3013 return 0;
3014
3015}
3016
3017
3019{
3025 Go( &SCH_EDIT_TOOL::Swap, EE_ACTIONS::swap.MakeEvent() );
3028
3050
3053
3066
3070
3072}
const char * name
Definition: DXF_plotter.cpp:57
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
static TOOL_ACTION paste
Definition: actions.h:72
static TOOL_ACTION unselectAll
Definition: actions.h:75
static TOOL_ACTION copy
Definition: actions.h:71
static TOOL_ACTION pickerTool
Definition: actions.h:194
static TOOL_ACTION pasteSpecial
Definition: actions.h:73
static TOOL_ACTION rightJustify
Definition: actions.h:81
static TOOL_ACTION pageSettings
Definition: actions.h:56
static TOOL_ACTION duplicate
Definition: actions.h:76
static TOOL_ACTION doDelete
Definition: actions.h:77
static TOOL_ACTION deleteTool
Definition: actions.h:78
static TOOL_ACTION leftJustify
Definition: actions.h:79
static TOOL_ACTION cut
Definition: actions.h:70
static TOOL_ACTION refreshPreview
Definition: actions.h:139
static TOOL_ACTION selectAll
Definition: actions.h:74
static TOOL_ACTION centerJustify
Definition: actions.h:80
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:49
TOOL_MANAGER * getToolManager() const
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.
void SetOrigin(const Vec &pos)
Definition: box2.h:227
const Vec & GetPosition() const
Definition: box2.h:201
const Vec & GetOrigin() const
Definition: box2.h:200
const Vec GetCenter() const
Definition: box2.h:220
coord_type GetTop() const
Definition: box2.h:219
const Vec GetEnd() const
Definition: box2.h:202
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:541
Vec Centre() const
Definition: box2.h:87
coord_type GetRight() const
Definition: box2.h:207
coord_type GetLeft() const
Definition: box2.h:218
coord_type GetBottom() const
Definition: box2.h:212
void SetEnd(coord_type x, coord_type y)
Definition: box2.h:280
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)
Notify observers that aItem has been removed.
Definition: commit.h:92
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Create an undo entry for an item that has been already modified.
Definition: commit.h:105
COMMIT & Added(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
Definition: commit.h:86
bool Empty() const
Returns status of an item.
Definition: commit.h:144
COMMIT & Removed(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Modify a given item in the model.
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()
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:243
virtual void SetPosition(const VECTOR2I &aPos)
Definition: eda_item.h:244
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:74
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
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:171
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:79
bool IsItalic() const
Definition: eda_text.h:140
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:130
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition: eda_text.cpp:373
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:94
virtual bool IsVisible() const
Definition: eda_text.h:147
KIFONT::FONT * GetFont() const
Definition: eda_text.h:207
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
Definition: eda_text.cpp:291
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition: eda_text.cpp:275
wxString GetHyperlink() const
Definition: eda_text.h:358
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition: eda_text.h:160
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:244
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:196
void SetBold(bool aBold)
Definition: eda_text.cpp:220
bool IsBold() const
Definition: eda_text.h:144
void SetHyperlink(wxString aLink)
Definition: eda_text.h:359
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition: eda_text.h:163
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:204
int GetTextThickness() const
Definition: eda_text.h:122
void SetItalic(bool aItalic)
Definition: eda_text.cpp:212
void SetFont(KIFONT::FONT *aFont)
Definition: eda_text.cpp:357
VECTOR2I GetTextSize() const
Definition: eda_text.h:218
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition: eda_text.cpp:267
PANEL_ANNOTATE m_AnnotatePanel
AUTOPLACE_FIELDS m_AutoplaceFields
static TOOL_ACTION mirrorV
Definition: ee_actions.h:126
static TOOL_ACTION unsetDNP
Definition: ee_actions.h:196
static TOOL_ACTION selectionActivate
Activation of the selection tool.
Definition: ee_actions.h:46
static TOOL_ACTION properties
Definition: ee_actions.h:129
static TOOL_ACTION toggleExcludeFromSimulation
Definition: ee_actions.h:191
static TOOL_ACTION unsetExcludeFromSimulation
Definition: ee_actions.h:190
static TOOL_ACTION setExcludeFromBoard
Definition: ee_actions.h:192
static TOOL_ACTION move
Definition: ee_actions.h:121
static TOOL_ACTION clearHighlight
Definition: ee_actions.h:292
static TOOL_ACTION toGLabel
Definition: ee_actions.h:141
static TOOL_ACTION toggleExcludeFromBoard
Definition: ee_actions.h:194
static TOOL_ACTION setDNP
Definition: ee_actions.h:195
static TOOL_ACTION cleanupSheetPins
Definition: ee_actions.h:229
static TOOL_ACTION slice
Definition: ee_actions.h:145
static TOOL_ACTION clearSelection
Clears the current selection.
Definition: ee_actions.h:56
static TOOL_ACTION drag
Definition: ee_actions.h:122
static TOOL_ACTION toText
Definition: ee_actions.h:142
static TOOL_ACTION placeClassLabel
Definition: ee_actions.h:88
static TOOL_ACTION showDeMorganAlternate
Definition: ee_actions.h:136
static TOOL_ACTION toggleExcludeFromBOM
Definition: ee_actions.h:188
static TOOL_ACTION autoplaceFields
Definition: ee_actions.h:133
static TOOL_ACTION showDeMorganStandard
Definition: ee_actions.h:135
static TOOL_ACTION rotateCCW
Definition: ee_actions.h:125
static TOOL_ACTION editValue
Definition: ee_actions.h:131
static TOOL_ACTION toLabel
Definition: ee_actions.h:138
static TOOL_ACTION toTextBox
Definition: ee_actions.h:143
static TOOL_ACTION breakWire
Definition: ee_actions.h:144
static TOOL_ACTION mirrorH
Definition: ee_actions.h:127
static TOOL_ACTION rotateCW
Definition: ee_actions.h:124
static TOOL_ACTION unsetExcludeFromBOM
Definition: ee_actions.h:187
static TOOL_ACTION editWithLibEdit
Definition: ee_actions.h:173
static TOOL_ACTION placeGlobalLabel
Definition: ee_actions.h:89
static TOOL_ACTION removeItemFromSel
Definition: ee_actions.h:60
static TOOL_ACTION ddAppendFile
Definition: ee_actions.h:298
static TOOL_ACTION placeHierLabel
Definition: ee_actions.h:90
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:164
static TOOL_ACTION changeSymbol
Definition: ee_actions.h:159
static TOOL_ACTION editFootprint
Definition: ee_actions.h:132
static TOOL_ACTION enterSheet
Definition: ee_actions.h:218
static TOOL_ACTION editReference
Definition: ee_actions.h:130
static TOOL_ACTION updateSymbols
Definition: ee_actions.h:158
static TOOL_ACTION placeSchematicText
Definition: ee_actions.h:97
static TOOL_ACTION setExcludeFromBOM
Definition: ee_actions.h:186
static TOOL_ACTION changeSymbols
Definition: ee_actions.h:157
static TOOL_ACTION setExcludeFromSimulation
Definition: ee_actions.h:189
static TOOL_ACTION unsetExcludeFromBoard
Definition: ee_actions.h:193
static TOOL_ACTION toCLabel
Definition: ee_actions.h:139
static TOOL_ACTION placeLabel
Definition: ee_actions.h:87
static TOOL_ACTION repeatDrawItem
Definition: ee_actions.h:123
static TOOL_ACTION toHLabel
Definition: ee_actions.h:140
static TOOL_ACTION editTextAndGraphics
Definition: ee_actions.h:230
static TOOL_ACTION toggleDNP
Definition: ee_actions.h:197
static TOOL_ACTION swap
Definition: ee_actions.h:128
static TOOL_ACTION toggleDeMorgan
Definition: ee_actions.h:134
static TOOL_ACTION updateSymbol
Definition: ee_actions.h:160
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:103
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
void RecacheAllItems()
Rebuild GAL display lists.
Definition: view.cpp:1454
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
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:223
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:142
void SetMotionHandler(MOTION_HANDLER aHandler)
Set a handler for mouse motion.
Definition: picker_tool.h:83
void SetClickHandler(CLICK_HANDLER aHandler)
Set a handler for mouse click event.
Definition: picker_tool.h:72
void SetSnapping(bool aSnap)
Definition: picker_tool.h:65
void SetCursor(KICURSOR aCursor)
Definition: picker_tool.h:63
void SetFinalizeHandler(FINALIZE_HANDLER aHandler)
Set a handler for the finalize event.
Definition: picker_tool.h:103
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.
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:297
SCH_SHEET & Root() const
Definition: schematic.h:113
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:41
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
Definition: sch_commit.cpp:406
virtual void Revert() override
Definition: sch_commit.cpp:484
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...
bool EditSheetProperties(SCH_SHEET *aSheet, SCH_SHEET_PATH *aHierarchy, bool *aIsUndoable=nullptr, bool *aClearAnnotationNewItems=nullptr, bool *aUpdateHierarchyNavigator=nullptr)
Edit an existing sheet or add a new sheet to the schematic.
Definition: sheet.cpp:593
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 SaveCopyInUndoList(SCH_SCREEN *aScreen, SCH_ITEM *aItemToCopy, UNDO_REDO aTypeCommand, bool aAppend, bool aDirtyConnectivity=true)
Create a copy of the current schematic item, and put it in the undo list.
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.
void FlipBodyStyle(SCH_SYMBOL *aSymbol)
Definition: picksymbol.cpp:126
void OnPageSettingsChange() override
Called when modifying the page settings.
bool AddSheetAndUpdateDisplay(const wxString aFullFileName)
Add a sheet file into the current sheet and updates display.
bool CheckSheetForRecursion(SCH_SHEET *aSheet, SCH_SHEET_PATH *aCurrentSheet)
Verify that aSheet will not cause a recursion error in aCurrentSheet.
Definition: sheet.cpp:51
void UpdateLabelsHierarchyNavigator()
Update the hierarchy navigation tree labels.
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)
Set up handlers for various events.
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 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)
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:1500
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
Definition: sch_field.cpp:1018
VECTOR2I GetPosition() const override
Definition: sch_field.cpp:1478
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:1245
int GetId() const
Definition: sch_field.h:133
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: sch_field.cpp:1220
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_field.cpp:1458
void SetText(const wxString &aText) override
Definition: sch_field.cpp:1205
VECTOR2I GetParentPosition() const
Definition: sch_field.cpp:1494
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:166
virtual bool IsConnectable() const
Definition: sch_item.h:449
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:232
virtual void MirrorHorizontally(int aCenter)
Mirror item horizontally about aCenter.
Definition: sch_item.h:343
virtual void Move(const VECTOR2I &aMoveVector)
Move the item by aMoveVector to a new position.
Definition: sch_item.h:335
int GetUnit() const
Definition: sch_item.h:229
void ClearFieldsAutoplaced()
Definition: sch_item.h:551
virtual void Rotate(const VECTOR2I &aCenter, bool aRotateCCW)
Rotate the item around aCenter 90 degrees in the clockwise direction.
Definition: sch_item.h:359
virtual void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual)
Definition: sch_item.h:566
wxString GetClass() const override
Return the class name.
Definition: sch_item.h:176
void AutoAutoplaceFields(SCH_SCREEN *aScreen)
Autoplace fields only if correct to do so automatically.
Definition: sch_item.h:560
virtual bool HasLineStroke() const
Check if this schematic item has line stoke properties.
Definition: sch_item.h:579
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition: sch_item.h:464
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:181
virtual void MirrorVertically(int aCenter)
Mirror item vertically about aCenter.
Definition: sch_item.h:351
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:499
SPIN_STYLE GetSpinStyle() const
Definition: sch_label.cpp:383
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:518
std::vector< SCH_FIELD > & GetFields()
Definition: sch_label.h:201
virtual void SetSpinStyle(SPIN_STYLE aSpinStyle)
Definition: sch_label.cpp:348
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:412
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 wxString & GetName() const
Definition: sch_pin.cpp:353
std::map< wxString, ALT > & GetAlternates()
Definition: sch_pin.h:121
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:710
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:486
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:391
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:117
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:71
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_shape.cpp:265
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:57
void SetFileName(const wxString &aFilename)
Definition: sch_sheet.h:312
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition: sch_sheet.h:306
VECTOR2I GetRotationCenter() const
Rotating around the boundingBox's center can cause walking when the sheetname or filename is longer t...
Definition: sch_sheet.cpp:753
void CleanupSheet()
Delete sheet label which do not have a corresponding hierarchical label.
Definition: sch_sheet.cpp:613
void RemovePin(const SCH_SHEET_PIN *aSheetPin)
Remove aSheetPin from the sheet.
Definition: sch_sheet.cpp:437
bool HasUndefinedPins() const
Check all sheet labels against schematic for undefined hierarchical labels.
Definition: sch_sheet.cpp:499
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:110
const BOX2I GetBodyBoundingBox() const
Return a bounding box for the sheet body but not the fields.
Definition: sch_sheet.cpp:721
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: sch_sheet.cpp:742
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
Definition: sch_sheet.cpp:920
Schematic symbol object.
Definition: sch_symbol.h:106
wxString SubReference(int aUnit, bool aAddSeparator=true) const
Definition: sch_symbol.cpp:851
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:934
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:235
const LIB_ID & GetLibId() const override
Definition: sch_symbol.h:195
int GetOrientation() const
Get the display symbol orientation.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:214
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
bool IsPower() const override
VECTOR2I GetPosition() const override
Definition: sch_table.cpp:115
VECTOR2I GetEnd() const
Definition: sch_table.cpp:121
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:171
virtual VECTOR2I GetCenter() const
Returns the center point of the selection area bounding box.
Definition: selection.cpp:93
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:265
bool OnlyContains(std::vector< KICAD_T > aList) const
Checks if all items in the selection have a type in aList.
Definition: selection.cpp:213
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:157
T * GetAppSettings()
Returns a handle to the a given settings by type If the settings have already been loaded,...
unsigned CCWRotationsTo(const SPIN_STYLE &aOther) const
Get CCW rotation needed to get to the given spin style.
Definition: sch_label.cpp:206
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.
void SetDNP(bool aDNP)
Definition: symbol.h:154
bool GetExcludedFromBoard() const
Definition: symbol.h:148
bool GetExcludedFromBOM() const
Definition: symbol.h:142
void SetExcludedFromSim(bool aExcludeFromSim) override
Set or clear the exclude from simulation flag.
Definition: symbol.h:135
bool GetDNP() const
Set or clear the 'Do Not Populate' flaga.
Definition: symbol.h:153
void SetExcludedFromBOM(bool aExcludeFromBOM)
Set or clear the exclude from schematic bill of materials flag.
Definition: symbol.h:141
void SetExcludedFromBoard(bool aExcludeFromBoard)
Set or clear exclude from board netlist flag.
Definition: symbol.h:147
bool GetExcludedFromSim() const override
Definition: symbol.h:136
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:42
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
Generic, UI-independent tool event.
Definition: tool_event.h:167
bool DisableGridSnapping() const
Definition: tool_event.h:363
bool Matches(const TOOL_EVENT &aEvent) const
Test whether two events match in terms of category & action or command.
Definition: tool_event.h:384
COMMIT * Commit() const
Returns information about difference between current mouse cursor position and the place where draggi...
Definition: tool_event.h:275
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:460
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_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.
#define HITTEST_THRESHOLD_PIXELS
static std::vector< KICAD_T > sheetTypes
@ 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:372
@ LAYER_SCHEMATIC_DRAWINGSHEET
Definition: layer_ids.h:398
#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:1059
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
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
@ SYM_MIRROR_Y
Definition: sch_symbol.h:87
@ SYM_MIRROR_X
Definition: sch_symbol.h:86
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
static const wxString GetDefaultFieldName(int aFieldNdx, bool aTranslateForHI=false)
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
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
#define TO_VJUSTIFY(x)
GR_TEXT_V_ALIGN_T
#define TO_HJUSTIFY(x)
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
constexpr ret_type KiROUND(fp_type v, bool aQuiet=false)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:100
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:676