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 <algorithm>
38#include <string_utils.h>
39#include <sch_bitmap.h>
40#include <sch_bus_entry.h>
41#include <sch_commit.h>
42#include <sch_group.h>
43#include <sch_junction.h>
44#include <sch_marker.h>
45#include <sch_rule_area.h>
46#include <sch_sheet_pin.h>
47#include <sch_textbox.h>
48#include <sch_table.h>
50#include <eeschema_id.h>
61#include <dialogs/dialog_text_properties.h>
62#include <dialogs/dialog_tablecell_properties.h>
63#include <dialogs/dialog_table_properties.h>
64#include <pgm_base.h>
67#include <core/kicad_algo.h>
68#include <view/view_controls.h>
69#include <wx/textdlg.h>
70#include <wx/msgdlg.h>
72
73
75{
76public:
78 ACTION_MENU( true )
79 {
81 SetTitle( _( "Symbol Unit" ) );
82 }
83
84protected:
85 ACTION_MENU* create() const override
86 {
87 return new SYMBOL_UNIT_MENU();
88 }
89
90private:
91 void update() override
92 {
94 SCH_SELECTION& selection = selTool->GetSelection();
95 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( selection.Front() );
96
97 Clear();
98
99 wxCHECK( symbol, /* void */ );
100
101 const int unit = symbol->GetUnit();
102 const int nUnits = symbol->GetLibSymbolRef()->GetUnitCount();
103 const std::set<int> missingUnits = GetUnplacedUnitsForSymbol( *symbol );
104
105 for( int ii = 0; ii < nUnits; ii++ )
106 {
107 wxString unit_text = symbol->GetUnitDisplayName( ii + 1, false );
108
109 if( missingUnits.count( ii + 1 ) == 0 )
110 unit_text += _( " (already placed)" );
111
112 wxMenuItem* item = Append( ID_POPUP_SCH_SELECT_UNIT1 + ii, unit_text, wxEmptyString,
113 wxITEM_CHECK );
114
115 if( unit == ii + 1 )
116 item->Check( true );
117
118 // The ID max for these submenus is ID_POPUP_SCH_SELECT_UNIT_END
119 // See eeschema_id to modify this value.
121 break; // We have used all IDs for these submenus
122 }
123
124 if( !missingUnits.empty() )
125 {
126 AppendSeparator();
127
128 for( int unitNumber : missingUnits )
129 {
130 wxString placeText = wxString::Format( _( "Place unit %s" ),
131 symbol->GetUnitDisplayName( unitNumber, false ) );
132 Append( ID_POPUP_SCH_PLACE_UNIT1 + unitNumber - 1, placeText );
133 }
134 }
135 }
136};
137
138
140{
141public:
143 ACTION_MENU( true )
144 {
146 SetTitle( _( "Body Style" ) );
147 }
148
149protected:
150 ACTION_MENU* create() const override
151 {
152 return new BODY_STYLE_MENU();
153 }
154
155private:
156 void update() override
157 {
159 SCH_SELECTION& selection = selTool->GetSelection();
160 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( selection.Front() );
161 wxMenuItem* item;
162
163 Clear();
164
165 wxCHECK( symbol, /* void */ );
166
167 if( symbol->HasDeMorganBodyStyles() )
168 {
169 item = Append( ID_POPUP_SCH_SELECT_BODY_STYLE, _( "Standard" ), wxEmptyString, wxITEM_CHECK );
170 item->Check( symbol->GetBodyStyle() == BODY_STYLE::BASE );
171
172 item = Append( ID_POPUP_SCH_SELECT_BODY_STYLE1, _( "Alternate" ), wxEmptyString, wxITEM_CHECK );
173 item->Check( symbol->GetBodyStyle() != BODY_STYLE::BASE );
174 }
175 else if( symbol->IsMultiBodyStyle() )
176 {
177 for( int i = 0; i < symbol->GetBodyStyleCount(); i++ )
178 {
179 item = Append( ID_POPUP_SCH_SELECT_BODY_STYLE + i, symbol->GetBodyStyleDescription( i + 1, true ),
180 wxEmptyString, wxITEM_CHECK );
181 item->Check( symbol->GetBodyStyle() == i + 1 );
182 }
183 }
184 }
185};
186
187
189{
190public:
192 ACTION_MENU( true )
193 {
195 SetTitle( _( "Pin Function" ) );
196 }
197
198protected:
199 ACTION_MENU* create() const override
200 {
201 return new ALT_PIN_FUNCTION_MENU();
202 }
203
204private:
205 void update() override
206 {
208 SCH_SELECTION& selection = selTool->GetSelection();
209 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( selection.Front() );
210 SCH_PIN* libPin = pin ? pin->GetLibPin() : nullptr;
211
212 Clear();
213
214 wxCHECK( libPin, /* void */ );
215
216 wxMenuItem* item = Append( ID_POPUP_SCH_ALT_PIN_FUNCTION, libPin->GetName(), wxEmptyString,
217 wxITEM_CHECK );
218
219 if( pin->GetAlt().IsEmpty() || ( pin->GetAlt() == libPin->GetName() ) )
220 item->Check( true );
221
222 int ii = 1;
223
224 for( const auto& [ name, definition ] : libPin->GetAlternates() )
225 {
226 // The default pin name is set above, avoid setting it again.
227 if( name == libPin->GetName() )
228 continue;
229
230 item = Append( ID_POPUP_SCH_ALT_PIN_FUNCTION + ii, name, wxEmptyString, wxITEM_CHECK );
231
232 if( name == pin->GetAlt() )
233 item->Check( true );
234
235 // The ID max for these submenus is ID_POPUP_SCH_ALT_PIN_FUNCTION_END
236 // See eeschema_id to modify this value.
238 break; // We have used all IDs for these submenus
239 }
240 }
241};
242
243
245{
246public:
248 {
250 SetTitle( _( "Pin Helpers" ) );
251 }
252
253protected:
254 ACTION_MENU* create() const override { return new PIN_TRICKS_MENU(); }
255
256private:
257 void update() override
258 {
260 SCH_SELECTION& selection = selTool->GetSelection();
261 SCH_PIN* pin = dynamic_cast<SCH_PIN*>( selection.Front() );
262 SCH_SHEET_PIN* sheetPin = dynamic_cast<SCH_SHEET_PIN*>( selection.Front() );
263
264 Clear();
265
266 if( !pin && !sheetPin )
267 return;
268
274 }
275};
276
277
279 SCH_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.InteractiveEdit" )
280{
281 m_pickerItem = nullptr;
282}
283
284
286
288{
290
291 SCH_DRAWING_TOOLS* drawingTools = m_toolMgr->GetTool<SCH_DRAWING_TOOLS>();
292 SCH_MOVE_TOOL* moveTool = m_toolMgr->GetTool<SCH_MOVE_TOOL>();
293
294 wxASSERT_MSG( drawingTools, "eeshema.InteractiveDrawing tool is not available" );
295
296 auto hasElements =
297 [this]( const SELECTION& aSel )
298 {
299 return !m_frame->GetScreen()->Items().empty();
300 };
301
302 auto sheetHasUndefinedPins =
303 []( const SELECTION& aSel )
304 {
305 if( aSel.Size() == 1 && aSel.Front()->Type() == SCH_SHEET_T )
306 return static_cast<SCH_SHEET*>( aSel.Front() )->HasUndefinedPins();
307
308 return false;
309 };
310
311 auto attribDNPCond =
312 [] ( const SELECTION& aSel )
313 {
314 return std::all_of( aSel.Items().begin(), aSel.Items().end(),
315 []( const EDA_ITEM* item )
316 {
317 return !item->IsType( { SCH_SYMBOL_T } )
318 || static_cast<const SCH_SYMBOL*>( item )->GetDNP();
319 } );
320 };
321
322 auto attribExcludeFromSimCond =
323 [] ( const SELECTION& aSel )
324 {
325 return std::all_of( aSel.Items().begin(), aSel.Items().end(),
326 []( const EDA_ITEM* item )
327 {
328 return !item->IsType( { SCH_SYMBOL_T } )
329 || static_cast<const SCH_SYMBOL*>( item )->GetExcludedFromSim();
330 } );
331 };
332
333 auto attribExcludeFromBOMCond =
334 [] ( const SELECTION& aSel )
335 {
336 return std::all_of( aSel.Items().begin(), aSel.Items().end(),
337 []( const EDA_ITEM* item )
338 {
339 return !item->IsType( { SCH_SYMBOL_T } )
340 || static_cast<const SCH_SYMBOL*>( item )->GetExcludedFromBOM();
341 } );
342 };
343
344
345 auto attribExcludeFromBoardCond =
346 [] ( const SELECTION& aSel )
347 {
348 return std::all_of( aSel.Items().begin(), aSel.Items().end(),
349 []( const EDA_ITEM* item )
350 {
351 return !item->IsType( { SCH_SYMBOL_T } )
352 || static_cast<const SCH_SYMBOL*>( item )->GetExcludedFromBoard();
353 } );
354 };
355
356 static const std::vector<KICAD_T> sheetTypes = { SCH_SHEET_T };
357
358 auto sheetSelection = S_C::Count( 1 ) && S_C::OnlyTypes( sheetTypes );
359
360 auto haveHighlight =
361 [this]( const SELECTION& sel )
362 {
363 SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
364
365 return editFrame && !editFrame->GetHighlightedConnection().IsEmpty();
366 };
367
368 auto anyTextTool =
369 [this]( const SELECTION& aSel )
370 {
371 return ( m_frame->IsCurrentTool( SCH_ACTIONS::placeLabel )
372 || m_frame->IsCurrentTool( SCH_ACTIONS::placeClassLabel )
373 || m_frame->IsCurrentTool( SCH_ACTIONS::placeGlobalLabel )
374 || m_frame->IsCurrentTool( SCH_ACTIONS::placeHierLabel )
375 || m_frame->IsCurrentTool( SCH_ACTIONS::placeSchematicText ) );
376 };
377
378 auto duplicateCondition =
379 []( const SELECTION& aSel )
380 {
382 return false;
383
384 return true;
385 };
386
387 auto orientCondition =
388 []( const SELECTION& aSel )
389 {
391 return false;
392
394 };
395
396 auto propertiesCondition =
397 [this]( const SELECTION& aSel )
398 {
399 if( aSel.GetSize() == 0 )
400 {
401 if( getView()->IsLayerVisible( LAYER_SCHEMATIC_DRAWINGSHEET ) )
402 {
403 DS_PROXY_VIEW_ITEM* ds = m_frame->GetCanvas()->GetView()->GetDrawingSheet();
404 VECTOR2D cursor = getViewControls()->GetCursorPosition( false );
405
406 if( ds && ds->HitTestDrawingSheetItems( getView(), cursor ) )
407 return true;
408 }
409
410 return false;
411 }
412
413 SCH_ITEM* firstItem = dynamic_cast<SCH_ITEM*>( aSel.Front() );
414 const SCH_SELECTION* eeSelection = dynamic_cast<const SCH_SELECTION*>( &aSel );
415
416 if( !firstItem || !eeSelection )
417 return false;
418
419 switch( firstItem->Type() )
420 {
421 case SCH_SYMBOL_T:
422 case SCH_SHEET_T:
423 case SCH_SHEET_PIN_T:
424 case SCH_TEXT_T:
425 case SCH_TEXTBOX_T:
426 case SCH_TABLE_T:
427 case SCH_TABLECELL_T:
428 case SCH_LABEL_T:
430 case SCH_HIER_LABEL_T:
432 case SCH_RULE_AREA_T:
433 case SCH_FIELD_T:
434 case SCH_SHAPE_T:
435 case SCH_BITMAP_T:
436 case SCH_GROUP_T:
437 return aSel.GetSize() == 1;
438
439 case SCH_LINE_T:
441 case SCH_JUNCTION_T:
442 if( std::all_of( aSel.Items().begin(), aSel.Items().end(),
443 [&]( const EDA_ITEM* item )
444 {
445 return item->Type() == SCH_LINE_T
446 && static_cast<const SCH_LINE*>( item )->IsGraphicLine();
447 } ) )
448 {
449 return true;
450 }
451 else if( std::all_of( aSel.Items().begin(), aSel.Items().end(),
452 [&]( const EDA_ITEM* item )
453 {
454 return item->Type() == SCH_JUNCTION_T;
455 } ) )
456 {
457 return true;
458 }
459 else if( std::all_of( aSel.Items().begin(), aSel.Items().end(),
460 [&]( const EDA_ITEM* item )
461 {
462 const SCH_ITEM* schItem = dynamic_cast<const SCH_ITEM*>( item );
463
464 wxCHECK( schItem, false );
465
466 return ( schItem->HasLineStroke() && schItem->IsConnectable() )
467 || item->Type() == SCH_JUNCTION_T;
468 } ) )
469 {
470 return true;
471 }
472
473 return false;
474
475 default:
476 return false;
477 }
478 };
479
480 auto autoplaceCondition =
481 []( const SELECTION& aSel )
482 {
483 for( const EDA_ITEM* item : aSel )
484 {
486 return true;
487 }
488
489 return false;
490 };
491
492 // allTextTypes does not include SCH_SHEET_PIN_T because one cannot convert other
493 // types to/from this type, living only in a SHEET
494 static const std::vector<KICAD_T> allTextTypes = { SCH_LABEL_T,
500
501 auto toChangeCondition = ( S_C::OnlyTypes( allTextTypes ) );
502
503 static const std::vector<KICAD_T> toLabelTypes = { SCH_DIRECTIVE_LABEL_T,
508
509 auto toLabelCondition = ( S_C::Count( 1 ) && S_C::OnlyTypes( toLabelTypes ) )
510 || ( S_C::MoreThan( 1 ) && S_C::OnlyTypes( allTextTypes ) );
511
512 static const std::vector<KICAD_T> toCLabelTypes = { SCH_LABEL_T,
517
518 auto toCLabelCondition = ( S_C::Count( 1 ) && S_C::OnlyTypes( toCLabelTypes ) )
519 || ( S_C::MoreThan( 1 ) && S_C::OnlyTypes( allTextTypes ) );
520
521 static const std::vector<KICAD_T> toHLabelTypes = { SCH_LABEL_T,
526
527 auto toHLabelCondition = ( S_C::Count( 1 ) && S_C::OnlyTypes( toHLabelTypes ) )
528 || ( S_C::MoreThan( 1 ) && S_C::OnlyTypes( allTextTypes ) );
529
530 static const std::vector<KICAD_T> toGLabelTypes = { SCH_LABEL_T,
535
536 auto toGLabelCondition = ( S_C::Count( 1 ) && S_C::OnlyTypes( toGLabelTypes ) )
537 || ( S_C::MoreThan( 1 ) && S_C::OnlyTypes( allTextTypes ) );
538
539 static const std::vector<KICAD_T> toTextTypes = { SCH_LABEL_T,
544
545 auto toTextCondition = ( S_C::Count( 1 ) && S_C::OnlyTypes( toTextTypes ) )
546 || ( S_C::MoreThan( 1 ) && S_C::OnlyTypes( allTextTypes ) );
547
548 static const std::vector<KICAD_T> toTextBoxTypes = { SCH_LABEL_T,
552 SCH_TEXT_T };
553
554 auto toTextBoxCondition = ( S_C::Count( 1 ) && S_C::OnlyTypes( toTextBoxTypes ) )
555 || ( S_C::MoreThan( 1 ) && S_C::OnlyTypes( allTextTypes ) );
556
557 static const std::vector<KICAD_T> busEntryTypes = { SCH_BUS_WIRE_ENTRY_T, SCH_BUS_BUS_ENTRY_T};
558
559 auto entryCondition = S_C::MoreThan( 0 ) && S_C::OnlyTypes( busEntryTypes );
560
561 auto singleSheetCondition = S_C::Count( 1 ) && S_C::OnlyTypes( sheetTypes );
562
563 auto makeSymbolUnitMenu =
564 [&]( TOOL_INTERACTIVE* tool )
565 {
566 std::shared_ptr<SYMBOL_UNIT_MENU> menu = std::make_shared<SYMBOL_UNIT_MENU>();
567 menu->SetTool( tool );
568 tool->GetToolMenu().RegisterSubMenu( menu );
569 return menu.get();
570 };
571
572 auto makeBodyStyleMenu =
573 [&]( TOOL_INTERACTIVE* tool )
574 {
575 std::shared_ptr<BODY_STYLE_MENU> menu = std::make_shared<BODY_STYLE_MENU>();
576 menu->SetTool( tool );
577 tool->GetToolMenu().RegisterSubMenu( menu );
578 return menu.get();
579 };
580
581 auto makePinFunctionMenu =
582 [&]( TOOL_INTERACTIVE* tool )
583 {
584 std::shared_ptr<ALT_PIN_FUNCTION_MENU> menu = std::make_shared<ALT_PIN_FUNCTION_MENU>();
585 menu->SetTool( tool );
586 tool->GetToolMenu().RegisterSubMenu( menu );
587 return menu.get();
588 };
589
590 auto makePinTricksMenu =
591 [&]( TOOL_INTERACTIVE* tool )
592 {
593 std::shared_ptr<PIN_TRICKS_MENU> menu = std::make_shared<PIN_TRICKS_MENU>();
594 menu->SetTool( tool );
595 tool->GetToolMenu().RegisterSubMenu( menu );
596 return menu.get();
597 };
598
599 auto makeTransformMenu =
600 [&]()
601 {
602 CONDITIONAL_MENU* menu = new CONDITIONAL_MENU( moveTool );
603 menu->SetTitle( _( "Transform Selection" ) );
604
605 menu->AddItem( SCH_ACTIONS::rotateCCW, orientCondition );
606 menu->AddItem( SCH_ACTIONS::rotateCW, orientCondition );
607 menu->AddItem( SCH_ACTIONS::mirrorV, orientCondition );
608 menu->AddItem( SCH_ACTIONS::mirrorH, orientCondition );
609
610 return menu;
611 };
612
613 auto makeAttributesMenu =
614 [&]()
615 {
616 CONDITIONAL_MENU* menu = new CONDITIONAL_MENU( moveTool );
617 menu->SetTitle( _( "Attributes" ) );
618
623
624 return menu;
625 };
626
627 auto makeEditFieldsMenu =
628 [&]()
629 {
630 CONDITIONAL_MENU* menu = new CONDITIONAL_MENU( m_selectionTool );
631 menu->SetTitle( _( "Edit Main Fields" ) );
632
636
637 return menu;
638 };
639
640 auto makeConvertToMenu =
641 [&]()
642 {
643 CONDITIONAL_MENU* menu = new CONDITIONAL_MENU( m_selectionTool );
644 menu->SetTitle( _( "Change To" ) );
645 menu->SetIcon( BITMAPS::right );
646
647 menu->AddItem( SCH_ACTIONS::toLabel, toLabelCondition );
648 menu->AddItem(SCH_ACTIONS::toDLabel, toCLabelCondition );
649 menu->AddItem( SCH_ACTIONS::toHLabel, toHLabelCondition );
650 menu->AddItem( SCH_ACTIONS::toGLabel, toGLabelCondition );
651 menu->AddItem( SCH_ACTIONS::toText, toTextCondition );
652 menu->AddItem( SCH_ACTIONS::toTextBox, toTextBoxCondition );
653
654 return menu;
655 };
656
657 const auto canCopyText = SCH_CONDITIONS::OnlyTypes( {
666 SCH_PIN_T,
669 } );
670
671 //
672 // Add edit actions to the move tool menu
673 //
674 CONDITIONAL_MENU& moveMenu = moveTool->GetToolMenu().GetMenu();
675
676 moveMenu.AddSeparator();
677 moveMenu.AddMenu( makeSymbolUnitMenu( moveTool ), S_C::SingleMultiUnitSymbol, 1 );
678 moveMenu.AddMenu( makeBodyStyleMenu( moveTool ), S_C::SingleMultiBodyStyleSymbol, 1 );
679
680 moveMenu.AddMenu( makeTransformMenu(), orientCondition, 200 );
681 moveMenu.AddMenu( makeAttributesMenu(), S_C::HasType( SCH_SYMBOL_T ), 200 );
682 moveMenu.AddItem( SCH_ACTIONS::swap, SELECTION_CONDITIONS::MoreThan( 1 ), 200);
683 moveMenu.AddItem( SCH_ACTIONS::properties, propertiesCondition, 200 );
684 moveMenu.AddMenu( makeEditFieldsMenu(), S_C::SingleSymbol, 200 );
685
686 moveMenu.AddSeparator();
687 moveMenu.AddItem( ACTIONS::cut, S_C::IdleSelection );
688 moveMenu.AddItem( ACTIONS::copy, S_C::IdleSelection );
689 moveMenu.AddItem( ACTIONS::copyAsText, canCopyText && S_C::IdleSelection );
690 moveMenu.AddItem( ACTIONS::doDelete, S_C::NotEmpty );
691 moveMenu.AddItem( ACTIONS::duplicate, duplicateCondition );
692
693 //
694 // Add editing actions to the drawing tool menu
695 //
696 CONDITIONAL_MENU& drawMenu = drawingTools->GetToolMenu().GetMenu();
697
698 drawMenu.AddItem( SCH_ACTIONS::clearHighlight, haveHighlight && SCH_CONDITIONS::Idle, 1 );
699 drawMenu.AddSeparator( haveHighlight && SCH_CONDITIONS::Idle, 1 );
700
701 drawMenu.AddItem( SCH_ACTIONS::enterSheet, sheetSelection && SCH_CONDITIONS::Idle, 1 );
702 drawMenu.AddSeparator( sheetSelection && SCH_CONDITIONS::Idle, 1 );
703
704 drawMenu.AddMenu( makeSymbolUnitMenu( drawingTools ), S_C::SingleMultiUnitSymbol, 1 );
705 drawMenu.AddMenu( makeBodyStyleMenu( drawingTools ), S_C::SingleMultiBodyStyleSymbol, 1 );
706
707 drawMenu.AddMenu( makeTransformMenu(), orientCondition, 200 );
708 drawMenu.AddMenu( makeAttributesMenu(), S_C::HasType( SCH_SYMBOL_T ), 200 );
709 drawMenu.AddItem( SCH_ACTIONS::properties, propertiesCondition, 200 );
710 drawMenu.AddMenu( makeEditFieldsMenu(), S_C::SingleSymbol, 200 );
711 drawMenu.AddItem( SCH_ACTIONS::autoplaceFields, autoplaceCondition, 200 );
712
714
715 drawMenu.AddItem( SCH_ACTIONS::toLabel, anyTextTool && S_C::Idle, 200 );
716 drawMenu.AddItem( SCH_ACTIONS::toHLabel, anyTextTool && S_C::Idle, 200 );
717 drawMenu.AddItem( SCH_ACTIONS::toGLabel, anyTextTool && S_C::Idle, 200 );
718 drawMenu.AddItem( SCH_ACTIONS::toText, anyTextTool && S_C::Idle, 200 );
719 drawMenu.AddItem( SCH_ACTIONS::toTextBox, anyTextTool && S_C::Idle, 200 );
720
721 //
722 // Add editing actions to the selection tool menu
723 //
724 CONDITIONAL_MENU& selToolMenu = m_selectionTool->GetToolMenu().GetMenu();
725
726 selToolMenu.AddMenu( makeSymbolUnitMenu( m_selectionTool ), S_C::SingleMultiUnitSymbol, 1 );
727 selToolMenu.AddMenu( makeBodyStyleMenu( m_selectionTool ), S_C::SingleMultiBodyStyleSymbol, 1 );
728 selToolMenu.AddMenu( makePinFunctionMenu( m_selectionTool ), S_C::SingleMultiFunctionPin, 1 );
729 selToolMenu.AddMenu( makePinTricksMenu( m_selectionTool ), S_C::AllPinsOrSheetPins, 1 );
730
731 selToolMenu.AddMenu( makeTransformMenu(), orientCondition, 200 );
732 selToolMenu.AddMenu( makeAttributesMenu(), S_C::HasType( SCH_SYMBOL_T ), 200 );
734 selToolMenu.AddItem( SCH_ACTIONS::properties, propertiesCondition, 200 );
735 selToolMenu.AddMenu( makeEditFieldsMenu(), S_C::SingleSymbol, 200 );
736 selToolMenu.AddItem( SCH_ACTIONS::autoplaceFields, autoplaceCondition, 200 );
737
743 selToolMenu.AddMenu( makeConvertToMenu(), toChangeCondition, 200 );
744
745 selToolMenu.AddItem( SCH_ACTIONS::cleanupSheetPins, sheetHasUndefinedPins, 250 );
746
747 selToolMenu.AddSeparator( 300 );
748 selToolMenu.AddItem( ACTIONS::cut, S_C::IdleSelection, 300 );
749 selToolMenu.AddItem( ACTIONS::copy, S_C::IdleSelection, 300 );
750 selToolMenu.AddItem( ACTIONS::copyAsText, canCopyText && S_C::IdleSelection, 300 );
751 selToolMenu.AddItem( ACTIONS::paste, S_C::Idle, 300 );
752 selToolMenu.AddItem( ACTIONS::pasteSpecial, S_C::Idle, 300 );
753 selToolMenu.AddItem( ACTIONS::doDelete, S_C::NotEmpty, 300 );
754 selToolMenu.AddItem( ACTIONS::duplicate, duplicateCondition, 300 );
755
756 selToolMenu.AddSeparator( 400 );
757 selToolMenu.AddItem( ACTIONS::selectAll, hasElements, 400 );
758 selToolMenu.AddItem( ACTIONS::unselectAll, hasElements, 400 );
759
760 ACTION_MANAGER* mgr = m_toolMgr->GetActionManager();
761 // clang-format off
762 mgr->SetConditions( SCH_ACTIONS::setDNP, ACTION_CONDITIONS().Check( attribDNPCond ) );
763 mgr->SetConditions( SCH_ACTIONS::setExcludeFromSimulation, ACTION_CONDITIONS().Check( attribExcludeFromSimCond ) );
764 mgr->SetConditions( SCH_ACTIONS::setExcludeFromBOM, ACTION_CONDITIONS().Check( attribExcludeFromBOMCond ) );
765 mgr->SetConditions( SCH_ACTIONS::setExcludeFromBoard, ACTION_CONDITIONS().Check( attribExcludeFromBoardCond ) );
766 // clang-format on
767
768 return true;
769}
770
771
772const std::vector<KICAD_T> SCH_EDIT_TOOL::RotatableItems = {
778 SCH_TABLECELL_T, // will be promoted to parent table(s)
794};
795
796
798{
799 bool clockwise = ( aEvent.Matches( SCH_ACTIONS::rotateCW.MakeEvent() ) );
800 SCH_SELECTION& selection = m_selectionTool->RequestSelection( RotatableItems, true, false );
801
802 if( selection.GetSize() == 0 )
803 return 0;
804
805 SCH_ITEM* head = nullptr;
806 int principalItemCount = 0; // User-selected items (as opposed to connected wires)
807 VECTOR2I rotPoint;
808 bool moving = false;
809 SCH_COMMIT localCommit( m_toolMgr );
810 SCH_COMMIT* commit = dynamic_cast<SCH_COMMIT*>( aEvent.Commit() );
811
812 if( !commit )
813 commit = &localCommit;
814
815 for( unsigned ii = 0; ii < selection.GetSize(); ii++ )
816 {
817 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.GetItem( ii ) );
818
819 if( item->HasFlag( SELECTED_BY_DRAG ) )
820 continue;
821
822 principalItemCount++;
823
824 if( !head )
825 head = item;
826 }
827
828 if( head && head->IsMoving() )
829 moving = true;
830
831 if( principalItemCount == 1 )
832 {
833 if( moving && selection.HasReferencePoint() )
834 rotPoint = selection.GetReferencePoint();
835 else if( head->IsConnectable() )
836 rotPoint = head->GetPosition();
837 else
838 rotPoint = m_frame->GetNearestHalfGridPosition( head->GetBoundingBox().GetCenter() );
839
840 if( !moving )
841 commit->Modify( head, m_frame->GetScreen(), RECURSE_MODE::RECURSE );
842
843 switch( head->Type() )
844 {
845 case SCH_SYMBOL_T:
846 {
847 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( head );
848
849 symbol->Rotate( rotPoint, !clockwise );
850
851 if( m_frame->eeconfig()->m_AutoplaceFields.enable )
852 {
853 AUTOPLACE_ALGO fieldsAutoplaced = symbol->GetFieldsAutoplaced();
854
855 if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
856 symbol->AutoplaceFields( m_frame->GetScreen(), fieldsAutoplaced );
857 }
858
859 break;
860 }
861
862 case SCH_TEXT_T:
863 case SCH_LABEL_T:
865 case SCH_HIER_LABEL_T:
867 {
868 SCH_TEXT* textItem = static_cast<SCH_TEXT*>( head );
869 textItem->Rotate90( clockwise );
870 break;
871 }
872
873 case SCH_SHEET_PIN_T:
874 {
875 // Rotate pin within parent sheet
876 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( head );
877 SCH_SHEET* sheet = pin->GetParent();
878
879 pin->Rotate( sheet->GetBoundingBox().GetCenter(), !clockwise );
880
881 break;
882 }
883
884 case SCH_LINE_T:
885 {
886 SCH_LINE* line = static_cast<SCH_LINE*>( head );
887
888 // Equal checks for both and neither. We need this because on undo
889 // the item will have both flags cleared, but will be selected, so it is possible
890 // for the user to get a selected line with neither endpoint selected. We
891 // set flags to make sure Rotate() works when we call it.
892 if( line->HasFlag( STARTPOINT ) == line->HasFlag( ENDPOINT ) )
893 {
894 line->SetFlags( STARTPOINT | ENDPOINT );
895
896 // When we allow off grid items, the rotPoint should be set to the midpoint
897 // of the line to allow rotation around the center, and the next if
898 // should become an else-if
899 }
900
901 if( line->HasFlag( STARTPOINT ) )
902 rotPoint = line->GetEndPoint();
903 else if( line->HasFlag( ENDPOINT ) )
904 rotPoint = line->GetStartPoint();
905 }
906
908 case SCH_JUNCTION_T:
909 case SCH_NO_CONNECT_T:
912 head->Rotate( rotPoint, !clockwise );
913
914 break;
915
916 case SCH_FIELD_T:
917 {
918 SCH_FIELD* field = static_cast<SCH_FIELD*>( head );
919
920 if( field->GetTextAngle().IsHorizontal() )
922 else
924
925 // Now that we're moving a field, they're no longer autoplaced.
926 static_cast<SCH_ITEM*>( head->GetParent() )->SetFieldsAutoplaced( AUTOPLACE_NONE );
927
928 break;
929 }
930
931 case SCH_RULE_AREA_T:
932 case SCH_SHAPE_T:
933 case SCH_TEXTBOX_T:
934 head->Rotate( rotPoint, !clockwise );
935
936 break;
937
938 case SCH_GROUP_T:
939 {
940 // Rotate the group on itself. Groups do not have an anchor point.
941 SCH_GROUP* group = static_cast<SCH_GROUP*>( head );
942 rotPoint = m_frame->GetNearestHalfGridPosition( group->GetPosition() );
943
944 group->Rotate( rotPoint, !clockwise );
945
946 group->Move( rotPoint - m_frame->GetNearestHalfGridPosition( group->GetPosition() ) );
947
948 break;
949 }
950
951 case SCH_TABLE_T:
952 {
953 // Rotate the table on itself. Tables do not have an anchor point.
954 SCH_TABLE* table = static_cast<SCH_TABLE*>( head );
955 rotPoint = m_frame->GetNearestHalfGridPosition( table->GetCenter() );
956
957 table->Rotate( rotPoint, !clockwise );
958
959 table->Move( rotPoint - m_frame->GetNearestHalfGridPosition( table->GetCenter() ) );
960
961 break;
962 }
963
964 case SCH_BITMAP_T:
965 head->Rotate( rotPoint, !clockwise );
966
967 // The bitmap is cached in Opengl: clear the cache to redraw
969 break;
970
971 case SCH_SHEET_T:
972 {
973 // Rotate the sheet on itself. Sheets do not have an anchor point.
974 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( head );
975
976 rotPoint = m_frame->GetNearestHalfGridPosition( sheet->GetRotationCenter() );
977 sheet->Rotate( rotPoint, !clockwise );
978
979 break;
980 }
981
982 default:
983 UNIMPLEMENTED_FOR( head->GetClass() );
984 }
985
986 m_frame->UpdateItem( head, false, true );
987 }
988 else
989 {
990 if( moving && selection.HasReferencePoint() )
991 rotPoint = selection.GetReferencePoint();
992 else
993 rotPoint = m_frame->GetNearestHalfGridPosition( selection.GetCenter() );
994 }
995
996 for( EDA_ITEM* edaItem : selection )
997 {
998 SCH_ITEM* item = static_cast<SCH_ITEM*>( edaItem );
999
1000 // We've already rotated the user selected item if there was only one. We're just
1001 // here to rotate the ends of wires that were attached to it.
1002 if( principalItemCount == 1 && !item->HasFlag( SELECTED_BY_DRAG ) )
1003 continue;
1004
1005 if( !moving )
1006 commit->Modify( item, m_frame->GetScreen(), RECURSE_MODE::RECURSE );
1007
1008 if( item->Type() == SCH_LINE_T )
1009 {
1010 SCH_LINE* line = (SCH_LINE*) item;
1011
1012 line->Rotate( rotPoint, !clockwise );
1013 }
1014 else if( item->Type() == SCH_SHEET_PIN_T )
1015 {
1016 if( item->GetParent()->IsSelected() )
1017 {
1018 // parent will rotate us
1019 }
1020 else
1021 {
1022 // rotate within parent
1023 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( item );
1024 SCH_SHEET* sheet = pin->GetParent();
1025
1026 pin->Rotate( sheet->GetBodyBoundingBox().GetCenter(), !clockwise );
1027 }
1028 }
1029 else if( item->Type() == SCH_FIELD_T )
1030 {
1031 if( item->GetParent()->IsSelected() )
1032 {
1033 // parent will rotate us
1034 }
1035 else
1036 {
1037 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
1038
1039 field->Rotate( rotPoint, !clockwise );
1040
1041 // Now that we're moving a field, they're no longer autoplaced.
1042 static_cast<SCH_ITEM*>( field->GetParent() )->SetFieldsAutoplaced( AUTOPLACE_NONE );
1043 }
1044 }
1045 else if( item->Type() == SCH_TABLE_T )
1046 {
1047 SCH_TABLE* table = static_cast<SCH_TABLE*>( item );
1048 VECTOR2I beforeCenter = table->GetCenter();
1049
1050 table->Rotate( rotPoint, !clockwise );
1051 RotatePoint( beforeCenter, rotPoint, clockwise ? -ANGLE_90 : ANGLE_90 );
1052
1053 table->Move( beforeCenter - table->GetCenter() );
1054 }
1055 else
1056 {
1057 item->Rotate( rotPoint, !clockwise );
1058 }
1059
1060 m_frame->UpdateItem( item, false, true );
1061 updateItem( item, true );
1062 }
1063
1064 if( moving )
1065 {
1066 m_toolMgr->PostAction( ACTIONS::refreshPreview );
1067 }
1068 else
1069 {
1070 SCH_SELECTION selectionCopy = selection;
1071
1072 if( selection.IsHover() )
1073 m_toolMgr->RunAction( ACTIONS::selectionClear );
1074
1076 lwbTool->TrimOverLappingWires( commit, &selectionCopy );
1077 lwbTool->AddJunctionsIfNeeded( commit, &selectionCopy );
1078
1079 m_frame->Schematic().CleanUp( commit );
1080
1081 if( !localCommit.Empty() )
1082 localCommit.Push( _( "Rotate" ) );
1083 }
1084
1085 return 0;
1086}
1087
1088
1090{
1091 SCH_SELECTION& selection = m_selectionTool->RequestSelection( RotatableItems, false, false );
1092
1093 if( selection.GetSize() == 0 )
1094 return 0;
1095
1096 bool vertical = ( aEvent.Matches( SCH_ACTIONS::mirrorV.MakeEvent() ) );
1097 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.Front() );
1098 bool connections = false;
1099 bool moving = item->IsMoving();
1100 SCH_COMMIT localCommit( m_toolMgr );
1101 SCH_COMMIT* commit = dynamic_cast<SCH_COMMIT*>( aEvent.Commit() );
1102
1103 if( !commit )
1104 commit = &localCommit;
1105
1106 if( selection.GetSize() == 1 )
1107 {
1108 if( !moving )
1109 commit->Modify( item, m_frame->GetScreen(), RECURSE_MODE::RECURSE );
1110
1111 switch( item->Type() )
1112 {
1113 case SCH_SYMBOL_T:
1114 {
1115 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1116
1117 if( vertical )
1118 symbol->SetOrientation( SYM_MIRROR_X );
1119 else
1120 symbol->SetOrientation( SYM_MIRROR_Y );
1121
1123 break;
1124 }
1125
1126 case SCH_TEXT_T:
1127 case SCH_LABEL_T:
1128 case SCH_GLOBAL_LABEL_T:
1129 case SCH_HIER_LABEL_T:
1131 {
1132 SCH_TEXT* textItem = static_cast<SCH_TEXT*>( item );
1133 textItem->MirrorSpinStyle( !vertical );
1134 break;
1135 }
1136
1137 case SCH_SHEET_PIN_T:
1138 {
1139 // mirror within parent sheet
1140 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( item );
1141 SCH_SHEET* sheet = pin->GetParent();
1142
1143 if( vertical )
1144 pin->MirrorVertically( sheet->GetBoundingBox().GetCenter().y );
1145 else
1146 pin->MirrorHorizontally( sheet->GetBoundingBox().GetCenter().x );
1147
1148 break;
1149 }
1150
1151 case SCH_FIELD_T:
1152 {
1153 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
1154
1155 if( vertical )
1157 else
1159
1160 // Now that we're re-justifying a field, they're no longer autoplaced.
1161 static_cast<SCH_ITEM*>( field->GetParent() )->SetFieldsAutoplaced( AUTOPLACE_NONE );
1162
1163 break;
1164 }
1165
1166 case SCH_BITMAP_T:
1167 if( vertical )
1168 item->MirrorVertically( item->GetPosition().y );
1169 else
1170 item->MirrorHorizontally( item->GetPosition().x );
1171
1172 // The bitmap is cached in Opengl: clear the cache to redraw
1174 break;
1175
1176 case SCH_SHEET_T:
1177 {
1178 // Mirror the sheet on itself. Sheets do not have a anchor point.
1179 VECTOR2I mirrorPoint = m_frame->GetNearestHalfGridPosition( item->GetBoundingBox().Centre() );
1180
1181 if( vertical )
1182 item->MirrorVertically( mirrorPoint.y );
1183 else
1184 item->MirrorHorizontally( mirrorPoint.x );
1185
1186 break;
1187 }
1188
1189 default:
1190 if( vertical )
1191 item->MirrorVertically( item->GetPosition().y );
1192 else
1193 item->MirrorHorizontally( item->GetPosition().x );
1194
1195 break;
1196 }
1197
1198 connections = item->IsConnectable();
1199 m_frame->UpdateItem( item, false, true );
1200 }
1201 else if( selection.GetSize() > 1 )
1202 {
1203 VECTOR2I mirrorPoint = m_frame->GetNearestHalfGridPosition( selection.GetCenter() );
1204
1205 for( EDA_ITEM* edaItem : selection )
1206 {
1207 item = static_cast<SCH_ITEM*>( edaItem );
1208
1209 if( !moving )
1210 commit->Modify( item, m_frame->GetScreen(), RECURSE_MODE::RECURSE );
1211
1212 if( item->Type() == SCH_SHEET_PIN_T )
1213 {
1214 if( item->GetParent()->IsSelected() )
1215 {
1216 // parent will mirror us
1217 }
1218 else
1219 {
1220 // mirror within parent sheet
1221 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( item );
1222 SCH_SHEET* sheet = pin->GetParent();
1223
1224 if( vertical )
1225 pin->MirrorVertically( sheet->GetBoundingBox().GetCenter().y );
1226 else
1227 pin->MirrorHorizontally( sheet->GetBoundingBox().GetCenter().x );
1228 }
1229 }
1230 else if( item->Type() == SCH_FIELD_T )
1231 {
1232 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
1233
1234 if( vertical )
1236 else
1238
1239 // Now that we're re-justifying a field, they're no longer autoplaced.
1240 static_cast<SCH_ITEM*>( field->GetParent() )->SetFieldsAutoplaced( AUTOPLACE_NONE );
1241 }
1242 else
1243 {
1244 if( vertical )
1245 item->MirrorVertically( mirrorPoint.y );
1246 else
1247 item->MirrorHorizontally( mirrorPoint.x );
1248 }
1249
1250 connections |= item->IsConnectable();
1251 m_frame->UpdateItem( item, false, true );
1252 }
1253 }
1254
1255 // Update R-Tree for modified items
1256 for( EDA_ITEM* selected : selection )
1257 updateItem( selected, true );
1258
1259 if( item->IsMoving() )
1260 {
1261 m_toolMgr->RunAction( ACTIONS::refreshPreview );
1262 }
1263 else
1264 {
1265 SCH_SELECTION selectionCopy = selection;
1266
1267 if( selection.IsHover() )
1268 m_toolMgr->RunAction( ACTIONS::selectionClear );
1269
1270 if( connections )
1271 {
1273 lwbTool->TrimOverLappingWires( commit, &selectionCopy );
1274 lwbTool->AddJunctionsIfNeeded( commit, &selectionCopy );
1275
1276 m_frame->Schematic().CleanUp( commit );
1277 }
1278
1279 if( !localCommit.Empty() )
1280 localCommit.Push( _( "Mirror" ) );
1281 }
1282
1283 return 0;
1284}
1285
1286
1304
1305
1316static void swapFieldPositionsWithMatching( std::vector<SCH_FIELD>& aAFields,
1317 std::vector<SCH_FIELD>& aBFields,
1318 unsigned aFallbackRotationsCCW )
1319{
1320 std::set<wxString> handledKeys;
1321
1322 const auto swapFieldTextProps = []( SCH_FIELD& aField, SCH_FIELD& bField )
1323 {
1324 const VECTOR2I aRelPos = aField.GetPosition() - aField.GetParentPosition();
1325 const GR_TEXT_H_ALIGN_T aTextJustifyH = aField.GetHorizJustify();
1326 const GR_TEXT_V_ALIGN_T aTextJustifyV = aField.GetVertJustify();
1327 const EDA_ANGLE aTextAngle = aField.GetTextAngle();
1328
1329 const VECTOR2I bRelPos = bField.GetPosition() - bField.GetParentPosition();
1330 const GR_TEXT_H_ALIGN_T bTextJustifyH = bField.GetHorizJustify();
1331 const GR_TEXT_V_ALIGN_T bTextJustifyV = bField.GetVertJustify();
1332 const EDA_ANGLE bTextAngle = bField.GetTextAngle();
1333
1334 aField.SetPosition( aField.GetParentPosition() + bRelPos );
1335 aField.SetHorizJustify( bTextJustifyH );
1336 aField.SetVertJustify( bTextJustifyV );
1337 aField.SetTextAngle( bTextAngle );
1338
1339 bField.SetPosition( bField.GetParentPosition() + aRelPos );
1340 bField.SetHorizJustify( aTextJustifyH );
1341 bField.SetVertJustify( aTextJustifyV );
1342 bField.SetTextAngle( aTextAngle );
1343 };
1344
1345 for( SCH_FIELD& aField : aAFields )
1346 {
1347 const wxString name = aField.GetCanonicalName();
1348
1349 auto it = std::find_if( aBFields.begin(), aBFields.end(),
1350 [name]( const SCH_FIELD& bField )
1351 {
1352 return bField.GetCanonicalName() == name;
1353 } );
1354
1355 if( it != aBFields.end() )
1356 {
1357 // We have a field with the same key in both labels
1358 SCH_FIELD& bField = *it;
1359 swapFieldTextProps( aField, bField );
1360 }
1361 else
1362 {
1363 // We only have this field in A, so just rotate it
1364 for( unsigned ii = 0; ii < aFallbackRotationsCCW; ii++ )
1365 {
1366 aField.Rotate( aField.GetParentPosition(), true );
1367 }
1368 }
1369
1370 // And keep track that we did this one
1371 handledKeys.insert( name );
1372 }
1373
1374 // Any fields in B that weren't in A weren't handled and need to be rotated
1375 // in reverse
1376 for( SCH_FIELD& bField : aBFields )
1377 {
1378 const wxString bName = bField.GetCanonicalName();
1379 if( handledKeys.find( bName ) == handledKeys.end() )
1380 {
1381 for( unsigned ii = 0; ii < aFallbackRotationsCCW; ii++ )
1382 {
1383 bField.Rotate( bField.GetParentPosition(), false );
1384 }
1385 }
1386 }
1387}
1388
1389
1391{
1392 SCH_SELECTION& selection = m_selectionTool->RequestSelection( swappableItems );
1393 std::vector<EDA_ITEM*> sorted = selection.GetItemsSortedBySelectionOrder();
1394
1395 // Sheet pins are special, we need to make sure if we have any sheet pins,
1396 // that we only have sheet pins, and that they have the same parent
1397 if( selection.CountType( SCH_SHEET_PIN_T ) > 0 )
1398 {
1399 if( !selection.OnlyContains( { SCH_SHEET_PIN_T } ) )
1400 return 0;
1401
1402 SCH_SHEET_PIN* firstPin = static_cast<SCH_SHEET_PIN*>( selection.Front() );
1403 SCH_SHEET* parent = firstPin->GetParent();
1404
1405 for( EDA_ITEM* item : selection )
1406 {
1407 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( item );
1408
1409 if( pin->GetParent() != parent )
1410 return 0;
1411 }
1412 }
1413
1414 if( selection.Size() < 2 )
1415 return 0;
1416
1417 bool isMoving = selection.Front()->IsMoving();
1418 bool appendUndo = isMoving;
1419 bool connections = false;
1420
1421 for( size_t i = 0; i < sorted.size() - 1; i++ )
1422 {
1423 SCH_ITEM* a = static_cast<SCH_ITEM*>( sorted[i] );
1424 SCH_ITEM* b = static_cast<SCH_ITEM*>( sorted[( i + 1 ) % sorted.size()] );
1425
1426 VECTOR2I aPos = a->GetPosition(), bPos = b->GetPosition();
1427 std::swap( aPos, bPos );
1428
1429 saveCopyInUndoList( a, UNDO_REDO::CHANGED, appendUndo );
1430 appendUndo = true;
1431 saveCopyInUndoList( b, UNDO_REDO::CHANGED, appendUndo );
1432
1433 // Sheet pins need to have their sides swapped before we change their
1434 // positions
1435 if( a->Type() == SCH_SHEET_PIN_T )
1436 {
1437 SCH_SHEET_PIN* aPin = static_cast<SCH_SHEET_PIN*>( a );
1438 SCH_SHEET_PIN* bPin = static_cast<SCH_SHEET_PIN*>( b );
1439 SHEET_SIDE aSide = aPin->GetSide(), bSide = bPin->GetSide();
1440 std::swap( aSide, bSide );
1441 aPin->SetSide( aSide );
1442 bPin->SetSide( bSide );
1443 }
1444
1445 a->SetPosition( aPos );
1446 b->SetPosition( bPos );
1447
1448 if( a->Type() == b->Type() )
1449 {
1450 switch( a->Type() )
1451 {
1452 case SCH_LABEL_T:
1453 case SCH_GLOBAL_LABEL_T:
1454 case SCH_HIER_LABEL_T:
1456 {
1457 SCH_LABEL_BASE& aLabelBase = static_cast<SCH_LABEL_BASE&>( *a );
1458 SCH_LABEL_BASE& bLabelBase = static_cast<SCH_LABEL_BASE&>( *b );
1459
1460 const SPIN_STYLE aSpinStyle = aLabelBase.GetSpinStyle();
1461 const SPIN_STYLE bSpinStyle = bLabelBase.GetSpinStyle();
1462
1463 // First, swap the label orientations
1464 aLabelBase.SetSpinStyle( bSpinStyle );
1465 bLabelBase.SetSpinStyle( aSpinStyle );
1466
1467 // And swap the fields as best we can
1468 std::vector<SCH_FIELD>& aFields = aLabelBase.GetFields();
1469 std::vector<SCH_FIELD>& bFields = bLabelBase.GetFields();
1470
1471 const unsigned rotationsAtoB = aSpinStyle.CCWRotationsTo( bSpinStyle );
1472
1473 swapFieldPositionsWithMatching( aFields, bFields, rotationsAtoB );
1474 break;
1475 }
1476 case SCH_SYMBOL_T:
1477 {
1478 SCH_SYMBOL* aSymbol = static_cast<SCH_SYMBOL*>( a );
1479 SCH_SYMBOL* bSymbol = static_cast<SCH_SYMBOL*>( b );
1480 int aOrient = aSymbol->GetOrientation(), bOrient = bSymbol->GetOrientation();
1481 std::swap( aOrient, bOrient );
1482 aSymbol->SetOrientation( aOrient );
1483 bSymbol->SetOrientation( bOrient );
1484 break;
1485 }
1486 default: break;
1487 }
1488 }
1489
1490 connections |= a->IsConnectable();
1491 connections |= b->IsConnectable();
1492 m_frame->UpdateItem( a, false, true );
1493 m_frame->UpdateItem( b, false, true );
1494 }
1495
1496 // Update R-Tree for modified items
1497 for( EDA_ITEM* selected : selection )
1498 updateItem( selected, true );
1499
1500 if( isMoving )
1501 {
1502 m_toolMgr->PostAction( ACTIONS::refreshPreview );
1503 }
1504 else
1505 {
1506 if( selection.IsHover() )
1507 m_toolMgr->RunAction( ACTIONS::selectionClear );
1508
1509 if( connections )
1510 m_frame->TestDanglingEnds();
1511
1512 m_frame->OnModify();
1513 }
1514
1515 return 0;
1516}
1517
1518
1520{
1521 const std::vector<std::unique_ptr<SCH_ITEM>>& sourceItems = m_frame->GetRepeatItems();
1522
1523 if( sourceItems.empty() )
1524 return 0;
1525
1526 m_toolMgr->RunAction( ACTIONS::selectionClear );
1527
1528 SCH_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
1529 SCH_COMMIT commit( m_toolMgr );
1530 SCH_SELECTION newItems;
1531
1532 for( const std::unique_ptr<SCH_ITEM>& item : sourceItems )
1533 {
1534 SCH_ITEM* newItem = item->Duplicate( IGNORE_PARENT_GROUP );
1535 bool restore_state = false;
1536
1537 // Ensure newItem has a suitable parent: the current screen, because an item from
1538 // a list of items to repeat must be attached to this current screen
1539 newItem->SetParent( m_frame->GetScreen() );
1540
1541 if( SCH_GROUP* enteredGroup = selectionTool->GetEnteredGroup() )
1542 {
1543 if( newItem->IsGroupableType() )
1544 {
1545 commit.Modify( enteredGroup, m_frame->GetScreen(), RECURSE_MODE::NO_RECURSE );
1546 enteredGroup->AddItem( newItem );
1547 }
1548 }
1549
1550 if( SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( newItem ) )
1551 {
1552 // If incrementing tries to go below zero, tell user why the value is repeated
1553 if( EESCHEMA_SETTINGS* cfg = GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" ) )
1554 {
1555 if( !label->IncrementLabel( cfg->m_Drawing.repeat_label_increment ) )
1556 m_frame->ShowInfoBarWarning( _( "Label value cannot go below zero" ), true );
1557 }
1558 }
1559
1560 // If cloning a symbol then put into 'move' mode.
1561 if( newItem->Type() == SCH_SYMBOL_T )
1562 {
1563 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( true );
1564 newItem->Move( cursorPos - newItem->GetPosition() );
1565 }
1566 else if( EESCHEMA_SETTINGS* cfg = GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" ) )
1567 {
1568 newItem->Move( VECTOR2I( schIUScale.MilsToIU( cfg->m_Drawing.default_repeat_offset_x ),
1569 schIUScale.MilsToIU( cfg->m_Drawing.default_repeat_offset_y ) ) );
1570 }
1571
1572 // If cloning a sheet, check that we aren't going to create recursion
1573 if( newItem->Type() == SCH_SHEET_T )
1574 {
1575 SCH_SHEET_PATH* currentSheet = &m_frame->GetCurrentSheet();
1576 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( newItem );
1577
1578 if( m_frame->CheckSheetForRecursion( sheet, currentSheet ) )
1579 {
1580 // Clear out the filename so that the user can pick a new one
1581 const wxString originalFileName = sheet->GetFileName();
1582 const wxString originalScreenFileName = sheet->GetScreen()->GetFileName();
1583
1584 sheet->SetFileName( wxEmptyString );
1585 sheet->GetScreen()->SetFileName( wxEmptyString );
1586 restore_state = !m_frame->EditSheetProperties( sheet, currentSheet );
1587
1588 if( restore_state )
1589 {
1590 sheet->SetFileName( originalFileName );
1591 sheet->GetScreen()->SetFileName( originalScreenFileName );
1592 }
1593 }
1594 }
1595
1596 m_toolMgr->RunAction<EDA_ITEM*>( ACTIONS::selectItem, newItem );
1597 newItem->SetFlags( IS_NEW );
1598 m_frame->AddToScreen( newItem, m_frame->GetScreen() );
1599 commit.Added( newItem, m_frame->GetScreen() );
1600
1601 if( newItem->Type() == SCH_SYMBOL_T )
1602 {
1603 SCHEMATIC_SETTINGS& projSettings = m_frame->Schematic().Settings();
1604 int annotateStartNum = projSettings.m_AnnotateStartNum;
1605 ANNOTATE_ORDER_T annotateOrder = static_cast<ANNOTATE_ORDER_T>( projSettings.m_AnnotateSortOrder );
1606 ANNOTATE_ALGO_T annotateAlgo = static_cast<ANNOTATE_ALGO_T>( projSettings.m_AnnotateMethod );
1607
1608 if( m_frame->eeconfig()->m_AnnotatePanel.automatic )
1609 {
1610 static_cast<SCH_SYMBOL*>( newItem )->ClearAnnotation( nullptr, false );
1611 NULL_REPORTER reporter;
1612 m_frame->AnnotateSymbols( &commit, ANNOTATE_SELECTION,
1613 annotateOrder,
1614 annotateAlgo, true /* recursive */,
1615 annotateStartNum, false, false, reporter );
1616 }
1617
1618 // Annotation clears the selection so re-add the item
1619 m_toolMgr->RunAction<EDA_ITEM*>( ACTIONS::selectItem, newItem );
1620
1621 restore_state = !m_toolMgr->RunSynchronousAction( SCH_ACTIONS::move, &commit );
1622 }
1623
1624 if( restore_state )
1625 {
1626 commit.Revert();
1627 }
1628 else
1629 {
1630 newItems.Add( newItem );
1631
1633 lwbTool->TrimOverLappingWires( &commit, &newItems );
1634 lwbTool->AddJunctionsIfNeeded( &commit, &newItems );
1635
1636 m_frame->Schematic().CleanUp( &commit );
1637 commit.Push( _( "Repeat Item" ) );
1638 }
1639 }
1640
1641 if( !newItems.Empty() )
1642 m_frame->SaveCopyForRepeatItem( static_cast<SCH_ITEM*>( newItems[0] ) );
1643
1644 for( size_t ii = 1; ii < newItems.GetSize(); ++ii )
1645 m_frame->AddCopyForRepeatItem( static_cast<SCH_ITEM*>( newItems[ii] ) );
1646
1647 return 0;
1648}
1649
1650
1652{
1653 SCH_SCREEN* screen = m_frame->GetScreen();
1654 std::deque<EDA_ITEM*> items = m_selectionTool->RequestSelection( SCH_COLLECTOR::DeletableItems ).GetItems();
1655 SCH_COMMIT commit( m_toolMgr );
1656 std::vector<VECTOR2I> pts;
1657 bool updateHierarchy = false;
1658
1659 if( items.empty() )
1660 return 0;
1661
1662 // Don't leave a freed pointer in the selection
1663 m_toolMgr->RunAction( ACTIONS::selectionClear );
1664
1665 for( EDA_ITEM* item : items )
1666 item->ClearFlags( STRUCT_DELETED );
1667
1668 for( EDA_ITEM* item : items )
1669 {
1670 SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( item );
1671
1672 if( !sch_item )
1673 continue;
1674
1675 if( sch_item->IsConnectable() )
1676 {
1677 std::vector<VECTOR2I> tmp_pts = sch_item->GetConnectionPoints();
1678 pts.insert( pts.end(), tmp_pts.begin(), tmp_pts.end() );
1679 }
1680
1681 if( sch_item->Type() == SCH_JUNCTION_T )
1682 {
1683 sch_item->SetFlags( STRUCT_DELETED );
1684 // clean up junctions at the end
1685 }
1686 else if( sch_item->Type() == SCH_SHEET_PIN_T )
1687 {
1688 SCH_SHEET_PIN* pin = (SCH_SHEET_PIN*) sch_item;
1689 SCH_SHEET* sheet = pin->GetParent();
1690
1691 if( !alg::contains( items, sheet ) )
1692 {
1693 commit.Modify( sheet, m_frame->GetScreen() );
1694 sheet->RemovePin( pin );
1695 }
1696 }
1697 else if( sch_item->Type() == SCH_FIELD_T )
1698 {
1699 // Hide field
1700 commit.Modify( item, m_frame->GetScreen() );
1701 static_cast<SCH_FIELD*>( sch_item )->SetVisible( false );
1702 }
1703 else if( sch_item->Type() == SCH_TABLECELL_T )
1704 {
1705 // Clear contents of table cell
1706 commit.Modify( item, m_frame->GetScreen() );
1707 static_cast<SCH_TABLECELL*>( sch_item )->SetText( wxEmptyString );
1708 }
1709 else if( sch_item->Type() == SCH_RULE_AREA_T )
1710 {
1711 sch_item->SetFlags( STRUCT_DELETED );
1712 commit.Remove( item, m_frame->GetScreen() );
1713 }
1714 else if( sch_item->Type() == SCH_GROUP_T )
1715 {
1716 // Groups need to delete their children
1717 sch_item->RunOnChildren(
1718 [&]( SCH_ITEM* aChild )
1719 {
1720 aChild->SetFlags( STRUCT_DELETED );
1721 commit.Remove( aChild, m_frame->GetScreen() );
1722 },
1724
1725 sch_item->SetFlags( STRUCT_DELETED );
1726 commit.Remove( sch_item, m_frame->GetScreen() );
1727 }
1728 else
1729 {
1730 sch_item->SetFlags( STRUCT_DELETED );
1731 commit.Remove( item, m_frame->GetScreen() );
1732 updateHierarchy |= ( sch_item->Type() == SCH_SHEET_T );
1733 }
1734 }
1735
1736 for( const VECTOR2I& point : pts )
1737 {
1738 SCH_ITEM* junction = screen->GetItem( point, 0, SCH_JUNCTION_T );
1739
1740 if( !junction )
1741 continue;
1742
1743 if( junction->HasFlag( STRUCT_DELETED ) || !screen->IsExplicitJunction( point ) )
1744 m_frame->DeleteJunction( &commit, junction );
1745 }
1746
1747 commit.Push( _( "Delete" ) );
1748
1749 if( updateHierarchy )
1750 m_frame->UpdateHierarchyNavigator();
1751
1752 return 0;
1753}
1754
1755
1757{
1758 KICAD_T parentType = aField->GetParent() ? aField->GetParent()->Type() : SCHEMATIC_T;
1759 SCH_COMMIT commit( m_toolMgr );
1760
1761 // Save old symbol in undo list if not already in edit, or moving.
1762 if( aField->GetEditFlags() == 0 ) // i.e. not edited, or moved
1763 commit.Modify( aField, m_frame->GetScreen() );
1764
1765 if( parentType == SCH_SYMBOL_T && aField->GetId() == FIELD_T::REFERENCE )
1766 static_cast<SCH_ITEM*>( aField->GetParent() )->SetConnectivityDirty();
1767
1768 wxString caption;
1769
1770 // Use title caps for mandatory fields. "Edit Sheet name Field" looks dorky.
1771 if( aField->IsMandatory() )
1772 {
1773 wxString fieldName = GetDefaultFieldName( aField->GetId(), DO_TRANSLATE );
1774 caption.Printf( _( "Edit %s Field" ), TitleCaps( fieldName ) );
1775 }
1776 else
1777 {
1778 caption.Printf( _( "Edit '%s' Field" ), aField->GetName() );
1779 }
1780
1781 DIALOG_FIELD_PROPERTIES dlg( m_frame, caption, aField );
1782
1783 // The footprint field dialog can invoke a KIWAY_PLAYER so we must use a quasi-modal
1784 if( dlg.ShowQuasiModal() != wxID_OK )
1785 return;
1786
1787 dlg.UpdateField( &commit, aField, &m_frame->GetCurrentSheet() );
1788
1789 if( m_frame->eeconfig()->m_AutoplaceFields.enable || parentType == SCH_SHEET_T )
1790 {
1791 SCH_ITEM* parent = static_cast<SCH_ITEM*>( aField->GetParent() );
1792 AUTOPLACE_ALGO fieldsAutoplaced = parent->GetFieldsAutoplaced();
1793
1794 if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
1795 parent->AutoplaceFields( m_frame->GetScreen(), fieldsAutoplaced );
1796 }
1797
1798 if( !commit.Empty() )
1799 commit.Push( caption );
1800}
1801
1802
1804{
1805 SCH_SELECTION sel = m_selectionTool->RequestSelection( { SCH_FIELD_T,
1807 SCH_PIN_T } );
1808
1809 if( sel.Size() != 1 )
1810 return 0;
1811
1812 bool clearSelection = sel.IsHover();
1813 EDA_ITEM* item = sel.Front();
1814
1815 if( item->Type() == SCH_FIELD_T )
1816 {
1817 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
1818
1819 if( ( aEvent.IsAction( &SCH_ACTIONS::editReference ) && field->GetId() != FIELD_T::REFERENCE )
1820 || ( aEvent.IsAction( &SCH_ACTIONS::editValue ) && field->GetId() != FIELD_T::VALUE )
1821 || ( aEvent.IsAction( &SCH_ACTIONS::editFootprint ) && field->GetId() != FIELD_T::FOOTPRINT ) )
1822 {
1823 item = field->GetParentSymbol();
1824
1825 m_selectionTool->ClearSelection( true );
1826
1827 // If the field to edit is not a symbol field, we cannot edit the ref, value or footprint
1828 if( item == nullptr )
1829 return 0;
1830
1831 m_selectionTool->AddItemToSel( item );
1832 }
1833 }
1834
1835 if( item->Type() == SCH_SYMBOL_T )
1836 {
1837 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1838
1839 if( aEvent.IsAction( &SCH_ACTIONS::editReference ) )
1840 {
1842 }
1843 else if( aEvent.IsAction( &SCH_ACTIONS::editValue ) )
1844 {
1846 }
1847 else if( aEvent.IsAction( &SCH_ACTIONS::editFootprint ) )
1848 {
1849 if( !symbol->IsPower() )
1851 }
1852 }
1853 else if( item->Type() == SCH_FIELD_T )
1854 {
1855 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
1856
1857 editFieldText( field );
1858
1859 if( !field->IsVisible() )
1860 clearSelection = true;
1861 }
1862 else if( item->Type() == SCH_PIN_T )
1863 {
1864 SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item->GetParent() );
1865
1866 if( symbol )
1867 {
1868 if( aEvent.IsAction( &SCH_ACTIONS::editReference ) )
1869 {
1871 }
1872 else if( aEvent.IsAction( &SCH_ACTIONS::editValue ) )
1873 {
1875 }
1876 else if( aEvent.IsAction( &SCH_ACTIONS::editFootprint ) )
1877 {
1878 if( !symbol->IsPower() )
1880 }
1881 }
1882 }
1883
1884 if( clearSelection )
1885 m_toolMgr->RunAction( ACTIONS::selectionClear );
1886
1887 return 0;
1888}
1889
1890
1892{
1893 SCH_SELECTION& selection = m_selectionTool->RequestSelection( RotatableItems );
1894 SCH_COMMIT commit( m_toolMgr );
1895 SCH_ITEM* head = static_cast<SCH_ITEM*>( selection.Front() );
1896 bool moving = head && head->IsMoving();
1897
1898 if( selection.Empty() )
1899 return 0;
1900
1901 std::vector<SCH_ITEM*> autoplaceItems;
1902
1903 for( unsigned ii = 0; ii < selection.GetSize(); ii++ )
1904 {
1905 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.GetItem( ii ) );
1906
1907 if( item->IsType( SCH_COLLECTOR::FieldOwners ) )
1908 autoplaceItems.push_back( item );
1909 else if( item->GetParent() && item->GetParent()->IsType( SCH_COLLECTOR::FieldOwners ) )
1910 autoplaceItems.push_back( static_cast<SCH_ITEM*>( item->GetParent() ) );
1911 }
1912
1913 for( SCH_ITEM* sch_item : autoplaceItems )
1914 {
1915 if( !moving && !sch_item->IsNew() )
1916 commit.Modify( sch_item, m_frame->GetScreen() );
1917
1918 sch_item->AutoplaceFields( m_frame->GetScreen(), AUTOPLACE_MANUAL );
1919
1920 updateItem( sch_item, true );
1921 }
1922
1923 if( moving )
1924 {
1925 m_toolMgr->PostAction( ACTIONS::refreshPreview );
1926 }
1927 else
1928 {
1929 if( !commit.Empty() )
1930 commit.Push( _( "Autoplace Fields" ) );
1931
1932 if( selection.IsHover() )
1933 m_toolMgr->RunAction( ACTIONS::selectionClear );
1934 }
1935
1936 return 0;
1937}
1938
1939
1941{
1942 SCH_SYMBOL* selectedSymbol = nullptr;
1943 SCH_SELECTION& selection = m_selectionTool->RequestSelection( { SCH_SYMBOL_T } );
1944
1945 if( !selection.Empty() )
1946 selectedSymbol = dynamic_cast<SCH_SYMBOL*>( selection.Front() );
1947
1949
1952
1953 DIALOG_CHANGE_SYMBOLS dlg( m_frame, selectedSymbol, mode );
1954
1955 // QuasiModal required to invoke symbol browser
1956 dlg.ShowQuasiModal();
1957
1958 if( selection.IsHover() )
1959 m_toolMgr->RunAction( ACTIONS::selectionClear );
1960
1961 return 0;
1962}
1963
1964
1966{
1967 SCH_SELECTION& selection = m_selectionTool->RequestSelection( { SCH_SYMBOL_T } );
1968
1969 if( selection.Empty() )
1970 return 0;
1971
1972 SCH_SYMBOL* symbol = (SCH_SYMBOL*) selection.Front();
1973 SCH_COMMIT commit( m_toolMgr );
1974
1975 if( !symbol->IsNew() )
1976 commit.Modify( symbol, m_frame->GetScreen() );
1977
1978 int nextBodyStyle = symbol->GetBodyStyle() + 1;
1979
1980 if( nextBodyStyle > symbol->GetBodyStyleCount() )
1981 nextBodyStyle = 1;
1982
1983 m_frame->SelectBodyStyle( symbol, nextBodyStyle );
1984
1985 if( symbol->IsNew() )
1986 m_toolMgr->PostAction( ACTIONS::refreshPreview );
1987
1988 if( !commit.Empty() )
1989 commit.Push( _( "Change Body Style" ) );
1990
1991 if( selection.IsHover() )
1992 m_toolMgr->RunAction( ACTIONS::selectionClear );
1993
1994 return 0;
1995}
1996
1997
1999{
2000 SCH_SELECTION& selection = m_selectionTool->RequestSelection();
2001 bool clearSelection = selection.IsHover();
2002
2003 if( selection.Empty() )
2004 {
2005 if( getView()->IsLayerVisible( LAYER_SCHEMATIC_DRAWINGSHEET ) )
2006 {
2007 DS_PROXY_VIEW_ITEM* ds = m_frame->GetCanvas()->GetView()->GetDrawingSheet();
2008 VECTOR2D cursorPos = getViewControls()->GetCursorPosition( false );
2009
2010 if( ds && ds->HitTestDrawingSheetItems( getView(), cursorPos ) )
2011 m_toolMgr->PostAction( ACTIONS::pageSettings );
2012 }
2013
2014 return 0;
2015 }
2016
2017 EDA_ITEM* curr_item = selection.Front();
2018
2019 // If a single pin is selected, promote to its parent symbol
2020 if( ( selection.GetSize() == 1 ) && ( curr_item->Type() == SCH_PIN_T ) )
2021 {
2022 EDA_ITEM* parent = curr_item->GetParent();
2023
2024 if( parent->Type() == SCH_SYMBOL_T )
2025 curr_item = parent;
2026 }
2027
2028 switch( curr_item->Type() )
2029 {
2030 case SCH_LINE_T:
2032 case SCH_JUNCTION_T:
2033 case SCH_TABLECELL_T:
2034 break;
2035
2036 default:
2037 if( selection.Size() > 1 )
2038 return 0;
2039
2040 break;
2041 }
2042
2043 switch( curr_item->Type() )
2044 {
2045 case SCH_SYMBOL_T:
2046 {
2047 int retval;
2048 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( curr_item );
2049
2050 // This needs to be scoped so the dialog destructor removes blocking status
2051 // before we launch the next dialog.
2052 {
2053 DIALOG_SYMBOL_PROPERTIES symbolPropsDialog( m_frame, symbol );
2054
2055 // This dialog itself subsequently can invoke a KIWAY_PLAYER as a quasimodal
2056 // frame. Therefore this dialog as a modal frame parent, MUST be run under
2057 // quasimodal mode for the quasimodal frame support to work. So don't use
2058 // the QUASIMODAL macros here.
2059 retval = symbolPropsDialog.ShowQuasiModal();
2060 }
2061
2062 if( retval == SYMBOL_PROPS_EDIT_OK )
2063 {
2064 if( m_frame->eeconfig()->m_AutoplaceFields.enable )
2065 {
2066 AUTOPLACE_ALGO fieldsAutoplaced = symbol->GetFieldsAutoplaced();
2067
2068 if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
2069 symbol->AutoplaceFields( m_frame->GetScreen(), fieldsAutoplaced );
2070 }
2071
2072 m_frame->OnModify();
2073 }
2074 else if( retval == SYMBOL_PROPS_EDIT_SCHEMATIC_SYMBOL )
2075 {
2076 if( KIWAY_PLAYER* frame = m_frame->Kiway().Player( FRAME_SCH_SYMBOL_EDITOR, true ) )
2077 {
2078 SYMBOL_EDIT_FRAME* editor = static_cast<SYMBOL_EDIT_FRAME*>( frame );
2079
2080 if( wxWindow* blocking_win = editor->Kiway().GetBlockingDialog() )
2081 blocking_win->Close( true );
2082
2083 // The broken library symbol link indicator cannot be edited.
2084 if( symbol->IsMissingLibSymbol() )
2085 return 0;
2086
2087 editor->LoadSymbolFromSchematic( symbol );
2088 editor->Show( true );
2089 editor->Raise();
2090 }
2091 }
2092 else if( retval == SYMBOL_PROPS_EDIT_LIBRARY_SYMBOL )
2093 {
2094 if( KIWAY_PLAYER* frame = m_frame->Kiway().Player( FRAME_SCH_SYMBOL_EDITOR, true ) )
2095 {
2096 SYMBOL_EDIT_FRAME* editor = static_cast<SYMBOL_EDIT_FRAME*>( frame );
2097
2098 if( wxWindow* blocking_win = editor->Kiway().GetBlockingDialog() )
2099 blocking_win->Close( true );
2100
2101 editor->LoadSymbol( symbol->GetLibId(), symbol->GetUnit(), symbol->GetBodyStyle() );
2102 editor->Show( true );
2103 editor->Raise();
2104 }
2105 }
2106 else if( retval == SYMBOL_PROPS_WANT_UPDATE_SYMBOL )
2107 {
2109 dlg.ShowQuasiModal();
2110 }
2111 else if( retval == SYMBOL_PROPS_WANT_EXCHANGE_SYMBOL )
2112 {
2114 dlg.ShowQuasiModal();
2115 }
2116
2117 break;
2118 }
2119
2120 case SCH_SHEET_T:
2121 {
2122 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( curr_item );
2123 bool isUndoable = false;
2124 bool doClearAnnotation = false;
2125 bool okPressed = false;
2126 bool updateHierarchyNavigator = false;
2127
2128 // Keep track of existing sheet paths. EditSheet() can modify this list.
2129 // Note that we use the validity checking/repairing version here just to make sure
2130 // we've got a valid hierarchy to begin with.
2131 SCH_SHEET_LIST originalHierarchy;
2132 originalHierarchy.BuildSheetList( &m_frame->Schematic().Root(), true );
2133
2134 SCH_COMMIT commit( m_toolMgr );
2135 commit.Modify( sheet, m_frame->GetScreen() );
2136 okPressed = m_frame->EditSheetProperties( sheet, &m_frame->GetCurrentSheet(), &isUndoable,
2137 &doClearAnnotation, &updateHierarchyNavigator );
2138
2139 if( okPressed )
2140 {
2141 if( isUndoable )
2142 {
2143 commit.Push( _( "Edit Sheet Properties" ) );
2144 }
2145 else
2146 {
2147 std::vector<SCH_ITEM*> items;
2148
2149 items.emplace_back( sheet );
2150 m_frame->Schematic().OnItemsRemoved( items );
2151 m_frame->Schematic().OnItemsAdded( items );
2152 m_frame->OnModify();
2153 m_frame->Schematic().RefreshHierarchy();
2154 m_frame->UpdateHierarchyNavigator();
2155 }
2156 }
2157 else
2158 {
2159 // If we are renaming files, the undo/redo list becomes invalid and must be cleared.
2160 m_frame->ClearUndoRedoList();
2161 m_frame->OnModify();
2162 }
2163
2164 // If the sheet file is changed and new sheet contents are loaded then we have to
2165 // clear the annotations on the new content (as it may have been set from some other
2166 // sheet path reference)
2167 if( doClearAnnotation )
2168 {
2169 SCH_SCREENS screensList( &m_frame->Schematic().Root() );
2170
2171 // We clear annotation of new sheet paths here:
2172 screensList.ClearAnnotationOfNewSheetPaths( originalHierarchy );
2173
2174 // Clear annotation of g_CurrentSheet itself, because its sheetpath is not a new
2175 // path, but symbols managed by its sheet path must have their annotation cleared
2176 // because they are new:
2177 sheet->GetScreen()->ClearAnnotation( &m_frame->GetCurrentSheet(), false );
2178 }
2179
2180 if( okPressed )
2181 m_frame->GetCanvas()->Refresh();
2182
2183 if( updateHierarchyNavigator )
2184 m_frame->UpdateHierarchyNavigator();
2185
2186 break;
2187 }
2188
2189 case SCH_SHEET_PIN_T:
2190 {
2191 SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( curr_item );
2193
2194 // QuasiModal required for help dialog
2195 dlg.ShowQuasiModal();
2196 break;
2197 }
2198
2199 case SCH_TEXT_T:
2200 case SCH_TEXTBOX_T:
2201 {
2202 DIALOG_TEXT_PROPERTIES dlg( m_frame, static_cast<SCH_ITEM*>( curr_item ) );
2203
2204 // QuasiModal required for syntax help and Scintilla auto-complete
2205 dlg.ShowQuasiModal();
2206 break;
2207 }
2208
2209 case SCH_TABLECELL_T:
2210 if( SELECTION_CONDITIONS::OnlyTypes( { SCH_TABLECELL_T } )( selection ) )
2211 {
2212 std::vector<SCH_TABLECELL*> cells;
2213
2214 for( EDA_ITEM* item : selection.Items() )
2215 cells.push_back( static_cast<SCH_TABLECELL*>( item ) );
2216
2218
2219 dlg.ShowModal();
2220
2222 {
2223 SCH_TABLE* table = static_cast<SCH_TABLE*>( cells[0]->GetParent() );
2225
2226 tableDlg.ShowModal();
2227 }
2228 }
2229
2230 break;
2231
2232 case SCH_TABLE_T:
2233 {
2234 DIALOG_TABLE_PROPERTIES dlg( m_frame, static_cast<SCH_TABLE*>( curr_item ) );
2235
2236 // QuasiModal required for Scintilla auto-complete
2237 dlg.ShowQuasiModal();
2238 break;
2239 }
2240
2241 case SCH_LABEL_T:
2242 case SCH_GLOBAL_LABEL_T:
2243 case SCH_HIER_LABEL_T:
2245 {
2246 DIALOG_LABEL_PROPERTIES dlg( m_frame, static_cast<SCH_LABEL_BASE*>( curr_item ), false );
2247
2248 // QuasiModal for syntax help and Scintilla auto-complete
2249 dlg.ShowQuasiModal();
2250 break;
2251 }
2252
2253 case SCH_FIELD_T:
2254 {
2255 SCH_FIELD* field = static_cast<SCH_FIELD*>( curr_item );
2256
2257 editFieldText( field );
2258
2259 if( !field->IsVisible() )
2260 clearSelection = true;
2261
2262 break;
2263 }
2264
2265 case SCH_SHAPE_T:
2266 {
2267 DIALOG_SHAPE_PROPERTIES dlg( m_frame, static_cast<SCH_SHAPE*>( curr_item ) );
2268
2269 dlg.ShowModal();
2270 break;
2271 }
2272
2273 case SCH_BITMAP_T:
2274 {
2275 SCH_BITMAP& bitmap = static_cast<SCH_BITMAP&>( *curr_item );
2276 DIALOG_IMAGE_PROPERTIES dlg( m_frame, bitmap );
2277
2278 if( dlg.ShowModal() == wxID_OK )
2279 {
2280 // The bitmap is cached in Opengl: clear the cache in case it has become invalid
2282 }
2283
2284 break;
2285 }
2286
2287 case SCH_RULE_AREA_T:
2288 {
2289 DIALOG_SHAPE_PROPERTIES dlg( m_frame, static_cast<SCH_SHAPE*>( curr_item ) );
2290 dlg.SetTitle( _( "Rule Area Properties" ) );
2291
2292 dlg.ShowModal();
2293 break;
2294 }
2295
2296 case SCH_LINE_T:
2298 case SCH_JUNCTION_T:
2300 {
2301 std::deque<SCH_LINE*> lines;
2302
2303 for( EDA_ITEM* selItem : selection.Items() )
2304 lines.push_back( static_cast<SCH_LINE*>( selItem ) );
2305
2306 DIALOG_LINE_PROPERTIES dlg( m_frame, lines );
2307
2308 dlg.ShowModal();
2309 }
2310 else if( SELECTION_CONDITIONS::OnlyTypes( { SCH_JUNCTION_T } )( selection ) )
2311 {
2312 std::deque<SCH_JUNCTION*> junctions;
2313
2314 for( EDA_ITEM* selItem : selection.Items() )
2315 junctions.push_back( static_cast<SCH_JUNCTION*>( selItem ) );
2316
2317 DIALOG_JUNCTION_PROPS dlg( m_frame, junctions );
2318
2319 dlg.ShowModal();
2320 }
2324 SCH_JUNCTION_T } )( selection ) )
2325 {
2326 std::deque<SCH_ITEM*> items;
2327
2328 for( EDA_ITEM* selItem : selection.Items() )
2329 items.push_back( static_cast<SCH_ITEM*>( selItem ) );
2330
2331 DIALOG_WIRE_BUS_PROPERTIES dlg( m_frame, items );
2332
2333 dlg.ShowModal();
2334 }
2335 else
2336 {
2337 return 0;
2338 }
2339
2340 break;
2341
2342 case SCH_MARKER_T:
2343 if( SELECTION_CONDITIONS::OnlyTypes( { SCH_MARKER_T } )( selection ) )
2344 {
2345 SCH_INSPECTION_TOOL* inspectionTool = m_toolMgr->GetTool<SCH_INSPECTION_TOOL>();
2346
2347 if( inspectionTool )
2348 inspectionTool->CrossProbe( static_cast<SCH_MARKER*> ( selection.Front() ) );
2349 }
2350 break;
2351
2352 case SCH_NO_CONNECT_T:
2353 case SCH_PIN_T:
2354 break;
2355
2356 case SCH_GROUP_T:
2358 static_cast<EDA_GROUP*>( static_cast<SCH_GROUP*>( curr_item ) ) );
2359
2360 break;
2361
2362 default: // Unexpected item
2363 wxFAIL_MSG( wxString( "Cannot edit schematic item type " ) + curr_item->GetClass() );
2364 }
2365
2366 updateItem( curr_item, true );
2367
2368 if( clearSelection )
2369 m_toolMgr->RunAction( ACTIONS::selectionClear );
2370
2371 return 0;
2372}
2373
2374
2376{
2377 KICAD_T convertTo = aEvent.Parameter<KICAD_T>();
2378 SCH_SELECTION selection = m_selectionTool->RequestSelection( { SCH_LABEL_LOCATE_ANY_T,
2379 SCH_TEXT_T,
2380 SCH_TEXTBOX_T } );
2381 SCH_COMMIT localCommit( m_toolMgr );
2382 SCH_COMMIT* commit = dynamic_cast<SCH_COMMIT*>( aEvent.Commit() );
2383
2384 if( !commit )
2385 commit = &localCommit;
2386
2387 for( unsigned int i = 0; i < selection.GetSize(); ++i )
2388 {
2389 SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( selection.GetItem( i ) );
2390
2391 if( item && item->Type() != convertTo )
2392 {
2393 EDA_TEXT* sourceText = dynamic_cast<EDA_TEXT*>( item );
2394 bool selected = item->IsSelected();
2395 SCH_ITEM* newtext = nullptr;
2396 VECTOR2I position = item->GetPosition();
2397 wxString txt;
2398 wxString href;
2401
2402 wxCHECK2( sourceText, continue );
2403
2404 switch( item->Type() )
2405 {
2406 case SCH_LABEL_T:
2407 case SCH_GLOBAL_LABEL_T:
2408 case SCH_HIER_LABEL_T:
2409 {
2410 SCH_LABEL_BASE* label = static_cast<SCH_LABEL_BASE*>( item );
2411
2412 txt = UnescapeString( label->GetText() );
2413 spinStyle = label->GetSpinStyle();
2414 shape = label->GetShape();
2415 href = label->GetHyperlink();
2416 break;
2417 }
2418
2420 {
2421 SCH_DIRECTIVE_LABEL* dirlabel = static_cast<SCH_DIRECTIVE_LABEL*>( item );
2422
2423 // a SCH_DIRECTIVE_LABEL has no text
2424 txt = _( "<empty>" );
2425
2426 spinStyle = dirlabel->GetSpinStyle();
2427 href = dirlabel->GetHyperlink();
2428 break;
2429 }
2430
2431 case SCH_TEXT_T:
2432 {
2433 SCH_TEXT* text = static_cast<SCH_TEXT*>( item );
2434
2435 txt = text->GetText();
2436 href = text->GetHyperlink();
2437 break;
2438 }
2439
2440 case SCH_TEXTBOX_T:
2441 {
2442 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( item );
2443 BOX2I bbox = textbox->GetBoundingBox();
2444
2445 bbox.SetOrigin( bbox.GetLeft() + textbox->GetMarginLeft(),
2446 bbox.GetTop() + textbox->GetMarginTop() );
2447 bbox.SetEnd( bbox.GetRight() - textbox->GetMarginRight(),
2448 bbox.GetBottom() - textbox->GetMarginBottom() );
2449
2450 if( convertTo == SCH_LABEL_T
2451 || convertTo == SCH_HIER_LABEL_T
2452 || convertTo == SCH_GLOBAL_LABEL_T )
2453 {
2454 EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item );
2455 wxCHECK( text, 0 );
2456 int textSize = text->GetTextSize().y;
2457 bbox.Inflate( KiROUND( item->Schematic()->Settings().m_LabelSizeRatio * textSize ) );
2458 }
2459
2460 txt = textbox->GetText();
2461
2462 if( textbox->GetTextAngle().IsVertical() )
2463 {
2464 if( textbox->GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
2465 {
2466 spinStyle = SPIN_STYLE::SPIN::BOTTOM;
2467 position = VECTOR2I( bbox.Centre().x, bbox.GetOrigin().y );
2468 }
2469 else
2470 {
2471 spinStyle = SPIN_STYLE::SPIN::UP;
2472 position = VECTOR2I( bbox.Centre().x, bbox.GetEnd().y );
2473 }
2474 }
2475 else
2476 {
2477 if( textbox->GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
2478 {
2479 spinStyle = SPIN_STYLE::SPIN::LEFT;
2480 position = VECTOR2I( bbox.GetEnd().x, bbox.Centre().y );
2481 }
2482 else
2483 {
2484 spinStyle = SPIN_STYLE::SPIN::RIGHT;
2485 position = VECTOR2I( bbox.GetOrigin().x, bbox.Centre().y );
2486 }
2487 }
2488
2489 position = m_frame->GetNearestGridPosition( position );
2490 href = textbox->GetHyperlink();
2491 break;
2492 }
2493
2494 default:
2495 UNIMPLEMENTED_FOR( item->GetClass() );
2496 break;
2497 }
2498
2499 auto getValidNetname =
2500 []( const wxString& aText )
2501 {
2502 wxString local_txt = aText;
2503 local_txt.Replace( "\n", "_" );
2504 local_txt.Replace( "\r", "_" );
2505 local_txt.Replace( "\t", "_" );
2506
2507 // Bus groups can have spaces; bus vectors and signal names cannot
2508 if( !NET_SETTINGS::ParseBusGroup( aText, nullptr, nullptr ) )
2509 local_txt.Replace( " ", "_" );
2510
2511 // label strings are "escaped" i.e. a '/' is replaced by "{slash}"
2512 local_txt = EscapeString( local_txt, CTX_NETNAME );
2513
2514 if( local_txt.IsEmpty() )
2515 return _( "<empty>" );
2516 else
2517 return local_txt;
2518 };
2519
2520 switch( convertTo )
2521 {
2522 case SCH_LABEL_T:
2523 {
2524 SCH_LABEL_BASE* new_label = new SCH_LABEL( position, getValidNetname( txt ) );
2525
2526 new_label->SetShape( shape );
2527 new_label->SetAttributes( *sourceText, false );
2528 new_label->SetSpinStyle( spinStyle );
2529 new_label->SetHyperlink( href );
2530
2531 if( item->Type() == SCH_GLOBAL_LABEL_T || item->Type() == SCH_HIER_LABEL_T )
2532 {
2533 if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::UP )
2534 new_label->MirrorVertically( position.y );
2535 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::BOTTOM )
2536 new_label->MirrorVertically( position.y );
2537 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::LEFT )
2538 new_label->MirrorHorizontally( position.x );
2539 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::RIGHT )
2540 new_label->MirrorHorizontally( position.x );
2541 }
2542
2543 newtext = new_label;
2544 break;
2545 }
2546
2547 case SCH_GLOBAL_LABEL_T:
2548 {
2549 SCH_LABEL_BASE* new_label = new SCH_GLOBALLABEL( position, getValidNetname( txt ) );
2550
2551 new_label->SetShape( shape );
2552 new_label->SetAttributes( *sourceText, false );
2553 new_label->SetSpinStyle( spinStyle );
2554 new_label->SetHyperlink( href );
2555
2556 if( item->Type() == SCH_LABEL_T )
2557 {
2558 if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::UP )
2559 new_label->MirrorVertically( position.y );
2560 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::BOTTOM )
2561 new_label->MirrorVertically( position.y );
2562 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::LEFT )
2563 new_label->MirrorHorizontally( position.x );
2564 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::RIGHT )
2565 new_label->MirrorHorizontally( position.x );
2566 }
2567
2568 newtext = new_label;
2569 break;
2570 }
2571
2572 case SCH_HIER_LABEL_T:
2573 {
2574 SCH_LABEL_BASE* new_label = new SCH_HIERLABEL( position, getValidNetname( txt ) );
2575
2576 new_label->SetShape( shape );
2577 new_label->SetAttributes( *sourceText, false );
2578 new_label->SetSpinStyle( spinStyle );
2579 new_label->SetHyperlink( href );
2580
2581 if( item->Type() == SCH_LABEL_T )
2582 {
2583 if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::UP )
2584 new_label->MirrorVertically( position.y );
2585 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::BOTTOM )
2586 new_label->MirrorVertically( position.y );
2587 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::LEFT )
2588 new_label->MirrorHorizontally( position.x );
2589 else if( static_cast<SCH_LABEL_BASE*>( item )->GetSpinStyle() == SPIN_STYLE::SPIN::RIGHT )
2590 new_label->MirrorHorizontally( position.x );
2591 }
2592
2593 newtext = new_label;
2594 break;
2595 }
2596
2598 {
2599 SCH_LABEL_BASE* new_label = new SCH_DIRECTIVE_LABEL( position );
2600
2601 // A SCH_DIRECTIVE_LABEL usually has at least one field containing the net class
2602 // name. If we're copying from a text object assume the text is the netclass
2603 // name. Otherwise, we'll just copy the fields which will either have a netclass
2604 // or not.
2605 if( !dynamic_cast<SCH_LABEL_BASE*>( item ) )
2606 {
2607 SCH_FIELD netclass( new_label, FIELD_T::USER, wxT( "Netclass" ) );
2608 netclass.SetText( txt );
2609 netclass.SetTextPos( position );
2610 new_label->GetFields().push_back( netclass );
2611 }
2612
2613 new_label->SetShape( LABEL_FLAG_SHAPE::F_ROUND );
2614 new_label->SetAttributes( *sourceText, false );
2615 new_label->SetSpinStyle( spinStyle );
2616 new_label->SetHyperlink( href );
2617 newtext = new_label;
2618 break;
2619 }
2620
2621 case SCH_TEXT_T:
2622 {
2623 SCH_TEXT* new_text = new SCH_TEXT( position, txt );
2624
2625 new_text->SetAttributes( *sourceText, false );
2626 new_text->SetHyperlink( href );
2627 newtext = new_text;
2628 break;
2629 }
2630
2631 case SCH_TEXTBOX_T:
2632 {
2633 SCH_TEXTBOX* new_textbox = new SCH_TEXTBOX( LAYER_NOTES, 0, FILL_T::NO_FILL, txt );
2634 BOX2I bbox = item->GetBoundingBox();
2635
2636 if( SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( item ) )
2637 bbox.Inflate( -label->GetLabelBoxExpansion() );
2638
2639 new_textbox->SetAttributes( *sourceText, false );
2640
2641 bbox.SetOrigin( bbox.GetLeft() - new_textbox->GetMarginLeft(),
2642 bbox.GetTop() - new_textbox->GetMarginTop() );
2643 bbox.SetEnd( bbox.GetRight() + new_textbox->GetMarginRight(),
2644 bbox.GetBottom() + new_textbox->GetMarginBottom() );
2645
2646 VECTOR2I topLeft = bbox.GetPosition();
2647 VECTOR2I botRight = bbox.GetEnd();
2648
2649 // Add 1/20 of the margin at the end to reduce line-breaking changes.
2650 int slop = new_textbox->GetLegacyTextMargin() / 20;
2651
2652 if( sourceText->GetTextAngle() == ANGLE_VERTICAL )
2653 {
2654 if( sourceText->GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
2655 botRight.y += slop;
2656 else
2657 topLeft.y -= slop;
2658 }
2659 else
2660 {
2661 if( sourceText->GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
2662 topLeft.x -= slop;
2663 else
2664 botRight.x += slop;
2665 }
2666
2667 new_textbox->SetPosition( topLeft );
2668 new_textbox->SetEnd( botRight );
2669
2670 new_textbox->SetHyperlink( href );
2671 newtext = new_textbox;
2672 break;
2673 }
2674
2675 default:
2676 UNIMPLEMENTED_FOR( wxString::Format( "%d.", convertTo ) );
2677 break;
2678 }
2679
2680 wxCHECK2( newtext, continue );
2681
2682 // Copy the old text item settings to the new one. Justifications are not copied
2683 // because they are not used in labels. Justifications will be set to default value
2684 // in the new text item type.
2685 //
2686 newtext->SetFlags( item->GetEditFlags() );
2687
2688 EDA_TEXT* eda_text = dynamic_cast<EDA_TEXT*>( item );
2689 EDA_TEXT* new_eda_text = dynamic_cast<EDA_TEXT*>( newtext );
2690
2691 wxCHECK2( eda_text && new_eda_text, continue );
2692
2693 new_eda_text->SetFont( eda_text->GetFont() );
2694 new_eda_text->SetTextSize( eda_text->GetTextSize() );
2695 new_eda_text->SetTextThickness( eda_text->GetTextThickness() );
2696
2697 // Must be after SetTextSize()
2698 new_eda_text->SetBold( eda_text->IsBold() );
2699 new_eda_text->SetItalic( eda_text->IsItalic() );
2700
2701 newtext->AutoplaceFields( m_frame->GetScreen(), AUTOPLACE_AUTO );
2702
2703 SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( item );
2704 SCH_LABEL_BASE* new_label = dynamic_cast<SCH_LABEL_BASE*>( newtext );
2705
2706 if( label && new_label )
2707 {
2708 new_label->AddFields( label->GetFields() );
2709
2710 // A SCH_GLOBALLABEL has a specific field for intersheet references that has
2711 // no meaning for other labels
2712 std::erase_if( new_label->GetFields(),
2713 [&]( SCH_FIELD& field )
2714 {
2715 return field.GetId() == FIELD_T::INTERSHEET_REFS
2716 && new_label->Type() != SCH_GLOBAL_LABEL_T;
2717 } );
2718 }
2719
2720 if( selected )
2721 m_toolMgr->RunAction<EDA_ITEM*>( ACTIONS::unselectItem, item );
2722
2723 m_frame->RemoveFromScreen( item, m_frame->GetScreen() );
2724
2725 if( commit->GetStatus( item, m_frame->GetScreen() ) == CHT_ADD )
2726 commit->Unstage( item, m_frame->GetScreen() );
2727 else
2728 commit->Removed( item, m_frame->GetScreen() );
2729
2730 m_frame->AddToScreen( newtext, m_frame->GetScreen() );
2731 commit->Added( newtext, m_frame->GetScreen() );
2732
2733 if( selected )
2734 m_toolMgr->RunAction<EDA_ITEM*>( ACTIONS::selectItem, newtext );
2735 }
2736 }
2737
2738 if( !localCommit.Empty() )
2739 localCommit.Push( _( "Change To" ) );
2740
2741 if( selection.IsHover() )
2742 m_toolMgr->RunAction( ACTIONS::selectionClear );
2743
2744 return 0;
2745}
2746
2747
2749{
2750 static std::vector<KICAD_T> justifiableItems = {
2752 SCH_TEXT_T,
2755 };
2756
2757 SCH_SELECTION& selection = m_selectionTool->RequestSelection( justifiableItems );
2758
2759 if( selection.GetSize() == 0 )
2760 return 0;
2761
2762 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.Front() );
2763 bool moving = item->IsMoving();
2764 SCH_COMMIT localCommit( m_toolMgr );
2765 SCH_COMMIT* commit = dynamic_cast<SCH_COMMIT*>( aEvent.Commit() );
2766
2767 if( !commit )
2768 commit = &localCommit;
2769
2770 auto setJustify =
2771 [&]( EDA_TEXT* aTextItem )
2772 {
2773 if( aEvent.Matches( ACTIONS::leftJustify.MakeEvent() ) )
2774 aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
2775 else if( aEvent.Matches( ACTIONS::centerJustify.MakeEvent() ) )
2776 aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER );
2777 else
2778 aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
2779 };
2780
2781 for( EDA_ITEM* edaItem : selection )
2782 {
2783 item = static_cast<SCH_ITEM*>( edaItem );
2784
2785 if( !moving )
2786 commit->Modify( item, m_frame->GetScreen() );
2787
2788 if( item->Type() == SCH_FIELD_T )
2789 {
2790 setJustify( static_cast<SCH_FIELD*>( item ) );
2791
2792 // Now that we're re-justifying a field, they're no longer autoplaced.
2793 static_cast<SCH_ITEM*>( item->GetParent() )->SetFieldsAutoplaced( AUTOPLACE_NONE );
2794 }
2795 else if( item->Type() == SCH_TEXT_T )
2796 {
2797 setJustify( static_cast<SCH_TEXT*>( item ) );
2798 }
2799 else if( item->Type() == SCH_TEXTBOX_T )
2800 {
2801 setJustify( static_cast<SCH_TEXTBOX*>( item ) );
2802 }
2803 else if( item->Type() == SCH_LABEL_T )
2804 {
2805 SCH_LABEL* label = static_cast<SCH_LABEL*>( item );
2806
2807 if( label->GetTextAngle() == ANGLE_HORIZONTAL )
2808 setJustify( label );
2809 }
2810
2811 m_frame->UpdateItem( item, false, true );
2812 }
2813
2814 // Update R-Tree for modified items
2815 for( EDA_ITEM* selected : selection )
2816 updateItem( selected, true );
2817
2818 if( item->IsMoving() )
2819 {
2820 m_toolMgr->RunAction( ACTIONS::refreshPreview );
2821 }
2822 else
2823 {
2824 SCH_SELECTION selectionCopy = selection;
2825
2826 if( selection.IsHover() )
2827 m_toolMgr->RunAction( ACTIONS::selectionClear );
2828
2829 if( !localCommit.Empty() )
2830 {
2831 if( aEvent.Matches( ACTIONS::leftJustify.MakeEvent() ) )
2832 localCommit.Push( _( "Left Justify" ) );
2833 else if( aEvent.Matches( ACTIONS::centerJustify.MakeEvent() ) )
2834 localCommit.Push( _( "Center Justify" ) );
2835 else
2836 localCommit.Push( _( "Right Justify" ) );
2837 }
2838 }
2839
2840 return 0;
2841}
2842
2843
2845{
2846 bool isSlice = aEvent.Matches( SCH_ACTIONS::slice.MakeEvent() );
2848 SCH_SELECTION& selection = m_selectionTool->RequestSelection( { SCH_LINE_T } );
2849 SCH_SCREEN* screen = m_frame->GetScreen();
2850 SCH_COMMIT commit( m_toolMgr );
2851
2853 std::vector<SCH_LINE*> lines;
2854
2855 // Save the current orthogonal mode so we can restore it later
2856 static enum LINE_MODE lineMode = LINE_MODE::LINE_MODE_90;
2857 static bool lineModeChanged = false;
2858
2859 auto revertLineMode =
2860 [&]()
2861 {
2862 if( lineModeChanged )
2863 {
2864 if( lineMode == LINE_MODE::LINE_MODE_90 )
2865 m_toolMgr->RunAction( SCH_ACTIONS::lineMode90 );
2866 else if( lineMode == LINE_MODE::LINE_MODE_45)
2867 m_toolMgr->RunAction( SCH_ACTIONS::lineMode45 );
2868
2869 lineModeChanged = false;
2870 }
2871 };
2872
2873 for( EDA_ITEM* item : selection )
2874 {
2875 if( item->Type() == SCH_LINE_T )
2876 lines.push_back( static_cast<SCH_LINE*>( item ) );
2877 }
2878
2879 m_selectionTool->ClearSelection();
2880
2881 for( SCH_LINE* line : lines )
2882 {
2883 SCH_LINE* newLine;
2884
2885 // We let the user select the break point if they're on a single line
2886 if( lines.size() == 1 && line->HitTest( cursorPos ) && !line->IsEndPoint( cursorPos ) )
2887 lwbTool->BreakSegment( &commit, line, cursorPos, &newLine, screen );
2888 else
2889 lwbTool->BreakSegment( &commit, line, line->GetMidPoint(), &newLine, screen );
2890
2891 // Make sure both endpoints are deselected
2892 newLine->ClearFlags( ENDPOINT | STARTPOINT );
2893 line->SetFlags( ENDPOINT );
2894
2895 // If we're a break, we want to drag both wires.
2896 // Side note: the drag/move tool only checks whether the first item is
2897 // new to determine if it should append undo or not, someday this should
2898 // be cleaned up and explictly controlled but for now the newLine
2899 // selection addition must be after the existing line.
2900 if( !isSlice )
2901 {
2902 m_selectionTool->AddItemToSel( newLine );
2903 newLine->SetFlags( STARTPOINT );
2904 }
2905 }
2906
2907 if( !lines.empty() )
2908 {
2909 if( EESCHEMA_SETTINGS* cfg = GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" ) )
2910 {
2911 if( cfg->m_Drawing.line_mode != LINE_MODE::LINE_MODE_FREE )
2912 {
2913 lineMode = (enum LINE_MODE) cfg->m_Drawing.line_mode;
2914 lineModeChanged = true;
2916 }
2917 }
2918
2919 m_frame->TestDanglingEnds();
2920
2921 if( m_toolMgr->RunSynchronousAction( SCH_ACTIONS::drag, &commit, isSlice ) )
2922 {
2923 commit.Push( isSlice ? _( "Slice Wire" ) : _( "Break Wire" ) );
2924
2925 // Breaking wires is usually a repeated action, e.g. to add bends
2926 if( !isSlice )
2927 m_toolMgr->PostAction( SCH_ACTIONS::breakWire );
2928 else
2929 revertLineMode();
2930 }
2931 else
2932 {
2933 commit.Revert();
2934 revertLineMode();
2935 }
2936 }
2937
2938 if( selection.IsHover() )
2939 m_toolMgr->RunAction( ACTIONS::selectionClear );
2940
2941 return 0;
2942}
2943
2944
2946{
2947 SCH_SELECTION& selection = m_selectionTool->RequestSelection( { SCH_SHEET_T } );
2948 SCH_SHEET* sheet = (SCH_SHEET*) selection.Front();
2949 SCH_COMMIT commit( m_toolMgr );
2950
2951 if( !sheet || !sheet->HasUndefinedPins() )
2952 return 0;
2953
2954 if( !IsOK( m_frame, _( "Do you wish to delete the unreferenced pins from this sheet?" ) ) )
2955 return 0;
2956
2957 commit.Modify( sheet, m_frame->GetScreen() );
2958
2959 sheet->CleanupSheet();
2960
2961 updateItem( sheet, true );
2962
2963 commit.Push( _( "Cleanup Sheet Pins" ) );
2964
2965 if( selection.IsHover() )
2966 m_toolMgr->RunAction( ACTIONS::selectionClear );
2967
2968 return 0;
2969}
2970
2971
2973{
2974 SCH_SELECTION& selection = m_selectionTool->RequestSelection( { SCH_SHEET_T } );
2975
2976 if( selection.GetSize() > 1 )
2977 return 0;
2978
2979 SCH_SHEET* sheet = (SCH_SHEET*) selection.Front();
2980
2981 SCH_SHEET_PATH instance = m_frame->GetCurrentSheet();
2982
2983 SCH_SCREEN* screen;
2984
2985 if( sheet )
2986 {
2987 // When changing the page number of a selected sheet, the current screen owns the sheet.
2988 screen = m_frame->GetScreen();
2989
2990 instance.push_back( sheet );
2991 }
2992 else
2993 {
2994 SCH_SHEET_PATH prevInstance = instance;
2995
2996 // When change the page number in the screen, the previous screen owns the sheet.
2997 if( prevInstance.size() )
2998 {
2999 prevInstance.pop_back();
3000 screen = prevInstance.LastScreen();
3001 }
3002 else
3003 {
3004 // The root sheet and root screen are effectively the same thing.
3005 screen = m_frame->GetScreen();
3006 }
3007
3008 sheet = m_frame->GetCurrentSheet().Last();
3009 }
3010
3011 wxString msg;
3012 wxString sheetPath = instance.PathHumanReadable( false );
3013 wxString pageNumber = instance.GetPageNumber();
3014
3015 msg.Printf( _( "Enter page number for sheet path%s" ),
3016 ( sheetPath.Length() > 20 ) ? "\n" + sheetPath : " " + sheetPath );
3017
3018 wxTextEntryDialog dlg( m_frame, msg, _( "Edit Sheet Page Number" ), pageNumber );
3019
3020 dlg.SetTextValidator( wxFILTER_ALPHANUMERIC ); // No white space.
3021
3022 if( dlg.ShowModal() == wxID_CANCEL || dlg.GetValue() == instance.GetPageNumber() )
3023 return 0;
3024
3025 SCH_COMMIT commit( m_frame );
3026
3027 commit.Modify( sheet, screen );
3028
3029 instance.SetPageNumber( dlg.GetValue() );
3030
3031 if( instance == m_frame->GetCurrentSheet() )
3032 {
3033 m_frame->GetScreen()->SetPageNumber( dlg.GetValue() );
3034 m_frame->OnPageSettingsChange();
3035 }
3036
3037 commit.Push( wxS( "Change Sheet Page Number" ) );
3038
3039 if( selection.IsHover() )
3040 m_toolMgr->RunAction( ACTIONS::selectionClear );
3041
3042 return 0;
3043}
3044
3045
3047{
3048 return m_toolMgr->RunAction( SCH_ACTIONS::importSheet, aEvent.Parameter<wxString*>() );
3049}
3050
3051
3053{
3054 wxString* filename = aEvent.Parameter<wxString*>();
3055
3056 if( !filename )
3057 return 0;
3058
3059 SCH_BITMAP* image = new SCH_BITMAP( VECTOR2I( 0, 0 ) );
3060
3061 if( !image->GetReferenceImage().ReadImageFile( *filename ) )
3062 {
3063 wxMessageBox( wxString::Format( _( "Could not load image from '%s'." ), *filename ) );
3064 delete image;
3065 return 0;
3066 }
3067
3068 return m_toolMgr->RunAction( SCH_ACTIONS::placeImage, image );
3069}
3070
3071
3073 std::set<std::pair<SCH_SYMBOL*, SCH_SCREEN*>>& aCollectedUnits )
3074{
3075 for( EDA_ITEM* item : aSelection )
3076 {
3077 if( item->Type() == SCH_SYMBOL_T )
3078 {
3079 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
3080
3081 aCollectedUnits.insert( { symbol, m_frame->GetScreen() } );
3082
3083 // The attributes should be kept in sync in multi-unit parts.
3084 // Of course the symbol must be annotated to collect other units.
3085 if( symbol->IsAnnotated( &m_frame->GetCurrentSheet() ) )
3086 {
3087 wxString ref = symbol->GetRef( &m_frame->GetCurrentSheet() );
3088 int unit = symbol->GetUnit();
3089 LIB_ID libId = symbol->GetLibId();
3090
3091 for( SCH_SHEET_PATH& sheet : m_frame->Schematic().Hierarchy() )
3092 {
3093 SCH_SCREEN* screen = sheet.LastScreen();
3094 std::vector<SCH_SYMBOL*> otherUnits;
3095
3096 CollectOtherUnits( ref, unit, libId, sheet, &otherUnits );
3097
3098 for( SCH_SYMBOL* otherUnit : otherUnits )
3099 aCollectedUnits.insert( { otherUnit, screen } );
3100 }
3101 }
3102 }
3103 }
3104}
3105
3106
3108{
3109 SCH_SELECTION& selection = m_selectionTool->RequestSelection( { SCH_SYMBOL_T } );
3110 SCH_COMMIT commit( m_toolMgr );
3111
3112 std::set<std::pair<SCH_SYMBOL*, SCH_SCREEN*>> collectedUnits;
3113
3114 collectUnits( selection, collectedUnits );
3115 bool new_state = false;
3116
3117 for( const auto& [symbol, _] : collectedUnits )
3118 {
3119 if( ( aEvent.IsAction( &SCH_ACTIONS::setDNP ) && !symbol->GetDNP() )
3120 || ( aEvent.IsAction( &SCH_ACTIONS::setExcludeFromSimulation ) && !symbol->GetExcludedFromSim() )
3121 || ( aEvent.IsAction( &SCH_ACTIONS::setExcludeFromBOM ) && !symbol->GetExcludedFromBOM() )
3122 || ( aEvent.IsAction( &SCH_ACTIONS::setExcludeFromBoard ) && !symbol->GetExcludedFromBoard() ) )
3123 {
3124 new_state = true;
3125 break;
3126 }
3127 }
3128
3129 for( const auto& [symbol, screen] : collectedUnits )
3130 {
3131 commit.Modify( symbol, screen );
3132
3133 if( aEvent.IsAction( &SCH_ACTIONS::setDNP ) )
3134 symbol->SetDNP( new_state );
3135
3137 symbol->SetExcludedFromSim( new_state );
3138
3140 symbol->SetExcludedFromBOM( new_state );
3141
3143 symbol->SetExcludedFromBoard( new_state );
3144 }
3145
3146 if( !commit.Empty() )
3147 commit.Push( _( "Toggle Attribute" ) );
3148
3149 if( selection.IsHover() )
3150 m_toolMgr->RunAction( ACTIONS::selectionClear );
3151
3152 return 0;
3153}
3154
3155
3157{
3158 // clang-format off
3164 Go( &SCH_EDIT_TOOL::Swap, SCH_ACTIONS::swap.MakeEvent() );
3167
3173
3193
3196
3201
3205
3208 // clang-format on
3209}
const char * name
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:114
@ add_hierarchical_label
@ component_select_unit
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
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:226
static TOOL_ACTION unselectItem
Definition actions.h:227
static TOOL_ACTION copy
Definition actions.h:78
static TOOL_ACTION pasteSpecial
Definition actions.h:81
static TOOL_ACTION groupProperties
Definition actions.h:246
static TOOL_ACTION rightJustify
Definition actions.h:89
static TOOL_ACTION pageSettings
Definition actions.h:63
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:223
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:158
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...
ACTION_MENU(bool isContextMenu, TOOL_INTERACTIVE *aTool=nullptr)
Default constructor.
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.
void SetIcon(BITMAPS aIcon)
Assign an icon for the entry.
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 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
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
Definition commit.h:90
COMMIT & Added(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
Definition commit.h:84
void Unstage(EDA_ITEM *aItem, BASE_SCREEN *aScreen)
Definition commit.cpp:136
bool Empty() const
Definition commit.h:137
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:106
COMMIT & Removed(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Definition commit.h:96
int GetStatus(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Returns status of an item.
Definition commit.cpp:167
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 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:142
bool IsVertical() const
Definition eda_angle.h:148
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:98
virtual VECTOR2I GetPosition() const
Definition eda_item.h:272
virtual void SetPosition(const VECTOR2I &aPos)
Definition eda_item.h:273
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition eda_item.cpp:110
EDA_ITEM_FLAGS GetEditFlags() const
Definition eda_item.h:148
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:142
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition eda_item.h:144
bool IsSelected() const
Definition eda_item.h:127
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition eda_item.h:192
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.h:113
EDA_ITEM * GetParent() const
Definition eda_item.h:112
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition eda_item.h:146
bool IsMoving() const
Definition eda_item.h:125
bool IsNew() const
Definition eda_item.h:124
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:168
const EDA_ANGLE & GetTextAngle() const
Definition eda_text.h:146
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition eda_text.cpp:534
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:186
void SetTextPos(const VECTOR2I &aPoint)
Definition eda_text.cpp:579
KIFONT::FONT * GetFont() const
Definition eda_text.h:246
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
Definition eda_text.cpp:434
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition eda_text.cpp:418
wxString GetHyperlink() const
Definition eda_text.h:400
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition eda_text.h:199
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition eda_text.cpp:285
void SetBold(bool aBold)
Set the text to be bold - this will also update the font if needed.
Definition eda_text.cpp:336
bool IsBold() const
Definition eda_text.h:183
void SetHyperlink(wxString aLink)
Definition eda_text.h:401
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition eda_text.h:202
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition eda_text.cpp:300
int GetTextThickness() const
Definition eda_text.h:127
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
Definition eda_text.cpp:308
void SetFont(KIFONT::FONT *aFont)
Definition eda_text.cpp:500
VECTOR2I GetTextSize() const
Definition eda_text.h:260
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition eda_text.cpp:410
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
virtual wxString GetClass() const =0
Return the class name.
void RecacheAllItems()
Rebuild GAL display lists.
Definition view.cpp:1451
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:49
int GetUnitCount() const override
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:216
void update() override
Update menu state stub.
ACTION_MENU * create() const override
Return an instance of this class. It has to be overridden in inheriting classes.
These are loaded from Eeschema settings but then overwritten by the project settings.
SCHEMATIC_SETTINGS & Settings() const
static TOOL_ACTION rotateCCW
static TOOL_ACTION placeClassLabel
Definition sch_actions.h:79
static TOOL_ACTION editValue
static TOOL_ACTION setExcludeFromBOM
static TOOL_ACTION mirrorV
static TOOL_ACTION clearHighlight
static TOOL_ACTION swap
static TOOL_ACTION placeGlobalLabel
Definition sch_actions.h:80
static TOOL_ACTION changeSymbols
static TOOL_ACTION updateSymbol
static TOOL_ACTION autoplaceFields
static TOOL_ACTION changeSymbol
static TOOL_ACTION ddAddImage
static TOOL_ACTION properties
static TOOL_ACTION editReference
static TOOL_ACTION breakWire
static TOOL_ACTION placeHierLabel
Definition sch_actions.h:81
static TOOL_ACTION placeLabel
Definition sch_actions.h:78
static TOOL_ACTION toText
static TOOL_ACTION toHLabel
static TOOL_ACTION lineMode45
static TOOL_ACTION rotateCW
static TOOL_ACTION importSheet
Definition sch_actions.h:87
static TOOL_ACTION drag
static TOOL_ACTION toLabel
static TOOL_ACTION setDNP
static TOOL_ACTION placeImage
static TOOL_ACTION editWithLibEdit
static TOOL_ACTION cleanupSheetPins
static TOOL_ACTION toDLabel
static TOOL_ACTION cycleBodyStyle
static TOOL_ACTION mirrorH
static TOOL_ACTION setExcludeFromSimulation
static TOOL_ACTION lineMode90
static TOOL_ACTION ddAppendFile
static TOOL_ACTION slice
static TOOL_ACTION placeSchematicText
Definition sch_actions.h:92
static TOOL_ACTION toTextBox
static TOOL_ACTION lineModeFree
static TOOL_ACTION updateSymbols
static TOOL_ACTION enterSheet
static TOOL_ACTION editFootprint
static TOOL_ACTION repeatDrawItem
static TOOL_ACTION editTextAndGraphics
static TOOL_ACTION editPageNumber
static TOOL_ACTION toGLabel
static TOOL_ACTION setExcludeFromBoard
static TOOL_ACTION move
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
static const std::vector< KICAD_T > DeletableItems
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
virtual void Revert() override
Revert the commit by restoring the modified items state.
static SELECTION_CONDITION SingleMultiFunctionPin
static SELECTION_CONDITION SingleSymbol
static SELECTION_CONDITION MultipleSymbolsOrPower
static SELECTION_CONDITION AllPinsOrSheetPins
static SELECTION_CONDITION SingleSymbolOrPower
static SELECTION_CONDITION SingleMultiUnitSymbol
static SELECTION_CONDITION SingleMultiBodyStyleSymbol
Tool responsible for drawing/placing items (symbols, wires, buses, labels, etc.).
Schematic editor (Eeschema) main window.
const wxString & GetHighlightedConnection() const
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
static const std::vector< KICAD_T > RotatableItems
int EditField(const TOOL_EVENT &aEvent)
int EditPageNumber(const TOOL_EVENT &aEvent)
int DoDelete(const TOOL_EVENT &aEvent)
bool Init() override
Init() is called once upon a registration of the tool.
int CleanupSheetPins(const TOOL_EVENT &aEvent)
void editFieldText(SCH_FIELD *aField)
int Mirror(const TOOL_EVENT &aEvent)
int GlobalEdit(const TOOL_EVENT &aEvent)
Delete the selected items, or the item under the cursor.
int SetAttribute(const TOOL_EVENT &aEvent)
Modify Attributes (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)
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 CycleBodyStyle(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 DdAddImage(const TOOL_EVENT &aEvent)
int RepeatDrawItem(const TOOL_EVENT &aEvent)
bool IsMandatory() const
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
VECTOR2I GetPosition() const override
FIELD_T GetId() const
Definition sch_field.h:116
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
void SetPosition(const VECTOR2I &aPosition) override
void SetText(const wxString &aText) override
VECTOR2I GetParentPosition() const
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:493
virtual void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo)
Definition sch_item.h:595
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode)
Definition sch_item.h:597
const SYMBOL * GetParentSymbol() const
Definition sch_item.cpp:223
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:217
int GetBodyStyle() const
Definition sch_item.h:244
virtual void MirrorHorizontally(int aCenter)
Mirror item horizontally about aCenter.
Definition sch_item.h:373
virtual void Move(const VECTOR2I &aMoveVector)
Move the item by aMoveVector to a new position.
Definition sch_item.h:365
int GetUnit() const
Definition sch_item.h:238
void SetConnectivityDirty(bool aDirty=true)
Definition sch_item.h:556
void SetFieldsAutoplaced(AUTOPLACE_ALGO aAlgo)
Definition sch_item.h:593
virtual void Rotate(const VECTOR2I &aCenter, bool aRotateCCW)
Rotate the item around aCenter 90 degrees in the clockwise direction.
Definition sch_item.h:389
AUTOPLACE_ALGO GetFieldsAutoplaced() const
Return whether the fields have been automatically placed.
Definition sch_item.h:592
wxString GetClass() const override
Return the class name.
Definition sch_item.h:177
bool IsGroupableType() const
Definition sch_item.cpp:105
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition sch_item.h:508
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:381
void AddFields(const std::vector< SCH_FIELD > &aFields)
Definition sch_label.h:225
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
SPIN_STYLE GetSpinStyle() const
void SetShape(LABEL_FLAG_SHAPE aShape)
Definition sch_label.h:181
LABEL_FLAG_SHAPE GetShape() const
Definition sch_label.h:180
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
std::vector< SCH_FIELD > & GetFields()
Definition sch_label.h:212
virtual void SetSpinStyle(SPIN_STYLE aSpinStyle)
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)
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.
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:42
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
Definition sch_line.cpp:380
VECTOR2I GetEndPoint() const
Definition sch_line.h:144
VECTOR2I GetStartPoint() const
Definition sch_line.h:139
const std::map< wxString, ALT > & GetAlternates() const
Definition sch_pin.h:147
const wxString & GetName() const
Definition sch_pin.cpp:400
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition sch_screen.h:758
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.
const wxString & GetFileName() const
Definition sch_screen.h:152
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.
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
void ClearAnnotation(SCH_SHEET_PATH *aSheetPath, bool aResetPrefix)
Clear the annotation for the symbols in aSheetPath on the screen.
SCH_SELECTION & GetSelection()
SCH_GROUP * GetEnteredGroup()
void SetPosition(const VECTOR2I &aPos) override
Definition sch_shape.h:86
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
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.
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.
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...
void CleanupSheet()
Delete sheet label which do not have a corresponding hierarchical label.
void RemovePin(const SCH_SHEET_PIN *aSheetPin)
Remove aSheetPin from the sheet.
bool HasUndefinedPins() const
Check all sheet labels against schematic for undefined hierarchical labels.
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.
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
Schematic symbol object.
Definition sch_symbol.h:75
wxString GetUnitDisplayName(int aUnit, bool aLabel) const override
Return the display name for a given unit aUnit.
bool IsAnnotated(const SCH_SHEET_PATH *aSheet) const
Check if the symbol has a valid annotation (reference) for the given sheet path.
bool IsMultiBodyStyle() const override
Definition sch_symbol.h:261
void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo) override
Automatically orient all the fields in the symbol.
wxString GetBodyStyleDescription(int aBodyStyle, bool aLabel) const override
bool HasDeMorganBodyStyles() const override
int GetBodyStyleCount() const override
Return the number of body styles of 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.
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
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.
int GetMarginBottom() const
Definition sch_textbox.h:66
int GetLegacyTextMargin() const
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:210
virtual void MirrorSpinStyle(bool aLeftRight)
Definition sch_text.cpp:222
void updateItem(EDA_ITEM *aItem, bool aUpdateRTree) const
int Increment(const TOOL_EVENT &aEvent)
void saveCopyInUndoList(EDA_ITEM *aItem, UNDO_REDO aType, bool aAppend=false, bool aDirtyConnectivity=true)
int InteractiveDelete(const TOOL_EVENT &aEvent)
bool Init() override
Init() is called once upon a registration of the tool.
SCH_TOOL_BASE(const std::string &aName)
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.
virtual void Add(EDA_ITEM *aItem)
Definition selection.cpp:42
virtual KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
Definition selection.cpp:75
VECTOR2I GetReferencePoint() const
virtual VECTOR2I GetCenter() const
Returns the center point of the selection area bounding box.
Definition selection.cpp:92
bool IsHover() const
Definition selection.h:89
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition selection.h:105
EDA_ITEM * Front() const
Definition selection.h:177
int Size() const
Returns the number of selected parts.
Definition selection.h:121
std::deque< EDA_ITEM * > & Items()
Definition selection.h:182
std::vector< EDA_ITEM * > GetItemsSortedBySelectionOrder() const
bool OnlyContains(std::vector< KICAD_T > aList) const
Checks if all items in the selection have a type in aList.
bool Empty() const
Checks if there is anything selected.
Definition selection.h:115
bool HasReferencePoint() const
Definition selection.h:216
size_t CountType(KICAD_T aType) const
unsigned CCWRotationsTo(const SPIN_STYLE &aOther) const
Get CCW rotation needed to get to the given spin style.
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.
KIGFX::VIEW_CONTROLS * getViewControls() const
Definition tool_base.cpp:44
KIGFX::VIEW * getView() const
Definition tool_base.cpp:38
Generic, UI-independent tool event.
Definition tool_event.h:171
bool DisableGridSnapping() const
Definition tool_event.h:371
bool Matches(const TOOL_EVENT &aEvent) const
Test whether two events match in terms of category & action or command.
Definition tool_event.h:392
COMMIT * Commit() const
Definition tool_event.h:283
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
T Parameter() const
Return a parameter assigned to the event.
Definition tool_event.h:473
void Go(int(SCH_EDIT_FRAME::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
@ CHT_ADD
Definition commit.h:42
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:251
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:413
static constexpr EDA_ANGLE ANGLE_VERTICAL
Definition eda_angle.h:408
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition eda_angle.h:407
@ RECURSE
Definition eda_item.h:51
@ NO_RECURSE
Definition eda_item.h:52
#define IGNORE_PARENT_GROUP
Definition eda_item.h:55
#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.
@ NO_FILL
Definition eda_shape.h:57
@ ID_POPUP_SCH_PIN_TRICKS_HIER_LABEL
@ ID_POPUP_SCH_PIN_TRICKS_WIRE
@ ID_POPUP_SCH_ALT_PIN_FUNCTION
@ ID_POPUP_SCH_SELECT_UNIT1
Definition eeschema_id.h:90
@ ID_POPUP_SCH_SELECT_UNIT
Definition eeschema_id.h:89
@ ID_POPUP_SCH_SELECT_BODY_STYLE
Definition eeschema_id.h:99
@ ID_POPUP_SCH_PLACE_UNIT1
Definition eeschema_id.h:96
@ ID_POPUP_SCH_SELECT_BODY_STYLE1
@ ID_POPUP_SCH_PIN_TRICKS_NET_LABEL
@ ID_POPUP_SCH_PIN_TRICKS_NO_CONNECT
@ ID_POPUP_SCH_SELECT_UNIT_END
Definition eeschema_id.h:93
@ ID_POPUP_SCH_ALT_PIN_FUNCTION_END
@ ID_POPUP_SCH_PIN_TRICKS_GLOBAL_LABEL
@ LINE_MODE_90
@ LINE_MODE_45
@ LINE_MODE_FREE
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:35
@ LAYER_NOTES
Definition layer_ids.h:466
@ LAYER_SCHEMATIC_DRAWINGSHEET
Definition layer_ids.h:494
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition macros.h:83
#define UNIMPLEMENTED_FOR(type)
Definition macros.h:96
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:100
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...
SCH_CONDITIONS S_C
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
@ BASE
Definition sch_item.h:59
LABEL_FLAG_SHAPE
Definition sch_label.h:99
@ L_UNSPECIFIED
Definition sch_label.h:104
@ F_ROUND
Definition sch_label.h:108
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.
std::set< int > GetUnplacedUnitsForSymbol(const SCH_SYMBOL &aSym)
Get a list of unplaced (i.e.
T * GetAppSettings(const char *aFilename)
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
Functors that can be used to figure out how the action controls should be displayed in the UI and if ...
@ 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
@ USER
The field ID hasn't been set yet; field is invalid.
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
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:175
@ SCH_TABLE_T
Definition typeinfo.h:167
@ SCH_LINE_T
Definition typeinfo.h:165
@ SCH_NO_CONNECT_T
Definition typeinfo.h:162
@ SCH_SYMBOL_T
Definition typeinfo.h:174
@ SCH_TABLECELL_T
Definition typeinfo.h:168
@ SCH_ITEM_LOCATE_WIRE_T
Definition typeinfo.h:188
@ SCH_FIELD_T
Definition typeinfo.h:152
@ SCH_DIRECTIVE_LABEL_T
Definition typeinfo.h:173
@ SCH_LABEL_T
Definition typeinfo.h:169
@ SCH_SHEET_T
Definition typeinfo.h:177
@ SCH_ITEM_LOCATE_BUS_T
Definition typeinfo.h:189
@ SCH_MARKER_T
Definition typeinfo.h:160
@ SCH_SHAPE_T
Definition typeinfo.h:151
@ SCH_RULE_AREA_T
Definition typeinfo.h:172
@ SCH_HIER_LABEL_T
Definition typeinfo.h:171
@ SCH_BUS_BUS_ENTRY_T
Definition typeinfo.h:164
@ SCH_LABEL_LOCATE_ANY_T
Definition typeinfo.h:193
@ SCH_ITEM_LOCATE_GRAPHIC_LINE_T
Definition typeinfo.h:190
@ SCHEMATIC_T
Definition typeinfo.h:206
@ SCH_SHEET_PIN_T
Definition typeinfo.h:176
@ SCH_TEXT_T
Definition typeinfo.h:153
@ SCH_BUS_WIRE_ENTRY_T
Definition typeinfo.h:163
@ SCH_BITMAP_T
Definition typeinfo.h:166
@ SCH_TEXTBOX_T
Definition typeinfo.h:154
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:170
@ SCH_JUNCTION_T
Definition typeinfo.h:161
@ SCH_PIN_T
Definition typeinfo.h:155
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694