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