KiCad PCB EDA Suite
Loading...
Searching...
No Matches
symbol_editor_drawing_tools.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2019 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <sch_actions.h>
26#include <optional>
27#include <symbol_edit_frame.h>
28#include <sch_commit.h>
33#include <dialogs/dialog_text_properties.h>
34#include <sch_shape.h>
35#include <sch_textbox.h>
36#include <pgm_base.h>
37#include <view/view_controls.h>
40#include <string_utils.h>
41#include <wx/msgdlg.h>
43
44
46
47
64
65
67{
69
70 auto isDrawingCondition =
71 [] ( const SELECTION& aSel )
72 {
73 SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aSel.Front() );
74 return item && item->IsNew();
75 };
76
77 m_menu->GetMenu().AddItem( ACTIONS::finishInteractive, isDrawingCondition, 2 );
78
79 return true;
80}
81
82
84{
85 KICAD_T type = aEvent.Parameter<KICAD_T>();
88 : nullptr;
89
91 return 0;
92
94
97 VECTOR2I cursorPos;
98 bool ignorePrimePosition = false;
99 SCH_ITEM* item = nullptr;
100 bool isText = aEvent.IsAction( &SCH_ACTIONS::placeSymbolText );
101 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
102
104
105 m_frame->PushTool( aEvent );
106
107 auto setCursor =
108 [&]()
109 {
110 if( item )
111 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PLACE );
112 else if( isText )
113 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::TEXT );
114 else
115 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
116 };
117
118 auto cleanup =
119 [&] ()
120 {
122 m_view->ClearPreview();
123 delete item;
124 item = nullptr;
125 };
126
127 Activate();
128 // Must be done after Activate() so that it gets set into the correct context
129 controls->ShowCursor( true );
130 // Set initial cursor
131 setCursor();
132
133 if( aEvent.HasPosition() )
134 {
135 m_toolMgr->PrimeTool( aEvent.Position() );
136 }
137 else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() )
138 {
139 m_toolMgr->PrimeTool( { 0, 0 } );
140 ignorePrimePosition = true;
141 }
142
143 SCH_COMMIT commit( m_toolMgr );
144
145 // Main loop: keep receiving events
146 while( TOOL_EVENT* evt = Wait() )
147 {
148 setCursor();
149 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
150 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
151
152 cursorPos = grid.Align( controls->GetMousePosition(), grid.GetItemGrid( item ) );
153 controls->ForceCursorPosition( true, cursorPos );
154
155 // The tool hotkey is interpreted as a click when drawing
156 bool isSyntheticClick = item && evt->IsActivate() && evt->HasPosition()
157 && evt->Matches( aEvent );
158
159 if( evt->IsCancelInteractive() )
160 {
161 m_frame->GetInfoBar()->Dismiss();
162
163 if( item )
164 {
165 cleanup();
166 }
167 else
168 {
169 m_frame->PopTool( aEvent );
170 break;
171 }
172 }
173 else if( evt->IsActivate() && !isSyntheticClick )
174 {
175 if( item && evt->IsMoveTool() )
176 {
177 // we're already moving our own item; ignore the move tool
178 evt->SetPassEvent( false );
179 continue;
180 }
181
182 if( item )
183 {
184 m_frame->ShowInfoBarMsg( _( "Press <ESC> to cancel item creation." ) );
185 evt->SetPassEvent( false );
186 continue;
187 }
188
189 if( evt->IsPointEditor() )
190 {
191 // don't exit (the point editor runs in the background)
192 }
193 else if( evt->IsMoveTool() )
194 {
195 break;
196 }
197 else
198 {
199 m_frame->PopTool( aEvent );
200 break;
201 }
202 }
203 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) || isSyntheticClick )
204 {
205 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
206
207 if( !symbol )
208 continue;
209
210 // First click creates...
211 if( !item )
212 {
214
215 switch( type )
216 {
217 case SCH_PIN_T:
218 {
219 item = pinTool->CreatePin( cursorPos, symbol );
220
221 if( item )
222 g_lastPin = item->m_Uuid;
223
224 break;
225 }
226 case SCH_TEXT_T:
227 {
228 SCH_TEXT* text = new SCH_TEXT( cursorPos, wxEmptyString, LAYER_DEVICE );
229
230 text->SetParent( symbol );
231
233 text->SetUnit( m_frame->GetUnit() );
234
236 text->SetBodyStyle( m_frame->GetBodyStyle() );
237
238 if( cfg )
239 {
240 text->SetTextSize( VECTOR2I( schIUScale.MilsToIU( cfg->m_Defaults.text_size ),
241 schIUScale.MilsToIU( cfg->m_Defaults.text_size ) ) );
242 }
243
244 text->SetTextAngle( m_lastTextAngle );
245
247
248 if( dlg.ShowModal() != wxID_OK || NoPrintableChars( text->GetText() ) )
249 delete text;
250 else
251 item = text;
252
253 break;
254 }
255 default:
256 wxFAIL_MSG( "TwoClickPlace(): unknown type" );
257 }
258
259 // If we started with a hotkey which has a position then warp back to that.
260 // Otherwise update to the current mouse position pinned inside the autoscroll
261 // boundaries.
262 if( evt->IsPrime() && !ignorePrimePosition )
263 {
264 cursorPos = grid.Align( evt->Position(), grid.GetItemGrid( item ) );
265 getViewControls()->WarpMouseCursor( cursorPos, true );
266 }
267 else
268 {
270 cursorPos = grid.Align( getViewControls()->GetMousePosition(), grid.GetItemGrid( item ) );
271 }
272
273 if( item )
274 {
275 item->SetPosition( VECTOR2I( cursorPos.x, -cursorPos.y ) );
276
277 item->SetFlags( IS_NEW | IS_MOVING );
278 m_view->ClearPreview();
279 m_view->AddToPreview( item, false );
280 m_selectionTool->AddItemToSel( item );
281
282 // update the cursor so it looks correct before another event
283 setCursor();
284 }
285
286 if( m_frame->GetMoveWarpsCursor() )
287 controls->SetCursorPosition( cursorPos, false );
288
289 m_toolMgr->PostAction( ACTIONS::refreshPreview );
290 }
291 // ... and second click places:
292 else
293 {
294 commit.Modify( symbol, m_frame->GetScreen() );
295
296 switch( item->Type() )
297 {
298 case SCH_PIN_T:
299 pinTool->PlacePin( &commit, static_cast<SCH_PIN*>( item ) );
300 item->ClearEditFlags();
301 commit.Push( _( "Place Pin" ) );
302 break;
303
304 case SCH_TEXT_T:
305 symbol->AddDrawItem( static_cast<SCH_TEXT*>( item ) );
306 item->ClearEditFlags();
307 commit.Push( _( "Draw Text" ) );
308 break;
309
310 default:
311 wxFAIL_MSG( "TwoClickPlace(): unknown type" );
312 }
313
314 item = nullptr;
315 m_view->ClearPreview();
316 m_frame->RebuildView();
317 }
318 }
319 else if( evt->IsClick( BUT_RIGHT ) )
320 {
321 // Warp after context menu only if dragging...
322 if( !item )
323 m_toolMgr->VetoContextMenuMouseWarp();
324
325 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
326 }
327 else if( evt->IsAction( &ACTIONS::increment ) )
328 {
329 if( evt->HasParameter() )
330 m_toolMgr->RunSynchronousAction( ACTIONS::increment, &commit, evt->Parameter<ACTIONS::INCREMENT>() );
331 else
332 m_toolMgr->RunSynchronousAction( ACTIONS::increment, &commit, ACTIONS::INCREMENT { 1, 0 } );
333 }
334 else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
335 {
336 item->SetPosition( VECTOR2I( cursorPos.x, cursorPos.y ) );
337 m_view->ClearPreview();
338 m_view->AddToPreview( item, false );
339 }
340 else
341 {
342 evt->SetPassEvent();
343 }
344
345 // Enable autopanning and cursor capture only when there is an item to be placed
346 controls->SetAutoPan( item != nullptr );
347 controls->CaptureCursor( item != nullptr );
348 }
349
350 controls->SetAutoPan( false );
351 controls->CaptureCursor( false );
352 controls->ForceCursorPosition( false );
353 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
354 return 0;
355}
356
357
359{
360 SHAPE_T requestedShape = aEvent.Parameter<SHAPE_T>();
361
362 return doDrawShape( aEvent, requestedShape );
363}
364
365
367{
368 return doDrawShape( aEvent, std::nullopt /* Draw text box */ );
369}
370
371
372int SYMBOL_EDITOR_DRAWING_TOOLS::doDrawShape( const TOOL_EVENT& aEvent, std::optional<SHAPE_T> aDrawingShape )
373{
374 bool isTextBox = !aDrawingShape.has_value();
375 SHAPE_T toolType = aDrawingShape.value_or( SHAPE_T::SEGMENT );
376
380 VECTOR2I cursorPos;
381 SHAPE_T shapeType = toolType == SHAPE_T::SEGMENT ? SHAPE_T::POLY : toolType;
382 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
383 SCH_SHAPE* item = nullptr;
384 wxString description;
385
386 if( m_inDrawShape )
387 return 0;
388
390
391 // We might be running as the same shape in another co-routine. Make sure that one
392 // gets whacked.
393 m_toolMgr->DeactivateTool();
394
396
397 m_frame->PushTool( aEvent );
398
399 auto setCursor =
400 [&]()
401 {
402 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
403 };
404
405 auto cleanup =
406 [&] ()
407 {
409 m_view->ClearPreview();
410 delete item;
411 item = nullptr;
412 };
413
414 Activate();
415 // Must be done after Activate() so that it gets set into the correct context
416 controls->ShowCursor( true );
417 // Set initial cursor
418 setCursor();
419
420 if( aEvent.HasPosition() )
421 m_toolMgr->PrimeTool( aEvent.Position() );
422
423 // Main loop: keep receiving events
424 while( TOOL_EVENT* evt = Wait() )
425 {
426 setCursor();
427 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
428 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
429
430 cursorPos = grid.Align( controls->GetMousePosition(), grid.GetItemGrid( item ) );
431 controls->ForceCursorPosition( true, cursorPos );
432
433 // The tool hotkey is interpreted as a click when drawing
434 bool isSyntheticClick = item && evt->IsActivate() && evt->HasPosition()
435 && evt->Matches( aEvent );
436
437 if( evt->IsCancelInteractive() )
438 {
439 if( item )
440 {
441 cleanup();
442 }
443 else
444 {
445 m_frame->PopTool( aEvent );
446 break;
447 }
448 }
449 else if( evt->IsActivate() && !isSyntheticClick )
450 {
451 if( item )
452 cleanup();
453
454 if( evt->IsPointEditor() )
455 {
456 // don't exit (the point editor runs in the background)
457 }
458 else if( evt->IsMoveTool() )
459 {
460 // leave ourselves on the stack so we come back after the move
461 break;
462 }
463 else
464 {
465 m_frame->PopTool( aEvent );
466 break;
467 }
468 }
469 else if( evt->IsClick( BUT_LEFT ) && !item )
470 {
471 // Update in case the symbol was changed while the tool was running
472 symbol = m_frame->GetCurSymbol();
473
474 if( !symbol )
475 continue;
476
478
479 int lineWidth = schIUScale.MilsToIU( cfg ? cfg->m_Defaults.line_width : DEFAULT_LINE_WIDTH_MILS );
480
481 if( isTextBox )
482 {
483 SCH_TEXTBOX* textbox = new SCH_TEXTBOX( LAYER_DEVICE, lineWidth, m_lastFillStyle );
484
485 textbox->SetParent( symbol );
486
487 if( cfg )
488 {
489 textbox->SetTextSize( VECTOR2I( schIUScale.MilsToIU( cfg->m_Defaults.text_size ),
490 schIUScale.MilsToIU( cfg->m_Defaults.text_size ) ) );
491 }
492
493 // Must be after SetTextSize()
494 textbox->SetBold( m_lastTextBold );
495 textbox->SetItalic( m_lastTextItalic );
496
497 textbox->SetTextAngle( m_lastTextAngle );
499
500 item = textbox;
501 description = _( "Add Text Box" );
502 }
503 else
504 {
505 item = new SCH_SHAPE( shapeType, LAYER_DEVICE, lineWidth, m_lastFillStyle );
506 item->SetParent( symbol );
507 description = wxString::Format( _( "Add %s" ), item->GetFriendlyName() );
508 }
509
510 item->SetStroke( m_lastStroke );
512
513 item->SetFlags( IS_NEW );
514 item->BeginEdit( cursorPos );
515
517 item->SetUnit( m_frame->GetUnit() );
518
520 item->SetBodyStyle( m_frame->GetBodyStyle() );
521
522 m_selectionTool->AddItemToSel( item );
523 }
524 else if( item && ( evt->IsClick( BUT_LEFT )
525 || evt->IsDblClick( BUT_LEFT )
526 || isSyntheticClick
527 || evt->IsAction( &ACTIONS::finishInteractive ) ) )
528 {
529 if( symbol != m_frame->GetCurSymbol() )
530 {
531 symbol = m_frame->GetCurSymbol();
532 item->SetParent( symbol );
533 }
534
535 if( evt->IsDblClick( BUT_LEFT ) || evt->IsAction( &ACTIONS::finishInteractive )
536 || !item->ContinueEdit( VECTOR2I( cursorPos.x, cursorPos.y ) ) )
537 {
538 if( toolType == SHAPE_T::POLY )
539 {
540 item->CalcEdit( item->GetPosition() ); // Close shape
541 item->EndEdit( true );
542 }
543 else
544 {
545 item->EndEdit();
546 }
547
548 item->ClearEditFlags();
549
550 if( isTextBox )
551 {
552 SCH_TEXTBOX* textbox = static_cast<SCH_TEXTBOX*>( item );
553 DIALOG_TEXT_PROPERTIES dlg( m_frame, static_cast<SCH_TEXTBOX*>( item ) );
554
555 // QuasiModal required for syntax help and Scintilla auto-complete
556 if( dlg.ShowQuasiModal() != wxID_OK )
557 {
558 cleanup();
559 continue;
560 }
561
562 m_lastTextBold = textbox->IsBold();
563 m_lastTextItalic = textbox->IsItalic();
564 m_lastTextAngle = textbox->GetTextAngle();
565 m_lastTextJust = textbox->GetHorizJustify();
566 }
567
568 m_lastStroke = item->GetStroke();
571
572 m_view->ClearPreview();
573
574 SCH_COMMIT commit( m_toolMgr );
575 commit.Modify( symbol, m_frame->GetScreen() );
576
577 symbol->AddDrawItem( item );
578 item = nullptr;
579
580 commit.Push( description );
581 m_frame->RebuildView();
583 }
584 }
585 else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
586 {
587 item->CalcEdit( cursorPos );
588 m_view->ClearPreview();
589 m_view->AddToPreview( item->Clone() );
590 }
591 else if( evt->IsDblClick( BUT_LEFT ) && !item )
592 {
594 }
595 else if( evt->IsClick( BUT_RIGHT ) )
596 {
597 // Warp after context menu only if dragging...
598 if( !item )
599 m_toolMgr->VetoContextMenuMouseWarp();
600
601 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
602 }
603 else
604 {
605 evt->SetPassEvent();
606 }
607
608 // Enable autopanning and cursor capture only when there is a shape being drawn
609 controls->SetAutoPan( item != nullptr );
610 controls->CaptureCursor( item != nullptr );
611 }
612
613 controls->SetAutoPan( false );
614 controls->CaptureCursor( false );
615 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
616 return 0;
617}
618
619
621{
622 if( m_inPlaceAnchor )
623 return 0;
624
626
627 m_frame->PushTool( aEvent );
628
629 auto setCursor =
630 [&]()
631 {
632 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::BULLSEYE );
633 };
634
635 Activate();
636 // Must be done after Activate() so that it gets set into the correct context
637 getViewControls()->ShowCursor( true );
638 // Set initial cursor
639 setCursor();
640
641 // Main loop: keep receiving events
642 while( TOOL_EVENT* evt = Wait() )
643 {
644 setCursor();
645
646 if( evt->IsCancelInteractive() )
647 {
648 m_frame->PopTool( aEvent );
649 break;
650 }
651 else if( evt->IsActivate() )
652 {
653 m_frame->PopTool( aEvent );
654 break;
655 }
656 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
657 {
658 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
659
660 if( !symbol )
661 continue;
662
663 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
664
665 symbol->Move( -cursorPos );
666
667 // Refresh the view without changing the viewport
668 m_view->SetCenter( m_view->GetCenter() + cursorPos );
669 m_view->RecacheAllItems();
670 m_frame->OnModify();
671 }
672 else if( evt->IsClick( BUT_RIGHT ) )
673 {
674 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
675 }
676 else
677 {
678 evt->SetPassEvent();
679 }
680 }
681
682 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
683 return 0;
684}
685
686
688{
689 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
690
691 if( !symbol )
692 return 0;
693
694 // Note: PlaceImportedGraphics() will convert PCB_SHAPE_T and PCB_TEXT_T to footprint
695 // items if needed
697 int dlgResult = dlg.ShowModal();
698
699 std::list<std::unique_ptr<EDA_ITEM>>& list = dlg.GetImportedItems();
700
701 if( dlgResult != wxID_OK )
702 return 0;
703
704 // Ensure the list is not empty:
705 if( list.empty() )
706 {
707 wxMessageBox( _( "No graphic items found in file." ) );
708 return 0;
709 }
710
712
714 std::vector<SCH_ITEM*> newItems; // all new items, including group
715 std::vector<SCH_ITEM*> selectedItems; // the group, or newItems if no group
716 SCH_SELECTION preview;
717 SCH_COMMIT commit( m_toolMgr );
718
719 for( std::unique_ptr<EDA_ITEM>& ptr : list )
720 {
721 SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( ptr.get() );
722 wxCHECK2( item, continue );
723
724 newItems.push_back( item );
725 selectedItems.push_back( item );
726 preview.Add( item );
727
728 ptr.release();
729 }
730
731 if( !dlg.IsPlacementInteractive() )
732 {
733 commit.Modify( symbol, m_frame->GetScreen() );
734
735 // Place the imported drawings
736 for( SCH_ITEM* item : newItems )
737 {
738 symbol->AddDrawItem( item );
739 item->ClearEditFlags();
740 }
741
742 commit.Push( _( "Import Graphic" ) );
743 m_frame->RebuildView();
744
745 return 0;
746 }
747
748 m_view->Add( &preview );
749
750 // Clear the current selection then select the drawings so that edit tools work on them
752
753 EDA_ITEMS selItems( selectedItems.begin(), selectedItems.end() );
754 m_toolMgr->RunAction<EDA_ITEMS*>( ACTIONS::selectItems, &selItems );
755
756 m_frame->PushTool( aEvent );
757
758 auto setCursor = [&]()
759 {
760 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::MOVING );
761 };
762
763 Activate();
764 // Must be done after Activate() so that it gets set into the correct context
765 controls->ShowCursor( true );
766 controls->ForceCursorPosition( false );
767 // Set initial cursor
768 setCursor();
769
770 //SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::DXF );
772
773 // Now move the new items to the current cursor position:
774 VECTOR2I cursorPos = controls->GetCursorPosition( !aEvent.DisableGridSnapping() );
775 VECTOR2I delta = cursorPos;
776 VECTOR2I currentOffset;
777
778 for( SCH_ITEM* item : selectedItems )
779 item->Move( delta );
780
781 currentOffset += delta;
782
783 m_view->Update( &preview );
784
785 // Main loop: keep receiving events
786 while( TOOL_EVENT* evt = Wait() )
787 {
788 setCursor();
789
790 grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
791 grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
792
793 cursorPos = grid.Align( controls->GetMousePosition(), GRID_GRAPHICS );
794 controls->ForceCursorPosition( true, cursorPos );
795
796 if( evt->IsCancelInteractive() || evt->IsActivate() )
797 {
799
800 for( SCH_ITEM* item : newItems )
801 delete item;
802
803 break;
804 }
805 else if( evt->IsMotion() )
806 {
807 delta = cursorPos - currentOffset;
808
809 for( SCH_ITEM* item : selectedItems )
810 item->Move( delta );
811
812 currentOffset += delta;
813
814 m_view->Update( &preview );
815 }
816 else if( evt->IsClick( BUT_RIGHT ) )
817 {
818 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
819 }
820 else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
821 {
822 commit.Modify( symbol, m_frame->GetScreen() );
823
824 // Place the imported drawings
825 for( SCH_ITEM* item : newItems )
826 {
827 symbol->AddDrawItem( item );
828 item->ClearEditFlags();
829 }
830
831 commit.Push( _( "Import Graphic" ) );
832 break; // This is a one-shot command, not a tool
833 }
834 else
835 {
836 evt->SetPassEvent();
837 }
838 }
839
840 preview.Clear();
841 m_view->Remove( &preview );
842
843 m_frame->RebuildView();
844
845 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
846 controls->ForceCursorPosition( false );
847
848 m_frame->PopTool( aEvent );
849
850 return 0;
851}
852
853
855{
857 LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
858 SCH_PIN* sourcePin = nullptr;
859
860 if( !symbol )
861 return 0;
862
863 for( SCH_PIN* test : symbol->GetPins() )
864 {
865 if( test->m_Uuid == g_lastPin )
866 {
867 sourcePin = test;
868 break;
869 }
870 }
871
872 if( sourcePin )
873 {
874 SCH_PIN* pin = pinTool->RepeatPin( sourcePin );
875
876 if( pin )
877 g_lastPin = pin->m_Uuid;
878
880
881 if( pin )
882 m_toolMgr->RunAction<EDA_ITEM*>( ACTIONS::selectItem, pin );
883 }
884
885 return 0;
886}
887
888
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:114
static TOOL_ACTION cancelInteractive
Definition actions.h:72
static TOOL_ACTION selectItem
Select an item (specified as the event parameter).
Definition actions.h:226
static TOOL_ACTION activatePointEditor
Definition actions.h:272
static TOOL_ACTION increment
Definition actions.h:94
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:223
static TOOL_ACTION refreshPreview
Definition actions.h:158
static TOOL_ACTION finishInteractive
Definition actions.h:73
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Definition actions.h:231
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:106
std::list< std::unique_ptr< EDA_ITEM > > & GetImportedItems()
int ShowModal() override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
virtual void ClearEditFlags()
Definition eda_item.h:156
virtual void SetPosition(const VECTOR2I &aPos)
Definition eda_item.h:273
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:142
const KIID m_Uuid
Definition eda_item.h:516
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
virtual bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const
Compare the item against the search criteria in aSearchData.
Definition eda_item.h:401
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.h:113
virtual wxString GetFriendlyName() const
Definition eda_item.cpp:401
bool IsNew() const
Definition eda_item.h:124
FILL_T GetFillMode() const
Definition eda_shape.h:142
void SetFillColor(const COLOR4D &aColor)
Definition eda_shape.h:153
COLOR4D GetFillColor() const
Definition eda_shape.h:152
bool IsItalic() const
Definition eda_text.h:168
const EDA_ANGLE & GetTextAngle() const
Definition eda_text.h:146
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition eda_text.cpp:534
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition eda_text.h:199
void SetBold(bool aBold)
Set the text to be bold - this will also update the font if needed.
Definition eda_text.cpp:336
bool IsBold() const
Definition eda_text.h:183
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition eda_text.cpp:300
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
Definition eda_text.cpp:308
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition eda_text.cpp:410
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:104
An interface for classes handling user events controlling the view behavior such as zooming,...
virtual void CaptureCursor(bool aEnabled)
Force the cursor to stay within the drawing panel area.
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Place the cursor immediately at a given point.
virtual void ShowCursor(bool aEnabled)
Enable or disables display of cursor.
virtual void WarpMouseCursor(const VECTOR2D &aPosition, bool aWorldCoordinates=false, bool aWarpView=false)=0
If enabled (.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Return the current mouse pointer position.
virtual void SetCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true, bool aTriggeredByArrows=false, long aArrowCommand=0)=0
Move cursor to the requested position expressed in world coordinates.
virtual void SetAutoPan(bool aEnabled)
Turn on/off auto panning (this feature is used when there is a tool active (eg.
virtual void PinCursorInsideNonAutoscrollArea(bool aWarpMouseCursor)=0
Definition kiid.h:49
Define a library symbol object.
Definition lib_symbol.h:85
void Move(const VECTOR2I &aOffset) override
Move the symbol aOffset.
void AddDrawItem(SCH_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition pgm_base.cpp:576
static TOOL_ACTION drawArc
Definition sch_actions.h:97
static TOOL_ACTION drawSymbolLines
static TOOL_ACTION placeSymbolPin
static TOOL_ACTION drawSymbolTextBox
static TOOL_ACTION properties
static TOOL_ACTION drawRectangle
Definition sch_actions.h:95
static TOOL_ACTION drawCircle
Definition sch_actions.h:96
static TOOL_ACTION importGraphics
static TOOL_ACTION drawBezier
Definition sch_actions.h:98
static TOOL_ACTION drawSymbolPolygon
static TOOL_ACTION placeSymbolAnchor
static TOOL_ACTION placeSymbolText
static TOOL_ACTION repeatDrawItem
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:167
virtual void SetBodyStyle(int aBodyStyle)
Definition sch_item.h:243
virtual void SetUnit(int aUnit)
Definition sch_item.h:237
void BeginEdit(const VECTOR2I &aStartPoint) override
Begin drawing a symbol library draw item at aPosition.
Definition sch_shape.h:90
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition sch_shape.cpp:47
void EndEdit(bool aClosed=false) override
End an object editing action.
Definition sch_shape.h:93
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition sch_shape.cpp:61
bool ContinueEdit(const VECTOR2I &aPosition) override
Continue an edit in progress at aPosition.
Definition sch_shape.h:91
void CalcEdit(const VECTOR2I &aPosition) override
Calculate the attributes of an item at aPosition when it is being edited.
Definition sch_shape.h:92
STROKE_PARAMS GetStroke() const override
Definition sch_shape.h:58
VECTOR2I GetPosition() const override
Definition sch_shape.h:85
bool Init() override
Init() is called once upon a registration of the tool.
SCH_TOOL_BASE(const std::string &aName)
SCH_SELECTION_TOOL * m_selectionTool
virtual void Add(EDA_ITEM *aItem)
Definition selection.cpp:42
virtual void Clear() override
Remove all the stored items from the group.
Definition selection.h:98
int PlaceAnchor(const TOOL_EVENT &aEvent)
bool Init() override
Init() is called once upon a registration of the tool.
bool m_drawSpecificUnit
Re-entrancy guards.
int RepeatDrawItem(const TOOL_EVENT &aEvent)
int doDrawShape(const TOOL_EVENT &aEvent, std::optional< SHAPE_T > aDrawingShape)
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
int ImportGraphics(const TOOL_EVENT &aEvent)
int DrawShape(const TOOL_EVENT &aEvent)
int DrawSymbolTextBox(const TOOL_EVENT &aEvent)
int TwoClickPlace(const TOOL_EVENT &aEvent)
SCH_PIN * RepeatPin(const SCH_PIN *aSourcePin)
SCH_PIN * CreatePin(const VECTOR2I &aPosition, LIB_SYMBOL *aSymbol)
bool PlacePin(SCH_COMMIT *aCommit, SCH_PIN *aPin)
The symbol library editor main window.
KIGFX::VIEW_CONTROLS * getViewControls() const
Definition tool_base.cpp:44
KIGFX::VIEW * getView() const
Definition tool_base.cpp:38
Generic, UI-independent tool event.
Definition tool_event.h:171
bool HasPosition() const
Returns if it this event has a valid position (true for mouse events and context-menu or hotkey-based...
Definition tool_event.h:260
bool DisableGridSnapping() const
Definition tool_event.h:371
const VECTOR2D Position() const
Return mouse cursor position in world coordinates.
Definition tool_event.h:293
bool IsReactivate() const
Control whether the tool is first being pushed to the stack or being reactivated after a pause.
Definition tool_event.h:273
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
T Parameter() const
Return a parameter assigned to the event.
Definition tool_event.h:473
void Go(int(SYMBOL_EDIT_FRAME::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
std::unique_ptr< TOOL_MENU > m_menu
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
@ PLACE
Definition cursors.h:96
@ MOVING
Definition cursors.h:48
@ ARROW
Definition cursors.h:46
@ BULLSEYE
Definition cursors.h:56
@ PENCIL
Definition cursors.h:50
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
#define _(s)
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition eda_angle.h:407
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
Definition eda_item.h:566
#define IS_NEW
New item, just created.
#define IS_MOVING
Item being moved.
SHAPE_T
Definition eda_shape.h:43
@ SEGMENT
Definition eda_shape.h:45
FILL_T
Definition eda_shape.h:56
@ NO_FILL
Definition eda_shape.h:57
@ GRID_GRAPHICS
Definition grid_helper.h:51
@ LAYER_DEVICE
Definition layer_ids.h:465
PGM_BASE & Pgm()
The global program "get" accessor.
Definition pgm_base.cpp:913
see class PGM_BASE
T * GetAppSettings(const char *aFilename)
bool NoPrintableChars(const wxString &aString)
Return true if the string is empty or contains only whitespace.
LINE_STYLE
Dashed line types.
int delta
@ GR_TEXT_H_ALIGN_LEFT
@ MD_SHIFT
Definition tool_event.h:143
@ BUT_LEFT
Definition tool_event.h:132
@ BUT_RIGHT
Definition tool_event.h:133
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:78
@ SCH_TEXT_T
Definition typeinfo.h:153
@ SCH_PIN_T
Definition typeinfo.h:155
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695