KiCad PCB EDA Suite
Loading...
Searching...
No Matches
symbol_editor_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-2021 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 <tool/picker_tool.h>
30#include <ee_actions.h>
31#include <string_utils.h>
32#include <symbol_edit_frame.h>
33#include <sch_commit.h>
35#include <dialogs/dialog_text_properties.h>
41#include <sch_textbox.h>
43#include <wx/textdlg.h> // for wxTextEntryDialog
44#include <math/util.h> // for KiROUND
45
47 EE_TOOL_BASE( "eeschema.SymbolEditTool" ),
48 m_pickerItem( nullptr )
49{
50}
51
52
54{
56
59
60 wxASSERT_MSG( drawingTools, "eeschema.SymbolDrawing tool is not available" );
61
62 auto haveSymbolCondition =
63 [&]( const SELECTION& sel )
64 {
66 };
67
68 auto canEdit =
69 [&]( const SELECTION& sel )
70 {
72 return false;
73
74 if( m_frame->IsSymbolAlias() )
75 {
76 for( EDA_ITEM* item : sel )
77 {
78 if( item->Type() != SCH_FIELD_T )
79 return false;
80 }
81 }
82
83 return true;
84 };
85
86 // Add edit actions to the move tool menu
87 if( moveTool )
88 {
89 CONDITIONAL_MENU& moveMenu = moveTool->GetToolMenu().GetMenu();
90
91 moveMenu.AddSeparator( 200 );
92 moveMenu.AddItem( EE_ACTIONS::rotateCCW, canEdit && EE_CONDITIONS::NotEmpty, 200 );
93 moveMenu.AddItem( EE_ACTIONS::rotateCW, canEdit && EE_CONDITIONS::NotEmpty, 200 );
94 moveMenu.AddItem( EE_ACTIONS::mirrorV, canEdit && EE_CONDITIONS::NotEmpty, 200 );
95 moveMenu.AddItem( EE_ACTIONS::mirrorH, canEdit && EE_CONDITIONS::NotEmpty, 200 );
96
97 moveMenu.AddItem( EE_ACTIONS::properties, canEdit && EE_CONDITIONS::Count( 1 ), 200 );
98
99 moveMenu.AddSeparator( 300 );
102 moveMenu.AddItem( ACTIONS::duplicate, canEdit && EE_CONDITIONS::NotEmpty, 300 );
103 moveMenu.AddItem( ACTIONS::doDelete, canEdit && EE_CONDITIONS::NotEmpty, 200 );
104
105 moveMenu.AddSeparator( 400 );
106 moveMenu.AddItem( ACTIONS::selectAll, haveSymbolCondition, 400 );
107 moveMenu.AddItem( ACTIONS::unselectAll, haveSymbolCondition, 400 );
108 }
109
110 // Add editing actions to the drawing tool menu
111 CONDITIONAL_MENU& drawMenu = drawingTools->GetToolMenu().GetMenu();
112
113 drawMenu.AddSeparator( 200 );
115 drawMenu.AddItem( EE_ACTIONS::rotateCW, canEdit && EE_CONDITIONS::IdleSelection, 200 );
116 drawMenu.AddItem( EE_ACTIONS::mirrorV, canEdit && EE_CONDITIONS::IdleSelection, 200 );
117 drawMenu.AddItem( EE_ACTIONS::mirrorH, canEdit && EE_CONDITIONS::IdleSelection, 200 );
118
119 drawMenu.AddItem( EE_ACTIONS::properties, canEdit && EE_CONDITIONS::Count( 1 ), 200 );
120
121 // Add editing actions to the selection tool menu
123
124 selToolMenu.AddItem( EE_ACTIONS::rotateCCW, canEdit && EE_CONDITIONS::NotEmpty, 200 );
125 selToolMenu.AddItem( EE_ACTIONS::rotateCW, canEdit && EE_CONDITIONS::NotEmpty, 200 );
126 selToolMenu.AddItem( EE_ACTIONS::mirrorV, canEdit && EE_CONDITIONS::NotEmpty, 200 );
127 selToolMenu.AddItem( EE_ACTIONS::mirrorH, canEdit && EE_CONDITIONS::NotEmpty, 200 );
128
129 selToolMenu.AddItem( EE_ACTIONS::properties, canEdit && EE_CONDITIONS::Count( 1 ), 200 );
130
131 selToolMenu.AddSeparator( 300 );
134 selToolMenu.AddItem( ACTIONS::paste, canEdit && EE_CONDITIONS::Idle, 300 );
135 selToolMenu.AddItem( ACTIONS::duplicate, canEdit && EE_CONDITIONS::NotEmpty, 300 );
136 selToolMenu.AddItem( ACTIONS::doDelete, canEdit && EE_CONDITIONS::NotEmpty, 300 );
137
138 selToolMenu.AddSeparator( 400 );
139 selToolMenu.AddItem( ACTIONS::selectAll, haveSymbolCondition, 400 );
140 selToolMenu.AddItem( ACTIONS::unselectAll, haveSymbolCondition, 400 );
141
142 return true;
143}
144
145
147{
149
150 if( selection.GetSize() == 0 )
151 return 0;
152
153 VECTOR2I rotPoint;
154 bool ccw = ( aEvent.Matches( EE_ACTIONS::rotateCCW.MakeEvent() ) );
155 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.Front() );
156 SCH_COMMIT localCommit( m_toolMgr );
157 SCH_COMMIT* commit = dynamic_cast<SCH_COMMIT*>( aEvent.Commit() );
158
159 if( !commit )
160 commit = &localCommit;
161
162 if( !item->IsMoving() )
163 commit->Modify( m_frame->GetCurSymbol(), m_frame->GetScreen() );
164
165 if( selection.GetSize() == 1 )
166 rotPoint = item->GetPosition();
167 else
168 rotPoint = m_frame->GetNearestHalfGridPosition( mapCoords( selection.GetCenter(), true ) );
169
170 for( unsigned ii = 0; ii < selection.GetSize(); ii++ )
171 {
172 item = static_cast<SCH_ITEM*>( selection.GetItem( ii ) );
173 item->Rotate( rotPoint, ccw );
174 m_frame->UpdateItem( item, false, true );
175 }
176
177 if( item->IsMoving() )
178 {
180 }
181 else
182 {
183 if( selection.IsHover() )
185
186 if( !localCommit.Empty() )
187 localCommit.Push( _( "Rotate" ) );
188 }
189
190 return 0;
191}
192
193
195{
197
198 if( selection.GetSize() == 0 )
199 return 0;
200
201 VECTOR2I mirrorPoint;
202 bool xAxis = ( aEvent.Matches( EE_ACTIONS::mirrorV.MakeEvent() ) );
203 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.Front() );
204
205 if( !item->IsMoving() )
206 saveCopyInUndoList( m_frame->GetCurSymbol(), UNDO_REDO::LIBEDIT );
207
208 if( selection.GetSize() == 1 )
209 {
210 mirrorPoint = item->GetPosition();
211
212 switch( item->Type() )
213 {
214 case SCH_FIELD_T:
215 {
216 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
217
218 if( xAxis )
219 field->SetVertJustify( TO_VJUSTIFY( -field->GetVertJustify() ) );
220 else
221 field->SetHorizJustify( TO_HJUSTIFY( -field->GetHorizJustify() ) );
222
223 break;
224 }
225
226 default:
227 if( xAxis )
228 item->MirrorVertically( mirrorPoint.y );
229 else
230 item->MirrorHorizontally( mirrorPoint.x );
231
232 break;
233 }
234
235
236 m_frame->UpdateItem( item, false, true );
237 }
238 else
239 {
240 mirrorPoint = m_frame->GetNearestHalfGridPosition( mapCoords( selection.GetCenter(), true ) );
241
242 for( unsigned ii = 0; ii < selection.GetSize(); ii++ )
243 {
244 item = static_cast<SCH_ITEM*>( selection.GetItem( ii ) );
245
246 if( xAxis )
247 item->MirrorVertically( mirrorPoint.y );
248 else
249 item->MirrorHorizontally( mirrorPoint.x );
250
251 m_frame->UpdateItem( item, false, true );
252 }
253 }
254
255 if( item->IsMoving() )
256 {
258 }
259 else
260 {
261 if( selection.IsHover() )
263
264 m_frame->OnModify();
265 }
266
267 return 0;
268}
269
270
271static std::vector<KICAD_T> nonFields =
272{
278};
279
280
282{
283 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
284 std::deque<EDA_ITEM*> items = m_selectionTool->RequestSelection().GetItems();
285 SCH_COMMIT commit( m_frame );
286
287 if( items.empty() )
288 return 0;
289
290 // Don't leave a freed pointer in the selection
292
293 commit.Modify( symbol, m_frame->GetScreen() );
294
295 std::set<SCH_ITEM*> toDelete;
296 int fieldsHidden = 0;
297 int fieldsAlreadyHidden = 0;
298
299 for( EDA_ITEM* item : items )
300 {
301 if( item->Type() == SCH_PIN_T )
302 {
303 SCH_PIN* curr_pin = static_cast<SCH_PIN*>( item );
304 VECTOR2I pos = curr_pin->GetPosition();
305
306 toDelete.insert( curr_pin );
307
308 // when pin editing is synchronized, pins in the same position, with the same name
309 // in different units are also removed. But only one pin per unit (matching)
310 if( m_frame->SynchronizePins() )
311 {
312 std::vector<bool> got_unit( symbol->GetUnitCount() + 1 );
313
314 got_unit[curr_pin->GetUnit()] = true;
315
316 for( SCH_PIN* pin : symbol->GetAllLibPins() )
317 {
318 if( got_unit[pin->GetUnit()] )
319 continue;
320
321 if( pin->GetPosition() != pos )
322 continue;
323
324 if( pin->GetBodyStyle() != curr_pin->GetBodyStyle() )
325 continue;
326
327 if( pin->GetType() != curr_pin->GetType() )
328 continue;
329
330 if( pin->GetName() != curr_pin->GetName() )
331 continue;
332
333 toDelete.insert( pin );
334 got_unit[pin->GetUnit()] = true;
335 }
336 }
337 }
338 else if( item->Type() == SCH_FIELD_T )
339 {
340 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
341
342 // Hide "deleted" fields
343 if( field->IsVisible() )
344 {
345 field->SetVisible( false );
346 fieldsHidden++;
347 }
348 else
349 {
350 fieldsAlreadyHidden++;
351 }
352 }
353 else if( SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( item ) )
354 {
355 toDelete.insert( schItem );
356 }
357 }
358
359 for( SCH_ITEM* item : toDelete )
360 symbol->RemoveDrawItem( item );
361
362 if( toDelete.size() == 0 )
363 {
364 if( fieldsHidden == 1 )
365 commit.Push( _( "Hide Field" ) );
366 else if( fieldsHidden > 1 )
367 commit.Push( _( "Hide Fields" ) );
368 else if( fieldsAlreadyHidden > 0 )
369 m_frame->ShowInfoBarError( _( "Use the Symbol Properties dialog to remove fields." ) );
370 }
371 else
372 {
373 commit.Push( _( "Delete" ) );
374 }
375
377 return 0;
378}
379
380
381#define HITTEST_THRESHOLD_PIXELS 5
382
383
385{
387
389 m_pickerItem = nullptr;
390
391 // Deactivate other tools; particularly important if another PICKER is currently running
392 Activate();
393
394 picker->SetCursor( KICURSOR::REMOVE );
395
396 picker->SetClickHandler(
397 [this]( const VECTOR2D& aPosition ) -> bool
398 {
399 if( m_pickerItem )
400 {
402 selectionTool->UnbrightenItem( m_pickerItem );
403 selectionTool->AddItemToSel( m_pickerItem, true /*quiet mode*/ );
405 m_pickerItem = nullptr;
406 }
407
408 return true;
409 } );
410
411 picker->SetMotionHandler(
412 [this]( const VECTOR2D& aPos )
413 {
415 EE_COLLECTOR collector;
416
417 selectionTool->CollectHits( collector, aPos, nonFields );
418
419 // Remove unselectable items
420 for( int i = collector.GetCount() - 1; i >= 0; --i )
421 {
422 if( !selectionTool->Selectable( collector[ i ] ) )
423 collector.Remove( i );
424 }
425
426 if( collector.GetCount() > 1 )
427 selectionTool->GuessSelectionCandidates( collector, aPos );
428
429 EDA_ITEM* item = collector.GetCount() == 1 ? collector[ 0 ] : nullptr;
430
431 if( m_pickerItem != item )
432 {
433 if( m_pickerItem )
434 selectionTool->UnbrightenItem( m_pickerItem );
435
436 m_pickerItem = item;
437
438 if( m_pickerItem )
439 selectionTool->BrightenItem( m_pickerItem );
440 }
441 } );
442
443 picker->SetFinalizeHandler(
444 [this]( const int& aFinalState )
445 {
446 if( m_pickerItem )
447 m_toolMgr->GetTool<EE_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
448
449 // Wake the selection tool after exiting to ensure the cursor gets updated
451 } );
452
454
455 return 0;
456}
457
458
460{
462
463 if( selection.Empty() || aEvent.IsAction( &EE_ACTIONS::symbolProperties ) )
464 {
465 if( m_frame->GetCurSymbol() )
467 }
468 else if( selection.Size() == 1 )
469 {
470 SCH_ITEM* item = static_cast<SCH_ITEM*>( selection.Front() );
471
472 // Save copy for undo if not in edit (edit command already handle the save copy)
473 if( item->GetEditFlags() == 0 )
474 saveCopyInUndoList( item->GetParent(), UNDO_REDO::LIBEDIT );
475
476 switch( item->Type() )
477 {
478 case SCH_PIN_T:
480 pinTool->EditPinProperties( static_cast<SCH_PIN*>( item ) );
481
482 break;
483
484 case SCH_SHAPE_T:
485 editShapeProperties( static_cast<SCH_SHAPE*>( item ) );
486 break;
487
488 case SCH_TEXT_T:
489 editTextProperties( item );
490 break;
491
492 case SCH_TEXTBOX_T:
493 editTextBoxProperties( item );
494 break;
495
496 case SCH_FIELD_T:
497 editFieldProperties( static_cast<SCH_FIELD*>( item ) );
498 break;
499
500 default:
501 wxFAIL_MSG( wxT( "Unhandled item <" ) + item->GetClass() + wxT( ">" ) );
502 break;
503 }
504 }
505
506 if( selection.IsHover() )
508
509 return 0;
510}
511
512
514{
515 DIALOG_SHAPE_PROPERTIES dlg( m_frame, aShape );
516
517 if( dlg.ShowModal() != wxID_OK )
518 return;
519
520 updateItem( aShape, true );
522 m_frame->OnModify();
523
526 drawingTools->SetDrawSpecificUnit( !dlg.GetApplyToAllUnits() );
527
528 std::vector<MSG_PANEL_ITEM> items;
529 aShape->GetMsgPanelInfo( m_frame, items );
530 m_frame->SetMsgPanel( items );
531}
532
533
535{
536 if ( aItem->Type() != SCH_TEXT_T )
537 return;
538
539 DIALOG_TEXT_PROPERTIES dlg( m_frame, static_cast<SCH_TEXT*>( aItem ) );
540
541 if( dlg.ShowModal() != wxID_OK )
542 return;
543
544 updateItem( aItem, true );
546 m_frame->OnModify( );
547}
548
549
551{
552 if ( aItem->Type() != SCH_TEXTBOX_T )
553 return;
554
555 DIALOG_TEXT_PROPERTIES dlg( m_frame, static_cast<SCH_TEXTBOX*>( aItem ) );
556
557 if( dlg.ShowModal() != wxID_OK )
558 return;
559
560 updateItem( aItem, true );
562 m_frame->OnModify( );
563}
564
565
567{
568 if( aField == nullptr )
569 return;
570
571 wxString caption;
572
573 if( aField->IsMandatory() )
574 caption.Printf( _( "Edit %s Field" ), TitleCaps( aField->GetName() ) );
575 else
576 caption.Printf( _( "Edit '%s' Field" ), aField->GetName() );
577
578 DIALOG_FIELD_PROPERTIES dlg( m_frame, caption, aField );
579
580 // The dialog may invoke a kiway player for footprint fields
581 // so we must use a quasimodal dialog.
582 if( dlg.ShowQuasiModal() != wxID_OK )
583 return;
584
585 wxString newFieldValue = EscapeString( dlg.GetText(), CTX_LIBID );
586 wxString oldFieldValue = aField->GetFullText( m_frame->GetUnit() );
587
588 SCH_COMMIT commit( m_toolMgr );
589 commit.Modify( aField, m_frame->GetScreen() );
590
591 dlg.UpdateField( aField );
592
593 commit.Push( caption );
594
597}
598
599
601{
602 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
603 bool partLocked = symbol->UnitsLocked();
604
607
609
610 // This dialog itself subsequently can invoke a KIWAY_PLAYER as a quasimodal
611 // frame. Therefore this dialog as a modal frame parent, MUST be run under
612 // quasimodal mode for the quasimodal frame support to work. So don't use
613 // the QUASIMODAL macros here.
614 if( dlg.ShowQuasiModal() != wxID_OK )
615 return;
616
617 m_frame->OnModify();
618
619 // if m_UnitSelectionLocked has changed, set some edit options or defaults
620 // to the best value
621 if( partLocked != symbol->UnitsLocked() )
622 {
624
625 // Enable synchronized pin edit mode for symbols with interchangeable units
626 m_frame->m_SyncPinEdit = !symbol->UnitsLocked();
627
628 // also set default edit options to the better value
629 // Usually if units are locked, graphic items are specific to each unit
630 // and if units are interchangeable, graphic items are common to units
631 tools->SetDrawSpecificUnit( symbol->UnitsLocked() );
632 }
633}
634
636 int& aSymbolLastPinNumber )
637{
638 if( !aNewPin->GetNumber().IsEmpty() )
639 {
640 // when duplicating a pin in symbol editor, assigning identical pin number
641 // to the old one does not makes any sense, so assign the next unassigned number to it
642 aSymbolLastPinNumber++;
643 aNewPin->SetNumber( wxString::Format( wxT( "%i" ), aSymbolLastPinNumber ) );
644 }
645}
646
648{
649 SCH_COMMIT commit( m_frame );
650 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
651
652 if( !symbol )
653 return 0;
654
655 commit.Modify( symbol );
656
658
659 DIALOG_LIB_EDIT_PIN_TABLE dlg( m_frame, symbol );
660
661 if( dlg.ShowModal() == wxID_CANCEL )
662 return -1;
663
664 commit.Push( _( "Edit Pins" ) );
666
667 return 0;
668}
669
670
672{
673 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
674
675 if( !symbol )
676 return 0;
677
678 if( !symbol->IsAlias() )
679 {
680 m_frame->ShowInfoBarError( _( "Symbol is not derived from another symbol." ) );
681 }
682 else
683 {
685
686 if( dlg.ShowModal() == wxID_CANCEL )
687 return -1;
688 }
689
690 return 0;
691}
692
693
695{
696 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
697
698 if( !symbol )
699 return 0;
700
701 int unitid = m_frame->GetUnit();
702
703 if( unitid == 0 )
704 {
705 return -1;
706 }
707
708 wxString promptText = wxString::Format( _( "Enter display name for unit %s" ),
709 symbol->GetUnitReference( unitid ) );
710 wxString currentvalue;
711
712 if( symbol->HasUnitDisplayName( unitid ) )
713 {
714 currentvalue = symbol->GetUnitDisplayName( unitid );
715 }
716
717 wxTextEntryDialog dlg( m_frame, promptText, _( "Set Unit Display Name" ), currentvalue );
718
719 if( dlg.ShowModal() == wxID_OK )
720 {
721 saveCopyInUndoList( symbol, UNDO_REDO::LIBEDIT );
722 symbol->SetUnitDisplayName( unitid, dlg.GetValue() );
724 m_frame->OnModify();
725 }
726 else
727 {
728 return -1;
729 }
730
731 return 0;
732}
733
734
736{
738
739 // Nuke the selection for later rebuilding. This does *not* clear the flags on any items;
740 // it just clears the SELECTION's reference to them.
741 selTool->GetSelection().Clear();
742 {
744 }
745 selTool->RebuildSelection();
746
747 return 0;
748}
749
750
752{
754
755 // Nuke the selection for later rebuilding. This does *not* clear the flags on any items;
756 // it just clears the SELECTION's reference to them.
757 selTool->GetSelection().Clear();
758 {
760 }
761 selTool->RebuildSelection();
762
763 return 0;
764}
765
766
768{
769 int retVal = Copy( aEvent );
770
771 if( retVal == 0 )
772 retVal = DoDelete( aEvent );
773
774 return retVal;
775}
776
777
779{
780 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
782
783 if( !symbol || !selection.GetSize() )
784 return 0;
785
786 for( SCH_ITEM& item : symbol->GetDrawItems() )
787 {
788 if( item.Type() == SCH_FIELD_T )
789 continue;
790
791 wxASSERT( !item.HasFlag( STRUCT_DELETED ) );
792
793 if( !item.IsSelected() )
794 item.SetFlags( STRUCT_DELETED );
795 }
796
797 LIB_SYMBOL* partCopy = new LIB_SYMBOL( *symbol );
798
799 STRING_FORMATTER formatter;
800 SCH_IO_KICAD_SEXPR::FormatLibSymbol( partCopy, formatter );
801
802 delete partCopy;
803
804 for( SCH_ITEM& item : symbol->GetDrawItems() )
806
807 if( m_toolMgr->SaveClipboard( formatter.GetString() ) )
808 return 0;
809 else
810 return -1;
811}
812
813
815{
816 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
817 LIB_SYMBOL* newPart = nullptr;
818
819 if( !symbol || symbol->IsAlias() )
820 return 0;
821
822 std::string clipboardData = m_toolMgr->GetClipboardUTF8();
823
824 try
825 {
826 std::vector<LIB_SYMBOL*> newParts = SCH_IO_KICAD_SEXPR::ParseLibSymbols( clipboardData, "Clipboard" );
827
828 if( newParts.empty() || !newParts[0] )
829 return -1;
830
831 newPart = newParts[0];
832 }
833 catch( IO_ERROR& )
834 {
835 // If it's not a symbol then paste as text
836 newPart = new LIB_SYMBOL( "dummy_part" );
837 SCH_TEXT* newText = new SCH_TEXT( { 0, 0 }, clipboardData, LAYER_DEVICE );
838 newPart->AddDrawItem( newText );
839 }
840
841 SCH_COMMIT commit( m_toolMgr );
842
843 commit.Modify( symbol );
845
846 for( SCH_ITEM& item : symbol->GetDrawItems() )
847 item.ClearFlags( IS_NEW | IS_PASTED | SELECTED );
848
849 for( SCH_ITEM& item : newPart->GetDrawItems() )
850 {
851 if( item.Type() == SCH_FIELD_T )
852 continue;
853
854 SCH_ITEM* newItem = item.Duplicate();
855 newItem->SetParent( symbol );
856 newItem->SetFlags( IS_NEW | IS_PASTED | SELECTED );
857
858 newItem->SetUnit( newItem->GetUnit() ? m_frame->GetUnit() : 0 );
859 newItem->SetBodyStyle( newItem->GetBodyStyle() ? m_frame->GetBodyStyle() : 0 );
860
861 symbol->AddDrawItem( newItem );
862 getView()->Add( newItem );
863 }
864
865 delete newPart;
866
868
870
871 if( !selection.Empty() )
872 {
873 selection.SetReferencePoint( getViewControls()->GetCursorPosition( true ) );
874
876 commit.Push( _( "Paste" ) );
877 else
878 commit.Revert();
879 }
880
881 return 0;
882}
883
884
886{
887 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
889 SCH_COMMIT commit( m_toolMgr );
890
891 if( selection.GetSize() == 0 )
892 return 0;
893
894 commit.Modify( symbol, m_frame->GetScreen() );
895
896 EDA_ITEMS newItems;
897
898 for( unsigned ii = 0; ii < selection.GetSize(); ++ii )
899 {
900 SCH_ITEM* oldItem = static_cast<SCH_ITEM*>( selection.GetItem( ii ) );
901 SCH_ITEM* newItem = oldItem->Duplicate();
902
903 if( newItem->Type() == SCH_PIN_T )
904 {
905 SCH_PIN* newPin = static_cast<SCH_PIN*>( newItem );
906
907 if( !newPin->GetNumber().IsEmpty() )
908 newPin->SetNumber( wxString::Format( wxT( "%i" ), symbol->GetMaxPinNumber() + 1 ) );
909 }
910
911 oldItem->ClearFlags( IS_NEW | IS_PASTED | SELECTED );
912 newItem->SetFlags( IS_NEW | IS_PASTED | SELECTED );
913 newItem->SetParent( symbol );
914 newItems.push_back( newItem );
915
916 symbol->AddDrawItem( newItem );
917 getView()->Add( newItem );
918 }
919
922
923 selection.SetReferencePoint( mapCoords( getViewControls()->GetCursorPosition( true ), true ) );
924
926 commit.Push( _( "Duplicate" ) );
927 else
928 commit.Revert();
929
930 return 0;
931}
932
933
935{
942
949
955}
VECTOR2D mapCoords(const VECTOR2D &aSource)
Definition: PS_plotter.cpp:531
static TOOL_ACTION paste
Definition: actions.h:70
static TOOL_ACTION cancelInteractive
Definition: actions.h:63
static TOOL_ACTION unselectAll
Definition: actions.h:73
static TOOL_ACTION copy
Definition: actions.h:69
static TOOL_ACTION pickerTool
Definition: actions.h:189
static TOOL_ACTION undo
Definition: actions.h:66
static TOOL_ACTION duplicate
Definition: actions.h:74
static TOOL_ACTION doDelete
Definition: actions.h:75
static TOOL_ACTION redo
Definition: actions.h:67
static TOOL_ACTION deleteTool
Definition: actions.h:76
static TOOL_ACTION cut
Definition: actions.h:68
static TOOL_ACTION refreshPreview
Definition: actions.h:137
static TOOL_ACTION selectAll
Definition: actions.h:72
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
bool Empty() const
Returns status of an item.
Definition: commit.h:144
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.
This class is setup in expectation of its children possibly using Kiway player so DIALOG_SHIM::ShowQu...
void UpdateField(SCH_FIELD *aField)
const wxString & GetText() const
int ShowQuasiModal()
Dialog to update or change schematic library symbols.
void ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false, WX_INFOBAR::MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an error icon on the left o...
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
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:88
virtual VECTOR2I GetPosition() const
Definition: eda_item.h:242
EDA_ITEM_FLAGS GetEditFlags() const
Definition: eda_item.h:132
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:126
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:100
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:128
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:103
EDA_ITEM * GetParent() const
Definition: eda_item.h:102
bool IsMoving() const
Definition: eda_item.h:107
virtual bool IsVisible() const
Definition: eda_text.h:151
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition: eda_text.cpp:276
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition: eda_text.h:164
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:245
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition: eda_text.h:167
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition: eda_text.cpp:268
static TOOL_ACTION mirrorV
Definition: ee_actions.h:126
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 addItemsToSel
Selects a list of items (specified as the event parameter)
Definition: ee_actions.h:63
static TOOL_ACTION move
Definition: ee_actions.h:121
static TOOL_ACTION pinTable
Definition: ee_actions.h:156
static TOOL_ACTION clearSelection
Clears the current selection.
Definition: ee_actions.h:56
static TOOL_ACTION rotateCCW
Definition: ee_actions.h:125
static TOOL_ACTION mirrorH
Definition: ee_actions.h:127
static TOOL_ACTION rotateCW
Definition: ee_actions.h:124
static TOOL_ACTION symbolProperties
Definition: ee_actions.h:155
static TOOL_ACTION setUnitDisplayName
Definition: ee_actions.h:214
static TOOL_ACTION updateSymbolFields
Definition: ee_actions.h:213
bool Selectable(const EDA_ITEM *aItem, const VECTOR2I *aPos=nullptr, bool checkVisibilityOnly=false) const
Check conditions for an item to be selected.
void GuessSelectionCandidates(EE_COLLECTOR &collector, const VECTOR2I &aPos)
Apply heuristics to try and determine a single object when multiple are found under the cursor.
bool CollectHits(EE_COLLECTOR &aCollector, const VECTOR2I &aWhere, const std::vector< KICAD_T > &aScanTypes={ SCH_LOCATE_ANY_T })
Collect one or more items at a given point.
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.
void RebuildSelection()
Rebuild the selection from the EDA_ITEMs' selection flags.
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
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:315
Define a library symbol object.
Definition: lib_symbol.h:77
bool UnitsLocked() const
Check whether symbol units are interchangeable.
Definition: lib_symbol.h:263
wxString GetUnitDisplayName(int aUnit) override
Return the user-defined display name for aUnit for symbols with units.
Definition: lib_symbol.cpp:535
bool IsAlias() const
Definition: lib_symbol.h:194
int GetMaxPinNumber() const
std::vector< SCH_PIN * > GetAllLibPins() const
Return a list of pin pointers for all units / converts.
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:486
void RemoveDrawItem(SCH_ITEM *aItem)
Remove draw aItem from list.
Definition: lib_symbol.cpp:944
bool HasUnitDisplayName(int aUnit) override
Return true if the given unit aUnit has a display name defined.
Definition: lib_symbol.cpp:529
wxString GetUnitReference(int aUnit) override
Return an identifier for aUnit for symbols with units.
Definition: lib_symbol.cpp:523
int GetUnitCount() const override
void SetUnitDisplayName(int aUnit, const wxString &aName)
Set the user-defined display name for aUnit to aName for symbols with units.
Definition: lib_symbol.cpp:551
void AddDrawItem(SCH_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
Definition: lib_symbol.cpp:969
void SetMotionHandler(MOTION_HANDLER aHandler)
Set a handler for mouse motion.
Definition: picker_tool.h:83
void SetClickHandler(CLICK_HANDLER aHandler)
Set a handler for mouse click event.
Definition: picker_tool.h:72
void SetCursor(KICURSOR aCursor)
Definition: picker_tool.h:63
void SetFinalizeHandler(FINALIZE_HANDLER aHandler)
Set a handler for the finalize event.
Definition: picker_tool.h:103
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
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:405
virtual void Revert() override
Definition: sch_commit.cpp:483
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:1429
wxString GetFullText(int unit=1) const
Return the text of a field.
Definition: sch_field.cpp:305
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: sch_field.cpp:1149
static void FormatLibSymbol(LIB_SYMBOL *aPart, OUTPUTFORMATTER &aFormatter)
static std::vector< LIB_SYMBOL * > ParseLibSymbols(std::string &aSymbolText, std::string aSource, int aFileVersion=SEXPR_SCHEMATIC_FILE_VERSION)
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:174
virtual void SetBodyStyle(int aBodyStyle)
Definition: sch_item.h:239
int GetBodyStyle() const
Definition: sch_item.h:240
virtual void MirrorHorizontally(int aCenter)
Mirror item horizontally about aCenter.
Definition: sch_item.h:351
int GetUnit() const
Definition: sch_item.h:237
virtual void Rotate(const VECTOR2I &aCenter, bool aRotateCCW)
Rotate the item around aCenter 90 degrees in the clockwise direction.
Definition: sch_item.h:367
virtual void SetUnit(int aUnit)
Definition: sch_item.h:236
wxString GetClass() const override
Return the class name.
Definition: sch_item.h:184
SCH_ITEM * Duplicate(bool doClone=false) const
Routine to create a new copy of given item.
Definition: sch_item.cpp:120
virtual void MirrorVertically(int aCenter)
Mirror item vertically about aCenter.
Definition: sch_item.h:359
void SetNumber(const wxString &aNumber)
Definition: sch_pin.cpp:465
const wxString & GetName() const
Definition: sch_pin.cpp:351
VECTOR2I GetPosition() const override
Definition: sch_pin.cpp:235
const wxString & GetNumber() const
Definition: sch_pin.h:111
ELECTRICAL_PINTYPE GetType() const
Definition: sch_pin.cpp:289
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
Definition: sch_shape.cpp:565
static bool NotEmpty(const SELECTION &aSelection)
Test if there are any items selected.
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.
void BrightenItem(EDA_ITEM *aItem)
int AddItemToSel(const TOOL_EVENT &aEvent)
void UnbrightenItem(EDA_ITEM *aItem)
virtual KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
Definition: selection.cpp:75
const std::deque< EDA_ITEM * > GetItems() const
Definition: selection.h:120
virtual VECTOR2I GetCenter() const
Returns the center point of the selection area bounding box.
Definition: selection.cpp:93
bool IsHover() const
Definition: selection.h:83
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition: selection.h:99
EDA_ITEM * Front() const
Definition: selection.h:208
virtual void Clear() override
Remove all the stored items from the group.
Definition: selection.h:92
int Size() const
Returns the number of selected parts.
Definition: selection.h:115
void SetReferencePoint(const VECTOR2I &aP)
Definition: selection.cpp:179
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:109
Implement an OUTPUTFORMATTER to a memory buffer.
Definition: richio.h:433
const std::string & GetString()
Definition: richio.h:456
SYMBOL_EDITOR_DRAWING_TOOLS.
void SetDrawSpecificBodyStyle(bool aSpecific)
int Undo(const TOOL_EVENT &aEvent)
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
void editTextBoxProperties(SCH_ITEM *aItem)
int PinTable(const TOOL_EVENT &aEvent)
int Copy(const TOOL_EVENT &aEvent)
int Paste(const TOOL_EVENT &aEvent)
int Cut(const TOOL_EVENT &aEvent)
bool Init() override
Init() is called once upon a registration of the tool.
int Redo(const TOOL_EVENT &aEvent)
void editTextProperties(SCH_ITEM *aItem)
void editFieldProperties(SCH_FIELD *aField)
void handlePinDuplication(SCH_PIN *aOldPin, SCH_PIN *aNewPin, int &aSymbolLastPinNumber)
Set up handlers for various events.
void editShapeProperties(SCH_SHAPE *aShape)
int Duplicate(const TOOL_EVENT &aEvent)
int Mirror(const TOOL_EVENT &aEvent)
int InteractiveDelete(const TOOL_EVENT &aEvent)
int Rotate(const TOOL_EVENT &aEvent)
int Properties(const TOOL_EVENT &aEvent)
int SetUnitDisplayName(const TOOL_EVENT &aEvent)
int UpdateSymbolFields(const TOOL_EVENT &aEvent)
int DoDelete(const TOOL_EVENT &aEvent)
Delete the selected items, or the item under the cursor.
void UpdateItem(EDA_ITEM *aItem, bool isAddOrDelete=false, bool aUpdateRtree=false) override
Mark an item for refresh.
bool IsSymbolAlias() const
Return true if aLibId is an alias for the editor screen symbol.
int GetBodyStyle() const
bool m_SyncPinEdit
Set to true to synchronize pins at the same position when editing symbols with multiple units or mult...
bool IsSymbolEditable() const
Test if a symbol is loaded and can be edited.
LIB_SYMBOL * GetCurSymbol() const
Return the current symbol being edited or NULL if none selected.
void UpdateSymbolMsgPanelInfo()
Display the documentation of the selected symbol.
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current symbol.
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:216
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 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
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:145
std::string GetClipboardUTF8() const
Return the information currently stored in the system clipboard.
bool PostAction(const std::string &aActionName, T aParam)
Run the specified action after the current action (coroutine) ends.
Definition: tool_manager.h:230
bool SaveClipboard(const std::string &aTextUTF8)
Store information to the system clipboard.
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:192
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:44
#define _(s)
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
Definition: eda_item.h:532
#define IS_PASTED
Modifier on IS_NEW which indicates it came from clipboard.
#define IS_NEW
New item, just created.
#define SELECTED
Item was manually selected by the user.
#define STRUCT_DELETED
flag indication structures to be erased
@ LAYER_DEVICE
Definition: layer_ids.h:370
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_LIBID
Definition: string_utils.h:54
static std::vector< KICAD_T > nonFields
#define TO_VJUSTIFY(x)
#define TO_HJUSTIFY(x)
@ LIB_SYMBOL_T
Definition: typeinfo.h:148
@ SCH_FIELD_T
Definition: typeinfo.h:150
@ SCH_SHAPE_T
Definition: typeinfo.h:149
@ SCH_TEXT_T
Definition: typeinfo.h:151
@ SCH_TEXTBOX_T
Definition: typeinfo.h:152
@ SCH_PIN_T
Definition: typeinfo.h:153