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