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