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